#include <signal.h>
#include <string.h>
#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/wait.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"
#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
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;
+}
+
/*----------------------------------------------------------
| helpers for handling list of arguments
+--------------------------------------------------------- */
+--------------------------------------------------------- */
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);
}
if (pid != 0)
_exit(0);
+
+ nostdin = 1;
}
/* closes the input */
close(fd);
}
- /* after that ctrl+C still works */
- close(0);
+ if (nostdin)
+ close(0); /* except if 'daemon', ctrl+C still works after that */
}
/*---------------------------------------------------------
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;
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;
}
{
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;
exit(1);
}
+ settings = NULL;
token = rootapi = tracesvc = traceditf = tracereq =
traceapi = traceevt = traceses = traceglob = NULL;
no_httpd = http_port = 0;
"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
"port", &http_port,
"rootapi", &rootapi,
+ "set", &settings,
#if !defined(REMOVE_LEGACY_TRACE)
"tracesvc", &tracesvc,
"traceditf", &traceditf,
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;
+ }
+ if (addenv_realpath("AFB_WORKDIR", "." /* resolved by realpath */)
+ || addenv_realpath("AFB_ROOTDIR", rootdir /* relative to current directory */)) {
+ ERROR("can't set environment");
goto error;
}
/* configure the daemon */
+ afb_export_set_config(settings);
if (afb_session_init(max_session_count, session_timeout, token)) {
ERROR("initialisation of session manager failed");
goto error;
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");
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) {
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");