Exemple #1
0
int
main(int argc, char *argv[])
{
	struct pidfh *pfh = NULL;
	int ch, nochdir, noclose, errcode;
	const char *pidfile, *user;
	pid_t otherpid;

	nochdir = noclose = 1;
	pidfile = user = NULL;
	while ((ch = getopt(argc, argv, "-cfp:u:")) != -1) {
		switch (ch) {
		case 'c':
			nochdir = 0;
			break;
		case 'f':
			noclose = 0;
			break;
		case 'p':
			pidfile = optarg;
			break;
		case 'u':
			user = optarg;
			break;
		default:
			usage();
		}
	}
	argc -= optind;
	argv += optind;

	if (argc == 0)
		usage();

	if (user != NULL)
		restrict_process(user);

	/*
	 * Try to open the pidfile before calling daemon(3),
	 * to be able to report the error intelligently
	 */
	if (pidfile) {
		pfh = pidfile_open(pidfile, 0600, &otherpid);
		if (pfh == NULL) {
			if (errno == EEXIST) {
				errx(3, "process already running, pid: %d",
				    otherpid);
			}
			err(2, "pidfile ``%s''", pidfile);
		}
	}

	if (daemon(nochdir, noclose) == -1)
		err(1, NULL);

	/* Now that we are the child, write out the pid */
	if (pidfile)
		pidfile_write(pfh);

	execvp(argv[0], argv);

	/*
	 * execvp() failed -- unlink pidfile if any, and
	 * report the error
	 */
	errcode = errno; /* Preserve errcode -- unlink may reset it */
	if (pidfile)
		pidfile_remove(pfh);

	/* The child is now running, so the exit status doesn't matter. */
	errc(1, errcode, "%s", argv[0]);
}
Exemple #2
0
void
tap_init(void)
{
	channel_t *chan;
	struct ifreq ifr;
	int fd, s;
	char pidfile[PATH_MAX];

	fd = open(interface_name, O_RDWR);
	if (fd == -1) {
		log_err("Could not open \"%s\": %m", interface_name);
		exit(EXIT_FAILURE);
	}

	memset(&ifr, 0, sizeof(ifr));
	if (ioctl(fd, TAPGIFNAME, &ifr) == -1) {
		log_err("Could not get interface name: %m");
		exit(EXIT_FAILURE);
	}

	s = socket(AF_INET, SOCK_DGRAM, 0);
	if (s == -1) {
		log_err("Could not open PF_LINK socket: %m");
		exit(EXIT_FAILURE);
	}

	ifr.ifr_addr.sa_family = AF_LINK;
	ifr.ifr_addr.sa_len = ETHER_ADDR_LEN;
	b2eaddr(ifr.ifr_addr.sa_data, &local_bdaddr);

	if (ioctl(s, SIOCSIFLLADDR, &ifr) == -1) {
		log_err("Could not set %s physical address: %m", ifr.ifr_name);
		exit(EXIT_FAILURE);
	}

	if (ioctl(s, SIOCGIFFLAGS, &ifr) == -1) {
		log_err("Could not get interface flags: %m");
		exit(EXIT_FAILURE);
	}

	if ((ifr.ifr_flags & IFF_UP) == 0) {
		ifr.ifr_flags |= IFF_UP;

		if (ioctl(s, SIOCSIFFLAGS, &ifr) == -1) {
			log_err("Could not set IFF_UP: %m");
			exit(EXIT_FAILURE);
		}
	}

	close(s);

	log_info("Using interface %s with addr %s", ifr.ifr_name,
		ether_ntoa((struct ether_addr *)&ifr.ifr_addr.sa_data));

	chan = channel_alloc();
	if (chan == NULL)
		exit(EXIT_FAILURE);

	chan->send = tap_send;
	chan->recv = tap_recv;
	chan->mru = ETHER_HDR_LEN + ETHER_MAX_LEN;
	memcpy(chan->raddr, ifr.ifr_addr.sa_data, ETHER_ADDR_LEN);
	memcpy(chan->laddr, ifr.ifr_addr.sa_data, ETHER_ADDR_LEN);
	chan->state = CHANNEL_OPEN;
	if (!channel_open(chan, fd))
		exit(EXIT_FAILURE);

	snprintf(pidfile, sizeof(pidfile), "%s/%s.pid",
		_PATH_VARRUN, ifr.ifr_name);
	chan->pfh = pidfile_open(pidfile, 0600, NULL);
	if (chan->pfh == NULL)
		log_err("can't create pidfile");
	else if (pidfile_write(chan->pfh) < 0) {
		log_err("can't write pidfile");
		pidfile_remove(chan->pfh);
		chan->pfh = NULL;
	}
}
Exemple #3
0
int main(int argc, char const* argv[])
{
    ir::IRXDaemon* instance;
    OperationEnum operation;
    ModeEnum mode;
    struct pidfh* pfh;
    pid_t pid;
    bool daemonize;
    int i;
    int result(EXIT_SUCCESS);
    
    if ((instance = ir::IRXDaemon::_new()) != NULL) {
        operation = OPERATION_UNKNOWN;
        mode = MODE_UNKNOWN;
        if (argc > 1) {
            if ((result = instance->usage(argc, argv)) == EXIT_SUCCESS) {
                for (i = 1; i < argc; ++i) {
                    if (strcmp(argv[i], "start") == 0) {
                        operation = OPERATION_START;
                    }
                    else if (strcmp(argv[i], "restart") == 0) {
                        operation = OPERATION_RESTART;
                    }
                    else if (strcmp(argv[i], "stop") == 0) {
                        operation = OPERATION_STOP;
                    }
                    else if (strcmp(argv[i], "--daemon") == 0) {
                        mode = MODE_DAEMON;
                    }
                    else if (strcmp(argv[i], "--application") == 0) {
                        mode = MODE_APPLICATION;
                    }
                }
            }
        }
        if (result == EXIT_SUCCESS) {
            if (operation == OPERATION_UNKNOWN) {
                operation = OPERATION_START;
            }
            if (mode == MODE_UNKNOWN) {
                mode = MODE_DAEMON;
            }
            g_quit = false;
            signal(SIGHUP, onSigHUP);
            signal(SIGINT, onSigINT);
            signal(SIGTERM, onSigTERM);
            signal(SIGCHLD, SIG_IGN);
            switch (operation) {
                case OPERATION_RESTART:
                case OPERATION_STOP:
                    if ((pfh = pidfile_open(NULL, 0600, &pid)) != NULL) {
                        instance->log(LOG_NOTICE, "already stopped");
                        pidfile_remove(pfh);
                    }
                    else {
                        switch (errno) {
                            case EEXIST:
                                if (kill(pid, SIGTERM) == 0) {
                                    instance->log(LOG_NOTICE, "stopping pid = %d...", pid);
                                    while (true) {
                                        if (g_quit) {
                                            result = EXIT_FAILURE;
                                            break;
                                        }
                                        if (kill(pid, 0) != 0) {
                                            instance->log(LOG_NOTICE, "stopping done");
                                            break;
                                        }
                                        sleep(1);
                                    }
                                }
                                else {
                                    instance->log(LOG_ERR, "can't stop pid = %d [%m]", pid);
                                    result = EX_OSERR;
                                }
                                break;
                            case EACCES:
                                instance->log(LOG_ERR, "run as super user");
                                result = EX_OSERR;
                                break;
                            default:
                                instance->log(LOG_ERR, "can't stop [%m]");
                                result = EX_OSERR;
                                break;
                        }
                    }
                    break;
                default:
                    // nop
                    break;
            }
            if (result == EXIT_SUCCESS) {
                switch (operation) {
                    case OPERATION_START:
                    case OPERATION_RESTART:
                        if ((pfh = pidfile_open(NULL, 0600, &pid)) != NULL) {
                            instance->log(LOG_NOTICE, "starting pid = %d...", getpid());
                            daemonize = true;
                            if (mode == MODE_APPLICATION) {
                                daemonize = false;
                            }
                            #ifdef __APPLE__
                            if (getppid() == 1) {
                                daemonize = false;
                            }
                            #endif
                            if (daemonize) {
                                if (daemon(0, 0) != 0) {
                                    instance->log(LOG_ERR, "can't daemonize pid = %d [%m]", getpid());
                                    result = EX_OSERR;
                                }
                            }
                            if (result == EXIT_SUCCESS) {
                                instance->log(LOG_NOTICE, "changing pid = %d...", getpid());
                                pidfile_write(pfh);
                                if ((result = instance->initialize()) == EXIT_SUCCESS) {
                                    instance->log(LOG_NOTICE, "starting done");
                                    while (true) {
                                        if (g_quit) {
                                            result = EXIT_FAILURE;
                                            break;
                                        }
                                        instance->loop();
                                    }
                                }
                                else {
                                    instance->log(LOG_ERR, "can't start pid = %d [%d]", getpid(), result);
                                }
                                instance->terminate();
                            }
                            pidfile_remove(pfh);
                        }
                        else {
                            switch (errno) {
                                case EEXIST:
                                    instance->log(LOG_ERR, "already started pid = %d", pid);
                                    result = EX_OSERR;
                                    break;
                                case EACCES:
                                    instance->log(LOG_ERR, "run as super user");
                                    result = EX_OSERR;
                                    break;
                                default:
                                    instance->log(LOG_ERR, "can't start [%m]");
                                    result = EX_OSERR;
                                    break;
                            }
                        }
                        break;
                    default:
                        // nop
                        break;
                }
            }
        }
        ir::IRXDaemon::_delete(instance);
    }
    else {
        result = EXIT_FAILURE;
    }
    return result;
}
Exemple #4
0
int
main(int argc, char *argv[])
{
	struct pidfh  *ppfh, *pfh;
	sigset_t mask, oldmask;
	int ch, nochdir, noclose, restart, serrno;
	const char *pidfile, *ppidfile,  *user;
	pid_t otherpid, pid;

	nochdir = noclose = 1;
	restart = 0;
	ppidfile = pidfile = user = NULL;
	while ((ch = getopt(argc, argv, "cfp:P:ru:")) != -1) {
		switch (ch) {
		case 'c':
			nochdir = 0;
			break;
		case 'f':
			noclose = 0;
			break;
		case 'p':
			pidfile = optarg;
			break;
		case 'P':
			ppidfile = optarg;
			break;
		case 'r':
			restart = 1;
			break;
		case 'u':
			user = optarg;
			break;
		default:
			usage();
		}
	}
	argc -= optind;
	argv += optind;

	if (argc == 0)
		usage();

	ppfh = pfh = NULL;
	/*
	 * Try to open the pidfile before calling daemon(3),
	 * to be able to report the error intelligently
	 */
	if (pidfile != NULL) {
		pfh = pidfile_open(pidfile, 0600, &otherpid);
		if (pfh == NULL) {
			if (errno == EEXIST) {
				errx(3, "process already running, pid: %d",
				    otherpid);
			}
			err(2, "pidfile ``%s''", pidfile);
		}
	}
	/* Do the same for actual daemon process. */
	if (ppidfile != NULL) {
		ppfh = pidfile_open(ppidfile, 0600, &otherpid);
		if (ppfh == NULL) {
			serrno = errno;
			pidfile_remove(pfh);
			errno = serrno;
			if (errno == EEXIST) {
				errx(3, "process already running, pid: %d",
				     otherpid);
			}
			err(2, "ppidfile ``%s''", ppidfile);
		}
	}

	if (daemon(nochdir, noclose) == -1) {
		warn("daemon");
		goto exit;
	}
	/* Write out parent pidfile if needed. */
	pidfile_write(ppfh);

	/*
	 * If the pidfile or restart option is specified the daemon
	 * executes the command in a forked process and wait on child
	 * exit to remove the pidfile or restart the command. Normally
	 * we don't want the monitoring daemon to be terminated
	 * leaving the running process and the stale pidfile, so we
	 * catch SIGTERM and forward it to the children expecting to
	 * get SIGCHLD eventually.
	 */
	pid = -1;
	if (pidfile != NULL || restart) {
		/*
		 * Restore default action for SIGTERM in case the
		 * parent process decided to ignore it.
		 */
		if (signal(SIGTERM, SIG_DFL) == SIG_ERR) {
			warn("signal");
			goto exit;
		}
		/*
		 * Because SIGCHLD is ignored by default, setup dummy handler
		 * for it, so we can mask it.
		 */
		if (signal(SIGCHLD, dummy_sighandler) == SIG_ERR) {
			warn("signal");
			goto exit;
		}
		/*
		 * Block interesting signals.
		 */
		sigemptyset(&mask);
		sigaddset(&mask, SIGTERM);
		sigaddset(&mask, SIGCHLD);
		if (sigprocmask(SIG_SETMASK, &mask, &oldmask) == -1) {
			warn("sigprocmask");
			goto exit;
		}
		/*
		 * Try to protect against pageout kill. Ignore the
		 * error, madvise(2) will fail only if a process does
		 * not have superuser privileges.
		 */
		(void)madvise(NULL, 0, MADV_PROTECT);
restart:
		/*
		 * Spawn a child to exec the command, so in the parent
		 * we could wait for it to exit and remove pidfile.
		 */
		pid = fork();
		if (pid == -1) {
			warn("fork");
			goto exit;
		}
	}
	if (pid <= 0) {
		if (pid == 0) {
			/* Restore old sigmask in the child. */
			if (sigprocmask(SIG_SETMASK, &oldmask, NULL) == -1)
				err(1, "sigprocmask");
		}
		/* Now that we are the child, write out the pid. */
		pidfile_write(pfh);

		if (user != NULL)
			restrict_process(user);

		execvp(argv[0], argv);

		/*
		 * execvp() failed -- report the error. The child is
		 * now running, so the exit status doesn't matter.
		 */
		err(1, "%s", argv[0]);
	}

	setproctitle("%s[%d]", argv[0], pid);
	if (wait_child(pid, &mask) == 0 && restart) {
		sleep(1);
		goto restart;
	}
exit:
	pidfile_remove(pfh);
	pidfile_remove(ppfh);
	exit(1); /* If daemon(3) succeeded exit status does not matter. */
}
Exemple #5
0
int
main(int argc, char * argv[])
{
	struct timeval timeout;
	fd_set fdset;
	int nfds;
	struct pidfh *pfh = NULL;
	const char *pidfile = NULL;
	int freq, curfreq, initfreq, *freqs, i, j, *mwatts, numfreqs, load;
	int minfreq = -1, maxfreq = -1;
	int ch, mode, mode_ac, mode_battery, mode_none, idle, to;
	uint64_t mjoules_used;
	size_t len;

	/* Default mode for all AC states is adaptive. */
	mode_ac = mode_none = MODE_HIADAPTIVE;
	mode_battery = MODE_ADAPTIVE;
	cpu_running_mark = DEFAULT_ACTIVE_PERCENT;
	cpu_idle_mark = DEFAULT_IDLE_PERCENT;
	poll_ival = DEFAULT_POLL_INTERVAL;
	mjoules_used = 0;
	vflag = 0;

	/* User must be root to control frequencies. */
	if (geteuid() != 0)
		errx(1, "must be root to run");

	while ((ch = getopt(argc, argv, "a:b:i:m:M:n:p:P:r:v")) != -1)
		switch (ch) {
		case 'a':
			parse_mode(optarg, &mode_ac, ch);
			break;
		case 'b':
			parse_mode(optarg, &mode_battery, ch);
			break;
		case 'i':
			cpu_idle_mark = atoi(optarg);
			if (cpu_idle_mark < 0 || cpu_idle_mark > 100) {
				warnx("%d is not a valid percent",
				    cpu_idle_mark);
				usage();
			}
			break;
		case 'm':
			minfreq = atoi(optarg);
			if (minfreq < 0) {
				warnx("%d is not a valid CPU frequency",
				    minfreq);
				usage();
			}
			break;
		case 'M':
			maxfreq = atoi(optarg);
			if (maxfreq < 0) {
				warnx("%d is not a valid CPU frequency",
				    maxfreq);
				usage();
			}
			break;
		case 'n':
			parse_mode(optarg, &mode_none, ch);
			break;
		case 'p':
			poll_ival = atoi(optarg);
			if (poll_ival < 5) {
				warnx("poll interval is in units of ms");
				usage();
			}
			break;
		case 'P':
			pidfile = optarg;
			break;
		case 'r':
			cpu_running_mark = atoi(optarg);
			if (cpu_running_mark <= 0 || cpu_running_mark > 100) {
				warnx("%d is not a valid percent",
				    cpu_running_mark);
				usage();
			}
			break;
		case 'v':
			vflag = 1;
			break;
		default:
			usage();
		}

	mode = mode_none;

	/* Poll interval is in units of ms. */
	poll_ival *= 1000;

	/* Look up various sysctl MIBs. */
	len = 2;
	if (sysctlnametomib("kern.cp_times", cp_times_mib, &len))
		err(1, "lookup kern.cp_times");
	len = 4;
	if (sysctlnametomib("dev.cpu.0.freq", freq_mib, &len))
		err(EX_UNAVAILABLE, "no cpufreq(4) support -- aborting");
	len = 4;
	if (sysctlnametomib("dev.cpu.0.freq_levels", levels_mib, &len))
		err(1, "lookup freq_levels");

	/* Check if we can read the load and supported freqs. */
	if (read_usage_times(NULL))
		err(1, "read_usage_times");
	if (read_freqs(&numfreqs, &freqs, &mwatts, minfreq, maxfreq))
		err(1, "error reading supported CPU frequencies");
	if (numfreqs == 0)
		errx(1, "no CPU frequencies in user-specified range");

	/* Run in the background unless in verbose mode. */
	if (!vflag) {
		pid_t otherpid;

		pfh = pidfile_open(pidfile, 0600, &otherpid);
		if (pfh == NULL) {
			if (errno == EEXIST) {
				errx(1, "powerd already running, pid: %d",
				    otherpid);
			}
			warn("cannot open pid file");
		}
		if (daemon(0, 0) != 0) {
			warn("cannot enter daemon mode, exiting");
			pidfile_remove(pfh);
			exit(EXIT_FAILURE);

		}
		pidfile_write(pfh);
	}

	/* Decide whether to use ACPI or APM to read the AC line status. */
	acline_init();

	/*
	 * Exit cleanly on signals.
	 */
	signal(SIGINT, handle_sigs);
	signal(SIGTERM, handle_sigs);

	freq = initfreq = curfreq = get_freq();
	i = get_freq_id(curfreq, freqs, numfreqs);
	if (freq < 1)
		freq = 1;

	/*
	 * If we are in adaptive mode and the current frequency is outside the
	 * user-defined range, adjust it to be within the user-defined range.
	 */
	acline_read();
	if (acline_status > SRC_UNKNOWN)
		errx(1, "invalid AC line status %d", acline_status);
	if ((acline_status == SRC_AC &&
	    (mode_ac == MODE_ADAPTIVE || mode_ac == MODE_HIADAPTIVE)) ||
	    (acline_status == SRC_BATTERY &&
	    (mode_battery == MODE_ADAPTIVE || mode_battery == MODE_HIADAPTIVE)) ||
	    (acline_status == SRC_UNKNOWN &&
	    (mode_none == MODE_ADAPTIVE || mode_none == MODE_HIADAPTIVE))) {
		/* Read the current frequency. */
		len = sizeof(curfreq);
		if (sysctl(freq_mib, 4, &curfreq, &len, NULL, 0) != 0) {
			if (vflag)
				warn("error reading current CPU frequency");
		}
		if (curfreq < freqs[numfreqs - 1]) {
			if (vflag) {
				printf("CPU frequency is below user-defined "
				    "minimum; changing frequency to %d "
				    "MHz\n", freqs[numfreqs - 1]);
			}
			if (set_freq(freqs[numfreqs - 1]) != 0) {
				warn("error setting CPU freq %d",
				    freqs[numfreqs - 1]);
			}
		} else if (curfreq > freqs[0]) {
			if (vflag) {
				printf("CPU frequency is above user-defined "
				    "maximum; changing frequency to %d "
				    "MHz\n", freqs[0]);
			}
			if (set_freq(freqs[0]) != 0) {
				warn("error setting CPU freq %d",
				    freqs[0]);
			}
		}
	}

	idle = 0;
	/* Main loop. */
	for (;;) {
		FD_ZERO(&fdset);
		if (devd_pipe >= 0) {
			FD_SET(devd_pipe, &fdset);
			nfds = devd_pipe + 1;
		} else {
			nfds = 0;
		}
		if (mode == MODE_HIADAPTIVE || idle < 120)
			to = poll_ival;
		else if (idle < 360)
			to = poll_ival * 2;
		else
			to = poll_ival * 4;
		timeout.tv_sec = to / 1000000;
		timeout.tv_usec = to % 1000000;
		select(nfds, &fdset, NULL, &fdset, &timeout);

		/* If the user requested we quit, print some statistics. */
		if (exit_requested) {
			if (vflag && mjoules_used != 0)
				printf("total joules used: %u.%03u\n",
				    (u_int)(mjoules_used / 1000),
				    (int)mjoules_used % 1000);
			break;
		}

		/* Read the current AC status and record the mode. */
		acline_read();
		switch (acline_status) {
		case SRC_AC:
			mode = mode_ac;
			break;
		case SRC_BATTERY:
			mode = mode_battery;
			break;
		case SRC_UNKNOWN:
			mode = mode_none;
			break;
		default:
			errx(1, "invalid AC line status %d", acline_status);
		}

		/* Read the current frequency. */
		if (idle % 32 == 0) {
			if ((curfreq = get_freq()) == 0)
				continue;
			i = get_freq_id(curfreq, freqs, numfreqs);
		}
		idle++;
		if (vflag) {
			/* Keep a sum of all power actually used. */
			if (mwatts[i] != -1)
				mjoules_used +=
				    (mwatts[i] * (poll_ival / 1000)) / 1000;
		}

		/* Always switch to the lowest frequency in min mode. */
		if (mode == MODE_MIN) {
			freq = freqs[numfreqs - 1];
			if (curfreq != freq) {
				if (vflag) {
					printf("now operating on %s power; "
					    "changing frequency to %d MHz\n",
					    modes[acline_status], freq);
				}
				idle = 0;
				if (set_freq(freq) != 0) {
					warn("error setting CPU freq %d",
					    freq);
					continue;
				}
			}
			continue;
		}

		/* Always switch to the highest frequency in max mode. */
		if (mode == MODE_MAX) {
			freq = freqs[0];
			if (curfreq != freq) {
				if (vflag) {
					printf("now operating on %s power; "
					    "changing frequency to %d MHz\n",
					    modes[acline_status], freq);
				}
				idle = 0;
				if (set_freq(freq) != 0) {
					warn("error setting CPU freq %d",
				    	    freq);
					continue;
				}
			}
			continue;
		}

		/* Adaptive mode; get the current CPU usage times. */
		if (read_usage_times(&load)) {
			if (vflag)
				warn("read_usage_times() failed");
			continue;
		}
		
		if (mode == MODE_ADAPTIVE) {
			if (load > cpu_running_mark) {
				if (load > 95 || load > cpu_running_mark * 2)
					freq *= 2;
				else
					freq = freq * load / cpu_running_mark;
				if (freq > freqs[0])
					freq = freqs[0];
			} else if (load < cpu_idle_mark &&
			    curfreq * load < freqs[get_freq_id(
			    freq * 7 / 8, freqs, numfreqs)] * 
			    cpu_running_mark) {
				freq = freq * 7 / 8;
				if (freq < freqs[numfreqs - 1])
					freq = freqs[numfreqs - 1];
			}
		} else { /* MODE_HIADAPTIVE */
			if (load > cpu_running_mark / 2) {
				if (load > 95 || load > cpu_running_mark)
					freq *= 4;
				else
					freq = freq * load * 2 / cpu_running_mark;
				if (freq > freqs[0] * 2)
					freq = freqs[0] * 2;
			} else if (load < cpu_idle_mark / 2 &&
			    curfreq * load < freqs[get_freq_id(
			    freq * 31 / 32, freqs, numfreqs)] * 
			    cpu_running_mark / 2) {
				freq = freq * 31 / 32;
				if (freq < freqs[numfreqs - 1])
					freq = freqs[numfreqs - 1];
			}
		}
		if (vflag) {
		    printf("load %3d%%, current freq %4d MHz (%2d), wanted freq %4d MHz\n",
			load, curfreq, i, freq);
		}
		j = get_freq_id(freq, freqs, numfreqs);
		if (i != j) {
			if (vflag) {
				printf("changing clock"
				    " speed from %d MHz to %d MHz\n",
				    freqs[i], freqs[j]);
			}
			idle = 0;
			if (set_freq(freqs[j]))
				warn("error setting CPU frequency %d",
				    freqs[j]);
		}
	}
	if (set_freq(initfreq))
		warn("error setting CPU frequency %d", initfreq);
	free(freqs);
	free(mwatts);
	devd_close();
	if (!vflag)
		pidfile_remove(pfh);

	exit(0);
}
Exemple #6
0
/*
 * Daemonize and persist pid
 */
