adds config file for launchers
authorJosé Bollo <jose.bollo@iot.bzh>
Mon, 8 Feb 2016 20:24:56 +0000 (21:24 +0100)
committerJosé Bollo <jose.bollo@iot.bzh>
Mon, 8 Feb 2016 20:38:37 +0000 (21:38 +0100)
Change-Id: Ibbedefcdedbfc7f6fe7c89f8e8f32d022a93ca19
Signed-off-by: José Bollo <jose.bollo@iot.bzh>
CMakeLists.txt
conf/CMakeLists.txt
conf/afm-launch.conf [new file with mode: 0644]
src/afm-launch.c
src/afm-launch.h
src/afm-run.c

index e8c98b4..48cb270 100644 (file)
@@ -53,6 +53,7 @@ defstr(FWK_ICON_DIR            "${afm_icondir}")
 defstr(FWK_APP_DIR             "${afm_appdir}")
 defstr(FWK_USER_APP_DIR        "${afm_user_appdir}")
 defstr(WGTPKG_TRUSTED_CERT_DIR "${wgtpkg_trusted_cert_dir}")
+defstr(FWK_LAUNCH_CONF         "${afm_confdir}/afm-launch.conf")
 
 add_subdirectory(src)
 add_subdirectory(conf)
index 312b764..62bdf0f 100644 (file)
@@ -27,4 +27,5 @@ install(FILES afm-system-daemon.conf    DESTINATION ${SYSCONFDIR_DBUS_SYSTEM})
 install(FILES afm-system-daemon.service DESTINATION ${UNITDIR_SYSTEM})
 install(FILES afm-user-daemon.conf      DESTINATION ${SYSCONFDIR_DBUS_USER})
 install(FILES afm-user-daemon.service   DESTINATION ${UNITDIR_USER})
+install(FILES afm-launch.conf           DESTINATION ${afm_confdir})
 
diff --git a/conf/afm-launch.conf b/conf/afm-launch.conf
new file mode 100644 (file)
index 0000000..771569b
--- /dev/null
@@ -0,0 +1,26 @@
+# %I icondir
+# %P port
+# %S secret
+# %D datadir
+# %r rootdir
+# %h homedir
+# %t tag (smack label)
+# %a appid
+# %c content
+# %m mime-type
+# %n name
+# %p plugins
+# %W width
+# %H height
+# %% %
+
+text/html
+       /usr/bin/afb-daemon --alias=/icons:%I --port=%P --rootdir=%r --token=%S --sessiondir=%D
+       /usr/bin/web-runtime http://localhost:%P/%c?token=%S
+
+application/x-executable
+       %r/%c
+
+text/vnd.qt.qml
+       /usr/bin/qt5/qmlscene -fullscreen -I %r -I %r/imports %r/%c
+
index c1c6fdd..c55297a 100644 (file)
@@ -52,6 +52,16 @@ extern char **environ;
 %H height                      desc->height
 */
 
