X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fmain-afb-daemon.c;h=3421be819c5fbd3f789c3a7d0a5e0e82be3e3ef8;hb=6f13ad1989875b5a0ce50b24211fd1fba093735f;hp=8b1a2b237eab25c57df2be7f006fed2d983ae007;hpb=4521c1e7ae5371ab9d639adc617d17fb4e8ded0c;p=src%2Fapp-framework-binder.git diff --git a/src/main-afb-daemon.c b/src/main-afb-daemon.c index 8b1a2b23..3421be81 100644 --- a/src/main-afb-daemon.c +++ b/src/main-afb-daemon.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2018 "IoT.bzh" + * Copyright (C) 2015-2019 "IoT.bzh" * Author "Fulup Ar Foll" * Author José Bollo * @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include #include #include @@ -36,72 +38,144 @@ #include -#include "afb-config.h" +#include "afb-args.h" #include "afb-hswitch.h" #include "afb-apiset.h" #include "afb-autoset.h" #include "afb-api-so.h" -#if defined(WITH_DBUS_TRANSPARENCY) +#if WITH_DBUS_TRANSPARENCY # include "afb-api-dbus.h" #endif #include "afb-api-ws.h" #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" +#if WITH_AFB_HOOK #include "afb-hook.h" +#include "afb-hook-flags.h" +#endif #include "afb-debug.h" +#if WITH_SUPERVISION +# include "afb-supervision.h" +#endif + #include "process-name.h" -#include "afb-supervision.h" +#include "wrap-json.h" +#include "jobs.h" +#include "sig-monitor.h" +#include "watchdog.h" + +#if !defined(DEFAULT_BINDER_INTERFACE) +# define DEFAULT_BINDER_INTERFACE NULL +#endif /* if SELF_PGROUP == 0 the launched command is the group leader if SELF_PGROUP != 0 afb-daemon is the group leader */ -#define SELF_PGROUP 1 +#define SELF_PGROUP 0 struct afb_apiset *main_apiset; -struct afb_config *main_config; +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 +--------------------------------------------------------- */ -/* - * Calls the callback 'run' for each value of the 'list' - * until the callback returns 0 or the end of the list is reached. - * Returns either NULL if the end of the list is reached or a pointer - * to the item whose value made 'run' return 0. - * 'closure' is used for passing user data. - */ -static struct afb_config_list *run_for_list(struct afb_config_list *list, - int (*run) (void *closure, char *value), +static const char *run_for_config_array_opt(const char *name, + int (*run) (void *closure, const char *value), void *closure) { - while (list && run(closure, list->value)) - list = list->next; - return list; + int i, n, rc; + struct json_object *array, *value; + + if (json_object_object_get_ex(main_config, name, &array)) { + if (!json_object_is_type(array, json_type_array)) + return json_object_get_string(array); + n = (int)json_object_array_length(array); + for (i = 0 ; i < n ; i++) { + value = json_object_array_get_idx(array, i); + rc = run(closure, json_object_get_string(value)); + if (!rc) + return json_object_get_string(value); + } + } + return NULL; } -static int run_start(void *closure, char *value) +static int run_start(void *closure, const char *value) { int (*starter) (const char *value, struct afb_apiset *declare_set, struct afb_apiset *call_set) = closure; return starter(value, main_apiset, main_apiset) >= 0; } -static void apiset_start_list(struct afb_config_list *list, +static void apiset_start_list(const char *name, int (*starter) (const char *value, struct afb_apiset *declare_set, struct afb_apiset *call_set), const char *message) { - list = run_for_list(list, run_start, starter); - if (list) { - ERROR("can't start %s %s", message, list->value); + const char *item = run_for_config_array_opt(name, run_start, starter); + if (item) { + ERROR("can't start %s %s", message, item); exit(1); } } @@ -163,50 +237,56 @@ static void setup_daemon() +--------------------------------------------------------- */ static void daemonize() { - int consoleFD; - int pid; + 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); + if (fd < 0) { + ERROR("Can't open output %s", output); + exit(1); + } + } - // open /dev/console to redirect output messAFBes - consoleFD = open(main_config->console, O_WRONLY | O_APPEND | O_CREAT, 0640); - if (consoleFD < 0) { - ERROR("AFB-daemon cannot open /dev/console (use --foreground)"); - exit(1); + if (daemon) { + INFO("entering background mode"); + + pid = fork(); + if (pid == -1) { + ERROR("Failed to fork daemon process"); + exit(1); + } + if (pid != 0) + _exit(0); + + nostdin = 1; } - // fork process when running background mode - pid = fork(); - // if fail nothing much to do - if (pid == -1) { - ERROR("AFB-daemon Failed to fork son process"); - exit(1); + /* closes the input */ + if (output) { + NOTICE("Redirecting output to %s", output); + close(2); + dup(fd); + close(1); + dup(fd); + close(fd); } - // if in father process, just leave - if (pid != 0) - _exit(0); - - // son process get all data in standalone mode - NOTICE("background mode [pid:%d console:%s]", getpid(), - main_config->console); - - // redirect default I/O on console - close(2); - dup(consoleFD); // redirect stderr - close(1); - dup(consoleFD); // redirect stdout - close(0); // no need for stdin - close(consoleFD); - -#if 0 - setsid(); // allow father process to fully exit - sleep(2); // allow main to leave and release port -#endif + + if (nostdin) + close(0); /* except if 'daemon', ctrl+C still works after that */ } /*--------------------------------------------------------- | http server | Handles the HTTP server +--------------------------------------------------------- */ -static int init_alias(void *closure, char *spec) +static int init_alias(void *closure, const char *spec) { struct afb_hsrv *hsrv = closure; char *path = strchr(spec, ':'); @@ -223,27 +303,38 @@ static int init_alias(void *closure, char *spec) static int init_http_server(struct afb_hsrv *hsrv) { - if (!afb_hsrv_add_handler - (hsrv, main_config->rootapi, afb_hswitch_websocket_switch, main_apiset, 20)) + int rc; + const char *rootapi, *roothttp, *rootbase; + + roothttp = NULL; + rc = wrap_json_unpack(main_config, "{ss ss s?s}", + "rootapi", &rootapi, + "rootbase", &rootbase, + "roothttp", &roothttp); + if (rc < 0) { + ERROR("Can't get HTTP server config"); + exit(1); + } + + if (!afb_hsrv_add_handler(hsrv, rootapi, + afb_hswitch_websocket_switch, main_apiset, 20)) return 0; - if (!afb_hsrv_add_handler - (hsrv, main_config->rootapi, afb_hswitch_apis, main_apiset, 10)) + if (!afb_hsrv_add_handler(hsrv, rootapi, + afb_hswitch_apis, main_apiset, 10)) return 0; - if (run_for_list(main_config->aliases, init_alias, hsrv)) + if (run_for_config_array_opt("alias", init_alias, hsrv)) return 0; - if (main_config->roothttp != NULL) { - if (!afb_hsrv_add_alias - (hsrv, "", afb_common_rootdir_get_fd(), main_config->roothttp, - -10, 1)) + if (roothttp != NULL) { + if (!afb_hsrv_add_alias(hsrv, "", + afb_common_rootdir_get_fd(), roothttp, -10, 1)) return 0; } - if (!afb_hsrv_add_handler - (hsrv, main_config->rootbase, afb_hswitch_one_page_api_redirect, NULL, - -20)) + if (!afb_hsrv_add_handler(hsrv, rootbase, + afb_hswitch_one_page_api_redirect, NULL, -20)) return 0; return 1; @@ -252,11 +343,27 @@ static int init_http_server(struct afb_hsrv *hsrv) static struct afb_hsrv *start_http_server() { int rc; + const char *uploaddir, *rootdir; struct afb_hsrv *hsrv; + int cache_timeout, http_port; + + rc = wrap_json_unpack(main_config, "{ss ss si si}", + "uploaddir", &uploaddir, + "rootdir", &rootdir, + "cache-eol", &cache_timeout, + "port", &http_port); + if (rc < 0) { + ERROR("Can't get HTTP server start config"); + exit(1); + } - if (afb_hreq_init_download_path(main_config->uploaddir)) { - ERROR("unable to set the upload directory %s", main_config->uploaddir); - return NULL; + if (afb_hreq_init_download_path(uploaddir)) { + static const char fallback_uploaddir[] = "/tmp"; + WARNING("unable to set the upload directory %s", uploaddir); + if (afb_hreq_init_download_path(fallback_uploaddir)) { + ERROR("unable to fallback to upload directory %s", fallback_uploaddir); + return NULL; + } } hsrv = afb_hsrv_create(); @@ -265,23 +372,30 @@ static struct afb_hsrv *start_http_server() return NULL; } - if (!afb_hsrv_set_cache_timeout(hsrv, main_config->cache_timeout) + if (!afb_hsrv_set_cache_timeout(hsrv, cache_timeout) || !init_http_server(hsrv)) { ERROR("initialisation of httpd failed"); afb_hsrv_put(hsrv); return NULL; } - NOTICE("Waiting port=%d rootdir=%s", main_config->http_port, main_config->rootdir); - NOTICE("Browser URL= http://localhost:%d", main_config->http_port); + NOTICE("Waiting port=%d rootdir=%s", http_port, rootdir); + NOTICE("Browser URL= http://localhost:%d", http_port); - rc = afb_hsrv_start(hsrv, (uint16_t) main_config->http_port, 15); + rc = afb_hsrv_start(hsrv, 15); if (!rc) { ERROR("starting of httpd failed"); afb_hsrv_put(hsrv); return NULL; } + rc = afb_hsrv_add_interface_tcp(hsrv, DEFAULT_BINDER_INTERFACE, (uint16_t) http_port); + if (!rc) { + ERROR("setting interface failed"); + afb_hsrv_put(hsrv); + return NULL; + } + return hsrv; } @@ -289,6 +403,27 @@ static struct afb_hsrv *start_http_server() | execute_command +--------------------------------------------------------- */ +static void exit_at_end() +{ + exit(0); +} + +static void wait_child(int signum, void* arg) +{ + pid_t pid = (pid_t)(intptr_t)arg; + pid_t pidchld = childpid; + + if (pidchld == pid) { + childpid = 0; + if (!SELF_PGROUP) + killpg(pidchld, SIGKILL); + waitpid(pidchld, NULL, 0); + jobs_exit(exit_at_end); + } else { + waitpid(pid, NULL, 0); + } +} + static void on_sigchld(int signum, siginfo_t *info, void *uctx) { if (info->si_pid == childpid) { @@ -296,11 +431,9 @@ static void on_sigchld(int signum, siginfo_t *info, void *uctx) case CLD_EXITED: case CLD_KILLED: case CLD_DUMPED: - childpid = 0; - if (!SELF_PGROUP) - killpg(info->si_pid, SIGKILL); - waitpid(info->si_pid, NULL, 0); - exit(0); + jobs_queue_lazy(0, 0, wait_child, (void*)(intptr_t)info->si_pid); + default: + break; } } } @@ -314,7 +447,7 @@ static void on_sigchld(int signum, siginfo_t *info, void *uctx) #define SUBST_CHAR '@' #define SUBST_STR "@" -static char *instanciate_string(char *arg, const char *port, const char *token) +static char *instanciate_string(const char *arg, const char *port, const char *token) { char *resu, *it, *wr; int chg, dif; @@ -335,7 +468,7 @@ static char *instanciate_string(char *arg, const char *port, const char *token) /* return arg when no change */ if (!chg) - return arg; + return strdup(arg); /* allocates the result */ resu = malloc((it - arg) + dif + 1); @@ -370,7 +503,7 @@ static int instanciate_environ(const char *port, const char *token) char *repl; int i; - /* instanciate the environment */ + /* instantiate the environment */ for (i = 0 ; environ[i] ; i++) { repl = instanciate_string(environ[i], port, token); if (!repl) @@ -380,30 +513,46 @@ static int instanciate_environ(const char *port, const char *token) return 0; } -static int instanciate_command_args(const char *port, const char *token) +static char **instanciate_command_args(struct json_object *exec, const char *port, const char *token) { + char **result; char *repl; - int i; + int i, n; + + /* allocates the result */ + n = (int)json_object_array_length(exec); + result = malloc((n + 1) * sizeof * result); + if (!result) { + ERROR("out of memory"); + return NULL; + } /* instanciate the arguments */ - for (i = 0 ; main_config->exec[i] ; i++) { - repl = instanciate_string(main_config->exec[i], port, token); - if (!repl) - return -1; - main_config->exec[i] = repl; + for (i = 0 ; i < n ; i++) { + repl = instanciate_string(json_object_get_string(json_object_array_get_idx(exec, i)), port, token); + if (!repl) { + while(i) + free(result[--i]); + free(result); + return NULL; + } + result[i] = repl; } - return 0; + result[i] = NULL; + return result; } static int execute_command() { + struct json_object *exec, *oport; struct sigaction siga; char port[20]; const char *token; + char **args; int rc; /* check whether a command is to execute or not */ - if (!main_config->exec || !main_config->exec[0]) + if (!json_object_object_get_ex(main_config, "exec", &exec)) return 0; if (SELF_PGROUP) @@ -421,23 +570,23 @@ static int execute_command() return 0; /* compute the string for port */ - if (main_config->http_port) - rc = snprintf(port, sizeof port, "%d", main_config->http_port); + if (json_object_object_get_ex(main_config, "port", &oport)) + rc = snprintf(port, sizeof port, "%s", json_object_get_string(oport)); else rc = snprintf(port, sizeof port, "%cp", SUBST_CHAR); if (rc < 0 || rc >= (int)(sizeof port)) { ERROR("port->txt failed"); } else { - /* instanciate arguments and environment */ + /* instantiate arguments and environment */ token = afb_session_initial_token(); - if (instanciate_command_args(port, token) >= 0 - && instanciate_environ(port, token) >= 0) { + args = instanciate_command_args(exec, port, token); + if (args && instanciate_environ(port, token) >= 0) { /* run */ if (!SELF_PGROUP) setpgid(0, 0); - execv(main_config->exec[0], main_config->exec); - ERROR("can't launch %s: %m", main_config->exec[0]); + execv(args[0], args); + ERROR("can't launch %s: %m", args[0]); } } exit(1); @@ -453,7 +602,10 @@ struct startup_req struct afb_xreq xreq; char *api; char *verb; - struct afb_config_list *current; + struct json_object *calls; + int index; + int count; + const char *callspec; struct afb_session *session; }; @@ -463,10 +615,10 @@ static void startup_call_reply(struct afb_xreq *xreq, struct json_object *object info = info ?: ""; if (!error) { - NOTICE("startup call %s returned %s (%s)", sreq->current->value, json_object_get_string(object), info); + NOTICE("startup call %s returned %s (%s)", sreq->callspec, json_object_get_string(object), info); json_object_put(object); } else { - ERROR("startup call %s ERROR! %s (%s)", sreq->current->value, error, info); + ERROR("startup call %s ERROR! %s (%s)", sreq->callspec, error, info); exit(1); } } @@ -480,8 +632,7 @@ static void startup_call_unref(struct afb_xreq *xreq) free(sreq->api); free(sreq->verb); json_object_put(sreq->xreq.json); - sreq->current = sreq->current->next; - if (sreq->current) + if (++sreq->index < sreq->count) startup_call_current(sreq); else { afb_session_close(sreq->session); @@ -498,9 +649,11 @@ static struct afb_xreq_query_itf startup_xreq_itf = static void startup_call_current(struct startup_req *sreq) { - char *api, *verb, *json; + const char *api, *verb, *json; + enum json_tokener_error jerr; - api = sreq->current->value; + sreq->callspec = json_object_get_string(json_object_array_get_idx(sreq->calls, sreq->index)), + api = sreq->callspec; verb = strchr(api, '/'); if (verb) { json = strchr(verb, ':'); @@ -512,27 +665,31 @@ 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; } } } - ERROR("Bad call specification %s", sreq->current->value); + ERROR("Bad call specification %s", sreq->callspec); exit(1); } static void run_startup_calls() { - struct afb_config_list *list; + struct json_object *calls; struct startup_req *sreq; + int count; - list = main_config->calls; - if (list) { + if (json_object_object_get_ex(main_config, "call", &calls) + && json_object_is_type(calls, json_type_array) + && (count = (int)json_object_array_length(calls))) { sreq = calloc(1, sizeof *sreq); sreq->session = afb_session_create(3600); - sreq->current = list; + sreq->calls = calls; + sreq->index = 0; + sreq->count = count; startup_call_current(sreq); } } @@ -543,7 +700,20 @@ static void run_startup_calls() static void start(int signum, void *arg) { +#if WITH_AFB_HOOK + const char *tracereq = NULL, *traceapi = NULL, *traceevt = NULL, +#if !defined(REMOVE_LEGACY_TRACE) + *tracesvc = NULL, *traceditf = NULL, +#endif + *traceses = NULL, *traceglob = NULL; +#endif + 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; + int rc; + afb_debug("start-entry"); @@ -552,23 +722,95 @@ static void start(int signum, void *arg) exit(1); } + settings = NULL; + no_httpd = 0; + http_port = -1; + rootapi = token = NULL; + rc = wrap_json_unpack(main_config, "{" + "ss ss s?s" + "si si si" + "s?b s?i s?s" +#if WITH_AFB_HOOK +#if !defined(REMOVE_LEGACY_TRACE) + "s?s s?s" +#endif + "s?s s?s s?s s?s s?s" +#endif + "s?o" + "}", + + "rootdir", &rootdir, + "workdir", &workdir, + "token", &token, + + "apitimeout", &api_timeout, + "cntxtimeout", &session_timeout, + "session-max", &max_session_count, + + "no-httpd", &no_httpd, + "port", &http_port, + "rootapi", &rootapi, + +#if WITH_AFB_HOOK +#if !defined(REMOVE_LEGACY_TRACE) + "tracesvc", &tracesvc, + "traceditf", &traceditf, +#endif + "tracereq", &tracereq, + "traceapi", &traceapi, + "traceevt", &traceevt, + "traceses", &traceses, + "traceglob", &traceglob, +#endif + "set", &settings + ); + if (rc < 0) { + ERROR("Unable to get start config"); + 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(main_config->workdir, S_IRWXU | S_IRGRP | S_IXGRP); - if (chdir(main_config->workdir) < 0) { - ERROR("Can't enter working dir %s", main_config->workdir); + mkdir(workdir, S_IRWXU | S_IRGRP | S_IXGRP); + if (chdir(workdir) < 0) { + ERROR("Can't enter working dir %s", workdir); goto error; } - if (afb_common_rootdir_set(main_config->rootdir) < 0) { - ERROR("failed to set common root directory"); + if (afb_common_rootdir_set(rootdir) < 0) { + ERROR("failed to set common root directory %s", rootdir); goto error; } - - /* configure the daemon */ - if (afb_session_init(main_config->max_session_count, main_config->session_timeout, main_config->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; } - main_apiset = afb_apiset_create("main", main_config->api_timeout); + + /* 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"); goto error; @@ -577,37 +819,46 @@ static void start(int signum, void *arg) ERROR("failed to setup monitor"); goto error; } - if (afb_supervision_init() < 0) { +#if WITH_SUPERVISION + if (afb_supervision_init(main_apiset, main_config) < 0) { ERROR("failed to setup supervision"); goto error; } +#endif +#if WITH_AFB_HOOK /* install hooks */ - if (main_config->tracereq) - afb_hook_create_xreq(NULL, NULL, NULL, main_config->tracereq, NULL, NULL); - if (main_config->traceapi) - afb_hook_create_api(NULL, main_config->traceapi, NULL, NULL); - if (main_config->traceevt) - afb_hook_create_evt(NULL, main_config->traceevt, NULL, NULL); - if (main_config->traceses) - afb_hook_create_session(NULL, main_config->traceses, NULL, NULL); - - /* load bindings */ + if (tracereq) + afb_hook_create_xreq(NULL, NULL, NULL, afb_hook_flags_xreq_from_text(tracereq), NULL, NULL); +#if !defined(REMOVE_LEGACY_TRACE) + if (traceapi || tracesvc || traceditf) + afb_hook_create_api(NULL, afb_hook_flags_api_from_text(traceapi) + | afb_hook_flags_legacy_ditf_from_text(traceditf) + | afb_hook_flags_legacy_svc_from_text(tracesvc), NULL, NULL); +#else + if (traceapi) + afb_hook_create_api(NULL, afb_hook_flags_api_from_text(traceapi), NULL, NULL); +#endif + if (traceevt) + afb_hook_create_evt(NULL, afb_hook_flags_evt_from_text(traceevt), NULL, NULL); + if (traceses) + afb_hook_create_session(NULL, afb_hook_flags_session_from_text(traceses), NULL, NULL); + if (traceglob) + afb_hook_create_global(afb_hook_flags_global_from_text(traceglob), NULL, NULL); +#endif + + /* load bindings and apis */ afb_debug("start-load"); - apiset_start_list(main_config->so_bindings, afb_api_so_add_binding, "the binding"); -#if defined(WITH_DBUS_TRANSPARENCY) - apiset_start_list(main_config->dbus_clients, afb_api_dbus_add_client, "the afb-dbus client"); +#if WITH_DYNAMIC_BINDING + 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"); #endif - apiset_start_list(main_config->ws_clients, afb_api_ws_add_client_weak, "the afb-websocket client"); - apiset_start_list(main_config->ldpaths, afb_api_so_add_pathset_fails, "the binding path set"); - apiset_start_list(main_config->weak_ldpaths, afb_api_so_add_pathset_nofails, "the weak binding path set"); - apiset_start_list(main_config->auto_ws, afb_autoset_add_ws, "the automatic afb-websocket path set"); - apiset_start_list(main_config->auto_link, afb_autoset_add_so, "the automatic link binding path set"); - -#if defined(WITH_DBUS_TRANSPARENCY) - apiset_start_list(main_config->dbus_servers, afb_api_dbus_add_server, "the afb-dbus service"); + apiset_start_list("auto-api", afb_autoset_add_any, "the automatic api path set"); +#if WITH_DBUS_TRANSPARENCY + apiset_start_list("dbus-client", afb_api_dbus_add_client, "the afb-dbus client"); #endif - apiset_start_list(main_config->ws_servers, afb_api_ws_add_server, "the afb-websocket service"); + apiset_start_list("ws-client", afb_api_ws_add_client_weak, "the afb-websocket client"); DEBUG("Init config done"); @@ -616,18 +867,19 @@ static void start(int signum, void *arg) #if !defined(NO_CALL_PERSONALITY) personality((unsigned long)-1L); #endif - if (afb_apiset_start_all_services(main_apiset, 1) < 0) + 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 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 (!main_config->no_httpd) { - if (main_config->http_port <= 0) { - ERROR("no port is defined"); - goto error; - } - - if (!afb_hreq_init_cookie(main_config->http_port, main_config->rootapi, main_config->session_timeout)) { + if (!no_httpd) { + if (!afb_hreq_init_cookie(http_port, rootapi, session_timeout)) { ERROR("initialisation of HTTP cookies failed"); goto error; } @@ -648,6 +900,13 @@ static void start(int signum, void *arg) /* ready */ sd_notify(1, "READY=1"); + + /* activate the watchdog */ +#if HAS_WATCHDOG + if (watchdog_activate() < 0) + ERROR("can't start the watchdog"); +#endif + return; error: exit(1); @@ -660,29 +919,28 @@ error: int main(int argc, char *argv[]) { + struct json_object *obj; afb_debug("main-entry"); - // let's run this program with a low priority - nice(20); - // ------------- Build session handler & init config ------- - main_config = afb_config_parse_arguments(argc, argv); - if (main_config->name) { - verbose_set_name(main_config->name, 0); - process_name_set_name(main_config->name); - process_name_replace_cmdline(argv, main_config->name); + main_config = afb_args_parse(argc, argv); + 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"); // --------- run ----------- - if (main_config->background) { - // --------- in background mode ----------- - INFO("entering background mode"); - daemonize(); - } else { - // ---- in foreground mode -------------------- - INFO("entering foreground mode"); - } + daemonize(); INFO("running with pid %d", getpid()); /* set the daemon environment */ @@ -691,7 +949,7 @@ int main(int argc, char *argv[]) afb_debug("main-start"); /* enter job processing */ - jobs_start(3, 0, 50, start, NULL); + jobs_start(3, 0, 100, start, NULL); WARNING("hoops returned from jobs_enter! [report bug]"); return 1; }