-int main(int argc, char *argv[]) {
- AFB_session *session;
- char* programName = argv [0];
- int optionIndex = 0;
- int optc, ind, consoleFD;
- int pid, nbcmd, status;
- AFB_config cliconfig; // temp structure to store CLI option before file config upload
-
- // ------------- Build session handler & init config -------
- session = configInit ();
- memset(&cliconfig,0,sizeof(cliconfig));
- memset(&aliasdir ,0,sizeof(aliasdir));
- cliconfig.aliasdir = aliasdir;
-
- // GNU CLI getopts nterface.
- struct option ggcOption;
- struct option *gnuOptions;
-
- // ------------------ Process Command Line -----------------------
-
- // if no argument print help and return
- if (argc < 2) {
- printHelp(programName);
- return (-1);
- }
-
- // build GNU getopt info from cliOptions
- nbcmd = sizeof (cliOptions) / sizeof (AFB_options);
- gnuOptions = malloc (sizeof (ggcOption) * nbcmd);
- for (ind=0; ind < nbcmd;ind++) {
- gnuOptions [ind].name = cliOptions[ind].name;
- gnuOptions [ind].has_arg = cliOptions[ind].has_arg;
- gnuOptions [ind].flag = 0;
- gnuOptions [ind].val = cliOptions[ind].val;
- }
-
- // get all options from command line
- while ((optc = getopt_long (argc, argv, "vsp?", gnuOptions, &optionIndex))
- != EOF)
- {
- switch (optc)
- {
- case SET_VERBOSE:
- verbose = 1;
- break;
-
- case SET_TCP_PORT:
- if (optarg == 0) goto needValueForOption;
- if (!sscanf (optarg, "%d", &cliconfig.httpdPort)) goto notAnInteger;
- break;
-
- case SET_APITIMEOUT:
- if (optarg == 0) goto needValueForOption;
- if (!sscanf (optarg, "%d", &cliconfig.apiTimeout)) goto notAnInteger;
- break;
-
- case SET_CNTXTIMEOUT:
- if (optarg == 0) goto needValueForOption;
- if (!sscanf (optarg, "%d", &cliconfig.cntxTimeout)) goto notAnInteger;
- break;
-
- case SET_ROOT_DIR:
- if (optarg == 0) goto needValueForOption;
- cliconfig.rootdir = optarg;
- if (verbose) fprintf(stderr, "Forcing Rootdir=%s\n",cliconfig.rootdir);
- break;
-
- case SET_ROOT_BASE:
- if (optarg == 0) goto needValueForOption;
- cliconfig.rootbase = optarg;
- if (verbose) fprintf(stderr, "Forcing Rootbase=%s\n",cliconfig.rootbase);
- break;
-
- case SET_ROOT_API:
- if (optarg == 0) goto needValueForOption;
- cliconfig.rootapi = optarg;
- if (verbose) fprintf(stderr, "Forcing Rootapi=%s\n",cliconfig.rootapi);
- break;
-
- case SET_ROOT_ALIAS:
- if (optarg == 0) goto needValueForOption;
- if (aliascount < MAX_ALIAS) {
- aliasdir[aliascount].url = strsep(&optarg,":");
- aliasdir[aliascount].path = strsep(&optarg,":");
- aliasdir[aliascount].len = strlen(aliasdir[aliascount].url);
- if (verbose) fprintf(stderr, "Alias url=%s path=%s\n", aliasdir[aliascount].url, aliasdir[aliascount].path);
- aliascount++;
- } else {
- fprintf(stderr, "Too many aliases [max:%s] %s ignored\n", optarg, MAX_ALIAS-1);
- }
- break;
-
- case SET_SMACK:
- if (optarg == 0) goto needValueForOption;
- fprintf (stderr, "Not Implemented yet\n");
- cliconfig.smack = optarg;
- break;
-
- case SET_AUTH_TOKEN:
- if (optarg == 0) goto needValueForOption;
- cliconfig.token = optarg;
- break;
-
- case SET_PLUGINS:
- if (optarg == 0) goto needValueForOption;
- cliconfig.plugins = optarg;
- break;
-
- case SET_PID_FILE:
- if (optarg == 0) goto needValueForOption;
- cliconfig.pidfile = optarg;
- break;
-
- case SET_SESSION_DIR:
- if (optarg == 0) goto needValueForOption;
- cliconfig.sessiondir = optarg;
- break;
-
- case SET_CONFIG_FILE:
- if (optarg == 0) goto needValueForOption;
- cliconfig.configfile = optarg;
- break;
-
- case SET_CACHE_TO:
- if (optarg == 0) goto needValueForOption;
- if (!sscanf (optarg, "%d", &cliconfig.cacheTimeout)) goto notAnInteger;
- break;
-
- case SET_CONFIG_EXIT:
- if (optarg != 0) goto noValueForOption;
- session->configsave = 1;
- session->forceexit = 1;
- break;
-
- case SET_CONFIG_SAVE:
- if (optarg != 0) goto noValueForOption;
- session->configsave = 1;
- break;
-
- case SET_USERID:
- if (optarg == 0) goto needValueForOption;
- if (!sscanf (optarg, "%s", &cliconfig.setuid)) goto notAnInteger;
- break;
-
- case SET_FAKE_MOD:
- if (optarg != 0) goto noValueForOption;
- session->fakemod = 1;
- break;
-
- case SET_FORGROUND:
- if (optarg != 0) goto noValueForOption;
- session->foreground = 1;
- break;
-
- case SET_BACKGROUND:
- if (optarg != 0) goto noValueForOption;
- session->background = 1;
- break;
-
- case KILL_PREV_REST:
- if (optarg != 0) goto noValueForOption;
- session->killPrevious = 1;
- break;
-
- case KILL_PREV_EXIT:
- if (optarg != 0) goto noValueForOption;
- session->killPrevious = 2;
- break;
-
- case DISPLAY_VERSION:
- if (optarg != 0) goto noValueForOption;
- printVersion();
- goto normalExit;
-
- case DISPLAY_HELP:
- default:
- printHelp(programName);
- goto normalExit;
-
- }
- }
-
- // if exist merge config file with CLI arguments
- configLoadFile (session, &cliconfig);
- initPlugins(session);
-
- // ------------------ sanity check ----------------------------------------
- if ((session->background) && (session->foreground)) {
- fprintf (stderr, "%s ERR: cannot select foreground & background at the same time\n",configTime());
- exit (-1);
- }
-
- // ------------------ Some useful default values -------------------------
- if ((session->background == 0) && (session->foreground == 0)) session->foreground=1;
-
- // open syslog if ever needed
- openlog("AGB-log", 0, LOG_DAEMON);
-
- // -------------- Try to kill any previsou process if asked ---------------------
- if (session->killPrevious) {
- pid = readPidFile (session->config); // enforce commandline option
- switch (pid) {
- case -1:
- fprintf (stderr, "%s ERR:main --kill ignored no PID file [%s]\n",configTime(), session->config->pidfile);
- break;
- case 0:
- fprintf (stderr, "%s ERR:main --kill ignored no active AFB process\n",configTime());
- break;
- default:
- status = kill (pid,SIGINT );
- if (status == 0) {
- if (verbose) printf ("%s INF:main signal INTR sent to pid:%d \n", configTime(), pid);
- } else {
- // try kill -9
- status = kill (pid,9);
- if (status != 0) fprintf (stderr, "%s ERR:main failled to killed pid=%d \n",configTime(), pid);
- }
- } // end switch pid
-
- if (session->killPrevious >= 2) goto normalExit;
- } // end killPrevious
-
-
- // ------------------ clean exit on CTR-C signal ------------------------
- if (signal (SIGINT, signalQuit) == SIG_ERR) {
- fprintf (stderr, "%s Quit Signal received.",configTime());
- return (-1);
- }
-
- // save exitPoint context when returning from longjmp closeSession and exit
- status = setjmp (exitPoint); // return !+ when coming from longjmp
- if (status != 0) {
- if (verbose) printf ("INF:main returning from longjump after signal [%d]\n", status);
- closeSession (session);
- goto exitOnSignal;
- }
-
- // let's run this program with a low priority
- status=nice (20);
-
- // ------------------ Finaly Process Commands -----------------------------
- // if --save then store config on disk upfront
- if (session->configsave) configStoreFile (session);
- if (session->forceexit) exit (0);
-
- if (session->config->setuid) {
- int err;
- struct passwd *passwd;
- passwd=getpwnam(session->config->setuid);
-
- if (passwd == NULL) goto errorSetuid;
-
- err = setuid(passwd->pw_uid);
- if (err) goto errorSetuid;
- }
-
- // let's not take the risk to run as ROOT
- //if (getuid() == 0) goto errorNoRoot;
-
- // check session dir and create if it does not exist
- if (sessionCheckdir (session) != AFB_SUCCESS) goto errSessiondir;
- if (verbose) fprintf (stderr, "AFB:notice Init config done\n");
-
-
-
- // ---- run in foreground mode --------------------
- if (session->foreground) {
-
- if (verbose) fprintf (stderr,"AFB:notice Foreground mode\n");
-
- // write a pid file for --kill-previous and --raise-debug option
- status = writePidFile (session->config, getpid());
- if (status == -1) goto errorPidFile;
-
- // enter listening loop in foreground
- listenLoop(session);
- goto exitInitLoop;
- } // end foreground
-
-
- // --------- run in background mode -----------
- if (session->background) {
-
- // if (status != 0) goto errorCommand;
- if (verbose) printf ("AFB: Entering background mode\n");
-
- // open /dev/console to redirect output messAFBes
- consoleFD = open(session->config->console, O_WRONLY | O_APPEND | O_CREAT , 0640);
- if (consoleFD < 0) goto errConsole;
-
- // fork process when running background mode
- pid = fork ();
-
- // son process get all data in standalone mode
- if (pid == 0) {
-
- printf ("\nAFB: background mode [pid:%d console:%s]\n", getpid(),session->config->console);
- if (verbose) printf ("AFB:info use '%s --restart --rootdir=%s # [--pidfile=%s] to restart daemon\n", programName,session->config->rootdir, session->config->pidfile);
-
- // redirect default I/O on console
- close (2); status=dup(consoleFD); // redirect stderr
- close (1); status=dup(consoleFD); // redirect stdout
- close (0); // no need for stdin
- close (consoleFD);
-
- setsid(); // allow father process to fully exit
- sleep (2); // allow main to leave and release port
-
- fprintf (stderr, "----------------------------\n");
- fprintf (stderr, "%s INF:main background pid=%d\n", configTime(), getpid());
- fflush (stderr);
-
- // if everything look OK then look forever
- syslog (LOG_ERR, "AFB: Entering infinite loop in background mode");
-
- // should normally never return from this loop
- listenLoop(session);
- syslog (LOG_ERR, "AFB:FAIL background infinite loop exited check [%s]\n", session->config->console);
-
- goto exitInitLoop;
- }
-
- // if fail nothing much to do
- if (pid == -1) goto errorFork;
-
- // fork worked and we are in father process
- status = writePidFile (session->config, pid);
- if (status == -1) goto errorPidFile;
-
- // we are in father process, we don't need this one
- exit (0);
-
- } // end background-foreground
-
-normalExit:
- closeSession (session); // try to close everything before leaving
- if (verbose) printf ("\n---- Application Framework Binder Normal End ------\n");
- exit (0);
-
-// ------------- Fatal ERROR display error and quit -------------
-errorSetuid:
- fprintf (stderr,"\nERR:AFB-daemon Failed to change UID to username=[%s]\n\n", session->config->setuid);
- exit (-1);
-
-//errorNoRoot:
-// fprintf (stderr,"\nERR:AFB-daemon Not allow to run as root [use --seteuid=username option]\n\n");
-// exit (-1);
-
-errorPidFile:
- fprintf (stderr,"\nERR:AFB-daemon Failed to write pid file [%s]\n\n", session->config->pidfile);
- exit (-1);
-
-errorFork:
- fprintf (stderr,"\nERR:AFB-daemon Failed to fork son process\n\n");
- exit (-1);
-
-needValueForOption:
- fprintf (stderr,"\nERR:AFB-daemon option [--%s] need a value i.e. --%s=xxx\n\n"
- ,gnuOptions[optionIndex].name, gnuOptions[optionIndex].name);
- exit (-1);
-
-noValueForOption:
- fprintf (stderr,"\nERR:AFB-daemon option [--%s] don't take value\n\n"
- ,gnuOptions[optionIndex].name);
- exit (-1);
-
-notAnInteger:
- fprintf (stderr,"\nERR:AFB-daemon option [--%s] requirer an interger i.e. --%s=9\n\n"
- ,gnuOptions[optionIndex].name, gnuOptions[optionIndex].name);
- exit (-1);
-
-exitOnSignal:
- fprintf (stderr,"\n%s INF:AFB-daemon pid=%d received exit signal (Hopefully crtl-C or --kill-previous !!!)\n\n"
- ,configTime(), getpid());
- exit (-1);
-
-errConsole:
- fprintf (stderr,"\nERR:AFB-daemon cannot open /dev/console (use --foreground)\n\n");
- exit (-1);
-
-errSessiondir:
- fprintf (stderr,"\nERR:AFB-daemon cannot read/write session dir\n\n");
- exit (-1);
-
-errSoundCard:
- fprintf (stderr,"\nERR:AFB-daemon fail to probe sound cards\n\n");
- exit (-1);
-
-exitInitLoop:
- // try to unlink pid file if any
- if (session->background && session->config->pidfile != NULL) unlink (session->config->pidfile);
- exit (-1);
-
-}; /* END AFB-daemon() */
-
+int main(int argc, char *argv[])
+{
+ struct afb_hsrv *hsrv;
+ struct sd_event *eventloop;
+
+ LOGAUTH("afb-daemon");
+
+ // ------------- Build session handler & init config -------
+ config = afb_config_parse_arguments(argc, argv);
+ atexit(exit_handler);
+
+ // ------------------ sanity check ----------------------------------------
+ if (config->httpdPort <= 0) {
+ ERROR("no port is defined");
+ exit(1);
+ }
+
+ afb_session_init(config->nbSessionMax, config->cntxTimeout, config->token, afb_apis_count());
+
+ afb_api_so_set_timeout(config->apiTimeout);
+ start_list(config->dbus_clients, afb_api_dbus_add_client, "the afb-dbus client");
+ start_list(config->ws_clients, afb_api_ws_add_client, "the afb-websocket client");
+ start_list(config->ldpaths, afb_api_so_add_pathset, "the binding path set");
+ start_list(config->so_bindings, afb_api_so_add_binding, "the binding");
+ start_list(config->dbus_servers, afb_api_dbus_add_server, "the afb-dbus service");
+ start_list(config->ws_servers, afb_api_ws_add_server, "the afb-websocket service");
+
+ if (!afb_hreq_init_cookie(config->httpdPort, config->rootapi, config->cntxTimeout)) {
+ ERROR("initialisation of cookies failed");
+ exit(1);
+ }
+
+ if (afb_sig_handler_init() < 0) {
+ ERROR("failed to initialise signal handlers");
+ return 1;
+ }
+ // if directory does not exist createit
+ mkdir(config->rootdir, O_RDWR | S_IRWXU | S_IRGRP);
+ if (afb_common_rootdir_set(config->rootdir) < 0) {
+ ERROR("failed to set common root directory");
+ return 1;
+ }
+
+ if (afb_thread_init(3, 1, 20) < 0) {
+ ERROR("failed to initialise threading");
+ return 1;
+ }
+ // let's run this program with a low priority
+ nice(20);
+
+ // ------------------ Finaly Process Commands -----------------------------
+ // let's not take the risk to run as ROOT
+ //if (getuid() == 0) goto errorNoRoot;
+
+ DEBUG("Init config done");
+
+ // --------- run -----------
+ if (config->background) {
+ // --------- in background mode -----------
+ INFO("entering background mode");
+ daemonize();
+ } else {
+ // ---- in foreground mode --------------------
+ INFO("entering foreground mode");
+ }
+
+ /* ignore any SIGPIPE */
+ signal(SIGPIPE, SIG_IGN);
+
+ /* install trace of requests */
+ if (config->tracereq)
+ afb_hook_req_create(NULL, NULL, NULL, config->tracereq, NULL, NULL);
+
+ /* start the services */
+ if (afb_apis_start_all_services(1) < 0)
+ exit(1);
+
+ /* start the HTTP server */
+ if (!config->noHttpd) {
+ hsrv = start_http_server();
+ if (hsrv == NULL)
+ exit(1);
+ }
+
+ /* run the command */
+ if (execute_command() < 0)
+ exit(1);
+
+ /* signal that ready */
+ if (config->readyfd != 0) {
+ static const char readystr[] = "READY=1";
+ write(config->readyfd, readystr, sizeof(readystr) - 1);
+ close(config->readyfd);
+ }
+
+ // infinite loop
+ eventloop = afb_common_get_event_loop();
+ for (;;)
+ sd_event_run(eventloop, 30000000);
+
+ WARNING("hoops returned from infinite loop [report bug]");
+
+ return 0;
+}