+#define DEFAULT_TYPE "text/html"
+
+const char separators[] = " \t\n";
+
+struct execdesc {
+       char *type;
+       char **execs[2];
+};
+
+#if 0
 static const char *args_for_afb_daemon[] = {
        "/usr/bin/afb-daemon",
        "--alias=/icons:%I",
@@ -83,28 +93,185 @@ static const char *args_for_binary[] = {
        NULL
 };
 
-struct execdesc {
-       const char *type;
-       const char **master_args;
-       const char **slave_args;
-};
-
 static struct execdesc known_launchers[] = {
        { "text/html",                args_for_afb_daemon, args_for_web_runtime },
        { "application/x-executable", args_for_binary,     NULL },
-       { "text/vnd.qt.qml",          args_for_qmlviewer,  NULL }
+       { "text/vnd.qt.qml",          args_for_qmlviewer,  NULL },
+       { NULL, NULL, NULL }
+};
+#endif
+
+struct launchers {
+       int count;
+       struct execdesc *descs;
 };
 
+static struct launchers launchers = { 0, NULL };
+
 struct launchparam {
        int port;
        const char *secret;
        const char *datadir;
-       const char **master_args;
-       const char **slave_args;
+       const char **master;
+       const char **slave;
 };
 
 static gid_t groupid = 0;
 
+static int read_type(const char *buffer, const char *filepath, int line)
+{
+       size_t length;
+       int count;
+       struct execdesc *descs;
+       char *type;
+
+       /* check the type */
+       length = strcspn(buffer, separators);
+       assert(length);
+       if (buffer[length + strspn(buffer + length, separators)] != 0) {
+               ERROR("%s:%d: extra characters found after type", filepath, line);
+               errno = EINVAL;
+               return -1;
+       }
+
+       /* allocates data */
+       type = strndup(buffer, length);
+       count = launchers.count + 1;
+       descs = realloc(launchers.descs, count * sizeof(struct execdesc));
+       if (descs == NULL || type == NULL) {
+               free(type);
+               errno = ENOMEM;
+               return -1;
+       }
+
+       /* fill data */
+       launchers.descs = descs;
+       descs += count - 1;
+       descs->type = type;
+       descs->execs[0] = NULL;
+       descs->execs[1] = NULL;
+       launchers.count = count;
+       return 0;
+}
+
+static int read_args(const char *buffer, int bottom, int offset, const char *filepath, int line)
+{
+       char **vector, *args;
+       size_t index, len, length;
+       int count;
+
+       /* count */
+       count = 0;
+       length = index = 0;
+       while(buffer[index]) {
+               count++;
+               /* skips the spaces */
+               len = strcspn(buffer + index, separators);
+               length += len;
+               /* skips the spaces */
+               index += len;
+               index += strspn(buffer + index, separators);
+       }
+       /* allocates */
+       while (bottom < launchers.count) {
+               vector = malloc(length + count + (count + 1) * sizeof(char*));
+               if (vector == NULL) {
+                       ERROR("%s:%d: out of memory", filepath, line);
+                       return -1;
+               }
+               args = (char*)(vector + count + 1);
+               count = 0;
+               index = 0;
+               while(buffer[index]) {
+                       /* skips the spaces */
+                       len = strcspn(buffer + index, separators);
+                       vector[count++] = args;
+                       memcpy(args, buffer + index, len);
+                       args += len;
+                       index += len;
+                       *args++ = 0;
+                       /* skips the spaces */
+                       len = strspn(buffer + index, separators);
+                       index += len;
+               }
+               vector[count] = NULL;
+               launchers.descs[bottom++].execs[offset] = vector;
+       }
+       return 0;
+}
+
+static int read_launchers(FILE *file, const char *filepath)
+{
+       char buffer[4096];
+       int index, line, rc, bottom, offset, typed;
+
+       /* reads the file */
+       line = 0;
+       offset = 0;
+       typed = 0;
+       bottom = launchers.count;
+       while (fgets(buffer, sizeof buffer, file) != NULL) {
+               line++;
+
+               /* find start of line */
+               index = strspn(buffer, separators);
+
+               /* skip empty lines and comments */
+               if (buffer[index] == 0 || buffer[index] == '#')
+                       continue;
+
+               if (index == 0) {
+                       if (!typed)
+                               bottom = launchers.count;
+                       rc = read_type(buffer, filepath, line);
+                       if (rc)
+                               return rc;
+                       if (!typed) {
+                               typed = 1;
+                               offset = 0;
+                       }
+               } else if (!typed && !offset) {
+                       ERROR("%s:%d: untyped launcher found", filepath, line);
+                       errno = EINVAL;
+                       return -1;
+               } else if (offset >= 2) {
+                       ERROR("%s:%d: extra launcher found", filepath, line);
+                       errno = EINVAL;
+                       return -1;
+               } else {
+                       rc = read_args(buffer + index, bottom, offset, filepath, line);
+                       if (rc)
+                               return rc;
+                       offset++;
+                       typed = 0;
+               }
+       }
+       if (ferror(file)) {
+               ERROR("%s:%d: error while reading, %m", filepath, line);
+               return -1;
+       }
+       return 0;
+}
+
+static int read_configuration_file(const char *filepath)
+{
+       int rc;
+       FILE *file;
+
+       /* opens the configuration file */
+       file = fopen(filepath, "r");
+       if (file == NULL) {
+               /* error */
+               ERROR("can't read file %s: %m", filepath);
+               rc = -1;
+       } else {
+               /* reads it */
+               rc = read_launchers(file, filepath);
+               fclose(file);
+       }
+       return rc;
+}
+
 static char **instantiate_arguments(const char **args, struct afm_launch_desc *desc, struct launchparam *params)
 {
        const char **iter, *p, *v;
@@ -193,8 +360,6 @@ static int mkport()
        return port;
 }
 
-
-
 static int launchexec1(struct afm_launch_desc *desc, pid_t children[2], struct launchparam *params)
 {
        int rc;
@@ -242,7 +407,7 @@ static int launchexec1(struct afm_launch_desc *desc, pid_t children[2], struct l
                _exit(1);
        }
 
-       args = instantiate_arguments(params->master_args, desc, params);
+       args = instantiate_arguments(params->master, desc, params);
        if (args == NULL) {
                ERROR("out of memory in master");
        }
@@ -358,7 +523,7 @@ static int launchexec2(struct afm_launch_desc *desc, pid_t children[2], struct l
                        _exit(1);
                }
 
-               args = instantiate_arguments(params->slave_args, desc, params);
+               args = instantiate_arguments(params->slave, desc, params);
                if (args == NULL) {
                        ERROR("out of memory in slave");
                }
@@ -371,7 +536,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_args, desc, params);
+       args = instantiate_arguments(params->master, desc, params);
        if (args == NULL) {
                ERROR("out of memory in master");
        }
@@ -389,39 +554,41 @@ static int launchexec2(struct afm_launch_desc *desc, pid_t children[2], struct l
        _exit(1);
 }
 
-static void afm_launch_init_group()
+int afm_launch_initialize()
 {
-       if (!groupid) {
-               gid_t r, e, s;
-               getresgid(&r, &e, &s);
-               if (s && s != e)
-                       groupid = s;
-               else
-                       groupid = -1;
-       }
+       gid_t r, e, s;
+       getresgid(&r, &e, &s);
+       if (s && s != e)
+               groupid = s;
+       else
+               groupid = -1;
+       return read_configuration_file(FWK_LAUNCH_CONF);
 }
 
 int afm_launch(struct afm_launch_desc *desc, pid_t children[2])
 {
        char datadir[PATH_MAX];
-       int ikl, nkl, rc;
+       int ikl, rc;
        char secret[9];
        struct launchparam params;
+       const char *type;
+
+       /* should be init */
+       assert(groupid != 0);
 
-       /* static init */
-       afm_launch_init_group();
+       /* init */
+       children[0] = 0;
+       children[1] = 0;
 
        /* what launcher ? */
+       type = desc->type != NULL && *desc->type ? desc->type : DEFAULT_TYPE;
        ikl = 0;
-       if (desc->type != NULL && *desc->type) {
-               nkl = sizeof known_launchers / sizeof * known_launchers;
-               while (ikl < nkl && strcmp(desc->type, known_launchers[ikl].type))
-                       ikl++;
-               if (ikl == nkl) {
-                       ERROR("type %s not found!", desc->type);
-                       errno = ENOENT;
-                       return -1;
-               }
+       while (ikl < launchers.count && strcmp(type, launchers.descs[ikl].type))
+               ikl++;
+       if (ikl == launchers.count) {
+               ERROR("type %s not found!", type);
+               errno = ENOENT;
+               return -1;
        }
 
        /* prepare paths */
@@ -437,9 +604,9 @@ int afm_launch(struct afm_launch_desc *desc, pid_t children[2])
        params.port = mkport();
        params.secret = secret;
        params.datadir = datadir;
-       params.master_args = known_launchers[ikl].master_args;
-       params.slave_args = known_launchers[ikl].slave_args;
+       params.master = (const char **)launchers.descs[ikl].execs[0];
+       params.slave = (const char **)launchers.descs[ikl].execs[1];
 
-       return params.slave_args ? launchexec2(desc, children, &params) : launchexec1(desc, children, &params);
+       return params.slave ? launchexec2(desc, children, &params) : launchexec1(desc, children, &params);
 }
 
index 8990901..d7fcde2 100644 (file)
@@ -29,4 +29,5 @@ struct afm_launch_desc {
        int height;
 };
 
+int afm_launch_initialize();
 int afm_launch(struct afm_launch_desc *desc, pid_t children[2]);
index 89d303f..b9e1e7c 100644 (file)
@@ -429,6 +429,11 @@ int afm_run_init()
        struct passwd passwd, *pw;
        struct sigaction siga;
 
+       /* init launcher */
+       rc = afm_launch_initialize();
+       if (rc)
+               return rc;
+
        /* computes the 'homeappdir' */
        me = geteuid();
        rc = getpwuid_r(me, &passwd, buf, sizeof buf, &pw);