Esempio n. 1
0
/**
 * infinoted_signal_register:
 * @run: A #InfinotedRun.
 *
 * Registers signal handlers for SIGINT and SIGTERM that terminate the given
 * infinote server. When you don't need the signal handlers anymore, you
 * must unregister them again using infinoted_signal_unregister().
 *
 * Returns: A #InfinotedSignal to unregister the signal handlers again later.
 */
InfinotedSignal*
infinoted_signal_register(InfinotedRun* run)
{
  InfinotedSignal* sig;
  sig = g_slice_new(InfinotedSignal);

#ifdef LIBINFINITY_HAVE_LIBDAEMON
  sig->run = run;

  /* TODO: Should we report when this fails? Should ideally happen before
   * actually forking then - are signal connections kept in fork()'s child? */
  if(daemon_signal_init(SIGINT, SIGTERM, SIGQUIT, SIGHUP, 0) == 0)
  {
    sig->signal_fd = daemon_signal_fd();

    sig->watch = inf_io_add_watch(
      INF_IO(run->io),
      &sig->signal_fd,
      INF_IO_INCOMING | INF_IO_ERROR,
      infinoted_signal_sig_func,
      sig,
      NULL
    );
  }

#else
  sig->previous_sigint_handler =
    signal(SIGINT, &infinoted_signal_sigint_handler);
  sig->previous_sigterm_handler =
    signal(SIGTERM, &infinoted_signal_sigterm_handler);
  sig->previous_sigquit_handler =
#ifndef G_OS_WIN32
    signal(SIGQUIT, &infinoted_signal_sigquit_handler);
  sig->previous_sighup_handler =
    signal(SIGHUP, &infinoted_signal_sighup_handler);
#endif /* !G_OS_WIN32 */
  _infinoted_signal_server = run;
#endif /* !LIBINFINITY_HAVE_LIBDAEMON */

#ifdef G_OS_WIN32
  SetConsoleCtrlHandler(infinoted_signal_console_handler, TRUE);
#endif

  return sig;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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;
	}
}
Esempio n. 4
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;
	}
}
Esempio n. 5
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.");
}
Esempio n. 6
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.");
}
Esempio n. 7
0
int action(interface_status_t status) {
    pid_t pid;
    int _pipe[2];
    unsigned n = 0;
    static char buf[256];
    char *arg = (status == IFSTATUS_UP ? "up" : "down");
    int sigfd, r;
    fd_set rfds;

    daemon_log(LOG_INFO, "Executing '%s %s %s'.", run, interface, arg);
    
    if (pipe(_pipe) < 0) {
        daemon_log(LOG_ERR, "pipe() failed: %s", strerror(errno));
        return -1;
    }

    if ((pid = fork()) < 0) {
        daemon_log(LOG_ERR, "fork() failed: %s", strerror(errno));
        return -1;
            
    } else if (pid == 0) {
        dup2(_pipe[1], 1);
        dup2(_pipe[1], 2);
        
        if (_pipe[0] > 2)
            close(_pipe[0]);

        if (_pipe[1] > 2)
            close(_pipe[1]);

        umask(0022); /* Set up a sane umask */
        
        execl(run, run, interface, arg, extra_arg, (char *) NULL);

        _exit(EXIT_FAILURE);
    }

    close(_pipe[1]);

    FD_ZERO(&rfds);
    FD_SET(_pipe[0], &rfds);
    sigfd = daemon_signal_fd();
    FD_SET(sigfd, &rfds);    

    n = 0;

    for (;;) {
        fd_set wrfds = rfds;

        if (select(FD_SETSIZE, &wrfds, NULL, NULL, NULL) < 0) {

            if (errno == EINTR)
                continue;

            break;
        }


        if (FD_ISSET(_pipe[0], &wrfds)) {
            char c;

            if (read(_pipe[0], &c, 1) != 1)
                break;

            buf[n] = c;
            
            if (c == '\n' || n >= sizeof(buf) - 2) {
                if (c != '\n') n++;
                buf[n] = 0;

                if (buf[0])
                    daemon_log(LOG_WARNING, "client: %s", buf);
            
                n = 0;
            } else
                n++;
        }

        if (FD_ISSET(sigfd, &wrfds)) {
            int sig;
            
            if ((sig = daemon_signal_next()) < 0) {
                daemon_log(LOG_ERR, "daemon_signal_next(): %s", strerror(errno));
                break;
            }

            if (sig != SIGCHLD) {
                daemon_log(LOG_WARNING, "Killing child.");
                kill(pid, SIGTERM);
            }
        }
        
    }

    if (n > 0) {
        buf[n] = 0;
        daemon_log(LOG_WARNING, "client: %s", buf);
    }

    waitpid(pid, &r, 0);

    close(_pipe[0]);

    if (!WIFEXITED(r) || WEXITSTATUS(r) != 0) {
        if (status == IFSTATUS_UP)
            beep(2);
        daemon_log(LOG_ERR, "Program execution failed, return value is %i.", WEXITSTATUS(r));

        return ignore_retval ? 0 : -1;
    } else {
        if (status == IFSTATUS_UP)
            beep(0);

        daemon_log(LOG_INFO, "Program executed successfully.");
        return 0;
    }
}
Esempio n. 8
0
/**
 * this is what the child process does continuously.  If
 * the child process dies, then it gets respawned by the
 * watchdog to maintain continuity.
 */
