示例#1
0
文件: svc.c 项目: cmatsuoka/finit
/**
 * svc_runlevel - Change to a new runlevel
 * @newlevel: New runlevel to activate
 *
 * Stops all services not in @newlevel and starts, or lets continue to run,
 * those in @newlevel.  Also updates @prevlevel and active @runlevel.
 */
void svc_runlevel (int newlevel)
{
	svc_t *svc;

	if (runlevel == newlevel)
		return;

	if (newlevel > 5 || newlevel < 1)
		return;

	prevlevel = runlevel;
	runlevel = newlevel;

	for (svc = svc_iterator(1); svc; svc = svc_iterator(0)) {
		int run = svc_enabled(svc, 0, NULL);

		if (svc->pid) {
			if (run == SVC_STOP)
				svc_stop(svc);
		} else {
			if (run == SVC_START)
				svc_start(svc);
		}
	}

	if (runlevel == 1)
		touch("/etc/nologin");	/* Disable login in single-user mode */
	else
		remove("/etc/nologin");
}
示例#2
0
文件: svc.c 项目: carriercomm/finit
void svc_monitor(pid_t lost)
{
	svc_t *svc;

	if (was_stopped && !is_norespawn()) {
		was_stopped = 0;
		restart_any_lost_procs();
		return;
	}

	if (fexist(SYNC_SHUTDOWN) || lost <= 1)
		return;

	/* Power user at the console, don't respawn tasks. */
	if (is_norespawn()) {
		was_stopped = 1;
		return;
	}

	if (tty_respawn(lost))
		return;

#ifndef INETD_DISABLED
	if (inetd_respawn(lost))
		return;
#endif

	for (svc = svc_iterator(1); svc; svc = svc_iterator(0)) {
		if (lost != svc->pid)
			continue;

		if (SVC_CMD_SERVICE != svc->type) {
			svc->pid = 0;
			continue;
		}

		_d("Ouch, lost pid %d - %s(%d)", lost, basename(svc->cmd), svc->pid);

		/* No longer running, update books. */
		svc->pid = 0;

		if (sig_stopped()) {
			_e("Stopped, not respawning killed processes.");
			break;
		}

		/* Cleanup any lingering or semi-restarting tasks before respawning */
		_d("Sending SIGTERM to service group %s", basename(svc->cmd));
		procname_kill(basename(svc->cmd), SIGTERM);

		/* Restarting lost service. */
		if (svc_enabled(svc, 0, NULL)) {
			svc->restart_counter++;
			svc_start(svc);
		}

		break;
	}
}
示例#3
0
文件: svc.c 项目: cmatsuoka/finit
int svc_start_by_name(char *name)
{
	svc_t *svc = svc_find(name);

	if (svc && svc_enabled(svc, 0, NULL))
		return svc_start(svc);

	return 1;
}
示例#4
0
文件: svc.c 项目: cmatsuoka/finit
void svc_start_all(void)
{
	svc_t *svc;
	svc_cmd_t cmd;

	for (svc = svc_iterator(1); svc; svc = svc_iterator(0)) {
		cmd = svc_enabled(svc, 0, NULL);
		if (SVC_START == cmd  || (SVC_RELOAD == cmd && svc->pid == 0))
			svc_start(svc);
		else if (SVC_RELOAD == cmd)
			svc_reload(svc);
	}

	_d("Running svc up hooks ...");
	plugin_run_hooks(HOOK_SVC_UP);
}
示例#5
0
文件: svc.c 项目: carriercomm/finit
static void restart_any_lost_procs(void)
{
	svc_t *svc;

	for (svc = svc_iterator(1); svc; svc = svc_iterator(0)) {
		if (svc->pid > 0 && pid_alive(svc->pid))
			continue;

		/* Only restart lost daemons, not task/run/inetd services */
		if (SVC_CMD_SERVICE != svc->type) {
			svc->pid = 0;
			continue;
		}

		svc_start(svc);
	}
}
示例#6
0
文件: svc.c 项目: carriercomm/finit
/**
 * svc_bootstrap - Start bootstrap services and tasks
 *
 * System startup, runlevel S, where only services, tasks and
 * run commands absolutely essential to bootstrap are located.
 */
