static gboolean infinoted_main(int argc, char* argv[], GError** error) { InfinotedStartup* startup; gboolean result; startup = infinoted_startup_new(&argc, &argv, error); if(startup == NULL) return FALSE; #ifdef LIBINFINITY_HAVE_LIBDAEMON if(startup->options->daemonize) { daemon_pid_file_ident = daemon_ident_from_argv0(argv[0]); daemon_log_ident = daemon_pid_file_ident; } #endif result = infinoted_main_run(startup, error); return result; }
void init(const char *pidfile, const char *progname) { #ifdef HAVE_LIBDAEMON // Set identification string for the daemon for both syslog and PID file daemon_pid_file_ident = daemon_log_ident = daemon_ident_from_argv0((char *)progname); if ( pidfile != NULL ) { fawkes_pid_file = pidfile; daemon_pid_file_proc = fawkes_daemon_pid_file_proc; } #else throw Exception("Daemonizing support is not available.\n" "(libdaemon[-devel] was not available at compile time)\n"); #endif }
int main(int argc, char *argv[]) { // create a configuration dtn::daemon::Configuration &conf = dtn::daemon::Configuration::getInstance(); // load parameter into the configuration conf.params(argc, argv); #ifdef HAVE_LIBDAEMON if (conf.getDaemon().daemonize()) { int ret = 0; pid_t pid; #ifdef HAVE_DAEMON_RESET_SIGS /* Reset signal handlers */ if (daemon_reset_sigs(-1) < 0) { daemon_log(LOG_ERR, "Failed to reset all signal handlers: %s", strerror(errno)); return 1; } /* Unblock signals */ if (daemon_unblock_sigs(-1) < 0) { daemon_log(LOG_ERR, "Failed to unblock all signals: %s", strerror(errno)); return 1; } #endif /* Set identification string for the daemon for both syslog and PID file */ daemon_pid_file_ident = daemon_log_ident = daemon_ident_from_argv0(argv[0]); /* set the pid file path */ try { std::string p = conf.getDaemon().getPidFile().getPath(); __daemon_pidfile__ = new char[p.length() + 1]; ::strcpy(__daemon_pidfile__, p.c_str()); daemon_pid_file_proc = __daemon_pid_file_proc__; } catch (const dtn::daemon::Configuration::ParameterNotSetException&) { }; /* Check if we are called with -k parameter */ if (conf.getDaemon().kill_daemon()) { int ret; /* Kill daemon with SIGTERM */ /* Check if the new function daemon_pid_file_kill_wait() is available, if it is, use it. */ if ((ret = daemon_pid_file_kill_wait(SIGTERM, 5)) < 0) daemon_log(LOG_WARNING, "Failed to kill daemon: %s", strerror(errno)); return ret < 0 ? 1 : 0; } /* Check that the daemon is not rung twice a the same time */ if ((pid = daemon_pid_file_is_running()) >= 0) { daemon_log(LOG_ERR, "Daemon already running on PID file %u", pid); return 1; } /* Prepare for return value passing from the initialization procedure of the daemon process */ if (daemon_retval_init() < 0) { daemon_log(LOG_ERR, "Failed to create pipe."); return 1; } /* Do the fork */ if ((pid = daemon_fork()) < 0) { /* Exit on error */ daemon_retval_done(); return 1; } else if (pid) { /* The parent */ int ret; /* Wait for 20 seconds for the return value passed from the daemon process */ if ((ret = daemon_retval_wait(20)) < 0) { daemon_log(LOG_ERR, "Could not recieve return value from daemon process: %s", strerror(errno)); return 255; } //daemon_log(ret != 0 ? LOG_ERR : LOG_INFO, "Daemon returned %i as return value.", ret); return ret; } else { /* The daemon */ /* Close FDs */ if (daemon_close_all(-1) < 0) { daemon_log(LOG_ERR, "Failed to close all file descriptors: %s", strerror(errno)); /* Send the error condition to the parent process */ daemon_retval_send(1); goto finish; } /* Create the PID file */ if (daemon_pid_file_create() < 0) { daemon_log(LOG_ERR, "Could not create PID file (%s).", strerror(errno)); daemon_retval_send(2); goto finish; } /* Initialize signal handling */ if (daemon_signal_init(SIGINT, SIGTERM, SIGQUIT, SIGHUP, SIGUSR1, SIGUSR2, 0) < 0) { daemon_log(LOG_ERR, "Could not register signal handlers (%s).", strerror(errno)); daemon_retval_send(3); goto finish; } ret = __daemon_run(); finish: /* Do a cleanup */ daemon_log(LOG_INFO, "Exiting..."); daemon_retval_send(255); daemon_signal_done(); daemon_pid_file_remove(); } return ret; } else { #endif // run the daemon return __daemon_run(); #ifdef HAVE_LIBDAEMON } #endif }
int main(int argc, char *argv[]) { pid_t pid; /* Reset signal handlers */ if (daemon_reset_sigs(-1) < 0) { daemon_log(LOG_ERR, "Failed to reset all signal handlers: %s", strerror(errno)); return 1; } /* Unblock signals */ if (daemon_unblock_sigs(-1) < 0) { daemon_log(LOG_ERR, "Failed to unblock all signals: %s", strerror(errno)); } /* Set indetification string for the daemon for both syslog and PID file */ daemon_log_ident = daemon_ident_from_argv0(argv[0]); daemon_pid_file_ident = daemon_log_ident; //(LOG_ERR, "The log ident is %s\n",daemon_log_ident); daemon_pid_file_proc = get_pid_file_proc; sprintf (image_pid_file, "/var/run/%s.pid", daemon_pid_file_ident); /* Check if we are called with -k parameter */ if (argc >= 2 && !strcmp(argv[1], "-k")) { int ret; /* Kill daemon with SIGTERM */ /* Check if the new function daemon_pid_file_kill_wait() is available, if it is, use it. */ if ((ret = daemon_pid_file_kill_wait(SIGTERM, 5)) < 0) daemon_log(LOG_WARNING, "Failed to kill daemon: %s", strerror(errno)); return ret < 0 ? 1 : 0; } /* Check that the daemon is not rung twice a the same time */ if ((pid = daemon_pid_file_is_running()) >= 0) { daemon_log(LOG_ERR, "Daemon already running on PID file %u", pid); return 1; } /* Prepare for return value passing from the initialization procedure of the daemon process */ if (daemon_retval_init() < 0) { daemon_log(LOG_ERR, "Failed to create pipe."); return 1; } /* Do the fork */ if ((pid = daemon_fork()) < 0) { /* Exit on error */ daemon_retval_done(); return 1; } else if (pid) { /* The parent */ int ret; /* Wait for 20 seconds for the return value passed from the daemon process */ if ((ret = daemon_retval_wait(20)) < 0) { daemon_log(LOG_ERR, "Count not receive return value from daemon" "process: %s", strerror(errno)); } //daemon_log(ret != 0 ? LOG_ERR : LOG_INFO, // "Daemon returned %i as return value.", ret); return ret; } else { /* The daemon */ int fd, quit = 0; fd_set fds; pthread_t sock_thread; pthread_t nl_thread; /* Close FDs */ if (daemon_close_all(-1) < 0) { daemon_log(LOG_ERR, "Failed to close all file descriptors: %s", strerror(errno)); /* Send the error condition to the parent process */ daemon_retval_send(1); goto finish; } /* Create the PID file */ if (daemon_pid_file_create() < 0) { daemon_log(LOG_ERR, "Could not create PID file (%s).", strerror(errno)); daemon_retval_send(2); goto finish; } /* Initialize signal handling */ if (daemon_signal_init(SIGINT, SIGTERM, SIGQUIT, SIGHUP, 0) < 0) { daemon_log(LOG_ERR, "Could not register signal handlers (%s).", strerror(errno)); daemon_retval_send(3); goto finish; } /* Init task */ init_image_config(argc, argv); init_netlink(); /* Send OK to parent process */ daemon_retval_send(0); daemon_log(LOG_INFO, "Sucessfully started"); /* Main task*/ pthread_create(&nl_thread, NULL, (void *)netlink_loop, (void *)NULL); #if 0 pthread_create(&sock_thread, NULL, (void *)socket_loop, (void *)NULL); #endif pthread_create(&sock_thread, NULL, (void *)mq_loop, (void *)NULL); /* Prepare for select() on the signal fd */ FD_ZERO(&fds); fd = daemon_signal_fd(); FD_SET(fd, &fds); while (!quit) { fd_set fds2 = fds; /* Wait for an incoming signal */ if (select(FD_SETSIZE, &fds2, 0, 0, 0) < 0) { /* If we've been interrupted by an incoming signal, continue */ if (errno == EINTR) continue; daemon_log(LOG_ERR, "select(): %s", strerror(errno)); break; } /* Check if a signal has been recieved */ if (FD_ISSET(fd, &fds2)) { int sig; /* Get signal */ if ((sig = daemon_signal_next()) <= 0) { daemon_log(LOG_ERR, "daemon_signal_next() failed: %s", strerror(errno)); break; } /* Dispatch signal */ switch (sig) { case SIGINT: case SIGQUIT: case SIGTERM: daemon_log(LOG_WARNING, "Got SIGINT, SIGQUIT or" "SIGTERM."); if (nl_image_config.nl_connected == 1) { nl_image_config.nl_connected = 0; if (nl_send_image_session_cmd( IMAGE_SESSION_CMD_DISCONNECT) < 0) { printf("Failed to remove connection with" "kernel!\n"); } } quit = 1; break; case SIGHUP: daemon_log(LOG_INFO, "Got a HUP"); daemon_exec("/", NULL, "/bin/ls", "ls", (char*) NULL); break; } } } /* Do a cleanup */ finish: delete_pid_file(IMAGE_SERVER_PROC); daemon_log(LOG_INFO, "Exiting..."); daemon_retval_send(255); daemon_signal_done(); daemon_pid_file_remove(); return 0; } }
/** Punto de entrada de la aplicacion de navegacion. * @return Estado de la aplicacion al terminar. */ int main(int argc, char *argv[]) { pid_t pid; /* Reset signal handlers */ if (daemon_reset_sigs(-1) < 0) { daemon_log(LOG_ERR, "Failed to reset all signal handlers: %s", strerror(errno)); return 1; } /* Unblock signals */ if (daemon_unblock_sigs(-1) < 0) { daemon_log(LOG_ERR, "Failed to unblock all signals: %s", strerror(errno)); return 1; } /* Set indetification string for the daemon for both syslog and PID file */ daemon_pid_file_ident = daemon_log_ident = daemon_ident_from_argv0(argv[0]); /* Check if we are called with -k parameter */ if (argc >= 2 && !strcmp(argv[1], "-k")) { int ret; /* Kill daemon with SIGTERM */ /* Check if the new function daemon_pid_file_kill_wait() is available, if it is, use it. */ if ((ret = daemon_pid_file_kill_wait(SIGTERM, 5)) < 0) daemon_log(LOG_WARNING, "Failed to kill daemon: %s", strerror(errno)); return ret < 0 ? 1 : 0; } /* Check that the daemon is not rung twice a the same time */ if ((pid = daemon_pid_file_is_running()) >= 0) { daemon_log(LOG_ERR, "Daemon already running on PID file %u", pid); return 1; } /* Prepare for return value passing from the initialization procedure of the daemon process */ if (daemon_retval_init() < 0) { daemon_log(LOG_ERR, "Failed to create pipe."); return 1; } /* Do the fork */ if ((pid = daemon_fork()) < 0) { /* Exit on error */ daemon_retval_done(); return 1; } else if (pid) { /* The parent */ int ret; /* Wait for 20 seconds for the return value passed from the daemon process */ if ((ret = daemon_retval_wait(20)) < 0) { daemon_log(LOG_ERR, "Could not recieve return value from daemon process: %s", strerror(errno)); return 255; } daemon_log(ret != 0 ? LOG_ERR : LOG_INFO, "Daemon returned %i as return value.", ret); return ret; } else { /* The daemon */ int fd, quit = 0; fd_set fds; char * config_file; config_t cfg; config_setting_t *setting; /* Base de Datos de Tiempo Real */ struct rtdb rtdb; /* Controlador de estado de la MTi-G */ struct mti_g mti_g; struct time_tracker tracker; struct sharksoft sharksoft; /* Close FDs */ if (daemon_close_all(-1) < 0) { daemon_log(LOG_ERR, "Failed to close all file descriptors: %s", strerror(errno)); /* Send the error condition to the parent process */ daemon_retval_send(1); goto finish; } /* Create the PID file */ if (daemon_pid_file_create() < 0) { daemon_log(LOG_ERR, "Could not create PID file (%s).", strerror(errno)); daemon_retval_send(2); goto finish; } /* Initialize signal handling */ if (daemon_signal_init(SIGINT, SIGTERM, SIGQUIT, SIGHUP, 0) < 0) { daemon_log(LOG_ERR, "Could not register signal handlers (%s).", strerror(errno)); daemon_retval_send(3); goto finish; } /*... do some further init work here */ daemon_log(LOG_INFO, "Starting"); /* cargar la configuración de la aplicación */ config_init(&cfg); config_file = malloc(strlen(CONFIG_PATH) + strlen(CONFIG_FILE) + 1); assert(config_file != NULL); strcpy(config_file, CONFIG_PATH); strcpy(config_file + strlen(CONFIG_PATH), CONFIG_FILE); /* Read the file. If there is an error, report it and exit. */ if (!config_read_file(&cfg, CONFIG_FILE)) { daemon_log(LOG_ERR, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg)); daemon_retval_send(4); goto finish; } daemon_log(LOG_INFO, "Config file readed"); /* Inicializar el controlador de estado de la MTi-G, enlazando * la RTDB como area de almacenamiento */ setting = config_lookup(&cfg, "mti_g"); mti_g_init(&mti_g, setting, &(rtdb.imu), &(rtdb.gps)); daemon_log(LOG_INFO, "MTi-G state controller inited"); setting = config_lookup(&cfg, "time_tracker"); time_tracker_init(&tracker, setting); daemon_log(LOG_INFO, "Time Tracker service inited"); setting = config_lookup(&cfg, "sharksoft"); sharksoft_init(&sharksoft, setting, &(rtdb.imu), &(rtdb.gps)); daemon_log(LOG_INFO, "Sharksoft data provider service inited"); /* Send OK to parent process */ daemon_retval_send(0); daemon_log(LOG_INFO, "Sucessfully started"); /* Prepare for select() on the signals */ FD_ZERO(&fds); fd = daemon_signal_fd(); FD_SET(fd, &fds); FD_SET(mti_g.fd, &fds); FD_SET(sharksoft.fd, &fds); while (!quit) { fd_set fds2 = fds; /* Wait for an incoming signal */ if (select(FD_SETSIZE, &fds2, 0, 0, 0) < 0) { /* If we've been interrupted by an incoming signal, continue */ if (errno == EINTR) continue; daemon_log(LOG_ERR, "select(): %s", strerror(errno)); break; } /* Check if a signal has been recieved */ if (FD_ISSET(fd, &fds2)) { int sig; /* Get signal */ if ((sig = daemon_signal_next()) <= 0) { daemon_log(LOG_ERR, "daemon_signal_next() failed: %s", strerror(errno)); break; } /* Dispatch signal */ switch (sig) { case SIGINT: case SIGQUIT: case SIGTERM: daemon_log(LOG_WARNING, "Got SIGINT, SIGQUIT or SIGTERM."); quit = 1; break; case SIGHUP: daemon_log(LOG_INFO, "Got a HUP"); daemon_exec("/", NULL, "/bin/ls", "ls", (char*) NULL); break; } } /* Procesar señales desde la MTi-G */ if (FD_ISSET(mti_g.fd, &fds2)) { mti_g_handle_request(&mti_g); //sharksoft_handle_getdata(&sharksoft); //time_tracker_handle(&tracker); } /* Procesar señales desde el HMI Sharksoft */ if (FD_ISSET(sharksoft.fd, &fds2)) { //time_tracker_handle(&tracker); sharksoft_handle_request(&sharksoft); } } time_tracker_dispose(&tracker); config_destroy(&cfg); /* Do a cleanup */ finish: daemon_log(LOG_INFO, "Exiting..."); daemon_retval_send(255); daemon_signal_done(); daemon_pid_file_remove(); return 0; } }
int main(int argc, char *argv[]) { fd_set rfds; struct timeval tv; int retval; pid_t pid; char *cpSerialDevice = NULL; { static struct option long_options[] = { /* Required arguments */ {"serial", required_argument, NULL, 's'}, /* Program options */ {"help", no_argument, NULL, 'h'}, {"foreground", no_argument, NULL, 'f'}, {"verbosity", required_argument, NULL, 'v'}, {"baud", required_argument, NULL, 'B'}, {"interface", required_argument, NULL, 'I'}, {"reset", no_argument, NULL, 'R'}, {"confignotify", required_argument, NULL, 'C'}, {"activityled", required_argument, NULL, 'A'}, /* Module options */ {"frontend", required_argument, NULL, 'F'}, {"diversity", no_argument, NULL, 'D'}, /* 6LoWPAN network options */ {"mode", required_argument, NULL, 'm'}, {"region", required_argument, NULL, 'r'}, {"channel", required_argument, NULL, 'c'}, {"pan", required_argument, NULL, 'p'}, {"network", required_argument, NULL, 'j'}, {"profile", required_argument, NULL, 'P'}, {"prefix", required_argument, NULL, '6'}, /* Security options */ {"key", required_argument, NULL, 'k'}, {"authscheme", required_argument, NULL, 'a'}, /* Radius with PAP options */ {"radiusip", required_argument, NULL, 'i'}, { NULL, 0, NULL, 0} }; signed char opt; int option_index; while ((opt = getopt_long(argc, argv, "s:hfv:B:I:RC:A:F:Dm:r:c:p:j:P:6:k:a:i:", long_options, &option_index)) != -1) { switch (opt) { case 'h': print_usage_exit(argv); break; case 'f': daemonize = 0; break; case 'v': verbosity = atoi(optarg); break; case 'B': { char *pcEnd; errno = 0; u32BaudRate = strtoul(optarg, &pcEnd, 0); if (errno) { printf("Baud rate '%s' cannot be converted to 32 bit integer (%s)\n", optarg, strerror(errno)); print_usage_exit(argv); } if (*pcEnd != '\0') { printf("Baud rate '%s' contains invalid characters\n", optarg); print_usage_exit(argv); } break; } case 's': cpSerialDevice = optarg; break; case 'C': { struct stat sStat; /* Check if the given program exists and is executable */ if (stat(optarg, &sStat) == 0) { /* File stat'd ok */ pcConfigProgram = optarg; vprConfigChanged = ConfigChangedCallback; } else { printf("Config stat notification program '%s' (%s)\n", optarg, strerror(errno)); print_usage_exit(argv); } break; } case 'A': { char *pcEnd; uint32_t u32ActivityLED; errno = 0; u32ActivityLED = strtoul(optarg, &pcEnd, 0); if (errno) { printf("Activity LED '%s' cannot be converted to 32 bit integer (%s)\n", optarg, strerror(errno)); print_usage_exit(argv); } if (*pcEnd != '\0') { printf("Activity LED '%s' contains invalid characters\n", optarg); print_usage_exit(argv); } eActivityLED = u32ActivityLED; break; } case 'F': if (strcmp(optarg, "SP") == 0) { eRadioFrontEnd = E_FRONTEND_STANDARD_POWER; } else if (strcmp(optarg, "HP") == 0) { eRadioFrontEnd = E_FRONTEND_HIGH_POWER; } else if (strcmp(optarg, "ETSI") == 0) { eRadioFrontEnd = E_FRONTEND_ETSI; } else { printf("Unknown mode '%s' specified. Supported modes are 'coordinator', 'router', 'commissioning'\n", optarg); print_usage_exit(argv); } break; case 'D': iAntennaDiversity = 1; break; case 'm': if (strcmp(optarg, "coordinator") == 0) { eModuleMode = E_MODE_COORDINATOR; } else if (strcmp(optarg, "router") == 0) { eModuleMode = E_MODE_ROUTER; } else if (strcmp(optarg, "commissioning") == 0) { eModuleMode = E_MODE_COMMISSIONING; } else { printf("Unknown mode '%s' specified. Supported modes are 'coordinator', 'router', 'commissioning'\n", optarg); print_usage_exit(argv); } break; case 'r': { char *pcEnd; uint32_t u32Region; errno = 0; u32Region = strtoul(optarg, &pcEnd, 0); if (errno) { printf("Region '%s' cannot be converted to 32 bit integer (%s)\n", optarg, strerror(errno)); print_usage_exit(argv); } if (*pcEnd != '\0') { printf("Region '%s' contains invalid characters\n", optarg); print_usage_exit(argv); } if (u32Region > E_REGION_MAX) { printf("Invalid region '%s' specified\n", optarg); print_usage_exit(argv); } eRegion = (uint8_t)u32Region; break; } case 'c': { char *pcEnd; uint32_t u32Channel; errno = 0; u32Channel = strtoul(optarg, &pcEnd, 0); if (errno) { printf("Channel '%s' cannot be converted to 32 bit integer (%s)\n", optarg, strerror(errno)); print_usage_exit(argv); } if (*pcEnd != '\0') { printf("Channel '%s' contains invalid characters\n", optarg); print_usage_exit(argv); } if ( !((u32Channel == E_CHANNEL_AUTOMATIC) || ((u32Channel >= E_CHANNEL_MINIMUM) && (u32Channel <= E_CHANNEL_MAXIMUM)))) { printf("Invalid Channel '%s' specified\n", optarg); print_usage_exit(argv); } eChannel = (uint8_t)u32Channel; break; } case 'p': { char *pcEnd; uint32_t u32PanID; errno = 0; u32PanID = strtoul(optarg, &pcEnd, 0); if (errno) { printf("PAN ID '%s' cannot be converted to 32 bit integer (%s)\n", optarg, strerror(errno)); print_usage_exit(argv); } if (*pcEnd != '\0') { printf("PAN ID '%s' contains invalid characters\n", optarg); print_usage_exit(argv); } if (u32PanID > 0xFFFF) { printf("Invalid PAN ID '%s' specified\n", optarg); print_usage_exit(argv); } u16PanID = (uint16_t)u32PanID; break; } case 'j': { char *pcEnd; uint32_t u32JenNetID; errno = 0; u32JenNetID = strtoul(optarg, &pcEnd, 0); if (errno) { printf("JenNet ID '%s' cannot be converted to 32 bit integer (%s)\n", optarg, strerror(errno)); print_usage_exit(argv); } if (*pcEnd != '\0') { printf("JenNet ID '%s' contains invalid characters\n", optarg); print_usage_exit(argv); } u32UserData = u32JenNetID; break; } case 'P': { char *pcEnd; uint32_t u32JenNetProfile; errno = 0; u32JenNetProfile = strtoul(optarg, &pcEnd, 0); if (errno) { printf("JenNet Profile '%s' cannot be converted to 32 bit integer (%s)\n", optarg, strerror(errno)); print_usage_exit(argv); } if (*pcEnd != '\0') { printf("JenNet Profile '%s' contains invalid characters\n", optarg); print_usage_exit(argv); } if (u32JenNetProfile > 0xFF) { printf("Invalid JenNet Profile '%s' specified\n", optarg); print_usage_exit(argv); } u8JenNetProfile = (uint8_t)u32JenNetProfile; break; } case '6': { int result; struct in6_addr address; result = inet_pton(AF_INET6, optarg, &address); if (result <= 0) { if (result == 0) { printf("Unknown host: %s\n", optarg); } else if (result < 0) { perror("inet_pton failed"); } exit(EXIT_FAILURE); } else { u64NetworkPrefix = ((uint64_t)address.s6_addr[0] << 56) | ((uint64_t)address.s6_addr[1] << 48) | ((uint64_t)address.s6_addr[2] << 40) | ((uint64_t)address.s6_addr[3] << 32) | ((uint64_t)address.s6_addr[4] << 24) | ((uint64_t)address.s6_addr[5] << 16) | ((uint64_t)address.s6_addr[6] << 8) | ((uint64_t)address.s6_addr[7] << 0); } break; } case 'I': cpTunDevice = optarg; break; case 'R': iResetCoordinator = 1; break; case 'k': { int result; /* The network key is specified like an IPv6 address, in 8 groups of 16-bit hexadecimal values separated by colons (:) */ result = inet_pton(AF_INET6, optarg, &sSecurityKey); if (result <= 0) { if (result == 0) { printf("Could not parse network key: %s\n", optarg); } else if (result < 0) { perror("inet_pton failed"); } exit(EXIT_FAILURE); } iSecureNetwork = 1; break; } case 'a': { char *pcEnd; uint32_t u32AuthScheme; errno = 0; u32AuthScheme = strtoul(optarg, &pcEnd, 0); if (errno) { printf("Authorisation scheme '%s' cannot be converted to 32 bit integer (%s)\n", optarg, strerror(errno)); print_usage_exit(argv); } if (*pcEnd != '\0') { printf("Authorisation scheme '%s' contains invalid characters\n", optarg); print_usage_exit(argv); } switch(u32AuthScheme) { case 0: printf("Warning - no authorisation scheme selected\n"); eAuthScheme = u32AuthScheme; break; case (1): eAuthScheme = u32AuthScheme; break; default: printf("Unknown authorisation scheme selected (%d)\n", u32AuthScheme); print_usage_exit(argv); break; } break; } case 'i': { switch(eAuthScheme) { case (E_AUTH_SCHEME_RADIUS_PAP): { int result = inet_pton(AF_INET6, optarg, &uAuthSchemeData.sRadiusPAP.sAuthServerIP); if (result <= 0) { if (result == 0) { printf("Unknown host: %s\n", optarg); } else if (result < 0) { perror("inet_pton failed"); } exit(EXIT_FAILURE); } break; } default: printf("Option '-i' is not appropriate for authorisation scheme %d\n", eAuthScheme); break; } break; } default: /* '?' */ print_usage_exit(argv); } } } /* Log everything into syslog */ daemon_log_ident = daemon_ident_from_argv0(argv[0]); if (!cpSerialDevice) { print_usage_exit(argv); } if (daemonize) { /* Prepare for return value passing from the initialization procedure of the daemon process */ if (daemon_retval_init() < 0) { daemon_log(LOG_ERR, "Failed to create pipe."); return 1; } /* Do the fork */ if ((pid = daemon_fork()) < 0) { /* Exit on error */ daemon_log(LOG_ERR, "Failed to fork() daemon process."); daemon_retval_done(); return 1; } else if (pid) { /* The parent */ int ret; /* Wait for 20 seconds for the return value passed from the daemon process */ if ((ret = daemon_retval_wait(20)) < 0) { daemon_log(LOG_ERR, "Could not recieve return value from daemon process: %s", strerror(errno)); return 255; } if (ret == 0) { daemon_log(LOG_INFO, "Daemon process started."); } else { daemon_log(LOG_ERR, "Daemon returned %i.", ret); } return ret; } else { /* The daemon */ /* Close FDs */ if (daemon_close_all(-1) < 0) { daemon_log(LOG_ERR, "Failed to close all file descriptors: %s", strerror(errno)); /* Send the error condition to the parent process */ daemon_retval_send(1); goto finish; } daemon_log_use = DAEMON_LOG_SYSLOG; /* Send OK to parent process */ daemon_retval_send(0); daemon_log(LOG_INFO, "Daemon started"); } } else { /* Running foreground - set verbosity */ if (verbosity > LOG_WARNING) { daemon_set_verbosity(verbosity); } } FD_ZERO(&rfds); /* Wait up to five seconds. */ tv.tv_sec = 5; tv.tv_usec = 0; if ((serial_open(cpSerialDevice, u32BaudRate) < 0) || (eTunDeviceOpen(cpTunDevice) != E_TUN_OK)) { goto finish; } /* Install signal handlers */ signal(SIGTERM, vQuitSignalHandler); signal(SIGINT, vQuitSignalHandler); eJennicModuleStart(); while (bRunning) { int max_fd = 0; /* Wait up to one second each loop. */ tv.tv_sec = 1; tv.tv_usec = 0; FD_ZERO(&rfds); FD_SET(serial_fd, &rfds); if (serial_fd > max_fd) { max_fd = serial_fd; } FD_SET(tun_fd, &rfds); if (tun_fd > max_fd) { max_fd = tun_fd; } /* Wait for data on one either the serial port or the TUN interface. */ retval = select(max_fd + 1, &rfds, NULL, NULL, &tv); if (retval == -1) { daemon_log(LOG_ERR, "error in select(): %s", strerror(errno)); } else if (retval) { int i; /* Got data on one of the file descriptors */ for (i = 0; i < max_fd + 1; i++) { if (FD_ISSET(i, &rfds) && (i == serial_fd)) { if(bSL_ReadMessage(&sIncomingMsg.u8Type, &sIncomingMsg.u16Length, sizeof(sIncomingMsg.u8Message), sIncomingMsg.u8Message)) { if (eJennicModuleProcessMessage(sIncomingMsg.u8Type, sIncomingMsg.u16Length, sIncomingMsg.u8Message) != E_MODULE_OK) { daemon_log(LOG_ERR, "Error communicating with border router module"); bRunning = FALSE; } } } else if (FD_ISSET(i, &rfds) && (i == tun_fd)) { if (eTunDeviceReadPacket() != E_TUN_OK) { daemon_log(LOG_ERR, "Error handling tun packet"); } /* Kick the state machine to prompt the sending of a ping packet if necessary. */ if (eJennicModuleStateMachine(1) != E_MODULE_OK) { daemon_log(LOG_ERR, "Error communicating with border router module"); bRunning = FALSE; } } else if (FD_ISSET(i, &rfds)) { daemon_log(LOG_DEBUG, "Data on unknown file desciptor (%d)", i); } else { /* Should not get here */ } } } else { /* Select timeout */ if (eJennicModuleStateMachine(1) != E_MODULE_OK) { daemon_log(LOG_ERR, "Error communicating with border router module"); bRunning = FALSE; } } } if (iResetCoordinator) { daemon_log(LOG_INFO, "Resetting Coordinator Module"); eJennicModuleReset(); } finish: if (daemonize) { daemon_log(LOG_INFO, "Daemon process exiting"); } return 0; }
int main(int argc, char *argv[]) { pid_t pid; const char *pcFD_GPIO = NULL; const char *pcI2Cbus = NULL; uint8_t u8I2CAddress = 0; const char *pcPWR_GPIO = NULL; { static struct option long_options[] = { /* Program options */ {"help", no_argument, NULL, 'h'}, {"foreground", no_argument, NULL, 'f'}, {"verbosity", required_argument, NULL, 'v'}, {"gpio-fd", required_argument, NULL, 0}, {"i2c-bus", required_argument, NULL, 1}, {"i2c-address", required_argument, NULL, 2}, {"gpio-pwr", required_argument, NULL, 3}, { NULL, 0, NULL, 0} }; signed char opt; int option_index; while ((opt = getopt_long(argc, argv, "hfv:", long_options, &option_index)) != -1) { switch (opt) { case 'h': print_usage_exit(argv); break; case 'f': daemonize = 0; break; case 'v': verbosity = atoi(optarg); break; case 0: pcFD_GPIO = optarg; break; case 1: pcI2Cbus = optarg; break; case 2: { char *pcEnd; errno = 0; uint32_t u32I2CAddress = strtoul(optarg, &pcEnd, 0); if (errno) { fprintf(stderr, "I2C Address '%s' cannot be converted to 32 bit integer (%s)\n", optarg, strerror(errno)); print_usage_exit(argv); } if (*pcEnd != '\0') { fprintf(stderr, "I2C Address '%s' contains invalid characters\n", optarg); print_usage_exit(argv); } if (u32I2CAddress > 0x7F) { fprintf(stderr, "I2C Address '%s' outside allowable range (0x01 - 0x7F)\n", optarg); print_usage_exit(argv); } u8I2CAddress = u32I2CAddress; break; } case 3: pcPWR_GPIO = optarg; break; default: /* '?' */ print_usage_exit(argv); } } } if (!pcFD_GPIO) { fprintf(stderr, "GPIO for field detect pin must be specified\n"); print_usage_exit(argv); } if (!pcI2Cbus) { fprintf(stderr, "I2C bus must be specified\n"); print_usage_exit(argv); } if (!u8I2CAddress) { fprintf(stderr, "I2C address must be specified\n"); print_usage_exit(argv); } /* Log everything into syslog */ daemon_log_ident = daemon_ident_from_argv0(argv[0]); if (daemonize) { /* Prepare for return value passing from the initialization procedure of the daemon process */ if (daemon_retval_init() < 0) { daemon_log(LOG_ERR, "Failed to create pipe."); return 1; } /* Do the fork */ if ((pid = daemon_fork()) < 0) { /* Exit on error */ daemon_log(LOG_ERR, "Failed to fork() daemon process."); daemon_retval_done(); return 1; } else if (pid) { /* The parent */ int ret; /* Wait for 20 seconds for the return value passed from the daemon process */ if ((ret = daemon_retval_wait(20)) < 0) { daemon_log(LOG_ERR, "Could not recieve return value from daemon process: %s", strerror(errno)); return 255; } if (ret == 0) { daemon_log(LOG_INFO, "Daemon process started."); } else { daemon_log(LOG_ERR, "Daemon returned %i.", ret); } return ret; } else { /* The daemon */ /* Close FDs */ if (daemon_close_all(-1) < 0) { daemon_log(LOG_ERR, "Failed to close all file descriptors: %s", strerror(errno)); /* Send the error condition to the parent process */ daemon_retval_send(1); goto finish; } daemon_log_use = DAEMON_LOG_SYSLOG; /* Send OK to parent process */ daemon_retval_send(0); daemon_log(LOG_INFO, "Daemon started"); } } else { /* Running foreground - set verbosity */ if (verbosity > LOG_WARNING) { daemon_set_verbosity(verbosity); } } /* Install signal handlers */ signal(SIGTERM, vQuitSignalHandler); signal(SIGINT, vQuitSignalHandler); if (eNtagSetup(pcPWR_GPIO, pcFD_GPIO, pcI2Cbus, u8I2CAddress) == E_NFC_OK) { if (eNdefSetup() == E_NFC_OK) { while (bRunning != 0) { if (eNtagWait(30000) == E_NFC_READER_PRESENT) { /* Tag detected */ while ((eNtagPresent() == E_NFC_READER_PRESENT) && bRunning) { sleep(1); teNfcStatus eStatus = eNtagRfUnlocked(); switch (eStatus) { case (E_NFC_OK): vHandleTag(); break; case (E_NFC_RF_LOCKED): DEBUG_PRINTF("RF Locked\n"); break; default: break; } //usleep(100000); //sleep(1); } } else { /* Blank the tag */ tsNdefData sData; eNdefInitData(&sData, 0, 0); eNdefWriteData(&sData); } } } } else { DEBUG_PRINTF("Failed to init NTAG\n"); } finish: if (daemonize) { daemon_log(LOG_INFO, "Daemon process exiting"); } return 0; }
int main(int argc, char *argv[]) { int index; int c; std::string ptp_dev("tun0"); std::string app_name("tunnel"); std::string endpoint("dtn:none"); unsigned int lifetime = 60; bool daemonize = false; bool stop_daemon = false; std::string pidfile; bool throughput = false; #ifdef HAVE_LIBDAEMON while ((c = getopt (argc, argv, "td:s:l:hDkp:")) != -1) #else while ((c = getopt (argc, argv, "td:s:l:h")) != -1) #endif switch (c) { #ifdef HAVE_LIBDAEMON case 'D': daemonize = true; break; case 'k': daemonize = true; stop_daemon = true; break; case 'p': pidfile = optarg; break; #endif case 'd': ptp_dev = optarg; break; case 't': throughput = true; break; case 's': app_name = optarg; break; case 'l': lifetime = atoi(optarg); break; default: print_help(argv[0]); return 1; } int optindex = 0; for (index = optind; index < argc; ++index) { switch (optindex) { case 0: endpoint = std::string(argv[index]); break; } optindex++; } // print help if not enough parameters are set if (!stop_daemon && (optindex < 1)) { print_help(argv[0]); exit(0); } // catch process signals ibrcommon::SignalHandler sighandler(term); sighandler.handle(SIGINT); sighandler.handle(SIGTERM); sighandler.handle(SIGQUIT); //initialize sighandler after possible exit call sighandler.initialize(); // logging options //const unsigned char logopts = ibrcommon::Logger::LOG_DATETIME | ibrcommon::Logger::LOG_LEVEL; const unsigned char logopts = 0; // error filter const unsigned char logerr = ibrcommon::Logger::LOGGER_ERR | ibrcommon::Logger::LOGGER_CRIT; // logging filter, everything but debug, err and crit const unsigned char logstd = ibrcommon::Logger::LOGGER_ALL ^ (ibrcommon::Logger::LOGGER_DEBUG | logerr); // syslog filter, everything but DEBUG and NOTICE const unsigned char logsys = ibrcommon::Logger::LOGGER_ALL ^ (ibrcommon::Logger::LOGGER_DEBUG | ibrcommon::Logger::LOGGER_NOTICE); #ifdef HAVE_LIBDAEMON if (daemonize) { // enable syslog logging ibrcommon::Logger::enableSyslog(argv[0], LOG_PID, LOG_DAEMON, logsys); } else #endif { // add logging to the cout ibrcommon::Logger::addStream(std::cout, logstd, logopts); // add logging to the cerr ibrcommon::Logger::addStream(std::cerr, logerr, logopts); } #ifdef HAVE_LIBDAEMON if (daemonize) { #ifdef HAVE_DAEMON_RESET_SIGS /* Reset signal handlers */ if (daemon_reset_sigs(-1) < 0) { IBRCOMMON_LOGGER_TAG("Core", error) << "Failed to reset all signal handlers: " << strerror(errno) << IBRCOMMON_LOGGER_ENDL; return 1; } /* Unblock signals */ if (daemon_unblock_sigs(-1) < 0) { IBRCOMMON_LOGGER_TAG("Core", error) << "Failed to unblock all signals: " << strerror(errno) << IBRCOMMON_LOGGER_ENDL; return 1; } #endif pid_t pid; /* Set identification string for the daemon for both syslog and PID file */ daemon_pid_file_ident = daemon_log_ident = daemon_ident_from_argv0(argv[0]); /* set the pid file path */ if (pidfile.length() > 0) { __daemon_pidfile__ = new char[pidfile.length() + 1]; ::strcpy(__daemon_pidfile__, pidfile.c_str()); daemon_pid_file_proc = __daemon_pid_file_proc__; } /* Check if we are called with -k parameter */ if (stop_daemon) { int ret; /* Kill daemon with SIGTERM */ /* Check if the new function daemon_pid_file_kill_wait() is available, if it is, use it. */ if ((ret = daemon_pid_file_kill_wait(SIGTERM, 5)) < 0) IBRCOMMON_LOGGER_TAG("Core", warning) << "Failed to kill daemon: " << strerror(errno) << IBRCOMMON_LOGGER_ENDL; return ret < 0 ? 1 : 0; } /* Check that the daemon is not rung twice a the same time */ if ((pid = daemon_pid_file_is_running()) >= 0) { IBRCOMMON_LOGGER_TAG("Core", error) << "Daemon already running on PID file " << pid << IBRCOMMON_LOGGER_ENDL; return 1; } /* Prepare for return value passing from the initialization procedure of the daemon process */ if (daemon_retval_init() < 0) { IBRCOMMON_LOGGER_TAG("Core", error) << "Failed to create pipe." << IBRCOMMON_LOGGER_ENDL; return 1; } /* Do the fork */ if ((pid = daemon_fork()) < 0) { /* Exit on error */ daemon_retval_done(); return 1; } else if (pid) { /* The parent */ int ret; /* Wait for 20 seconds for the return value passed from the daemon process */ if ((ret = daemon_retval_wait(20)) < 0) { IBRCOMMON_LOGGER_TAG("Core", error) << "Could not recieve return value from daemon process: " << strerror(errno) << IBRCOMMON_LOGGER_ENDL; return 255; } return ret; } else { /* The daemon */ /* Close FDs */ if (daemon_close_all(-1) < 0) { IBRCOMMON_LOGGER_TAG("Core", error) << "Failed to close all file descriptors: " << strerror(errno) << IBRCOMMON_LOGGER_ENDL; /* Send the error condition to the parent process */ daemon_retval_send(1); /* Do a cleanup */ daemon_retval_send(255); daemon_signal_done(); daemon_pid_file_remove(); return -1; } /* Create the PID file */ if (daemon_pid_file_create() < 0) { IBRCOMMON_LOGGER_TAG("Core", error) << "Could not create PID file ( " << strerror(errno) << ")." << IBRCOMMON_LOGGER_ENDL; daemon_retval_send(2); /* Do a cleanup */ daemon_retval_send(255); daemon_signal_done(); daemon_pid_file_remove(); return -1; } /* Send OK to parent process */ daemon_retval_send(0); } } #endif IBRCOMMON_LOGGER_TAG("Core", info) << "IBR-DTN IP <-> Bundle Tunnel" << IBRCOMMON_LOGGER_ENDL; // create a connection to the dtn daemon ibrcommon::vaddress addr("localhost", 4550); ibrcommon::socketstream conn(new ibrcommon::tcpsocket(addr)); try { // set-up tun2bundle gateway TUN2BundleGateway gateway(app_name, conn, ptp_dev); _gateway = &gateway; IBRCOMMON_LOGGER_TAG("Core", info) << "Local: " << app_name << IBRCOMMON_LOGGER_ENDL; IBRCOMMON_LOGGER_TAG("Core", info) << "Peer: " << endpoint << IBRCOMMON_LOGGER_ENDL; IBRCOMMON_LOGGER_TAG("Core", info) << "Device: " << gateway.getDeviceName() << IBRCOMMON_LOGGER_ENDL; IBRCOMMON_LOGGER_TAG("Core", notice) << IBRCOMMON_LOGGER_ENDL; IBRCOMMON_LOGGER_TAG("Core", notice) << "Now you need to set-up the ip tunnel. You can use commands like this:" << IBRCOMMON_LOGGER_ENDL; IBRCOMMON_LOGGER_TAG("Core", notice) << "# sudo ip link set " << gateway.getDeviceName() << " up mtu 65535" << IBRCOMMON_LOGGER_ENDL; IBRCOMMON_LOGGER_TAG("Core", notice) << "# sudo ip addr add 10.0.0.1/24 dev " << gateway.getDeviceName() << IBRCOMMON_LOGGER_ENDL; IBRCOMMON_LOGGER_TAG("Core", notice) << IBRCOMMON_LOGGER_ENDL; timer_t timerid; struct sigevent sev; if (!daemonize && throughput) { // enable throughput timer signal(SIGRTMIN, timer_display_throughput); sev.sigev_notify = SIGEV_SIGNAL; sev.sigev_signo = SIGRTMIN; sev.sigev_value.sival_ptr = &timerid; // create a timer timer_create(CLOCK_MONOTONIC, &sev, &timerid); // arm the timer struct itimerspec its; size_t freq_nanosecs = 200000000; its.it_value.tv_sec = freq_nanosecs / 1000000000;; its.it_value.tv_nsec = freq_nanosecs % 1000000000; its.it_interval.tv_sec = its.it_value.tv_sec; its.it_interval.tv_nsec = its.it_value.tv_nsec; if (timer_settime(timerid, 0, &its, NULL) == -1) { IBRCOMMON_LOGGER_TAG("Core", error) << "Timer set failed." << IBRCOMMON_LOGGER_ENDL; } } // destination dtn::data::EID eid(endpoint); while (m_running) { gateway.process(eid, lifetime); } gateway.shutdown(); } catch (const ibrcommon::Exception &ex) { if (m_running) { IBRCOMMON_LOGGER_TAG("Core", error) << ex.what() << IBRCOMMON_LOGGER_ENDL; return -1; } } #ifdef HAVE_LIBDAEMON if (daemonize) { /* Do a cleanup */ IBRCOMMON_LOGGER_TAG("Core", info) << "Stopped " << app_name << IBRCOMMON_LOGGER_ENDL; daemon_retval_send(255); daemon_signal_done(); daemon_pid_file_remove(); } else #endif { std::cout << std::endl; } return 0; }
int main(int argc, char **argv) { int pid, ret; struct sigaction new_action, old_action; GOptionContext *ctx; GError *parse_err = NULL; daemon_pid_file_ident = daemon_log_ident = daemon_ident_from_argv0(argv[0]); daemon_pid_file_proc = conf_pid_file_proc; if (conf_init() < 0) return EXIT_FAILURE; ctx = g_option_context_new(""); g_option_context_add_main_entries(ctx, options, PACKAGE); g_option_context_set_summary(ctx, PACKAGE"-"VERSION GITHEAD" - mpd cron daemon"); if (!g_option_context_parse(ctx, &argc, &argv, &parse_err)) { g_printerr("option parsing failed: %s\n", parse_err->message); g_option_context_free(ctx); g_error_free(parse_err); return EXIT_FAILURE; } g_option_context_free(ctx); if (optv) { about(); cleanup(); return EXIT_SUCCESS; } #ifdef DAEMON_SET_VERBOSITY_AVAILABLE if (conf.no_daemon) daemon_set_verbosity(LOG_DEBUG); #endif /* DAEMON_SET_VERBOSITY_AVAILABLE */ /* Version to environment variable */ g_setenv("MPDCRON_PACKAGE", PACKAGE, 1); g_setenv("MPDCRON_VERSION", VERSION, 1); g_setenv("MPDCRON_GITHEAD", GITHEAD, 1); /* Command line options to environment variables */ if (conf.no_daemon) g_unsetenv("MCOPT_DAEMONIZE"); else g_setenv("MCOPT_DAEMONIZE", "1", 1); /* Important! Parse configuration file before killing the daemon * because the configuration file has a pidfile and killwait option. */ cfd = g_key_file_new(); if (keyfile_load(&cfd) < 0) { cleanup(); return EXIT_FAILURE; } if (optk) { if (daemon_pid_file_kill_wait(SIGINT, conf.killwait) < 0) { g_warning("Failed to kill daemon: %s", strerror(errno)); cleanup(); return EXIT_FAILURE; } daemon_pid_file_remove(); cleanup(); return EXIT_SUCCESS; } /* Logging */ g_log_set_default_handler(log_handler, GINT_TO_POINTER(conf.no_daemon ? 5 : conf.loglevel)); /* Signal handling */ new_action.sa_handler = sig_cleanup; sigemptyset(&new_action.sa_mask); new_action.sa_flags = 0; #define HANDLE_SIGNAL(sig) \ do { \ sigaction((sig), NULL, &old_action); \ if (old_action.sa_handler != SIG_IGN) \ sigaction((sig), &new_action, NULL); \ } while (0) HANDLE_SIGNAL(SIGABRT); HANDLE_SIGNAL(SIGSEGV); HANDLE_SIGNAL(SIGINT); HANDLE_SIGNAL(SIGTERM); #undef HANDLE_SIGNAL if (conf.no_daemon) { /* Create the main loop */ loop = g_main_loop_new(NULL, FALSE); #ifdef HAVE_GMODULE /* Load modules which may add initial events */ keyfile_load_modules(&cfd); #endif /* HAVE_GMODULE */ g_key_file_free(cfd); cfd = NULL; /* Add default initial events */ loop_connect(); /* Run the main loop */ g_main_loop_run(loop); cleanup(); return EXIT_SUCCESS; } /* Daemonize */ if ((pid = daemon_pid_file_is_running()) > 0) { g_critical("Daemon already running on PID %u", pid); return EXIT_FAILURE; } daemon_retval_init(); pid = daemon_fork(); if (pid < 0) { g_critical("Failed to fork: %s", strerror(errno)); daemon_retval_done(); return EXIT_FAILURE; } else if (pid != 0) { /* Parent */ cleanup(); if ((ret = daemon_retval_wait(2)) < 0) { g_critical("Could not receive return value from daemon process: %s", strerror(errno)); return 255; } if (ret != 0) g_critical("Daemon returned %i as return value", ret); else g_critical("Daemon returned %i as return value", ret); return ret; } else { /* Daemon */ if (daemon_close_all(-1) < 0) { g_critical("Failed to close all file descriptors: %s", strerror(errno)); daemon_retval_send(1); return EXIT_FAILURE; } if (daemon_pid_file_create() < 0) { g_critical("Failed to create PID file: %s", strerror(errno)); daemon_retval_send(2); return EXIT_FAILURE; } /* Send OK to parent process */ daemon_retval_send(0); /* Create the main loop */ loop = g_main_loop_new(NULL, FALSE); #ifdef HAVE_GMODULE /* Load modules which may add initial events */ keyfile_load_modules(&cfd); #endif /* HAVE_GMODULE */ g_key_file_free(cfd); cfd = NULL; /* Add default initial events */ loop_connect(); /* Run the main loop */ g_main_loop_run(loop); cleanup(); return EXIT_SUCCESS; } return EXIT_SUCCESS; }
/** * Read the config file, determine if we should daemonize or not, * and set up libevent dispatches. */ int main(int argc, char *argv[]) { int cmdline_debug_level = 0; int foreground = 0; int option; pid_t pid; int kill=0; int ret; /* set some sane config defaults */ memset((void*)&config, 0, sizeof(gopher_conf_t)); config.port = 70; config.base_dir = "."; config.socket_backlog = 5; config.config_file = DEFAULT_CONFIGFILE; while((option = getopt(argc, argv, "d:c:fp:s:k")) != -1) { switch(option) { case 'd': cmdline_debug_level = atoi(optarg); if(cmdline_debug_level < 1 || cmdline_debug_level > 5) { ERROR("Debug level must be 1-5 (default %d)", DEFAULT_DEBUGLEVEL); usage_quit(argv[0]); } break; case 'c': config.config_file = optarg; break; case 'f': foreground = 1; break; case 'p': config.port = atoi(optarg); break; case 's': config.base_dir = optarg; case 'k': kill = 1; break; default: usage_quit(argv[0]); } } debug_level(cmdline_debug_level ? cmdline_debug_level : DEFAULT_DEBUGLEVEL); /* kill before config, so we don't have to specify a config file */ daemon_pid_file_ident = daemon_ident_from_argv0(argv[0]); /* kill? */ if(kill) { if((ret = daemon_pid_file_kill_wait(SIGTERM, 5)) < 0) { ERROR("Failed to kill daemon: %s", strerror(errno)); } exit(ret < 0 ? EXIT_FAILURE : EXIT_SUCCESS); } if((pid = daemon_pid_file_is_running()) >= 0) { ERROR("Daemon already running as pid %u", pid); exit(EXIT_FAILURE); } /* TODO: read the config file and verify sufficient config */ debug_level(cmdline_debug_level); /* daemonize, or check for background daemon */ if(!foreground) { debug_output(DBG_OUTPUT_SYSLOG, "evgopherd"); if(daemon_retval_init() < 0) { ERROR("Could not set up daemon pipe"); exit(EXIT_FAILURE); } if((pid = daemon_fork()) < 0) { daemon_retval_done(); ERROR("Forking error: %s", strerror(errno)); exit(EXIT_FAILURE); } else if (pid) { /* parent */ if((ret = daemon_retval_wait(5)) < 0) { ERROR("Could not receive startup retval from daemon process: %s", strerror(errno)); exit(EXIT_FAILURE); } if(ret > 0) ERROR("Daemon declined to start. Error: %d\n", ret); exit(ret == 0 ? EXIT_SUCCESS :EXIT_FAILURE); } } if(daemon_signal_init(SIGINT, SIGTERM, SIGQUIT, SIGHUP, SIGPIPE, 0) < 0) { ERROR("Could not set up signal handlers: %s", strerror(errno)); goto finish; } if(!foreground) { if(daemon_pid_file_create() < 0) { ERROR("Could not create pidfile: %s", strerror(errno)); if(!foreground) daemon_retval_send(2); goto finish; } /* should close handles here */ daemon_retval_send(0); /* started up to the point that we can rely on syslog */ } WARN("Daemon started"); /* need to fork off a watchdog process */ while(!g_quitflag) { /* fork and wait */ pid_t pid = fork(); if(pid == -1) { ERROR("Error forking child process. Aborting"); g_quitflag = 1; } else if(pid == 0) { /* child */ do_child_process(); } else { /* parent */ int status; waitpid(pid, &status, 0); if(WIFEXITED(status) && WEXITSTATUS(status)) { /* exited with error */ ERROR("Error initializing child process. Aborting"); g_quitflag=1; } else if(!WIFEXITED(status)) { ERROR("Child process (%d) crashed. Restarting.", pid); } else { /* graceful exit... we've obviously terminated */ g_quitflag = 1; } } } WARN("Daemon exiting gracefully"); finish: daemon_signal_done(); daemon_pid_file_remove(); return EXIT_SUCCESS; }