launcher more parametric
authorJosé Bollo <jose.bollo@iot.bzh>
Mon, 21 Dec 2015 22:18:10 +0000 (23:18 +0100)
committerJosé Bollo <jose.bollo@iot.bzh>
Mon, 21 Dec 2015 22:18:51 +0000 (23:18 +0100)
Change-Id: Id73ae4cb907cc4555a008737ead97403514f5dd6

src/af-launch.c

index 438dca6..ce42221 100644 (file)
@@ -35,28 +35,145 @@ extern char **environ;
 #include "af-launch.h"
 #include "secmgr-wrap.h"
 
-struct launchparam {
-       int port;
-       const char *secret;
+/*
+%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
+%m mime-type                   desc->type
+%n name                                desc->name
+%p plugins                     desc->plugins
+%W width                       desc->width
+%H height                      desc->height
+*/
+
+static const char *launch_master_args[] = {
+       "/usr/bin/echo",
+       "--alias=/icons:%I",
+       "--port=%P",
+       "--rootdir=%D",
+       "--token=%S",
+       NULL
 };
 
-static int launch_html(struct af_launch_desc *desc, struct launchparam *params);
-static int launch_bin(struct af_launch_desc *desc, struct launchparam *params);
-static int launch_qml(struct af_launch_desc *desc, struct launchparam *params);
+static const char *launch_html_args[] = {
+       "/usr/bin/chromium",
+       "--single-process",
+       "--user-data-dir=%D",
+       "--data-path=%r",
+       "file://%r/%c",
+/*
+       "http://localhost:%P",
+*/
+       NULL
+};
+
+static const char *launch_bin_args[] = {
+       "/usr/bin/echo",
+       "BINARY",
+       NULL
+};
 
-static int launch_master(struct af_launch_desc *desc, struct launchparam *params, int fd, pid_t child);
+static const char *launch_qml_args[] = {
+       "/usr/bin/echo",
+       "QML",
+       NULL
+};
 
 static struct {
        const char *type;
-       int (*launcher)(struct af_launch_desc *desc, struct launchparam *params);
+       const char **launch_args;
 }
 known_launchers[] = {
-       { "text/html", launch_html },
-       { "application/x-executable", launch_bin },
-       { "application/octet-stream", launch_bin },
-       { "text/vnd.qt.qml", launch_qml }
+       { "text/html",                launch_html_args },
+       { "application/x-executable", launch_bin_args },
+       { "application/octet-stream", launch_bin_args },
+       { "text/vnd.qt.qml",          launch_qml_args }
 };
 
+struct launchparam {
+       int port;
+       const char *secret;
+       const char *datadir;
+};
+
+static char **instantiate_arguments(const char **args, struct af_launch_desc *desc, struct launchparam *params)
+{
+       const char **iter, *p, *v;
+       char *data, **result, port[20], width[20], height[20], mini[3], c;
+       int n, s, x;
+
+       /* init */
+       mini[0] = '%';
+       mini[2] = 0;
+
+       /* loop that either compute the size and build the result */
+       n = s = x = 0;
+       for (;;) {
+               iter = args;
+               n = 0;
+               while (*iter) {
+                       p = *iter++;
+                       if (x)
+                               result[n] = data;
+                       n++;
+                       while((c = *p++) != 0) {
+                               if (c != '%') {
+                                       if (x)
+                                               *data++ = c;
+                                       else
+                                               s++;
+                               } else {
+                                       c = *p++;
+                                       switch (c) {
+                                       case 'I': v = FWK_ICON_DIR; break;
+                                       case 'P': if(!x) 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 'm': v = desc->type; break;
+                                       case 'n': v = desc->name; break;
+                                       case 'p': v = "" /*desc->plugins*/; break;
+                                       case 'W': if(!x) sprintf(width, "%d", desc->width); v = width; break;
+                                       case 'H': if(!x) sprintf(height, "%d", desc->height); v = height; break;
+                                       case '%': c = 0;
+                                       default: mini[1] = c; v = mini; break;
+                                       }
+                                       if (x)
+                                               data = stpcpy(data, v);
+                                       else
+                                               s += strlen(v);
+                               }
+                       }
+                       if (x)
+                               *data++ = 0;
+                       else
+                               s++;
+               }
+               if (x) {
+                       result[n] = NULL;
+                       return result;
+               }
+               /* allocation */
+               result = malloc((n+1)*sizeof(char*) + s);
+               if (result == NULL) {
+                       errno = ENOMEM;
+                       return NULL;
+               }
+               data = (char*)(&result[n + 1]);
+               x = 1;
+       }
+}
+
 static void mksecret(char buffer[9])
 {
        snprintf(buffer, 9, "%08lX", (0xffffffff & random()));
@@ -82,6 +199,7 @@ int af_launch(struct af_launch_desc *desc, pid_t children[2])
        int mpipe[2];
        int spipe[2];
        struct launchparam params;
+       char **args;
 
        /* what launcher ? */
        ikl = 0;
@@ -110,6 +228,7 @@ int af_launch(struct af_launch_desc *desc, pid_t children[2])
 
        params.port = port;
        params.secret = secret;
+       params.datadir = datadir;
 
        /* prepare the pipes */
        rc = pipe2(mpipe, O_CLOEXEC);
@@ -205,65 +324,35 @@ int af_launch(struct af_launch_desc *desc, pid_t children[2])
                        ERROR("reading slave pipe failed: %m");
                        _exit(1);
                }
-               rc = known_launchers[ikl].launcher(desc, &params);
-               ERROR("slave launch failed: %m");
+
+               args = instantiate_arguments(known_launchers[ikl].launch_args, desc, &params);
+               if (args == NULL) {
+                       ERROR("out of memory in slave");
+               }
+               else {
+                       rc = execve(args[0], args, environ);
+                       ERROR("failed to exec slave %s: %m", args[0]);
+               }
                _exit(1);
        }
 
        /********* still in the master child ************/
        close(spipe[1]);