void svc_bootstrap(void)
{
	svc_t *svc;

	_d("Bootstrapping all services in runlevel S from %s", FINIT_CONF);
	for (svc = svc_iterator(1); svc; svc = svc_iterator(0)) {
		svc_cmd_t cmd;

		/* Inetd services cannot be part of bootstrap currently. */
		if (svc->type == SVC_CMD_INETD)
			continue;

		cmd = svc_enabled(svc, 0, NULL);
		if (SVC_START == cmd  || (SVC_RELOAD == cmd))
			svc_start(svc);
	}
}
示例#7
0
文件: svc.c 项目: cmatsuoka/finit
void svc_monitor(void)
{
	pid_t lost;
	svc_t *svc;

	lost = waitpid(-1, NULL, WNOHANG);
	if (lost < 1)
		return;

	if (fexist(SYNC_SHUTDOWN) || lost <= 1)
		return;

	/* Power user at the console, don't respawn tasks. */
	if (is_norespawn())
		return;

	for (svc = svc_iterator(1); svc; svc = svc_iterator(0)) {
		char *name = basename(svc->cmd);

		if (lost != svc->pid)
			continue;

		_d("Ouch, lost pid %d - %s(%d)", lost, name, svc->pid);

		/* No longer running, update books. */
		svc->pid = 0;

		if (sig_stopped()) {
			_e("Stopped, not respawning killed processes.");
			break;
		}

		/* Cleanup any lingering or semi-restarting tasks before respawning */
		_d("Sending SIGTERM to service group %s", name);
		procname_kill(name, SIGTERM);

		/* Restarting lost service. */
		if (svc_enabled(svc, 0, NULL)) {
			svc->stat_restart_counter++;
			svc_start(svc);
		}

		break;
	}
}
示例#8
0
文件: main.c 项目: Sunshine-OS/runit
int
svc_transition_if_necessary(int *kq, struct kevent *ke, Service *svc)
{
	// if Svc Wants To Be Online
	// and State is inactive, startpre, start
	// then (either advance to startpre or, if startpre has exited, advance
	// to start. If start and type=simple, and PID runs, -> online. If
	// type = forking AND pidfile found, -> online. If MainPIDExited, kill
	if(svc->PIDsPurged)
	{
		if(svc->Want == S_ONLINE && (svc->State == S_INACTIVE ||
		                             svc->State == S_EXITED || svc->State == S_STOP_POST))
		{
			if(svc->State == S_EXITED) /* not doing poststop */
				return svc_stop_post(kq, ke, svc);
			else if((svc->State == S_STOP_POST && svc->MainPIDExited) ||
			        svc->State == S_INACTIVE)
				return svc_start_pre(kq, ke, svc);
		}
		if(svc->Want == S_ONLINE && svc->State == S_START_PRE)
		{
			// check timeout ?
			// check if ExecStartPre exited cleanly too
			if (svc->MainPIDExited)
				return svc_start(kq, ke, svc);
		}
	}
	if ((! svc->PIDFileRead) && svc->PIDFile && svc->State == S_START)
	{
		int res =check_pidfile(svc);
		if(svc->MainPID && !res)
		{
			dbg("entering state S_ONLINE\n");
			//svc->
			svc->State =S_ONLINE;
			svc->AuxWant =S_START_POST;
			return 0;
		}
	}
	if ((svc->State == S_START || svc->State == S_ONLINE) &&
	        svc->PIDsPurged == 1 && svc->Type != T_ONESHOT)
	{
		// IF CLEAN
		dbg("entering state S_EXITED\n");
		svc->State =S_EXITED;
		svc->DoubleTransition =1;
		if (svc->PIDFile)
			remove(svc->PIDFile);
		svc->MainPID =0;
		// IF DODGY
		// Set a 'failed' flag, and when we finish off the S_STOP_POST lark,
		// enter S_FAILED
		return 0;
	}
	if(svc->Type == T_ONESHOT)
	{
		if (svc->State == S_START)
		{
			svc_start_post_oneshot(kq, ke, svc);
		}
		else if (svc->State == S_START_POST)/* oneshot still executing at last pass */
		{
			// Check if exit status was 0 before doing this
			dbg ("entering state S_ONLINE\n");
			svc->State =S_ONLINE;
			return 0;
		}
	}
	if (svc->AuxWant == S_START_POST)
	{
		svc_start_post(kq, ke, svc);
	}
	return 0;
}
示例#9
0
文件: rpcapd.c 项目: ExtraHop/rpcapd
//! Program main
int main(int argc, char *argv[], char *envp[])
{
char savefile[MAX_LINE + 1];		// name of the file on which we have to save the configuration
int isdaemon= 0;					// Not null if the user wants to run this program as a daemon
int retval;							// keeps the returning value from several functions
char errbuf[PCAP_ERRBUF_SIZE + 1];	// keeps the error string, prior to be printed
int k;


	savefile[0]= 0;
	loadfile[0]= 0;
	hostlist[0]= 0;

	// Initialize errbuf
	memset(errbuf, 0, sizeof(errbuf) );

	if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1)
	{
		log_warn("%s", errbuf);
		exit(-1);
	}

	strncpy(address, RPCAP_DEFAULT_NETADDR, MAX_LINE);
	strncpy(port, RPCAP_DEFAULT_NETPORT, MAX_LINE);

	// Prepare to open a new server socket
	memset(&mainhints, 0, sizeof(struct addrinfo));

	mainhints.ai_family = PF_UNSPEC;
	mainhints.ai_flags = AI_PASSIVE;	// Ready to a bind() socket
	mainhints.ai_socktype = SOCK_STREAM;

	// Getting the proper command line options
	while ((retval = getopt(argc, argv, "b:dhp:4l:na:s:f:vyz:u:gc:e:m:k:t:SLi:")) != -1)
	{
		switch (retval)
		{
			case 'b':
				strncpy(address, optarg, MAX_LINE);
				break;
			case 'p':
				strncpy(port, optarg, MAX_LINE);
				break;
			case '4':
				mainhints.ai_family = PF_INET;		// IPv4 server only
				break;
			case 'd':
				isdaemon= 1;
				break;
			case 'n':
				nullAuthAllowed= 1;
				break;
			case 'v':
				passivemode= 0;
				break;
			case 'l':
			{
				strncpy(hostlist, optarg, sizeof(hostlist) );
				break;
			}
			case 'a':
			{
			char *tmpaddress, *tmpport;
			int i= 0;

				tmpaddress= strtok(optarg, RPCAP_HOSTLIST_SEP);

				while ( (tmpaddress != NULL) && (i < MAX_ACTIVE_LIST) )
				{
					tmpport= strtok(NULL, RPCAP_HOSTLIST_SEP);

					snprintf(activelist[i].address, MAX_LINE, "%s", tmpaddress);
					
					if ( (tmpport == NULL) || (strcmp(tmpport, "DEFAULT") == 0) ) // the user choose a custom port
						snprintf(activelist[i].port, MAX_LINE, RPCAP_DEFAULT_NETPORT_ACTIVE);
					else
						snprintf(activelist[i].port, MAX_LINE, "%s", tmpport);

					tmpaddress = strtok(NULL, RPCAP_HOSTLIST_SEP);

					i++;
				}
				
				if (i > MAX_ACTIVE_LIST)
					log_warn("Only MAX_ACTIVE_LIST active connections are currently supported.");

				// I don't initialize the remaining part of the structure, since
				// it is already zeroed (it is a global var)
				break;
			}
			case 'f':
				strncpy(loadfile, optarg, MAX_LINE);
				break;
			case 's':
				strncpy(savefile, optarg, MAX_LINE);
				break;
			case 'm':
			    rpcapd_opt.ringbuf_max_pkt_data = atoi(optarg) * 1000 * 1000;
				if (rpcapd_opt.ringbuf_max_pkt_data <= 0) {
					log_warn("ignoring invalid ringbuf memory size");
				}
			    break;
			case 'k':
			    k = atoi(optarg);
			    if (k <= 0) {
			        log_warn("ignoring invalid ringbuf pkt count");
			        break;
			    }
			    rpcapd_opt.ringbuf_max_pkts = 1;
			    while (rpcapd_opt.ringbuf_max_pkts < k) {
			        rpcapd_opt.ringbuf_max_pkts <<= 1;
			    }
			    break;
            case 'y':
                rpcapd_opt.no_udp = 1;
                log_warn("DRY RUN - NO UDP WILL BE SENT");
                break;
            case 'z':
                rpcapd_opt.pcap_buffer_size = atoi(optarg);
                break;
			case 'u':
			    rpcapd_opt.udp_sndbuf_size = atoi(optarg);
			    if (rpcapd_opt.udp_sndbuf_size <= 0) {
					log_warn("ignoring invalid udp sndbuf size");
			    }
			    break;
            case 'g':
                rpcapd_opt.blocking_udp_socket = 1;
                break;
            case 'c':
                if (strcmp("single", optarg) == 0) {
                    rpcapd_opt.single_threaded = 1;
                    break;
                }
                if (sscanf(optarg, "%d,%d", &rpcapd_opt.cpu_affinity_pcap,
                           &rpcapd_opt.cpu_affinity_udp) < 2) {
                    rpcapd_opt.single_threaded = 1;
                }
                else {
                    rpcapd_opt.single_threaded = 0;
                }
                break;
            case 'e':
                sscanf(optarg, "%d,%d", &rpcapd_opt.nice_pcap,
                       &rpcapd_opt.nice_udp);
                break;
            case 't':
                rpcapd_opt.udp_mtu = atoi(optarg);
                if (rpcapd_opt.udp_mtu > 65000) {
                    rpcapd_opt.udp_mtu = 65000;
                }
                break;
            case 'S':
                rpcapd_opt.print_stats = 1;
                break;
            case 'L':
                rpcapd_opt.use_syslog = 1;
                break;
            case 'i':
                if (strlen(optarg) >= sizeof(rpcapd_opt.preselected_ifname)) {
                    log_warn("-i option too long");
                    break;
                }
                strncpy(rpcapd_opt.preselected_ifname, optarg,
                        sizeof(rpcapd_opt.preselected_ifname));
                break;
			case 'h':
				printusage();
				exit(0);
			default:
				break;
		}
	}

	if (rpcapd_opt.use_syslog) {
	    rpcapd_log_init(argv[0], !isdaemon);
	}

	if (savefile[0])
	{
		if (fileconf_save(savefile) )
			log_warn("Error when saving the configuration to file");
	}

	// If the file does not exist, it keeps the settings provided by the command line
	if (loadfile[0])
		fileconf_read(0);

