/** * infinoted_signal_unregister: * @sig: A #InfinotedSignal. * * Unregisters signal handlers registered with infinoted_signal_register(). */ void infinoted_signal_unregister(InfinotedSignal* sig) { #ifdef G_OS_WIN32 SetConsoleCtrlHandler(infinoted_signal_console_handler, FALSE); #endif #ifdef LIBINFINITY_HAVE_LIBDAEMON if(sig->run) { inf_io_remove_watch(INF_IO(sig->run->io), sig->watch); sig->watch = NULL; daemon_signal_done(); } #else signal(SIGINT, sig->previous_sigint_handler); signal(SIGTERM, sig->previous_sigterm_handler); #ifndef G_OS_WIN32 signal(SIGQUIT, sig->previous_sigquit_handler); signal(SIGHUP, sig->previous_sighup_handler); #endif /* !G_OS_WIN32 */ _infinoted_signal_server = NULL; #endif /* !LIBINFINITY_HAVE_LIBDAEMON */ g_slice_free(InfinotedSignal, sig); }
static void infinoted_signal_sig_func(InfNativeSocket* fd, InfIoEvent event, gpointer user_data) { InfinotedSignal* sig; int occured; GError* error; sig = (InfinotedSignal*)user_data; if(event & INF_IO_ERROR) { inf_io_remove_watch(INF_IO(sig->run->io), sig->watch); daemon_signal_done(); sig->run = NULL; sig->signal_fd = 0; sig->watch = NULL; infinoted_log_error( sig->run->startup->log, _("Error on signal handler connection; signal " "handlers have been removed from now on") ); } else if(event & INF_IO_INCOMING) { occured = daemon_signal_next(); if(occured == SIGINT || occured == SIGTERM || occured == SIGQUIT) { printf("\n"); inf_standalone_io_loop_quit(sig->run->io); } else if(occured == SIGHUP) { error = NULL; if(!infinoted_config_reload(sig->run, &error)) { infinoted_log_error( sig->run->startup->log, _("Configuration reload failed: %s"), error->message ); g_error_free(error); } else { infinoted_log_info( sig->run->startup->log, _("Configuration reloaded") ); } } } }
static int _init(void) { if (_signal_pipe[0] < 0 || _signal_pipe[1] < 0) { if (pipe(_signal_pipe) < 0) { daemon_log(LOG_ERR, "pipe(): %s", strerror(errno)); return -1; } fcntl(_signal_pipe[0],F_SETFD, fcntl(_signal_pipe[0],F_GETFD,0)|FD_CLOEXEC); fcntl(_signal_pipe[1],F_SETFD, fcntl(_signal_pipe[1],F_GETFD,0)|FD_CLOEXEC); if (daemon_nonblock(_signal_pipe[0], 1) < 0 || daemon_nonblock(_signal_pipe[1], 1) < 0) { daemon_signal_done(); return -1; } } return 0; }
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 }
static int run_server(DaemonConfig *c) { int r = -1; int error; const AvahiPoll *poll_api = NULL; AvahiWatch *sig_watch = NULL; int retval_is_sent = 0; #ifdef HAVE_INOTIFY AvahiWatch *inotify_watch = NULL; #endif #ifdef HAVE_KQUEUE int i; AvahiWatch *kqueue_watch = NULL; #endif assert(c); ignore_signal(SIGPIPE); if (!(nss_support = avahi_nss_support())) avahi_log_warn("WARNING: No NSS support for mDNS detected, consider installing nss-mdns!"); if (!(simple_poll_api = avahi_simple_poll_new())) { avahi_log_error("Failed to create main loop object."); goto finish; } poll_api = avahi_simple_poll_get(simple_poll_api); if (daemon_signal_init(SIGINT, SIGHUP, SIGTERM, SIGUSR1, 0) < 0) { avahi_log_error("Could not register signal handlers (%s).", strerror(errno)); goto finish; } if (!(sig_watch = poll_api->watch_new(poll_api, daemon_signal_fd(), AVAHI_WATCH_IN, signal_callback, simple_poll_api))) { avahi_log_error( "Failed to create signal watcher"); goto finish; } if (simple_protocol_setup(poll_api) < 0) goto finish; #ifdef HAVE_DBUS if (c->enable_dbus) { if (dbus_protocol_setup(poll_api, config.disable_user_service_publishing, config.n_clients_max, config.n_objects_per_client_max, config.n_entries_per_entry_group_max, !c->fail_on_missing_dbus #ifdef ENABLE_CHROOT && !config.use_chroot #endif ) < 0) { avahi_log_warn("WARNING: Failed to contact D-Bus daemon."); if (c->fail_on_missing_dbus) goto finish; } } #endif #ifdef ENABLE_CHROOT if (config.drop_root && config.use_chroot) { if (chroot(AVAHI_CONFIG_DIR) < 0) { avahi_log_error("Failed to chroot(): %s", strerror(errno)); goto finish; } avahi_log_info("Successfully called chroot()."); chdir("/"); if (avahi_caps_drop_all() < 0) { avahi_log_error("Failed to drop capabilities."); goto finish; } avahi_log_info("Successfully dropped remaining capabilities."); } #endif #ifdef HAVE_INOTIFY if ((inotify_fd = inotify_init()) < 0) avahi_log_warn( "Failed to initialize inotify: %s", strerror(errno)); else { add_inotify_watches(); if (!(inotify_watch = poll_api->watch_new(poll_api, inotify_fd, AVAHI_WATCH_IN, inotify_callback, NULL))) { avahi_log_error( "Failed to create inotify watcher"); goto finish; } } #endif #ifdef HAVE_KQUEUE if ((kq = kqueue()) < 0) avahi_log_warn( "Failed to initialize kqueue: %s", strerror(errno)); else { add_kqueue_watches(); if (!(kqueue_watch = poll_api->watch_new(poll_api, kq, AVAHI_WATCH_IN, kqueue_callback, NULL))) { avahi_log_error( "Failed to create kqueue watcher"); goto finish; } } #endif load_resolv_conf(); #ifdef ENABLE_CHROOT static_service_load(config.use_chroot); static_hosts_load(config.use_chroot); #else static_service_load(0); static_hosts_load(0); #endif if (!(avahi_server = avahi_server_new(poll_api, &c->server_config, server_callback, c, &error))) { avahi_log_error("Failed to create server: %s", avahi_strerror(error)); goto finish; } update_wide_area_servers(); update_browse_domains(); if (c->daemonize) { daemon_retval_send(0); retval_is_sent = 1; } for (;;) { if ((r = avahi_simple_poll_iterate(simple_poll_api, -1)) < 0) { /* We handle signals through an FD, so let's continue */ if (errno == EINTR) continue; avahi_log_error("poll(): %s", strerror(errno)); goto finish; } else if (r > 0) /* Quit */ break; } r = 0; finish: static_service_remove_from_server(); static_service_free_all(); static_hosts_remove_from_server(); static_hosts_free_all(); remove_dns_server_entry_groups(); simple_protocol_shutdown(); #ifdef HAVE_DBUS if (c->enable_dbus) dbus_protocol_shutdown(); #endif if (avahi_server) { avahi_server_free(avahi_server); avahi_server = NULL; } daemon_signal_done(); if (sig_watch) poll_api->watch_free(sig_watch); #ifdef HAVE_INOTIFY if (inotify_watch) poll_api->watch_free(inotify_watch); if (inotify_fd >= 0) close(inotify_fd); #endif #ifdef HAVE_KQUEUE if (kqueue_watch) poll_api->watch_free(kqueue_watch); if (kq >= 0) close(kq); for (i = 0; i < num_kfds; i++) { if (kfds[i] >= 0) close(kfds[i]); } #endif if (simple_poll_api) { avahi_simple_poll_free(simple_poll_api); simple_poll_api = NULL; } if (!retval_is_sent && c->daemonize) daemon_retval_send(1); return r; }
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; } }
void work(void) { fd_set fds; int sigfd; static char log_ident[256]; snprintf(log_ident, sizeof(log_ident), "ifplugd"); daemon_log_ident = log_ident; daemon_log(LOG_INFO, "ifplugd "VERSION" initializing, using NETLINK device monitoring"); if (daemon_pid_file_create() < 0) { daemon_log(LOG_ERR, "Could not create PID file %s.", daemon_pid_file_proc()); goto finish; } if (daemon_signal_init(SIGINT, SIGTERM, SIGQUIT, SIGHUP, SIGCHLD, SIGUSR1, SIGUSR2, -1) < 0) { daemon_log(LOG_ERR, "Could not register signal handler: %s", strerror(errno)); goto finish; } if ((netlink = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0) { daemon_log(LOG_ERR, "socket(): %s", strerror(errno)); goto finish; } rbus = rbus_init("unix!/tmp/ifplugd.9p"); rbus->rbus.childs = &root_children[0]; discover(netlink); if (nlapi_open(RTMGRP_LINK) < 0) goto finish; if (ifmonitor_init(ifmonitor_cb) < 0) goto finish; FD_ZERO(&fds); sigfd = daemon_signal_fd(); FD_SET(sigfd, &fds); FD_SET(nlapi_fd, &fds); for (;;) { struct interface_state *iface; fd_set qfds = fds; struct timeval tv; IxpConn *c; for(c = rbus->srv->conn; c; c = c->next) { if(c->read) { FD_SET(c->fd, &qfds); } } tv.tv_sec = polltime; tv.tv_usec = 0; if (select(FD_SETSIZE, &qfds, NULL, NULL, &tv) < 0) { if (errno == EINTR) continue; daemon_log(LOG_ERR, "select(): %s", strerror(errno)); goto finish; } //daemon_log(LOG_INFO, "select()"); for(c = rbus->srv->conn; c; c = c->next) { if(c->read && FD_ISSET(c->fd, &qfds)) { c->read(c); } } if (FD_ISSET(nlapi_fd, &qfds)) { if (nlapi_work(0) < 0) goto finish; } for(iface = interface; iface; iface=iface->next) { if(! is_iface_available(netlink, iface->name)) { drop_interface(iface); continue; } detect_beat(netlink, iface); status_change(iface); } if (FD_ISSET(sigfd, &qfds)) { int sig; if ((sig = daemon_signal_next()) < 0) { daemon_log(LOG_ERR, "daemon_signal_next(): %s", strerror(errno)); goto finish; } switch (sig) { case SIGINT: case SIGTERM: goto cleanup; case SIGQUIT: goto finish; case SIGCHLD: break; case SIGHUP: break; default: daemon_log(LOG_INFO, "Ignoring unknown signal %s", strsignal(sig)); break; } } } cleanup: finish: if (netlink >= 0) close(netlink); nlapi_close(); daemon_pid_file_remove(); daemon_signal_done(); daemon_log(LOG_INFO, "Exiting."); }
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; }
void work(void) { interface_status_t status; int fd = -1; fd_set fds; int sigfd; time_t t = 0; int send_retval = 1; int paused = 0; static char log_ident[256]; snprintf(log_ident, sizeof(log_ident), "ifplugd(%s)", interface); daemon_log_ident = log_ident; daemon_log(LOG_INFO, "ifplugd "VERSION" initializing%s.", use_ifmonitor ? ", using NETLINK device monitoring" : ""); if (daemon_pid_file_create() < 0) { daemon_log(LOG_ERR, "Could not create PID file %s.", daemon_pid_file_proc()); goto finish; } if (daemon_signal_init(SIGINT, SIGTERM, SIGQUIT, SIGHUP, SIGCHLD, SIGUSR1, SIGUSR2, -1) < 0) { daemon_log(LOG_ERR, "Could not register signal handler: %s", strerror(errno)); goto finish; } switch (api_mode) { case API_ETHTOOL: detect_beat_func = interface_detect_beat_ethtool; break; case API_MII: detect_beat_func = interface_detect_beat_mii; break; case API_PRIVATE: detect_beat_func = interface_detect_beat_priv; break; case API_WLAN: detect_beat_func = interface_detect_beat_wlan; break; case API_IFF: detect_beat_func = interface_detect_beat_iff; break; default: detect_beat_func = detect_beat_auto; interface_do_message = 0; break; } if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { daemon_log(LOG_ERR, "socket(): %s", strerror(errno)); goto finish; } if (use_ifmonitor) { int b; if ((b = is_iface_available(fd, interface)) < 0) { daemon_log(LOG_ERR, "Failed to check interface availabilty!"); goto finish; } disabled = !b; if (nlapi_open(RTMGRP_LINK) < 0) goto finish; if (ifmonitor_init(ifmonitor_cb) < 0) goto finish; } else disabled = 0; if (!disabled) { if (welcome_iface(fd, interface) < 0) goto finish; } if ((status = detect_beat(fd, interface)) == IFSTATUS_ERR) goto finish; daemon_log(LOG_INFO, "Initialization complete, link beat %sdetected%s.", status == IFSTATUS_UP ? "" : "not ", use_ifmonitor ? (disabled ? ", interface disabled" : ", interface enabled") : ""); beep(status == IFSTATUS_UP ? 0 : 1); if ((!no_startup_script && status == IFSTATUS_UP) || initial_down) if (action(status) < 0) goto finish; if (send_retval && daemonize && wait_on_fork) { char c = status == IFSTATUS_UP ? 2 : (status == IFSTATUS_DOWN ? 3 : 1); daemon_retval_send(c); send_retval = 0; } FD_ZERO(&fds); sigfd = daemon_signal_fd(); FD_SET(sigfd, &fds); if (use_ifmonitor) FD_SET(nlapi_fd, &fds); for (;;) { interface_status_t s; fd_set qfds = fds; int d; struct timeval tv; tv.tv_sec = polltime; tv.tv_usec = 0; if (select(FD_SETSIZE, &qfds, NULL, NULL, &tv) < 0) { if (errno == EINTR) continue; daemon_log(LOG_ERR, "select(): %s", strerror(errno)); goto finish; } //daemon_log(LOG_INFO, "select()"); d = disabled; s = status; if (use_ifmonitor) { if (FD_ISSET(nlapi_fd, &qfds)) { if (nlapi_work(0) < 0) goto finish; } if (d && !disabled) { daemon_log(LOG_INFO, "Interface enabled"); welcome_iface(fd, interface); status = IFSTATUS_DOWN; } if (!d && disabled) { daemon_log(LOG_INFO, "Interface disabled"); status = IFSTATUS_DOWN; } } if (!paused && !disabled) { //daemon_log(LOG_INFO, "detect"); if ((status = detect_beat(fd, interface)) == IFSTATUS_ERR) { if (!use_ifmonitor) goto finish; status = IFSTATUS_DOWN; } } if (status != s) { daemon_log(LOG_INFO, "Link beat %s.", status == IFSTATUS_DOWN ? "lost" : "detected"); beep(status == IFSTATUS_UP ? 0 : 1); if (t) t = 0; else { t = time(NULL); if (status == IFSTATUS_UP) t += delay_up; if (status == IFSTATUS_DOWN) t += delay_down; } } if (FD_ISSET(sigfd, &qfds)) { int sig; if ((sig = daemon_signal_next()) < 0) { daemon_log(LOG_ERR, "daemon_signal_next(): %s", strerror(errno)); goto finish; } switch (sig) { case SIGINT: case SIGTERM: goto cleanup; case SIGQUIT: goto finish; case SIGCHLD: break; case SIGHUP: daemon_log(LOG_INFO, "SIGHUP: %s, link detected on %s: %s", paused ? "Suspended" : "Running", interface, status == IFSTATUS_DOWN ? "no" : "yes"); if (use_ifmonitor) daemon_log(LOG_INFO, "SIGHUP: Interface %s", disabled ? "disabled" : "enabled"); break; case SIGUSR1: daemon_log(LOG_INFO, "SIGUSR1: Daemon suspended (#%i)", ++paused); break; case SIGUSR2: if (paused > 0) { daemon_log(LOG_INFO, "SIGUSR2: Daemon resumed (#%i)", paused); paused --; } break; default: daemon_log(LOG_INFO, "Ignoring unknown signal %s", strsignal(sig)); break; } } if (t && t < time(NULL)) { t = 0; if (action(status) < 0) goto finish; } } cleanup: if (!no_shutdown_script && (status == IFSTATUS_UP || (status == IFSTATUS_DOWN && t))) { setenv(IFPLUGD_ENV_PREVIOUS, strstatus(status), 1); setenv(IFPLUGD_ENV_CURRENT, strstatus(-1), 1); action(IFSTATUS_DOWN); beep(1); } finish: if (fd >= 0) close(fd); if (use_ifmonitor) nlapi_close(); if (send_retval && daemonize && wait_on_fork) daemon_retval_send(255); daemon_pid_file_remove(); daemon_signal_done(); daemon_log(LOG_INFO, "Exiting."); }
/** * 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; }