X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fmain-afb-daemon.c;h=4fb4792c7248ceff83eaa3bda3fe1772e733905c;hb=83c9e99afda0f18e01b9f6dead29d81877568ef4;hp=3f32e879ca7f937f2e2be64467b195737712a3d9;hpb=f96bbb49cc9bcd81693300191cf7a01b879fd83d;p=src%2Fapp-framework-binder.git diff --git a/src/main-afb-daemon.c b/src/main-afb-daemon.c index 3f32e879..4fb4792c 100644 --- a/src/main-afb-daemon.c +++ b/src/main-afb-daemon.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include #include #include @@ -48,20 +50,23 @@ #include "afb-hsrv.h" #include "afb-hreq.h" #include "afb-xreq.h" -#include "jobs.h" #include "afb-session.h" #include "verbose.h" #include "afb-common.h" +#include "afb-export.h" #include "afb-monitor.h" #include "afb-hook.h" #include "afb-hook-flags.h" #include "afb-debug.h" -#include "process-name.h" -#include "wrap-json.h" #if defined(WITH_SUPERVISION) # include "afb-supervision.h" #endif +#include "process-name.h" +#include "wrap-json.h" +#include "jobs.h" +#include "sig-monitor.h" + /* if SELF_PGROUP == 0 the launched command is the group leader if SELF_PGROUP != 0 afb-daemon is the group leader @@ -73,6 +78,59 @@ struct json_object *main_config; static pid_t childpid; +/** + * Tiny helper around putenv: add the variable name=value + * + * @param name name of the variable to set + * @param value value to set to the variable + * + * @return 0 in case of success or -1 in case of error (with errno set to ENOMEM) + */ +static int addenv(const char *name, const char *value) +{ + char *head, *middle; + + head = malloc(2 + strlen(name) + strlen(value)); + if (head == NULL) { + errno = ENOMEM; + return -1; + } + middle = stpcpy(head, name); + middle[0] = '='; + strcpy(&middle[1], value); + return putenv(head); +} + +/** + * Tiny helper around addenv that export the real path + * + * @param name name of the variable to set + * @param path the path value to export to the variable + * + * @return 0 in case of success or -1 in case of error (with errno set to ENOMEM) + */ +static int addenv_realpath(const char *name, const char *path) +{ + char buffer[PATH_MAX]; + char *p = realpath(path, buffer); + return p ? addenv(name, p) : -1; +} + +/** + * Tiny helper around addenv that export an integer + * + * @param name name of the variable to set + * @param value the integer value to export + * + * @return 0 in case of success or -1 in case of error (with errno set to ENOMEM) + */ +static int addenv_int(const char *name, int value) +{ + char buffer[64]; + snprintf(buffer, sizeof buffer, "%d", value); + return addenv(name, buffer); +} + /*---------------------------------------------------------- | helpers for handling list of arguments +--------------------------------------------------------- */ @@ -172,13 +230,14 @@ static void setup_daemon() +--------------------------------------------------------- */ static void daemonize() { - int fd, daemon; + int fd = 0, daemon, nostdin; const char *output; pid_t pid; daemon = 0; output = NULL; wrap_json_unpack(main_config, "{s?b s?s}", "daemon", &daemon, "output", &output); + nostdin = 0; if (output) { fd = open(output, O_WRONLY | O_APPEND | O_CREAT, 0640); @@ -198,6 +257,8 @@ static void daemonize() } if (pid != 0) _exit(0); + + nostdin = 1; } /* closes the input */ @@ -210,8 +271,8 @@ static void daemonize() close(fd); } - /* after that ctrl+C still works */ - close(0); + if (nostdin) + close(0); /* except if 'daemon', ctrl+C still works after that */ } /*--------------------------------------------------------- @@ -480,7 +541,7 @@ static int execute_command() ERROR("port->txt failed"); } else { - /* instanciate arguments and environment */ + /* instantiate arguments and environment */ token = afb_session_initial_token(); args = instanciate_command_args(exec, port, token); if (args && instanciate_environ(port, token) >= 0) { @@ -534,8 +595,7 @@ static void startup_call_unref(struct afb_xreq *xreq) free(sreq->api); free(sreq->verb); json_object_put(sreq->xreq.json); - sreq->index++; - if (sreq->index < sreq->count) + if (++sreq->index < sreq->count) startup_call_current(sreq); else { afb_session_close(sreq->session); @@ -553,6 +613,7 @@ static struct afb_xreq_query_itf startup_xreq_itf = static void startup_call_current(struct startup_req *sreq) { const char *api, *verb, *json; + enum json_tokener_error jerr; sreq->callspec = json_object_get_string(json_object_array_get_idx(sreq->calls, sreq->index)), api = sreq->callspec; @@ -567,8 +628,8 @@ static void startup_call_current(struct startup_req *sreq) sreq->verb = strndup(verb + 1, json - verb - 1); sreq->xreq.request.called_api = sreq->api; sreq->xreq.request.called_verb = sreq->verb; - sreq->xreq.json = json_tokener_parse(json + 1); - if (sreq->api && sreq->verb && sreq->xreq.json) { + sreq->xreq.json = json_tokener_parse_verbose(json + 1, &jerr); + if (sreq->api && sreq->verb && jerr == json_tokener_success) { afb_xreq_process(&sreq->xreq, main_apiset); return; } @@ -604,6 +665,7 @@ static void start(int signum, void *arg) { const char *tracereq, *traceapi, *traceevt, *traceses, *tracesvc, *traceditf, *traceglob; const char *workdir, *rootdir, *token, *rootapi; + struct json_object *settings; struct afb_hsrv *hsrv; int max_session_count, session_timeout, api_timeout; int no_httpd, http_port; @@ -617,13 +679,16 @@ static void start(int signum, void *arg) exit(1); } + settings = NULL; token = rootapi = tracesvc = traceditf = tracereq = traceapi = traceevt = traceses = traceglob = NULL; - no_httpd = http_port = 0; + no_httpd = 0; + http_port = -1; rc = wrap_json_unpack(main_config, "{" "ss ss s?s" "si si si" "s?b s?i s?s" + "s?o" #if !defined(REMOVE_LEGACY_TRACE) "s?s s?s" #endif @@ -642,6 +707,7 @@ static void start(int signum, void *arg) "port", &http_port, "rootapi", &rootapi, + "set", &settings, #if !defined(REMOVE_LEGACY_TRACE) "tracesvc", &tracesvc, "traceditf", &traceditf, @@ -657,6 +723,12 @@ static void start(int signum, void *arg) exit(1); } + /* initialize session handling */ + if (afb_session_init(max_session_count, session_timeout, token)) { + ERROR("initialisation of session manager failed"); + goto error; + } + /* set the directories */ mkdir(workdir, S_IRWXU | S_IRGRP | S_IXGRP); if (chdir(workdir) < 0) { @@ -664,15 +736,34 @@ static void start(int signum, void *arg) goto error; } if (afb_common_rootdir_set(rootdir) < 0) { - ERROR("failed to set common root directory"); + ERROR("failed to set common root directory %s", rootdir); goto error; } - - /* configure the daemon */ - if (afb_session_init(max_session_count, session_timeout, token)) { - ERROR("initialisation of session manager failed"); + if (addenv_realpath("AFB_WORKDIR", "." /* resolved by realpath */) + || addenv_realpath("AFB_ROOTDIR", rootdir /* relative to current directory */)) { + ERROR("can't set DIR environment"); goto error; } + + /* setup HTTP */ + if (!no_httpd) { + if (http_port < 0) { + ERROR("no port is defined"); + goto error; + } + if (http_port == 0) { + ERROR("random port is not implemented"); + goto error; + } + if (addenv_int("AFB_PORT", http_port) + || addenv("AFB_TOKEN", afb_session_initial_token())) { + ERROR("can't set HTTP environment"); + goto error; + } + } + + /* configure the daemon */ + afb_export_set_config(settings); main_apiset = afb_apiset_create("main", api_timeout); if (!main_apiset) { ERROR("can't create main api set"); @@ -708,15 +799,13 @@ static void start(int signum, void *arg) if (traceglob) afb_hook_create_global(afb_hook_flags_global_from_text(traceglob), NULL, NULL); - /* load bindings */ + /* load bindings and apis */ afb_debug("start-load"); apiset_start_list("binding", afb_api_so_add_binding, "the binding"); apiset_start_list("ldpaths", afb_api_so_add_pathset_fails, "the binding path set"); apiset_start_list("weak-ldpaths", afb_api_so_add_pathset_nofails, "the weak binding path set"); apiset_start_list("auto-api", afb_autoset_add_any, "the automatic api path set"); - apiset_start_list("ws-server", afb_api_ws_add_server, "the afb-websocket service"); #if defined(WITH_DBUS_TRANSPARENCY) - apiset_start_list("dbus-server", afb_api_dbus_add_server, "the afb-dbus service"); apiset_start_list("dbus-client", afb_api_dbus_add_client, "the afb-dbus client"); #endif apiset_start_list("ws-client", afb_api_ws_add_client_weak, "the afb-websocket client"); @@ -731,14 +820,15 @@ static void start(int signum, void *arg) if (afb_apiset_start_all_services(main_apiset) < 0) goto error; + /* export started apis */ + apiset_start_list("ws-server", afb_api_ws_add_server, "the afb-websocket service"); +#if defined(WITH_DBUS_TRANSPARENCY) + apiset_start_list("dbus-server", afb_api_dbus_add_server, "the afb-dbus service"); +#endif + /* start the HTTP server */ afb_debug("start-http"); if (!no_httpd) { - if (http_port <= 0) { - ERROR("no port is defined"); - goto error; - } - if (!afb_hreq_init_cookie(http_port, rootapi, session_timeout)) { ERROR("initialisation of HTTP cookies failed"); goto error; @@ -772,15 +862,23 @@ error: int main(int argc, char *argv[]) { - struct json_object *name; + struct json_object *obj; afb_debug("main-entry"); // ------------- Build session handler & init config ------- main_config = afb_config_parse_arguments(argc, argv); - if (json_object_object_get_ex(main_config, "name", &name)) { - verbose_set_name(json_object_get_string(name), 0); - process_name_set_name(json_object_get_string(name)); - process_name_replace_cmdline(argv, json_object_get_string(name)); + if (sig_monitor_init( + !json_object_object_get_ex(main_config, "trap-faults", &obj) + || json_object_get_boolean(obj)) < 0) { + ERROR("failed to initialise signal handlers"); + return 1; + } + + + if (json_object_object_get_ex(main_config, "name", &obj)) { + verbose_set_name(json_object_get_string(obj), 0); + process_name_set_name(json_object_get_string(obj)); + process_name_replace_cmdline(argv, json_object_get_string(obj)); } afb_debug("main-args");