#ifdef linux
	// SIGTERM (i.e. kill -15) is not generated in WIN32, although it is included for ANSI compatibility
	signal(SIGTERM, main_cleanup);
	signal(SIGCHLD, main_cleanup_childs);
#endif

	// forking a daemon, if it is needed
	if (isdaemon)
	{
	#ifndef WIN32
	int pid;

		// Unix Network Programming, pg 336
		if ( (pid = fork() ) != 0)
			exit(0);		// Parent terminates

		// First child continues
		// Set daemon mode
		setsid();
		
		// generated under unix with 'kill -HUP', needed to reload the configuration
		signal(SIGHUP, fileconf_read);

		if ( (pid = fork() ) != 0)
			exit(0);		// First child terminates

		// LINUX WARNING: the current linux implementation of pthreads requires a management thread
		// to handle some hidden stuff. So, as soon as you create the first thread, two threads are
		// created. Fom this point on, the number of threads active are always one more compared
		// to the number you're expecting

		// Second child continues
//		umask(0);
//		chdir("/");
	#else
		// We use the SIGABRT signal to kill the Win32 service
		signal(SIGABRT, main_cleanup);

		// If this call succeeds, it is blocking on Win32
		if ( svc_start() != 1)
			log_warn("Unable to start the service");

		// When the previous call returns, the entire application has to be stopped.
		exit(0);
	#endif
	}
	else	// Console mode
	{
		// Enable the catching of Ctrl+C
		signal(SIGINT, main_cleanup);

#ifndef WIN32
		// generated under unix with 'kill -HUP', needed to reload the configuration
		// We do not have this kind of signal in Win32
		signal(SIGHUP, fileconf_read);
#endif

		printf("Press CTRL + C to stop the server...\n");
	}

	// If we're a Win32 service, we have already called this function in the service_main
	main_startup();

	// The code should never arrive here (since the main_startup is blocking)
	//  however this avoids a compiler warning
	exit(0);
}
示例#10
0
//! Program main
int main(int argc, char *argv[], char *envp[])
{
	char savefile[MAX_LINE + 1];		// name of the file on which we have to save the configuration
	int isdaemon = 0;			// Not null if the user wants to run this program as a daemon
	int retval;				// keeps the returning value from several functions
	char errbuf[PCAP_ERRBUF_SIZE + 1];	// keeps the error string, prior to be printed

	savefile[0] = 0;
	loadfile[0] = 0;
	hostlist[0] = 0;

	// Initialize errbuf
	memset(errbuf, 0, sizeof(errbuf));

	if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1)
	{
		SOCK_ASSERT(errbuf, 1);
		exit(-1);
	}

	strncpy(address, RPCAP_DEFAULT_NETADDR, MAX_LINE);
	strncpy(port, RPCAP_DEFAULT_NETPORT, MAX_LINE);

	// Prepare to open a new server socket
	memset(&mainhints, 0, sizeof(struct addrinfo));

	mainhints.ai_family = PF_UNSPEC;
	mainhints.ai_flags = AI_PASSIVE;	// Ready to a bind() socket
	mainhints.ai_socktype = SOCK_STREAM;

	// Getting the proper command line options
	while ((retval = getopt(argc, argv, "b:dhp:4l:na:s:f:v")) != -1)
	{
		switch (retval)
		{
			case 'b':
				strncpy(address, optarg, MAX_LINE);
				break;
			case 'p':
				strncpy(port, optarg, MAX_LINE);
				break;
			case '4':
				mainhints.ai_family = PF_INET;		// IPv4 server only
				break;
			case 'd':
				isdaemon = 1;
				break;
			case 'n':
				nullAuthAllowed = 1;
				break;
			case 'v':
				passivemode = 0;
				break;
			case 'l':
			{
				strncpy(hostlist, optarg, sizeof(hostlist));
				break;
			}
			case 'a':
			{
				char *tmpaddress, *tmpport;
				char *lasts;
				int i = 0;

				tmpaddress = pcap_strtok_r(optarg, RPCAP_HOSTLIST_SEP, &lasts);

				while ((tmpaddress != NULL) && (i < MAX_ACTIVE_LIST))
				{
					tmpport = pcap_strtok_r(NULL, RPCAP_HOSTLIST_SEP, &lasts);

					strlcpy(activelist[i].address, tmpaddress, MAX_LINE);
					
					if ((tmpport == NULL) || (strcmp(tmpport, "DEFAULT") == 0)) // the user choose a custom port
						strlcpy(activelist[i].port, RPCAP_DEFAULT_NETPORT_ACTIVE, MAX_LINE);
					else
						strlcpy(activelist[i].port, tmpport, MAX_LINE);

					tmpaddress = pcap_strtok_r(NULL, RPCAP_HOSTLIST_SEP, &lasts);

					i++;
				}
				
				if (i > MAX_ACTIVE_LIST)
					SOCK_ASSERT("Only MAX_ACTIVE_LIST active connections are currently supported.", 1);

				// I don't initialize the remaining part of the structure, since
				// it is already zeroed (it is a global var)
				break;
			}
			case 'f':
				strlcpy(loadfile, optarg, MAX_LINE);
				break;
			case 's':
				strlcpy(savefile, optarg, MAX_LINE);
				break;
			case 'h':
				printusage();
				exit(0);
			default:
				break;
		}
	}

	if (savefile[0])
	{
		if (fileconf_save(savefile))
			SOCK_ASSERT("Error when saving the configuration to file", 1);
	}

	// If the file does not exist, it keeps the settings provided by the command line
	if (loadfile[0])
		fileconf_read(0);