int
daemon_start()
{
	struct sigaction sig_action;
	sigset_t sig_set;
	pid_t otherpid;
	int curPID;
	pthread_t tcp4_thread, udp4_thread;
	pthread_t tcp6_thread, udp6_thread;

	/* Check if we can acquire the pid file */
	pfh = pidfile_open(NULL, 0644, &otherpid);

	if (pfh == NULL) {
		if (errno == EEXIST) {
			errx(EXIT_FAILURE, "Daemon already running, pid: %jd.", (intmax_t)otherpid);
		}
		err(EXIT_FAILURE, "Cannot open or create pidfile");
	}
	init_logger();

	/* Initialize TCP46 and UDP46 sockets */
	if (init_tcp() == EXIT_FAILURE)
		return (EXIT_FAILURE);
	if (init_udp() == EXIT_FAILURE)
		return (EXIT_FAILURE);

	/* start daemonizing */
	curPID = fork();

	switch (curPID) {
	case 0:			/* This process is the child */
		break;
	case -1:			/* fork() failed, should exit */
		perror("fork");
		return (EXIT_FAILURE);
	default:			/* fork() successful, should exit
					 * (parent) */
		return (EXIT_SUCCESS);
	}

	/* we are the child, complete the daemonization */

	/* Close standard IO */
	fclose(stdin);
	fclose(stdout);
	fclose(stderr);

	/* Block unnecessary signals */
	sigemptyset(&sig_set);
	sigaddset(&sig_set, SIGCHLD);	/* ignore child - i.e. we don't need
					 * to wait for it */
	sigaddset(&sig_set, SIGTSTP);	/* ignore tty stop signals */
	sigaddset(&sig_set, SIGTTOU);	/* ignore tty background writes */
	sigaddset(&sig_set, SIGTTIN);	/* ignore tty background reads */
	sigprocmask(SIG_BLOCK, &sig_set, NULL);	/* Block the above specified
						 * signals */

	/* Catch necessary signals */
	sig_action.sa_handler = signal_handler;
	sigemptyset(&sig_action.sa_mask);
	sig_action.sa_flags = 0;

	sigaction(SIGTERM, &sig_action, NULL);
	sigaction(SIGHUP, &sig_action, NULL);
	sigaction(SIGINT, &sig_action, NULL);

	/* create new session and process group */
	setsid();

	/* persist pid */
	pidfile_write(pfh);

	/* Create TCP and UDP listener threads */
	pthread_create(&tcp4_thread, NULL, tcp4_handler, NULL);
	pthread_create(&udp4_thread, NULL, udp4_handler, NULL);
#ifdef PF_INET6
	pthread_create(&tcp6_thread, NULL, tcp6_handler, NULL);
	pthread_create(&udp6_thread, NULL, udp6_handler, NULL);
#endif

	/*
	 * Wait for threads to terminate, which normally shouldn't ever
	 * happen
	 */
	pthread_join(tcp4_thread, NULL);
	pthread_join(udp4_thread, NULL);
#ifdef PF_INET6
	pthread_join(tcp6_thread, NULL);
	pthread_join(udp6_thread, NULL);
#endif

	return (EXIT_SUCCESS);
}
Exemple #7
0
/*
 * Periodically pat the watchdog, preventing it from firing.
 */
