afm-launch: add readyfd and improves typing
[src/app-framework-main.git] / src / afm-launch.c
index 87e8e3a..75bd4b0 100644 (file)
@@ -43,19 +43,26 @@ struct type_list {
        char type[1];
 };
 
+struct exec_vector {
+       int has_readyfd;
+       const char **args;
+};
+
 struct desc_list {
        struct desc_list *next;
        enum afm_launch_mode mode;
        struct type_list *types;
-       char **execs[2];
+       struct exec_vector execs[2];
 };
 
 struct launchparam {
        int port;
+       int readyfd;
+       char **uri;
        const char *secret;
        const char *datadir;
-       const char **master;
-       const char **slave;
+       struct exec_vector *master;
+       struct exec_vector *slave;
 };
 
 struct confread {
@@ -84,9 +91,9 @@ static void dump_launchers()
                for (type = desc->types ; type != NULL ; type = type->next)
                        printf("%s\n", type->type);
                for ( j = 0 ; j < 2 ; j++)
-                       if (desc->execs[j] != NULL) {
-                               for (k = 0 ; desc->execs[j][k] != NULL ; k++)
-                                       printf("  %s", desc->execs[j][k]);
+                       if (desc->execs[j].args != NULL) {
+                               for (k = 0 ; desc->execs[j].args[k] != NULL ; k++)
+                                       printf("  %s", desc->execs[j].args[k]);
                                printf("\n");
                        }
                printf("\n");
@@ -95,7 +102,8 @@ static void dump_launchers()
 
 static int next_token(struct confread *cread)
 {
-       cread->index += cread->length + strspn(&cread->buffer[cread->index + cread->length], separators);
+       int idx = cread->index + cread->length;
+       cread->index = idx + strspn(&cread->buffer[idx], separators);
        cread->length = strcspn(&cread->buffer[cread->index], separators);
        return cread->length;
 }
@@ -118,10 +126,11 @@ static int read_line(struct confread *cread)
        return 0;
 }
 
-static char **read_vector(struct confread *cread)
+static const char **read_vector(struct confread *cread)
 {
        int index0, length0;
-       char **vector, *args;
+       const char **vector;
+       char *args;
        int count, length;
 
        /* record origin */
@@ -171,7 +180,8 @@ static struct type_list *read_type(struct confread *cread)
 
        /* check no extra characters */
        if (next_token(cread)) {
-               ERROR("%s:%d: extra characters found after type %.*s", cread->filepath, cread->lineno, length, &cread->buffer[index]);
+               ERROR("%s:%d: extra characters found after type %.*s",
+                       cread->filepath, cread->lineno, length, &cread->buffer[index]);
                errno = EINVAL;
                return NULL;
        }
@@ -211,7 +221,8 @@ static enum afm_launch_mode read_mode(struct confread *cread)
 
        /* check no extra characters */
        if (next_token(cread)) {
-               ERROR("%s:%d: extra characters found after mode %.*s", cread->filepath, cread->lineno, length, &cread->buffer[index]);
+               ERROR("%s:%d: extra characters found after mode %.*s",
+                       cread->filepath, cread->lineno, length, &cread->buffer[index]);
                errno = EINVAL;
                return invalid_launch_mode;
        }
@@ -220,7 +231,8 @@ static enum afm_launch_mode read_mode(struct confread *cread)
        cread->buffer[index + length] = 0;
        result = launch_mode_of_string(&cread->buffer[index]);
        if (result == invalid_launch_mode) {
-               ERROR("%s:%d: invalid mode value %s", cread->filepath, cread->lineno, &cread->buffer[index]);
+               ERROR("%s:%d: invalid mode value %s",
+                       cread->filepath, cread->lineno, &cread->buffer[index]);
                errno = EINVAL;
        }
        return result;
@@ -237,11 +249,11 @@ static void free_type_list(struct type_list *types)
 
 static int read_launchers(struct confread *cread)
 {
-       int rc;
+       int rc, has_readyfd;
        struct type_list *types, *lt;
        struct desc_list *desc;
        enum afm_launch_mode mode;
-       char **vector;
+       const char **vector;
 
        /* reads the file */
        lt = NULL;
@@ -251,10 +263,12 @@ static int read_launchers(struct confread *cread)
        rc = read_line(cread);
        while (rc > 0) {
                if (cread->index == 0) {
-                       if (cread->length == 4 && !memcmp(&cread->buffer[cread->index], "mode", 4)) {
+                       if (cread->length == 4
+                       && !memcmp(&cread->buffer[cread->index], "mode", 4)) {
                                /* check if allowed */
                                if (types != NULL) {
-                                       ERROR("%s:%d: mode found before launch vector", cread->filepath, cread->lineno);
+                                       ERROR("%s:%d: mode found before launch vector",
+                                               cread->filepath, cread->lineno);
                                        errno = EINVAL;
                                        free_type_list(types);
                                        return -1;
@@ -266,7 +280,8 @@ static int read_launchers(struct confread *cread)
                                        return -1;
                        } else {
                                if (mode == invalid_launch_mode) {
-                                       ERROR("%s:%d: mode not found before type", cread->filepath, cread->lineno);
+                                       ERROR("%s:%d: mode not found before type",
+                                                       cread->filepath, cread->lineno);
                                        errno = EINVAL;
                                        assert(types == NULL);
                                        return -1;
@@ -283,15 +298,19 @@ static int read_launchers(struct confread *cread)
                        desc = NULL;
                } else if (types == NULL && desc == NULL) {
                        if (lt == NULL)
-                               ERROR("%s:%d: untyped launch vector found", cread->filepath, cread->lineno);
+                               ERROR("%s:%d: untyped launch vector found",
+                                       cread->filepath, cread->lineno);
                        else
-                               ERROR("%s:%d: extra launch vector found (2 max)", cread->filepath, cread->lineno);
+                               ERROR("%s:%d: extra launch vector found (2 max)",
+                                       cread->filepath, cread->lineno);
                        errno = EINVAL;
                        return -1;
                } else {
+                       has_readyfd = NULL != strstr(&cread->buffer[cread->index], "%R");
                        vector = read_vector(cread);
                        if (vector == NULL) {
-                               ERROR("%s:%d: out of memory", cread->filepath, cread->lineno);
+                               ERROR("%s:%d: out of memory",
+                                       cread->filepath, cread->lineno);
                                free_type_list(types);
                                errno = ENOMEM;
                                return -1;
@@ -300,7 +319,8 @@ static int read_launchers(struct confread *cread)
                                assert(desc == NULL);
                                desc = malloc(sizeof * desc);
                                if (desc == NULL) {
-                                       ERROR("%s:%d: out of memory", cread->filepath, cread->lineno);
+                                       ERROR("%s:%d: out of memory",
+                                               cread->filepath, cread->lineno);
                                        free_type_list(types);
                                        errno = ENOMEM;
                                        return -1;
@@ -308,19 +328,23 @@ static int read_launchers(struct confread *cread)
                                desc->next = launchers;
                                desc->mode = mode;
                                desc->types = types;
-                               desc->execs[0] = vector;
-                               desc->execs[1] = NULL;
+                               desc->execs[0].has_readyfd = has_readyfd;
+                               desc->execs[0].args = vector;
+                               desc->execs[1].has_readyfd = 0;
+                               desc->execs[1].args = NULL;
                                types = NULL;
                                launchers = desc;
                        } else {
-                               desc->execs[1] = vector;
+                               desc->execs[1].has_readyfd = has_readyfd;
+                               desc->execs[1].args = vector;
                                desc = NULL;
                        }
                }
                rc = read_line(cread);
        }
        if (types != NULL) {
-               ERROR("%s:%d: end of file found before launch vector", cread->filepath, cread->lineno);
+               ERROR("%s:%d: end of file found before launch vector",
+                       cread->filepath, cread->lineno);
                free_type_list(types);
                errno = EINVAL;
                return -1;
@@ -350,44 +374,59 @@ static int read_configuration_file(const char *filepath)
 }
 
 /*
-%I icondir                     FWK_ICON_DIR
-%P port                                params->port
-%S secret                      params->secret
-%D datadir                     params->datadir
-%r rootdir                     desc->path
-%h homedir                     desc->home
-%t tag (smack label)           desc->tag
+%% %
 %a appid                       desc->appid
 %c content                     desc->content
+%D datadir                     params->datadir
+%H height                      desc->height
+%h homedir                     desc->home
+%I icondir                     FWK_ICON_DIR
 %m mime-type                   desc->type
 %n name                                desc->name
 %p plugins                     desc->plugins
+%P port                                params->port
+%r rootdir                     desc->path
+%R readyfd                      params->readyfd
+%S secret                      params->secret
+%t tag (smack label)           desc->tag
 %W width                       desc->width
-%H height                      desc->height
-%% %
 */
 
-static char **instantiate_arguments(const char **args, struct afm_launch_desc *desc, struct launchparam *params)
+union arguments {
+       char *scalar;
+       char **vector;
+};
+
+static union arguments instantiate_arguments(
+       const char * const     *args,
+       struct afm_launch_desc *desc,
+       struct launchparam     *params,
+       int                     wants_vector
+)
 {
-       const char **iter, *p, *v;
-       char *data, **result, port[20], width[20], height[20], mini[3], c;
+       const char * const *iter;
+       const char *p, *v;
+       char *data, port[20], width[20], height[20], readyfd[20], mini[3], c, sep;
        int n, s;
+       union arguments result;
 
        /* init */
+       sep = wants_vector ? 0 : ' ';
        mini[0] = '%';
        mini[2] = 0;
 
        /* loop that either compute the size and build the result */
+       result.vector = NULL;
+       result.scalar = NULL;
        data = NULL;
-       result = NULL;
        n = s = 0;
        for (;;) {
                iter = args;
                n = 0;
                while (*iter) {
                        p = *iter++;
-                       if (data)
-                               result[n] = data;
+                       if (data && !sep)
+                               result.vector[n] = data;
                        n++;
                        while((c = *p++) != 0) {
                                if (c != '%') {
@@ -398,22 +437,43 @@ static char **instantiate_arguments(const char **args, struct afm_launch_desc *d
                                } else {
                                        c = *p++;
                                        switch (c) {
-                                       case 'I': v = FWK_ICON_DIR; break;
-                                       case 'P': if(!data) sprintf(port, "%d", params->port); v = port; break;
-                                       case 'S': v = params->secret; break;
-                                       case 'D': v = params->datadir; break;
-                                       case 'r': v = desc->path; break;
-                                       case 'h': v = desc->home; break;
-                                       case 't': v = desc->tag; break;
                                        case 'a': v = desc->appid; break;
                                        case 'c': v = desc->content; break;
+                                       case 'D': v = params->datadir; break;
+                                       case 'H':
+                                               if(!data)
+                                                       sprintf(height, "%d", desc->height);
+                                               v = height;
+                                               break;
+                                       case 'h': v = desc->home; break;
+                                       case 'I': v = FWK_ICON_DIR; break;
                                        case 'm': v = desc->type; break;
                                        case 'n': v = desc->name; break;
+                                       case 'P':
+                                               if(!data)
+                                                       sprintf(port, "%d", params->port);
+                                               v = port;
+                                               break;
                                        case 'p': v = "" /*desc->plugins*/; break;
-                                       case 'W': if(!data) sprintf(width, "%d", desc->width); v = width; break;
-                                       case 'H': if(!data) sprintf(height, "%d", desc->height); v = height; break;
-                                       case '%': c = 0;
-                                       default: mini[1] = c; v = mini; break;
+                                       case 'R':
+                                               if(!data)
+                                                       sprintf(readyfd, "%d", params->readyfd);
+                                               v = readyfd;
+                                               break;
+                                       case 'r': v = desc->path; break;
+                                       case 'S': v = params->secret; break;
+                                       case 't': v = desc->tag; break;
+                                       case 'W':
+                                               if(!data)
+                                                       sprintf(width, "%d", desc->width);
+                                               v = width;
+                                               break;
+                                       case '%':
+                                               c = 0;
+                                       default:
+                                               mini[1] = c;
+                                               v = mini;
+                                               break;
                                        }
                                        if (data)
                                                data = stpcpy(data, v);
@@ -422,21 +482,37 @@ static char **instantiate_arguments(const char **args, struct afm_launch_desc *d
                                }
                        }
                        if (data)
-                               *data++ = 0;
+                               *data++ = sep;
                        else
                                s++;
                }
-               if (data) {
-                       result[n] = NULL;
-                       return result;
-               }
-               /* allocation */
-               result = malloc((n+1)*sizeof(char*) + s);
-               if (result == NULL) {
-                       errno = ENOMEM;
-                       return NULL;
+               if (sep) {
+                       assert(!wants_vector);
+                       if (data) {
+                               *--data = 0;
+                               return result;
+                       }
+                       /* allocation */
+                       result.scalar = malloc(s);
+                       if (result.scalar == NULL) {
+                               errno = ENOMEM;
+                               return result;
+                       }
+                       data = result.scalar;
+               } else {
+                       assert(wants_vector);
+                       if (data) {
+                               result.vector[n] = NULL;
+                               return result;
+                       }
+                       /* allocation */
+                       result.vector = malloc((n+1)*sizeof(char*) + s);
+                       if (result.vector == NULL) {
+                               errno = ENOMEM;
+                               return result;
+                       }
+                       data = (char*)(&result.vector[n + 1]);
                }
-               data = (char*)(&result[n + 1]);
        }
 }
 
@@ -455,7 +531,11 @@ static int mkport()
        return port;
 }
 
-static int launchexec1(struct afm_launch_desc *desc, pid_t children[2], struct launchparam *params)
+static int launch_local_1(
+       struct afm_launch_desc *desc,
+       pid_t                   children[2],
+       struct launchparam     *params
+)
 {
        int rc;
        char **args;
@@ -502,7 +582,7 @@ static int launchexec1(struct afm_launch_desc *desc, pid_t children[2], struct l
                _exit(1);
        }
 
-       args = instantiate_arguments(params->master, desc, params);
+       args = instantiate_arguments(params->master->args, desc, params, 1).vector;
        if (args == NULL) {
                ERROR("out of memory in master");
        }
@@ -513,7 +593,11 @@ static int launchexec1(struct afm_launch_desc *desc, pid_t children[2], struct l
        _exit(1);
 }
 
-static int launchexec2(struct afm_launch_desc *desc, pid_t children[2], struct launchparam *params)
+static int launch_local_2(
+       struct afm_launch_desc *desc,
+       pid_t                   children[2],
+       struct launchparam     *params
+)
 {
        int rc;
        char message[10];
@@ -618,7 +702,7 @@ static int launchexec2(struct afm_launch_desc *desc, pid_t children[2], struct l
                        _exit(1);
                }
 
-               args = instantiate_arguments(params->slave, desc, params);
+               args = instantiate_arguments(params->slave->args, desc, params, 1).vector;
                if (args == NULL) {
                        ERROR("out of memory in slave");
                }
@@ -631,7 +715,7 @@ static int launchexec2(struct afm_launch_desc *desc, pid_t children[2], struct l
 
        /********* still in the master child ************/
        close(spipe[1]);
-       args = instantiate_arguments(params->master, desc, params);
+       args = instantiate_arguments(params->master->args, desc, params, 1).vector;
        if (args == NULL) {
                ERROR("out of memory in master");
        }
@@ -649,19 +733,43 @@ static int launchexec2(struct afm_launch_desc *desc, pid_t children[2], struct l
        _exit(1);
 }
 
-int afm_launch_initialize()
+static int launch_local(
+       struct afm_launch_desc *desc,
+       pid_t                   children[2],
+       struct launchparam     *params
+)
+{
+       if (params->slave == NULL)
+               return launch_local_1(desc, children, params);
+       return launch_local_2(desc, children, params);
+}
+
+static int launch_remote(
+       struct afm_launch_desc *desc,
+       pid_t                   children[2],
+       struct launchparam     *params
+)
 {
        int rc;
-       gid_t r, e, s;
+       char *uri;
 
-       getresgid(&r, &e, &s);
-       if (s && s != e)
-               groupid = s;
+       /* instanciate the uri */
+       if (params->slave == NULL)
+               uri = NULL;
        else
-               groupid = -1;
+               uri = instantiate_arguments(params->slave->args, desc, params, 0).scalar;
+       if (uri == NULL) {
+               ERROR("out of memory for remote uri");
+               errno = ENOMEM;
+               return -1;
+       }
 
-       rc = read_configuration_file(FWK_LAUNCH_CONF);
-       dump_launchers();
+       /* launch the command */
+       rc = launch_local_1(desc, children, params);
+       if (rc)
+               free(uri);
+       else
+               *params->uri = uri;
        return rc;
 }
 
@@ -680,8 +788,8 @@ static struct desc_list *search_launcher(const char *type, enum afm_launch_mode
 
 int afm_launch(struct afm_launch_desc *desc, pid_t children[2], char **uri)
 {
-       char datadir[PATH_MAX];
        int rc;
+       char datadir[PATH_MAX];
        char secret[9];
        struct launchparam params;
        const char *type;
@@ -690,6 +798,8 @@ int afm_launch(struct afm_launch_desc *desc, pid_t children[2], char **uri)
        /* should be init */
        assert(groupid != 0);
        assert(launch_mode_is_valid(desc->mode));
+       assert(desc->mode == mode_local || uri != NULL);
+       assert(uri == NULL || *uri == NULL);
 
        /* init */
        children[0] = 0;
@@ -714,12 +824,37 @@ int afm_launch(struct afm_launch_desc *desc, pid_t children[2], char **uri)
 
        /* make the secret and port */
        mksecret(secret);
+       params.uri = uri;
        params.port = mkport();
        params.secret = secret;
        params.datadir = datadir;
-       params.master = (const char **)dl->execs[0];
-       params.slave = (const char **)dl->execs[1];
+       params.master = &dl->execs[0];
+       params.slave = &dl->execs[1];
+
+       switch (desc->mode) {
+       case mode_local:
+               return launch_local(desc, children, &params);
+       case mode_remote:
+               return launch_remote(desc, children, &params);
+       default:
+               assert(0);
+               return -1;
+       }
+}
+
+int afm_launch_initialize()
+{
+       int rc;
+       gid_t r, e, s;
+
+       getresgid(&r, &e, &s);
+       if (s && s != e)
+               groupid = s;
+       else
+               groupid = -1;
 
-       return params.slave ? launchexec2(desc, children, &params) : launchexec1(desc, children, &params);
+       rc = read_configuration_file(FWK_LAUNCH_CONF);
+       dump_launchers();
+       return rc;
 }