-       rc = launch_master(desc, &params, mpipe[1], children[1]);
-       ERROR("master launch failed: %m");
-       _exit(1);
-}
-
-static int launch_master(struct af_launch_desc *desc, struct launchparam *params, int fd, pid_t child)
-{
-       int rc;
-       char *argv[6];
-       argv[0] = "/usr/bin/echo";
-       (void)asprintf(&argv[1], "--alias=/icons:%s", FWK_ICON_DIR);
-       (void)asprintf(&argv[2], "--port=%d", params->port);
-       (void)asprintf(&argv[3], "--rootdir=%s", desc->path);
-       (void)asprintf(&argv[4], "--token=%s", params->secret);
-       argv[5] = NULL;
-
-       rc = write(fd, &child, sizeof child);
-       if (rc < 0) {
-               ERROR("can't write master pipe: %m");
-               return -1;
+       args = instantiate_arguments(launch_master_args, desc, &params);
+       if (args == NULL) {
+               ERROR("out of memory in master");
        }
-       close(fd);
-       rc = execve(argv[0], argv, environ);
-       ERROR("failed to exec master %s: %m", argv[0]);
-       return rc;
-}
-
-static int launch_html(struct af_launch_desc *desc, struct launchparam *params)
-{
-/*
-       char *url = asprintf("http://localhost:%d/", params->port);
-*/
-       int rc;
-       char *argv[3];
-       argv[0] = "/usr/bin/chromium";
-       (void)asprintf(&argv[1], "file://%s/%s", desc->path, desc->content);
-       argv[2] = NULL;
-       rc = execve(argv[0], argv, environ);
-       ERROR("failed to exec slave %s: %m", argv[0]);
-       return rc;
-}
-
-static int launch_bin(struct af_launch_desc *desc, struct launchparam *params)
-{
-       ERROR("unimplemented launch_bin");
-       return -1;
-}
-
-static int launch_qml(struct af_launch_desc *desc, struct launchparam *params)
-{
-       ERROR("unimplemented launch_qml");
-       return -1;
+       else {
+               rc = write(mpipe[1], &children[1], sizeof children[1]);
+               if (rc < 0) {
+                       ERROR("can't write master pipe: %m");
+               }
+               else {
+                       close(mpipe[1]);
+                       rc = execve(args[0], args, environ);
+                       ERROR("failed to exec master %s: %m", args[0]);
+               }
+       }
+       _exit(1);
 }
 
-