int
main(int argc, char *argv[])
{
	struct rtprio rtp;
	struct pidfh *pfh;
	pid_t otherpid;

	if (getuid() != 0)
		errx(EX_SOFTWARE, "not super user");
		
	parseargs(argc, argv);

	if (do_syslog)
		openlog("watchdogd", LOG_CONS|LOG_NDELAY|LOG_PERROR,
		    LOG_DAEMON);

	rtp.type = RTP_PRIO_REALTIME;
	rtp.prio = 0;
	if (rtprio(RTP_SET, 0, &rtp) == -1)
		err(EX_OSERR, "rtprio");

	if (!is_dry_run && watchdog_init() == -1)
		errx(EX_SOFTWARE, "unable to initialize watchdog");

	if (is_daemon) {
		if (watchdog_onoff(1) == -1)
			err(EX_OSERR, "patting the dog");

		pfh = pidfile_open(pidfile, 0600, &otherpid);
		if (pfh == NULL) {
			if (errno == EEXIST) {
				watchdog_onoff(0);
				errx(EX_SOFTWARE, "%s already running, pid: %d",
				    getprogname(), otherpid);
			}
			warn("Cannot open or create pidfile");
		}

		if (debugging == 0 && daemon(0, 0) == -1) {
			watchdog_onoff(0);
			pidfile_remove(pfh);
			err(EX_OSERR, "daemon");
		}

		signal(SIGHUP, SIG_IGN);
		signal(SIGINT, sighandler);
		signal(SIGTERM, sighandler);

		pidfile_write(pfh);
		if (madvise(0, 0, MADV_PROTECT) != 0)
			warn("madvise failed");
		if (mlockall(MCL_CURRENT | MCL_FUTURE) != 0)
			warn("mlockall failed");

		watchdog_loop();

		/* exiting */
		pidfile_remove(pfh);
		return (EX_OK);
	} else {
		if (passive)
			timeout |= WD_PASSIVE;
		else
			timeout |= WD_ACTIVE;
		if (watchdog_patpat(timeout) < 0)
			err(EX_OSERR, "patting the dog");
		return (EX_OK);
	}
}