#ifndef _WIN32
	// SIGTERM (i.e. kill -15) is not generated in Win32, although it is included for ANSI compatibility
	signal(SIGTERM, main_cleanup);
	signal(SIGCHLD, main_cleanup_childs);
#endif

	// forking a daemon, if it is needed
	if (isdaemon)
	{
#ifndef _WIN32
		int pid;

		// Unix Network Programming, pg 336
		if ((pid = fork()) != 0)
			exit(0);		// Parent terminates

		// First child continues
		// Set daemon mode
		setsid();
		
		// generated under unix with 'kill -HUP', needed to reload the configuration
		signal(SIGHUP, fileconf_read);

		if ((pid = fork()) != 0)
			exit(0);		// First child terminates

		// LINUX WARNING: the current linux implementation of pthreads requires a management thread
		// to handle some hidden stuff. So, as soon as you create the first thread, two threads are
		// created. Fom this point on, the number of threads active are always one more compared
		// to the number you're expecting

		// Second child continues
//		umask(0);
//		chdir("/");
#else
		// We use the SIGABRT signal to kill the Win32 service
		signal(SIGABRT, main_cleanup);

		// If this call succeeds, it is blocking on Win32
		if (svc_start() != 1)
			SOCK_ASSERT("Unable to start the service", 1);

		// When the previous call returns, the entire application has to be stopped.
		exit(0);
#endif
	}
	else	// Console mode
	{
		// Enable the catching of Ctrl+C
		signal(SIGINT, main_cleanup);

#ifndef _WIN32
		// generated under unix with 'kill -HUP', needed to reload the configuration
		// We do not have this kind of signal in Win32
		signal(SIGHUP, fileconf_read);
#endif

		printf("Press CTRL + C to stop the server...\n");
	}

	// If we're a Win32 service, we have already called this function in the service_main
	main_startup();

	// The code should never arrive here (since the main_startup is blocking)
	//  however this avoids a compiler warning
	exit(0);
}
示例#11
0
文件: svc.c 项目: carriercomm/finit
/**
 * svc_runlevel - Change to a new runlevel
 * @newlevel: New runlevel to activate
 *
 * Stops all services not in @newlevel and starts, or lets continue to run,
 * those in @newlevel.  Also updates @prevlevel and active @runlevel.
 */
