extern char **environ;
#include "verbose.h"
+#include "afm-launch-mode.h"
#include "afm-launch.h"
#include "secmgr-wrap.h"
+#define DEFAULT_TYPE "text/html"
+
+const char separators[] = " \t\n";
+
+struct execdesc {
+ char *type;
+ char **execs[2];
+};
+
+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;
+ const char **slave;
+};
+
+static gid_t groupid = 0;
+
+struct confread {
+ const char *filepath;
+ FILE *file;
+ int lineno;
+ int index;
+ int length;
+ char buffer[4096];
+};
+
+static void dump_launchers(struct launchers *launchs)
+{
+ int i, j, k;
+ for (i = 0 ; i < launchs->count ; i++) {
+ printf("%s\n", launchs->descs[i].type);
+ for ( j = 0 ; j < 2 ; j++)
+ if (launchs->descs[i].execs[j] != NULL) {
+ for (k = 0 ; launchs->descs[i].execs[j][k] != NULL ; k++)
+ printf(" %s", launchs->descs[i].execs[j][k]);
+ printf("\n");
+ }
+ }
+}
+
+static int next_token(struct confread *cread)
+{
+ cread->index += cread->length + strspn(&cread->buffer[cread->index + cread->length], separators);
+ cread->length = strcspn(&cread->buffer[cread->index], separators);
+ return cread->length;
+}
+
+static int read_line(struct confread *cread)
+{
+ while (fgets(cread->buffer, sizeof cread->buffer, cread->file) != NULL) {
+ cread->lineno++;
+ cread->index = strspn(cread->buffer, separators);
+ if (cread->buffer[cread->index] && cread->buffer[cread->index] != '#') {
+ cread->length = strcspn(&cread->buffer[cread->index], separators);
+ assert(cread->length > 0);
+ return cread->length;
+ }
+ }
+ if (ferror(cread->file)) {
+ ERROR("%s:%d: error while reading, %m", cread->filepath, cread->lineno);
+ return -1;
+ }
+ return 0;
+}
+
+static char *dup_token(struct confread *cread)
+{
+ assert(cread->length);
+ return strndup(&cread->buffer[cread->index], cread->length);
+}
+
+static char **dup_tokens_vector(struct confread *cread)
+{
+ int index0, length0;
+ char **vector, *args;
+ int count, length;
+
+ /* record origin */
+ index0 = cread->index;
+ length0 = cread->length;
+
+ /* count */
+ count = 0;
+ length = 0;
+ while(cread->length) {
+ count++;
+ length += cread->length;
+ next_token(cread);
+ }
+
+ /* allocates */
+ cread->index = index0;
+ cread->length = length0;
+ vector = malloc(length + count + (count + 1) * sizeof(char*));
+ if (vector == NULL)
+ return NULL;
+
+ /* copies */
+ args = (char*)(vector + count + 1);
+ count = 0;
+ while(cread->length) {
+ vector[count++] = args;
+ memcpy(args, &cread->buffer[cread->index], cread->length);
+ args += cread->length;
+ *args++ = 0;
+ next_token(cread);
+ }
+ vector[count] = NULL;
+ cread->index = index0;
+ cread->length = length0;
+ return vector;
+}
+
+static int read_type(struct confread *cread)
+{
+ int count;
+ struct execdesc *descs;
+ char *type;
+
+ /* get the type */
+ type = dup_token(cread);
+ if (type == NULL) {
+ ERROR("%s:%d: out of memory", cread->filepath, cread->lineno);
+ errno = ENOMEM;
+ return -1;
+ }
+
+ /* check the type */
+ if (next_token(cread)) {
+ ERROR("%s:%d: extra characters found after type %s", cread->filepath, cread->lineno, type);
+ free(type);
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* allocates data */
+ count = launchers.count + 1;
+ descs = realloc(launchers.descs, count * sizeof(struct execdesc));
+ if (descs == 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(struct confread *cread, int bottom, int offset)
+{
+ char **vector;
+
+ while (bottom < launchers.count) {
+ vector = dup_tokens_vector(cread);
+ if (vector == NULL) {
+ ERROR("%s:%d: out of memory", cread->filepath, cread->lineno);
+ return -1;
+ }
+ launchers.descs[bottom++].execs[offset] = vector;
+ }
+ return 0;
+}
+
+static int read_launchers(struct confread *cread)
+{
+ int rc, bottom, offset, typed;
+
+ /* reads the file */
+ offset = 0;
+ typed = 0;
+ bottom = launchers.count;
+ rc = read_line(cread);
+ while (rc > 0) {
+ if (cread->index == 0) {
+ if (!typed)
+ bottom = launchers.count;
+ rc = read_type(cread);
+ if (rc)
+ return rc;
+ if (!typed) {
+ typed = 1;
+ offset = 0;
+ }
+ } else if (!typed && !offset) {
+ ERROR("%s:%d: untyped launcher found", cread->filepath, cread->lineno);
+ errno = EINVAL;
+ return -1;
+ } else if (offset >= 2) {
+ ERROR("%s:%d: extra launcher found", cread->filepath, cread->lineno);
+ errno = EINVAL;
+ return -1;
+ } else {
+ rc = read_args(cread, bottom, offset);
+ if (rc)
+ return rc;
+ offset++;
+ typed = 0;
+ }
+ rc = read_line(cread);
+ }
+ return rc;
+}
+
+static int read_configuration_file(const char *filepath)
+{
+ int rc;
+ struct confread cread;
+
+ /* opens the configuration file */
+ cread.file = fopen(filepath, "r");
+ if (cread.file == NULL) {
+ /* error */
+ ERROR("can't read file %s: %m", filepath);
+ rc = -1;
+ } else {
+ /* reads it */
+ cread.filepath = filepath;
+ cread.lineno = 0;
+ rc = read_launchers(&cread);
+ fclose(cread.file);
+ }
+ return rc;
+}
+
/*
%I icondir FWK_ICON_DIR
%P port params->port
%p plugins desc->plugins
%W width desc->width
%H height desc->height
+%% %
*/
-static const char *args_for_afb_daemon[] = {
- "/usr/bin/afb-daemon",
- "--alias=/icons:%I",
- "--port=%P",
- "--rootdir=%D",
- "--token=%S",
- NULL
-};
-
-static const char *args_for_qmlviewer[] = {
- "/usr/bin/qt5/qmlscene",
- "-fullscreen",
- "-I",
- "%r",
- "-I",
- "%r/imports",
- "%r/%c",
- NULL
-};
-
-static const char *args_for_web_runtime[] = {
- "/usr/bin/web-runtime",
- "http://localhost:%P/%c?token=%S",
- NULL
-};
-
-static const char *args_for_binary[] = {
- "%r/%c",
- 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 }
-};
-
-struct launchparam {
- int port;
- const char *secret;
- const char *datadir;
- const char **master_args;
- const char **slave_args;
-};
-
static char **instantiate_arguments(const char **args, struct afm_launch_desc *desc, struct launchparam *params)
{
const char **iter, *p, *v;
/* loop that either compute the size and build the result */
data = NULL;
+ result = NULL;
n = s = 0;
for (;;) {
iter = args;
return port;
}
-
-
static int launchexec1(struct afm_launch_desc *desc, pid_t children[2], struct launchparam *params)
{
int rc;
}
/********* in the master child ************/
+
+ /* avoid set-gid effect */
+ setresgid(groupid, groupid, groupid);
+
/* enter the process group */
rc = setpgid(0, 0);
if (rc) {
_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");
}
close(mpipe[0]);
close(spipe[1]);
+ /* avoid set-gid effect */
+ setresgid(groupid, groupid, groupid);
+
/* enter the process group */
rc = setpgid(0, 0);
if (rc) {
_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");
}
/********* 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");
}
_exit(1);
}
-int afm_launch(struct afm_launch_desc *desc, pid_t children[2])
+int afm_launch_initialize()
+{
+ int rc;
+ gid_t r, e, s;
+
+ getresgid(&r, &e, &s);
+ if (s && s != e)
+ groupid = s;
+ else
+ groupid = -1;
+
+ rc = read_configuration_file(FWK_LAUNCH_CONF);
+ dump_launchers(&launchers);
+ return rc;
+}
+
+int afm_launch(struct afm_launch_desc *desc, pid_t children[2], char **uri)
{
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);
+ assert(launch_mode_is_valid(desc->mode));
+
+ /* 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 */
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, ¶ms) : launchexec1(desc, children, ¶ms);
+ return params.slave ? launchexec2(desc, children, ¶ms) : launchexec1(desc, children, ¶ms);
}