static int do_child_process(void) {
    int server_sockfd;
    struct sockaddr_in server_address;
    struct event_base *pbase = NULL;
    struct event evsignal;   /* libdaemon's signal fd */
    struct event evaccept;   /* server socket */
    int retval = 1;

    /* if(lookup_config.drop_core) { */
    /*     const struct rlimit rlim = { */
    /*         RLIM_INFINITY, */
    /*         RLIM_INFINITY */
    /*     }; */

    /*     setrlimit(RLIMIT_CORE, &rlim); */
    /*     prctl(PR_SET_DUMPABLE, 1); */
    /* } */

    server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(server_sockfd == -1) {
        ERROR("Cannot create server socket: %s", strerror(errno));
        goto finish;
    }

    server_address.sin_family = AF_INET;
    server_address.sin_addr.s_addr = INADDR_ANY;
    server_address.sin_port = htons(config.port);

    if(bind(server_sockfd, (struct sockaddr*)&server_address, (socklen_t)sizeof(server_address)) < 0) {
        ERROR("Bind error: %s", strerror(errno));
        goto finish;
    }

    if(listen(server_sockfd, config.socket_backlog) < 0) {
        ERROR("Listen error: %s", strerror(errno));
        goto finish;
    }

    if(setnonblock(server_sockfd) < 0) {
        ERROR("Could not set server socket to non-blocking: %s", strerror(errno));
        goto finish;
    }

    /* FIXME: drop privs */

    /* set up events */
    pbase = event_init();
    if(!pbase) {
        ERROR("Could not get event_base.  Failing");
        goto finish;
    }

    /* set up event for libdaemon's signal fd */
    event_set(&evsignal, daemon_signal_fd(), EV_READ | EV_PERSIST, on_signal, &evsignal);
    event_add(&evsignal, NULL);

    /* set up events for listening AF_INET socket */
    event_set(&evaccept, server_sockfd, EV_READ | EV_PERSIST, on_accept, &evaccept);
    event_add(&evaccept, NULL);


    while(!g_quitflag) {
        event_base_loop(pbase, EVLOOP_ONCE);
    }

    retval = 0;

 finish:
    if(pbase) {
        event_del(&evaccept);
        event_del(&evsignal);
    }

    if(server_sockfd != -1) {
        shutdown(server_sockfd, SHUT_RDWR);
        close(server_sockfd);
    }

    exit(retval);
}