void svc_runlevel(int newlevel)
{
	svc_t *svc;

	if (runlevel == newlevel)
		return;

	if (newlevel < 0 || newlevel > 9)
		return;

	prevlevel = runlevel;
	runlevel  = newlevel;
	utmp_save(prevlevel, newlevel);

	_d("Setting new runlevel --> %d <-- previous %d", runlevel, prevlevel);

	for (svc = svc_iterator(1); svc; svc = svc_iterator(0)) {
		svc_cmd_t cmd;

		/* Inetd services have slightly different semantics */
#ifndef INETD_DISABLED
		if (svc->type == SVC_CMD_INETD) {
			if (!ISSET(svc->runlevels, runlevel))
				inetd_stop(&svc->inetd);
			else
				inetd_start(&svc->inetd);

			continue;
		}
#endif

		/* All other services consult their callback here */
		cmd = svc_enabled(svc, 0, NULL);
		if (svc->pid) {
			if (cmd == SVC_STOP)
				svc_stop(svc);
			else if (cmd == SVC_RELOAD)
				svc_reload(svc);
		} else {
			if (cmd == SVC_START)
				svc_start(svc);
		}
	}

	if (0 == runlevel) {
		do_shutdown(SIGUSR2);
		return;
	}
	if (6 == runlevel) {
		do_shutdown(SIGUSR1);
		return;
	}

	if (runlevel == 1)
		touch("/etc/nologin");	/* Disable login in single-user mode */
	else
		erase("/etc/nologin");

	if (0 != prevlevel)
		tty_runlevel(runlevel);
}