Exemple #1
0
/**
 * read a signal from the libdaemon signal queue (event dispatch routine).
 *
 * @param fd fd signalled (via libevent)
 * @param event event (read/write, etc... from libevent)
 * @param arg opaqe pointer (from libevent), underlying event struct
 */
static void on_signal(int fd, short event, void *arg) {
    //    struct event *ev = arg;
    int sig;

    while((sig = daemon_signal_next()) > 0) {
        switch(sig) {
        case SIGINT:
        case SIGQUIT:
        case SIGTERM:
            INFO("Got signal -- terminating");
            g_quitflag = 1;
            break;
        case SIGHUP:
            INFO("Got HUP");
            break;
        case SIGPIPE:
            INFO("Got SIGPIPE");
            break;
        }
    }

    if(sig < 0) {
        ERROR("daemon_signal_next() failed: %s.  Aborting", strerror(errno));
        g_quitflag = 1;
    }
}
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")
        );
      }
    }
  }
}
Exemple #3
0
static void signal_callback(AvahiWatch *watch, AVAHI_GCC_UNUSED int fd, AVAHI_GCC_UNUSED AvahiWatchEvent event, AVAHI_GCC_UNUSED void *userdata) {
    int sig;
    const AvahiPoll *poll_api;

    assert(watch);
    assert(simple_poll_api);

    poll_api = avahi_simple_poll_get(simple_poll_api);

    if ((sig = daemon_signal_next()) <= 0) {
        avahi_log_error("daemon_signal_next() failed");
        poll_api->watch_free(watch);
        return;
    }

    switch (sig) {
        case SIGINT:
        case SIGQUIT:
        case SIGTERM:
            avahi_log_info(
                    "Got %s, quitting.",
                    sig == SIGINT ? "SIGINT" :
                    (sig == SIGQUIT ? "SIGQUIT" : "SIGTERM"));
            avahi_simple_poll_quit(simple_poll_api);
            break;

        case SIGHUP:
            avahi_log_info("Got SIGHUP, reloading.");

            reload_config();
            break;

        case SIGUSR1:
            avahi_log_info("Got SIGUSR1, dumping record data.");
            avahi_server_dump(avahi_server, dump, NULL);
            break;

        default:
            avahi_log_warn("Got spurious signal, ignoring.");
            break;
    }
}
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;
	}
}
Exemple #6
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.");
}
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.");
}
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;
    }
}