X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fafm-run.c;h=089aa778194aafc5fcd0d0a23c4cb10321495898;hb=59c4af98b761d0f11514e9080a46a32bb440ebc0;hp=c5d15523c3d125922c68adc4feb7332e2aca1c83;hpb=448982b69026464c16ca0545aa91173a935e49f7;p=src%2Fapp-framework-main.git diff --git a/src/afm-run.c b/src/afm-run.c index c5d1552..089aa77 100644 --- a/src/afm-run.c +++ b/src/afm-run.c @@ -1,5 +1,5 @@ /* - Copyright 2015 IoT.bzh + Copyright 2015, 2016, 2017 IoT.bzh author: José Bollo @@ -16,6 +16,8 @@ limitations under the License. */ +#define _GNU_SOURCE + #include #include #include @@ -27,6 +29,13 @@ #include #include +#include +#if SIMULATE_LIBSMACK +#include "simulation/smack.h" +#else +#include +#endif + #include #include "verbose.h" @@ -42,7 +51,7 @@ enum appstate { as_starting, /* start in progress */ as_running, /* started and running */ - as_stopped, /* stopped */ + as_paused, /* paused */ as_terminating, /* termination in progress */ as_terminated /* terminated */ }; @@ -95,6 +104,7 @@ static int runnerid = 0; * home directory of the user. */ static const char fwk_user_app_dir[] = FWK_USER_APP_DIR; +static const char fwk_user_app_label[] = FWK_USER_APP_DIR_LABEL; /* * Path of the root directory for applications of the @@ -169,6 +179,61 @@ static void pgid_remove(struct apprun *runner) /****************** manages runners (by runid) **********************/ +/* + * Is a 'runner' alive? + */ +static inline int is_alive(struct apprun *runner) +{ + switch(runner->state) { + case as_terminating: + case as_terminated: + return 0; + default: + return 1; + } +} + +/* + * Is a 'runner' dead? + */ +static inline int is_dead(struct apprun *runner) +{ + switch(runner->state) { + case as_terminating: + case as_terminated: + return 1; + default: + return 0; + } +} + +/* + * Is a 'runner' running? + */ +static inline int is_running(struct apprun *runner) +{ + switch(runner->state) { + case as_starting: + case as_running: + return 1; + default: + return 0; + } +} + +/* + * Is a 'runner' paused? + */ +static inline int is_paused(struct apprun *runner) +{ + switch(runner->state) { + case as_paused: + return 1; + default: + return 0; + } +} + /* * Get a runner by its 'runid' (NULL if not found) */ @@ -182,6 +247,25 @@ static struct apprun *getrunner(int runid) return result; } +/* + * Get first runner of 'appli' (NULL if not found) + */ +static struct apprun *getrunner_appli(json_object *appli) +{ + int i; + struct apprun *result; + + for (i = 0 ; i < ROOT_RUNNERS_COUNT ; i++) { + result = runners_by_pgid[i]; + while (result != NULL) { + if (result->appli == appli) + return result; + result = result->next_by_pgid; + } + } + return NULL; +} + /* * Free an existing 'runner' */ @@ -269,11 +353,11 @@ static void started(int runid) { } -static void stopped(int runid) +static void paused(int runid) { } -static void continued(int runid) +static void resumed(int runid) { } @@ -292,7 +376,7 @@ static void removed(int runid) * for 'runid' and put the runner's state to 'tostate' * in case of success. * - * Only processes in the state 'as_running' or 'as_stopped' + * Only processes in the state 'as_running' or 'as_paused' * can be signalled. * * Returns 0 in case of success or -1 in case of error. @@ -305,7 +389,7 @@ static int killrunner(int runid, int sig, enum appstate tostate) errno = ENOENT; rc = -1; } - else if (runner->state != as_running && runner->state != as_stopped) { + else if (is_dead(runner)) { errno = EINVAL; rc = -1; } @@ -344,13 +428,13 @@ static void on_sigchld(int signum, siginfo_t *info, void *uctxt) pgid_remove(runner); runner->next_by_pgid = terminated_runners; terminated_runners = runner; - /* ensures that all the group stops */ + /* ensures that all the group terminates */ killpg(runner->pids[0], SIGKILL); break; case CLD_STOPPED: /* update the state */ - runner->state = as_stopped; + runner->state = as_paused; break; case CLD_CONTINUED: @@ -384,6 +468,7 @@ static int fill_launch_desc(struct json_object *appli, || !j_read_string_at(pub, "name", &desc->name) || !j_read_integer_at(pub, "width", &desc->width) || !j_read_integer_at(pub, "height", &desc->height)) { + ERROR("bad internal description of the application to launch: %s", json_object_get_string(appli)); errno = EINVAL; return -1; } @@ -411,7 +496,7 @@ static int fill_launch_desc(struct json_object *appli, static json_object *mkstate(struct apprun *runner) { const char *state; - struct json_object *result, *obj; + struct json_object *result, *obj, *pids; int rc; /* the structure */ @@ -423,14 +508,25 @@ static json_object *mkstate(struct apprun *runner) if (!j_add_integer(result, "runid", runner->runid)) goto error2; + /* the pids */ + if (is_alive(runner)) { + pids = j_add_new_array(result, "pids"); + if (!pids) + goto error2; + if (!j_add_integer(pids, NULL, runner->pids[0])) + goto error2; + if (runner->pids[1] && !j_add_integer(pids, NULL, runner->pids[1])) + goto error2; + } + /* the state */ switch(runner->state) { case as_starting: case as_running: state = "running"; break; - case as_stopped: - state = "stopped"; + case as_paused: + state = "paused"; break; default: state = "terminated"; @@ -469,12 +565,12 @@ error: * runner. This is made using json_object_get. Thus be aware * that further modifications to 'appli' might create errors. * - * Returns 0 in case of success or -1 in case of error + * Returns the runid in case of success or -1 in case of error */ int afm_run_start(struct json_object *appli, enum afm_launch_mode mode, char **uri) { - static struct apprun *runner; + struct apprun *runner; struct afm_launch_desc desc; int rc; sigset_t saved, blocked; @@ -516,6 +612,23 @@ int afm_run_start(struct json_object *appli, enum afm_launch_mode mode, return rc; } +/* + * Returns the runid of a previously started application 'appli' + * or if none is running, starts the application described by 'appli' + * in local mode. + * + * A reference to 'appli' is kept during the live of the + * runner. This is made using json_object_get. Thus be aware + * that further modifications to 'appli' might create errors. + * + * Returns the runid in case of success or -1 in case of error + */ +int afm_run_once(struct json_object *appli) +{ + struct apprun *runner = getrunner_appli(appli); + return runner && is_alive(runner) ? runner->runid : afm_run_start(appli, mode_local, NULL); +} + /* * Terminates the runner of 'runid' * @@ -531,9 +644,9 @@ int afm_run_terminate(int runid) * * Returns 0 in case of success or -1 in case of error */ -int afm_run_stop(int runid) +int afm_run_pause(int runid) { - return killrunner(runid, SIGSTOP, as_stopped); + return killrunner(runid, SIGSTOP, as_paused); } /* @@ -541,7 +654,7 @@ int afm_run_stop(int runid) * * Returns 0 in case of success or -1 in case of error */ -int afm_run_continue(int runid) +int afm_run_resume(int runid) { return killrunner(runid, SIGCONT, as_running); } @@ -566,8 +679,7 @@ struct json_object *afm_run_list() for (i = 0 ; i < ROOT_RUNNERS_COUNT ; i++) { runner = runners_by_runid[i]; while (runner) { - if (runner->state != as_terminating - && runner->state != as_terminated) { + if (is_alive(runner)) { /* adds the living runner */ obj = mkstate(runner); if (obj == NULL) @@ -597,8 +709,7 @@ error: struct json_object *afm_run_state(int runid) { struct apprun *runner = getrunner(runid); - if (runner == NULL || runner->state == as_terminating - || runner->state == as_terminated) { + if (runner == NULL || is_dead(runner)) { errno = ENOENT; return NULL; } @@ -613,7 +724,6 @@ struct json_object *afm_run_state(int runid) int afm_run_init() { char buf[2048]; - char dir[PATH_MAX]; int rc; uid_t me; struct passwd passwd, *pw; @@ -632,25 +742,34 @@ int afm_run_init() ERROR("getpwuid_r failed for uid=%d: %m",(int)me); return -1; } - rc = snprintf(dir, sizeof dir, "%s/%s", passwd.pw_dir, - fwk_user_app_dir); - if (rc >= (int)sizeof dir) { - ERROR("buffer overflow in user_app_dir for uid=%d",(int)me); + rc = asprintf(&homeappdir, "%s/%s", passwd.pw_dir, fwk_user_app_dir); + if (rc < 0) { + errno = ENOMEM; + ERROR("allocating homeappdir for uid=%d failed", (int)me); return -1; } - rc = create_directory(dir, 0755, 1); + rc = create_directory(homeappdir, 0755, 1); if (rc && errno != EEXIST) { - ERROR("creation of directory %s failed in user_app_dir: %m", - dir); + ERROR("creation of directory %s failed: %m", homeappdir); + free(homeappdir); return -1; } - homeappdir = strdup(dir); - if (homeappdir == NULL) { - errno = ENOMEM; - ERROR("out of memory in user_app_dir for %s : %m", dir); + rc = smack_remove_label_for_path(homeappdir, + XATTR_NAME_SMACKTRANSMUTE, 0); + if (rc < 0 && errno != ENODATA) { + ERROR("can't remove smack transmutation of directory %s: %m", + homeappdir); + free(homeappdir); + return -1; + } + rc = smack_set_label_for_path(homeappdir, XATTR_NAME_SMACK, 0, + fwk_user_app_label); + if (rc < 0) { + ERROR("can't set smack label %s to directory %s: %m", + fwk_user_app_label, homeappdir); + free(homeappdir); return -1; } - /* install signal handlers */ siga.sa_flags = SA_SIGINFO | SA_NOCLDWAIT; sigemptyset(&siga.sa_mask);