summaryrefslogtreecommitdiff
path: root/start-stop-daemon.c
blob: e9720425afc81ae3320081dd85f5d3c9e4f9b7fd (plain)
    1 /*
    2  * A rewrite of the original Debian's start-stop-daemon Perl script
    3  * in C (faster - it is executed many times during system startup).
    4  *
    5  * Written by Marek Michalkiewicz <marekm@i17linuxb.ists.pwr.wroc.pl>,
    6  * public domain.  Based conceptually on start-stop-daemon.pl, by Ian
    7  * Jackson <ijackson@gnu.ai.mit.edu>.  May be used and distributed
    8  * freely for any purpose.  Changes by Christian Schwarz
    9  * <schwarz@monet.m.isar.de>, to make output conform to the Debian
   10  * Console Message Standard, also placed in public domain.  Minor
   11  * changes by Klee Dienes <klee@debian.org>, also placed in the Public
   12  * Domain.
   13  *
   14  * Changes by Ben Collins <bcollins@debian.org>, added --chuid, --background
   15  * and --make-pidfile options, placed in public domain as well.
   16  *
   17  * Port to OpenBSD by Sontri Tomo Huynh <huynh.29@osu.edu>
   18  *                 and Andreas Schuldei <andreas@schuldei.org>
   19  *
   20  * Changes by Ian Jackson: added --retry (and associated rearrangements).
   21  */
   22 
   23 #include <config.h>
   24 #include <compat.h>
   25 
   26 #include <dpkg/macros.h>
   27 
   28 #if defined(__linux__)
   29 #  define OS_Linux
   30 #elif defined(__GNU__)
   31 #  define OS_Hurd
   32 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
   33 #  define OS_FreeBSD
   34 #elif defined(__NetBSD__)
   35 #  define OS_NetBSD
   36 #elif defined(__OpenBSD__)
   37 #  define OS_OpenBSD
   38 #elif defined(__DragonFly__)
   39 #  define OS_DragonFlyBSD
   40 #elif defined(__APPLE__) && defined(__MACH__)
   41 #  define OS_Darwin
   42 #elif defined(__sun)
   43 #  define OS_Solaris
   44 #elif defined(_AIX)
   45 #  define OS_AIX
   46 #elif defined(__hpux)
   47 #  define OS_HPUX
   48 #else
   49 #  error Unknown architecture - cannot build start-stop-daemon
   50 #endif
   51 
   52 /* NetBSD needs this to expose struct proc. */
   53 #define _KMEMUSER 1
   54 
   55 #ifdef HAVE_SYS_PARAM_H
   56 #include <sys/param.h>
   57 #endif
   58 #ifdef HAVE_SYS_SYSCALL_H
   59 #include <sys/syscall.h>
   60 #endif
   61 #ifdef HAVE_SYS_SYSCTL_H
   62 #include <sys/sysctl.h>
   63 #endif
   64 #ifdef HAVE_SYS_PROCFS_H
   65 #include <sys/procfs.h>
   66 #endif
   67 #ifdef HAVE_SYS_PROC_H
   68 #include <sys/proc.h>
   69 #endif
   70 #ifdef HAVE_SYS_USER_H
   71 #include <sys/user.h>
   72 #endif
   73 #ifdef HAVE_SYS_PSTAT_H
   74 #include <sys/pstat.h>
   75 #endif
   76 #include <sys/types.h>
   77 #include <sys/time.h>
   78 #include <sys/stat.h>
   79 #include <sys/wait.h>
   80 #include <sys/select.h>
   81 #include <sys/ioctl.h>
   82 
   83 #include <errno.h>
   84 #include <limits.h>
   85 #include <time.h>
   86 #include <fcntl.h>
   87 #include <dirent.h>
   88 #include <ctype.h>
   89 #include <string.h>
   90 #include <pwd.h>
   91 #include <grp.h>
   92 #include <signal.h>
   93 #include <termios.h>
   94 #include <unistd.h>
   95 #ifdef HAVE_STDDEF_H
   96 #include <stddef.h>
   97 #endif
   98 #include <stdbool.h>
   99 #include <stdarg.h>
  100 #include <stdlib.h>
  101 #include <stdio.h>
  102 #include <getopt.h>
  103 #ifdef HAVE_ERROR_H
  104 #include <error.h>
  105 #endif
  106 #ifdef HAVE_ERR_H
  107 #include <err.h>
  108 #endif
  109 
  110 #if defined(OS_Hurd)
  111 #include <hurd.h>
  112 #include <ps.h>
  113 #endif
  114 
  115 #if defined(OS_Darwin)
  116 #include <libproc.h>
  117 #endif
  118 
  119 #ifdef HAVE_KVM_H
  120 #include <kvm.h>
  121 #if defined(OS_FreeBSD)
  122 #define KVM_MEMFILE "/dev/null"
  123 #else
  124 #define KVM_MEMFILE NULL
  125 #endif
  126 #endif
  127 
  128 #if defined(_POSIX_PRIORITY_SCHEDULING) && _POSIX_PRIORITY_SCHEDULING > 0
  129 #include <sched.h>
  130 #else
  131 #define SCHED_OTHER -1
  132 #define SCHED_FIFO -1
  133 #define SCHED_RR -1
  134 #endif
  135 
  136 #if defined(OS_Linux)
  137 /* This comes from TASK_COMM_LEN defined in Linux' include/linux/sched.h. */
  138 #define PROCESS_NAME_SIZE 15
  139 #elif defined(OS_Solaris)
  140 #define PROCESS_NAME_SIZE 15
  141 #elif defined(OS_Darwin)
  142 #define PROCESS_NAME_SIZE 16
  143 #elif defined(OS_AIX)
  144 /* This comes from PRFNSZ defined in AIX's <sys/procfs.h>. */
  145 #define PROCESS_NAME_SIZE 16
  146 #elif defined(OS_NetBSD)
  147 #define PROCESS_NAME_SIZE 16
  148 #elif defined(OS_OpenBSD)
  149 #define PROCESS_NAME_SIZE 16
  150 #elif defined(OS_FreeBSD)
  151 #define PROCESS_NAME_SIZE 19
  152 #elif defined(OS_DragonFlyBSD)
  153 /* On DragonFlyBSD MAXCOMLEN expands to 16. */
  154 #define PROCESS_NAME_SIZE MAXCOMLEN
  155 #endif
  156 
  157 #if defined(SYS_ioprio_set) && defined(linux)
  158 #define HAVE_IOPRIO_SET
  159 #endif
  160 
  161 #define IOPRIO_CLASS_SHIFT 13
  162 #define IOPRIO_PRIO_VALUE(class, prio) (((class) << IOPRIO_CLASS_SHIFT) | (prio))
  163 #define IO_SCHED_PRIO_MIN 0
  164 #define IO_SCHED_PRIO_MAX 7
  165 
  166 enum {
  167 	IOPRIO_WHO_PROCESS = 1,
  168 	IOPRIO_WHO_PGRP,
  169 	IOPRIO_WHO_USER,
  170 };
  171 
  172 enum {
  173 	IOPRIO_CLASS_NONE,
  174 	IOPRIO_CLASS_RT,
  175 	IOPRIO_CLASS_BE,
  176 	IOPRIO_CLASS_IDLE,
  177 };
  178 
  179 enum action_code {
  180 	ACTION_NONE,
  181 	ACTION_START,
  182 	ACTION_STOP,
  183 	ACTION_STATUS,
  184 };
  185 
  186 /* Time conversion constants. */
  187 enum {
  188 	NANOSEC_IN_SEC      = 1000000000L,
  189 	NANOSEC_IN_MILLISEC = 1000000L,
  190 	NANOSEC_IN_MICROSEC = 1000L,
  191 };
  192 
  193 /* The minimum polling interval, 20ms. */
  194 static const long MIN_POLL_INTERVAL = 20L * NANOSEC_IN_MILLISEC;
  195 
  196 static enum action_code action;
  197 static bool testmode = false;
  198 static int quietmode = 0;
  199 static int exitnodo = 1;
  200 static bool background = false;
  201 static bool close_io = true;
  202 static bool mpidfile = false;
  203 static bool rpidfile = false;
  204 static int signal_nr = SIGTERM;
  205 static int user_id = -1;
  206 static int runas_uid = -1;
  207 static int runas_gid = -1;
  208 static const char *userspec = NULL;
  209 static char *changeuser = NULL;
  210 static const char *changegroup = NULL;
  211 static char *changeroot = NULL;
  212 static const char *changedir = "/";
  213 static const char *cmdname = NULL;
  214 static char *execname = NULL;
  215 static char *startas = NULL;
  216 static pid_t match_pid = -1;
  217 static pid_t match_ppid = -1;
  218 static const char *pidfile = NULL;
  219 static char *what_stop = NULL;
  220 static const char *progname = "";
  221 static int nicelevel = 0;
  222 static int umask_value = -1;
  223 
  224 static struct stat exec_stat;
  225 #if defined(OS_Hurd)
  226 static struct proc_stat_list *procset = NULL;
  227 #endif
  228 
  229 /* LSB Init Script process status exit codes. */
  230 enum status_code {
  231 	STATUS_OK = 0,
  232 	STATUS_DEAD_PIDFILE = 1,
  233 	STATUS_DEAD_LOCKFILE = 2,
  234 	STATUS_DEAD = 3,
  235 	STATUS_UNKNOWN = 4,
  236 };
  237 
  238 struct pid_list {
  239 	struct pid_list *next;
  240 	pid_t pid;
  241 };
  242 
  243 static struct pid_list *found = NULL;
  244 static struct pid_list *killed = NULL;
  245 
  246 /* Resource scheduling policy. */
  247 struct res_schedule {
  248 	const char *policy_name;
  249 	int policy;
  250 	int priority;
  251 };
  252 
  253 struct schedule_item {
  254 	enum {
  255 		sched_timeout,
  256 		sched_signal,
  257 		sched_goto,
  258 		/* Only seen within parse_schedule and callees. */
  259 		sched_forever,
  260 	} type;
  261 	/* Seconds, signal no., or index into array. */
  262 	int value;
  263 };
  264 
  265 static struct res_schedule *proc_sched = NULL;
  266 static struct res_schedule *io_sched = NULL;
  267 
  268 static int schedule_length;
  269 static struct schedule_item *schedule = NULL;
  270 
  271 
  272 static void DPKG_ATTR_PRINTF(1)
  273 warning(const char *format, ...)
  274 {
  275 	va_list arglist;
  276 
  277 	fprintf(stderr, "%s: warning: ", progname);
  278 	va_start(arglist, format);
  279 	vfprintf(stderr, format, arglist);
  280 	va_end(arglist);
  281 }
  282 
  283 static void DPKG_ATTR_NORET DPKG_ATTR_PRINTF(1)
  284 fatal(const char *format, ...)
  285 {
  286 	va_list arglist;
  287 	int errno_fatal = errno;
  288 
  289 	fprintf(stderr, "%s: ", progname);
  290 	va_start(arglist, format);
  291 	vfprintf(stderr, format, arglist);
  292 	va_end(arglist);
  293 	if (errno_fatal)
  294 		fprintf(stderr, " (%s)\n", strerror(errno_fatal));
  295 	else
  296 		fprintf(stderr, "\n");
  297 
  298 	if (action == ACTION_STATUS)
  299 		exit(STATUS_UNKNOWN);
  300 	else
  301 		exit(2);
  302 }
  303 
  304 #define BUG(...) bug(__FILE__, __LINE__, __func__, __VA_ARGS__)
  305 
  306 static void DPKG_ATTR_NORET DPKG_ATTR_PRINTF(4)
  307 bug(const char *file, int line, const char *func, const char *format, ...)
  308 {
  309 	va_list arglist;
  310 
  311 	fprintf(stderr, "%s:%s:%d:%s: internal error: ",
  312 	        progname, file, line, func);
  313 	va_start(arglist, format);
  314 	vfprintf(stderr, format, arglist);
  315 	va_end(arglist);
  316 
  317 	if (action == ACTION_STATUS)
  318 		exit(STATUS_UNKNOWN);
  319 	else
  320 		exit(3);
  321 }
  322 
  323 static void *
  324 xmalloc(int size)
  325 {
  326 	void *ptr;
  327 
  328 	ptr = malloc(size);
  329 	if (ptr)
  330 		return ptr;
  331 	fatal("malloc(%d) failed", size);
  332 }
  333 
  334 static char *
  335 xstrndup(const char *str, size_t n)
  336 {
  337 	char *new_str;
  338 
  339 	new_str = strndup(str, n);
  340 	if (new_str)
  341 		return new_str;
  342 	fatal("strndup(%s, %zu) failed", str, n);
  343 }
  344 
  345 static void
  346 timespec_gettime(struct timespec *ts)
  347 {
  348 #if defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0 && \
  349     defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK > 0
  350 	if (clock_gettime(CLOCK_MONOTONIC, ts) < 0)
  351 		fatal("clock_gettime failed");
  352 #else
  353 	struct timeval tv;
  354 
  355 	if (gettimeofday(&tv, NULL) != 0)
  356 		fatal("gettimeofday failed");
  357 
  358 	ts->tv_sec = tv.tv_sec;
  359 	ts->tv_nsec = tv.tv_usec * NANOSEC_IN_MICROSEC;
  360 #endif
  361 }
  362 
  363 #define timespec_cmp(a, b, OP) \
  364 	(((a)->tv_sec == (b)->tv_sec) ? \
  365 	 ((a)->tv_nsec OP (b)->tv_nsec) : \
  366 	 ((a)->tv_sec OP (b)->tv_sec))
  367 
  368 static void
  369 timespec_sub(struct timespec *a, struct timespec *b, struct timespec *res)
  370 {
  371 	res->tv_sec = a->tv_sec - b->tv_sec;
  372 	res->tv_nsec = a->tv_nsec - b->tv_nsec;
  373 	if (res->tv_nsec < 0) {
  374 		res->tv_sec--;
  375 		res->tv_nsec += NANOSEC_IN_SEC;
  376 	}
  377 }
  378 
  379 static void
  380 timespec_mul(struct timespec *a, int b)
  381 {
  382 	long nsec = a->tv_nsec * b;
  383 
  384 	a->tv_sec *= b;
  385 	a->tv_sec += nsec / NANOSEC_IN_SEC;
  386 	a->tv_nsec = nsec % NANOSEC_IN_SEC;
  387 }
  388 
  389 static char *
  390 newpath(const char *dirname, const char *filename)
  391 {
  392 	char *path;
  393 	size_t path_len;
  394 
  395 	path_len = strlen(dirname) + 1 + strlen(filename) + 1;
  396 	path = xmalloc(path_len);
  397 	snprintf(path, path_len, "%s/%s", dirname, filename);
  398 
  399 	return path;
  400 }
  401 
  402 static long
  403 get_open_fd_max(void)
  404 {
  405 #ifdef HAVE_GETDTABLESIZE
  406 	return getdtablesize();
  407 #else
  408 	return sysconf(_SC_OPEN_MAX);
  409 #endif
  410 }
  411 
  412 #ifndef HAVE_SETSID
  413 static void
  414 detach_controlling_tty(void)
  415 {
  416 #ifdef HAVE_TIOCNOTTY
  417 	int tty_fd;
  418 
  419 	tty_fd = open("/dev/tty", O_RDWR);
  420 
  421 	/* The current process does not have a controlling tty. */
  422 	if (tty_fd < 0)
  423 		return;
  424 
  425 	if (ioctl(tty_fd, TIOCNOTTY, 0) != 0)
  426 		fatal("unable to detach controlling tty");
  427 
  428 	close(tty_fd);
  429 #endif
  430 }
  431 
  432 static pid_t
  433 setsid(void)
  434 {
  435 	if (setpgid(0, 0) < 0)
  436 		return -1:
  437 
  438 	detach_controlling_tty();
  439 
  440 	return 0;
  441 }
  442 #endif
  443 
  444 static void
  445 wait_for_child(pid_t pid)
  446 {
  447 	pid_t child;
  448 	int status;
  449 
  450 	do {
  451 		child = waitpid(pid, &status, 0);
  452 	} while (child == -1 && errno == EINTR);
  453 
  454 	if (child != pid)
  455 		fatal("error waiting for child");
  456 
  457 	if (WIFEXITED(status)) {
  458 		int ret = WEXITSTATUS(status);
  459 
  460 		if (ret != 0)
  461 			fatal("child returned error exit status %d", ret);
  462 	} else if (WIFSIGNALED(status)) {
  463 		int signo = WTERMSIG(status);
  464 
  465 		fatal("child was killed by signal %d", signo);
  466 	} else {
  467 		fatal("unexpected status %d waiting for child", status);
  468 	}
  469 }
  470 
  471 static void
  472 write_pidfile(const char *filename, pid_t pid)
  473 {
  474 	FILE *fp;
  475 	int fd;
  476 
  477 	fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW, 0666);
  478 	if (fd < 0)
  479 		fp = NULL;
  480 	else
  481 		fp = fdopen(fd, "w");
  482 
  483 	if (fp == NULL)
  484 		fatal("unable to open pidfile '%s' for writing", filename);
  485 
  486 	fprintf(fp, "%d\n", pid);
  487 
  488 	if (fclose(fp))
  489 		fatal("unable to close pidfile '%s'", filename);
  490 }
  491 
  492 static void
  493 remove_pidfile(const char *filename)
  494 {
  495 	if (unlink(filename) < 0 && errno != ENOENT)
  496 		fatal("cannot remove pidfile '%s'", filename);
  497 }
  498 
  499 static void
  500 daemonize(void)
  501 {
  502 	pid_t pid;
  503 	sigset_t mask;
  504 	sigset_t oldmask;
  505 
  506 	if (quietmode < 0)
  507 		printf("Detaching to start %s...", startas);
  508 
  509 	/* Block SIGCHLD to allow waiting for the child process while it is
  510 	 * performing actions, such as creating a pidfile. */
  511 	sigemptyset(&mask);
  512 	sigaddset(&mask, SIGCHLD);
  513 	if (sigprocmask(SIG_BLOCK, &mask, &oldmask) == -1)
  514 		fatal("cannot block SIGCHLD");
  515 
  516 	pid = fork();
  517 	if (pid < 0)
  518 		fatal("unable to do first fork");
  519 	else if (pid) { /* First Parent. */
  520 		/* Wait for the second parent to exit, so that if we need to
  521 		 * perform any actions there, like creating a pidfile, we do
  522 		 * not suffer from race conditions on return. */
  523 		wait_for_child(pid);
  524 
  525 		_exit(0);
  526 	}
  527 
  528 	/* Create a new session. */
  529 	if (setsid() < 0)
  530 		fatal("cannot set session ID");
  531 
  532 	pid = fork();
  533 	if (pid < 0)
  534 		fatal("unable to do second fork");
  535 	else if (pid) { /* Second parent. */
  536 		/* Set a default umask for dumb programs, which might get
  537 		 * overridden by the --umask option later on, so that we get
  538 		 * a defined umask when creating the pidfille. */
  539 		umask(022);
  540 
  541 		if (mpidfile && pidfile != NULL)
  542 			/* User wants _us_ to make the pidfile. */
  543 			write_pidfile(pidfile, pid);
  544 
  545 		_exit(0);
  546 	}
  547 
  548 	if (sigprocmask(SIG_SETMASK, &oldmask, NULL) == -1)
  549 		fatal("cannot restore signal mask");
  550 
  551 	if (quietmode < 0)
  552 		printf("done.\n");
  553 }
  554 
  555 static void
  556 pid_list_push(struct pid_list **list, pid_t pid)
  557 {
  558 	struct pid_list *p;
  559 
  560 	p = xmalloc(sizeof(*p));
  561 	p->next = *list;
  562 	p->pid = pid;
  563 	*list = p;
  564 }
  565 
  566 static void
  567 pid_list_free(struct pid_list **list)
  568 {
  569 	struct pid_list *here, *next;
  570 
  571 	for (here = *list; here != NULL; here = next) {
  572 		next = here->next;
  573 		free(here);
  574 	}
  575 
  576 	*list = NULL;
  577 }
  578 
  579 static void
  580 usage(void)
  581 {
  582 	printf(
  583 "Usage: start-stop-daemon [<option>...] <command>\n"
  584 "\n");
  585 
  586 	printf(
  587 "Commands:\n"
  588 "  -S, --start -- <argument>...  start a program and pass <arguments> to it\n"
  589 "  -K, --stop                    stop a program\n"
  590 "  -T, --status                  get the program status\n"
  591 "  -H, --help                    print help information\n"
  592 "  -V, --version                 print version\n"
  593 "\n");
  594 
  595 	printf(
  596 "Matching options (at least one is required):\n"
  597 "      --pid <pid>               pid to check\n"
  598 "      --ppid <ppid>             parent pid to check\n"
  599 "  -p, --pidfile <pid-file>      pid file to check\n"
  600 "  -x, --exec <executable>       program to start/check if it is running\n"
  601 "  -n, --name <process-name>     process name to check\n"
  602 "  -u, --user <username|uid>     process owner to check\n"
  603 "\n");
  604 
  605 	printf(
  606 "Options:\n"
  607 "  -g, --group <group|gid>       run process as this group\n"
  608 "  -c, --chuid <name|uid[:group|gid]>\n"
  609 "                                change to this user/group before starting\n"
  610 "                                  process\n"
  611 "  -s, --signal <signal>         signal to send (default TERM)\n"
  612 "  -a, --startas <pathname>      program to start (default is <executable>)\n"
  613 "  -r, --chroot <directory>      chroot to <directory> before starting\n"
  614 "  -d, --chdir <directory>       change to <directory> (default is /)\n"
  615 "  -N, --nicelevel <incr>        add incr to the process' nice level\n"
  616 "  -P, --procsched <policy[:prio]>\n"
  617 "                                use <policy> with <prio> for the kernel\n"
  618 "                                  process scheduler (default prio is 0)\n"
  619 "  -I, --iosched <class[:prio]>  use <class> with <prio> to set the IO\n"
  620 "                                  scheduler (default prio is 4)\n"
  621 "  -k, --umask <mask>            change the umask to <mask> before starting\n"
  622 "  -b, --background              force the process to detach\n"
  623 "  -C, --no-close                do not close any file descriptor\n"
  624 "  -m, --make-pidfile            create the pidfile before starting\n"
  625 "      --remove-pidfile          delete the pidfile after stopping\n"
  626 "  -R, --retry <schedule>        check whether processes die, and retry\n"
  627 "  -t, --test                    test mode, don't do anything\n"
  628 "  -o, --oknodo                  exit status 0 (not 1) if nothing done\n"
  629 "  -q, --quiet                   be more quiet\n"
  630 "  -v, --verbose                 be more verbose\n"
  631 "\n");
  632 
  633 	printf(
  634 "Retry <schedule> is <item>|/<item>/... where <item> is one of\n"
  635 " -<signal-num>|[-]<signal-name>  send that signal\n"
  636 " <timeout>                       wait that many seconds\n"
  637 " forever                         repeat remainder forever\n"
  638 "or <schedule> may be just <timeout>, meaning <signal>/<timeout>/KILL/<timeout>\n"
  639 "\n");
  640 
  641 	printf(
  642 "The process scheduler <policy> can be one of:\n"
  643 "  other, fifo or rr\n"
  644 "\n");
  645 
  646 	printf(
  647 "The IO scheduler <class> can be one of:\n"
  648 "  real-time, best-effort or idle\n"
  649 "\n");
  650 
  651 	printf(
  652 "Exit status:\n"
  653 "  0 = done\n"
  654 "  1 = nothing done (=> 0 if --oknodo)\n"
  655 "  2 = with --retry, processes would not die\n"
  656 "  3 = trouble\n"
  657 "Exit status with --status:\n"
  658 "  0 = program is running\n"
  659 "  1 = program is not running and the pid file exists\n"
  660 "  3 = program is not running\n"
  661 "  4 = unable to determine status\n");
  662 }
  663 
  664 static void
  665 do_version(void)
  666 {
  667 	printf("start-stop-daemon %s for Debian\n\n", VERSION);
  668 
  669 	printf("Written by Marek Michalkiewicz, public domain.\n");
  670 }
  671 
  672 static void DPKG_ATTR_NORET
  673 badusage(const char *msg)
  674 {
  675 	if (msg)
  676 		fprintf(stderr, "%s: %s\n", progname, msg);
  677 	fprintf(stderr, "Try '%s --help' for more information.\n", progname);
  678 
  679 	if (action == ACTION_STATUS)
  680 		exit(STATUS_UNKNOWN);
  681 	else
  682 		exit(3);
  683 }
  684 
  685 struct sigpair {
  686 	const char *name;
  687 	int signal;
  688 };
  689 
  690 static const struct sigpair siglist[] = {
  691 	{ "ABRT",	SIGABRT	},
  692 	{ "ALRM",	SIGALRM	},
  693 	{ "FPE",	SIGFPE	},
  694 	{ "HUP",	SIGHUP	},
  695 	{ "ILL",	SIGILL	},
  696 	{ "INT",	SIGINT	},
  697 	{ "KILL",	SIGKILL	},
  698 	{ "PIPE",	SIGPIPE	},
  699 	{ "QUIT",	SIGQUIT	},
  700 	{ "SEGV",	SIGSEGV	},
  701 	{ "TERM",	SIGTERM	},
  702 	{ "USR1",	SIGUSR1	},
  703 	{ "USR2",	SIGUSR2	},
  704 	{ "CHLD",	SIGCHLD	},
  705 	{ "CONT",	SIGCONT	},
  706 	{ "STOP",	SIGSTOP	},
  707 	{ "TSTP",	SIGTSTP	},
  708 	{ "TTIN",	SIGTTIN	},
  709 	{ "TTOU",	SIGTTOU	}
  710 };
  711 
  712 static int
  713 parse_unsigned(const char *string, int base, int *value_r)
  714 {
  715 	long value;
  716 	char *endptr;
  717 
  718 	if (!string[0])
  719 		return -1;
  720 
  721 	errno = 0;
  722 	value = strtol(string, &endptr, base);
  723 	if (string == endptr || *endptr != '\0' || errno != 0)
  724 		return -1;
  725 	if (value < 0 || value > INT_MAX)
  726 		return -1;
  727 
  728 	*value_r = value;
  729 	return 0;
  730 }
  731 
  732 static int
  733 parse_pid(const char *pid_str, int *pid_num)
  734 {
  735 	if (parse_unsigned(pid_str, 10, pid_num) != 0)
  736 		return -1;
  737 	if (*pid_num == 0)
  738 		return -1;
  739 
  740 	return 0;
  741 }
  742 
  743 static int
  744 parse_signal(const char *sig_str, int *sig_num)
  745 {
  746 	unsigned int i;
  747 
  748 	if (parse_unsigned(sig_str, 10, sig_num) == 0)
  749 		return 0;
  750 
  751 	for (i = 0; i < array_count(siglist); i++) {
  752 		if (strcmp(sig_str, siglist[i].name) == 0) {
  753 			*sig_num = siglist[i].signal;
  754 			return 0;
  755 		}
  756 	}
  757 	return -1;
  758 }
  759 
  760 static int
  761 parse_umask(const char *string, int *value_r)
  762 {
  763 	return parse_unsigned(string, 0, value_r);
  764 }
  765 
  766 static void
  767 validate_proc_schedule(void)
  768 {
  769 #if defined(_POSIX_PRIORITY_SCHEDULING) && _POSIX_PRIORITY_SCHEDULING > 0
  770 	int prio_min, prio_max;
  771 
  772 	prio_min = sched_get_priority_min(proc_sched->policy);
  773 	prio_max = sched_get_priority_max(proc_sched->policy);
  774 
  775 	if (proc_sched->priority < prio_min)
  776 		badusage("process scheduler priority less than min");
  777 	if (proc_sched->priority > prio_max)
  778 		badusage("process scheduler priority greater than max");
  779 #endif
  780 }
  781 
  782 static void
  783 parse_proc_schedule(const char *string)
  784 {
  785 	char *policy_str;
  786 	size_t policy_len;
  787 	int prio = 0;
  788 
  789 	policy_len = strcspn(string, ":");
  790 	policy_str = xstrndup(string, policy_len);
  791 
  792 	if (string[policy_len] == ':' &&
  793 	    parse_unsigned(string + policy_len + 1, 10, &prio) != 0)
  794 		fatal("invalid process scheduler priority");
  795 
  796 	proc_sched = xmalloc(sizeof(*proc_sched));
  797 	proc_sched->policy_name = policy_str;
  798 
  799 	if (strcmp(policy_str, "other") == 0) {
  800 		proc_sched->policy = SCHED_OTHER;
  801 		proc_sched->priority = 0;
  802 	} else if (strcmp(policy_str, "fifo") == 0) {
  803 		proc_sched->policy = SCHED_FIFO;
  804 		proc_sched->priority = prio;
  805 	} else if (strcmp(policy_str, "rr") == 0) {
  806 		proc_sched->policy = SCHED_RR;
  807 		proc_sched->priority = prio;
  808 	} else
  809 		badusage("invalid process scheduler policy");
  810 
  811 	validate_proc_schedule();
  812 }
  813 
  814 static void
  815 parse_io_schedule(const char *string)
  816 {
  817 	char *class_str;
  818 	size_t class_len;
  819 	int prio = 4;
  820 
  821 	class_len = strcspn(string, ":");
  822 	class_str = xstrndup(string, class_len);
  823 
  824 	if (string[class_len] == ':' &&
  825 	    parse_unsigned(string + class_len + 1, 10, &prio) != 0)
  826 		fatal("invalid IO scheduler priority");
  827 
  828 	io_sched = xmalloc(sizeof(*io_sched));
  829 	io_sched->policy_name = class_str;
  830 
  831 	if (strcmp(class_str, "real-time") == 0) {
  832 		io_sched->policy = IOPRIO_CLASS_RT;
  833 		io_sched->priority = prio;
  834 	} else if (strcmp(class_str, "best-effort") == 0) {
  835 		io_sched->policy = IOPRIO_CLASS_BE;
  836 		io_sched->priority = prio;
  837 	} else if (strcmp(class_str, "idle") == 0) {
  838 		io_sched->policy = IOPRIO_CLASS_IDLE;
  839 		io_sched->priority = 7;
  840 	} else
  841 		badusage("invalid IO scheduler policy");
  842 
  843 	if (io_sched->priority < IO_SCHED_PRIO_MIN)
  844 		badusage("IO scheduler priority less than min");
  845 	if (io_sched->priority > IO_SCHED_PRIO_MAX)
  846 		badusage("IO scheduler priority greater than max");
  847 }
  848 
  849 static void
  850 set_proc_schedule(struct res_schedule *sched)
  851 {
  852 #if defined(_POSIX_PRIORITY_SCHEDULING) && _POSIX_PRIORITY_SCHEDULING > 0
  853 	struct sched_param param;
  854 
  855 	param.sched_priority = sched->priority;
  856 
  857 	if (sched_setscheduler(getpid(), sched->policy, &param) == -1)
  858 		fatal("unable to set process scheduler");
  859 #endif
  860 }
  861 
  862 #ifdef HAVE_IOPRIO_SET
  863 static inline int
  864 ioprio_set(int which, int who, int ioprio)
  865 {
  866 	return syscall(SYS_ioprio_set, which, who, ioprio);
  867 }
  868 #endif
  869 
  870 static void
  871 set_io_schedule(struct res_schedule *sched)
  872 {
  873 #ifdef HAVE_IOPRIO_SET
  874 	int io_sched_mask;
  875 
  876 	io_sched_mask = IOPRIO_PRIO_VALUE(sched->policy, sched->priority);
  877 	if (ioprio_set(IOPRIO_WHO_PROCESS, getpid(), io_sched_mask) == -1)
  878 		warning("unable to alter IO priority to mask %i (%s)\n",
  879 		        io_sched_mask, strerror(errno));
  880 #endif
  881 }
  882 
  883 static void
  884 parse_schedule_item(const char *string, struct schedule_item *item)
  885 {
  886 	const char *after_hyph;
  887 
  888 	if (strcmp(string, "forever") == 0) {
  889 		item->type = sched_forever;
  890 	} else if (isdigit(string[0])) {
  891 		item->type = sched_timeout;
  892 		if (parse_unsigned(string, 10, &item->value) != 0)
  893 			badusage("invalid timeout value in schedule");
  894 	} else if ((after_hyph = string + (string[0] == '-')) &&
  895 	           parse_signal(after_hyph, &item->value) == 0) {
  896 		item->type = sched_signal;
  897 	} else {
  898 		badusage("invalid schedule item (must be [-]<signal-name>, "
  899 		         "-<signal-number>, <timeout> or 'forever'");
  900 	}
  901 }
  902 
  903 static void
  904 parse_schedule(const char *schedule_str)
  905 {
  906 	char item_buf[20];
  907 	const char *slash;
  908 	int count, repeatat;
  909 	size_t str_len;
  910 
  911 	count = 0;
  912 	for (slash = schedule_str; *slash; slash++)
  913 		if (*slash == '/')
  914 			count++;
  915 
  916 	schedule_length = (count == 0) ? 4 : count + 1;
  917 	schedule = xmalloc(sizeof(*schedule) * schedule_length);
  918 
  919 	if (count == 0) {
  920 		schedule[0].type = sched_signal;
  921 		schedule[0].value = signal_nr;
  922 		parse_schedule_item(schedule_str, &schedule[1]);
  923 		if (schedule[1].type != sched_timeout) {
  924 			badusage("--retry takes timeout, or schedule list"
  925 			         " of at least two items");
  926 		}
  927 		schedule[2].type = sched_signal;
  928 		schedule[2].value = SIGKILL;
  929 		schedule[3] = schedule[1];
  930 	} else {
  931 		count = 0;
  932 		repeatat = -1;
  933 		while (schedule_str != NULL) {
  934 			slash = strchr(schedule_str, '/');
  935 			str_len = slash ? (size_t)(slash - schedule_str) : strlen(schedule_str);
  936 			if (str_len >= sizeof(item_buf))
  937 				badusage("invalid schedule item: far too long"
  938 				         " (you must delimit items with slashes)");
  939 			memcpy(item_buf, schedule_str, str_len);
  940 			item_buf[str_len] = '\0';
  941 			schedule_str = slash ? slash + 1 : NULL;
  942 
  943 			parse_schedule_item(item_buf, &schedule[count]);
  944 			if (schedule[count].type == sched_forever) {
  945 				if (repeatat >= 0)
  946 					badusage("invalid schedule: 'forever'"
  947 					         " appears more than once");
  948 				repeatat = count;
  949 				continue;
  950 			}
  951 			count++;
  952 		}
  953 		if (repeatat == count)
  954 			badusage("invalid schedule: 'forever' appears last, "
  955 			         "nothing to repeat");
  956 		if (repeatat >= 0) {
  957 			schedule[count].type = sched_goto;
  958 			schedule[count].value = repeatat;
  959 			count++;
  960 		}
  961 		if (count != schedule_length)
  962 			BUG("count=%d != schedule_length=%d",
  963 			    count, schedule_length);
  964 	}
  965 }
  966 
  967 static void
  968 set_action(enum action_code new_action)
  969 {
  970 	if (action == new_action)
  971 		return;
  972 
  973 	if (action != ACTION_NONE)
  974 		badusage("only one command can be specified");
  975 
  976 	action = new_action;
  977 }
  978 
  979 #define OPT_PID		500
  980 #define OPT_PPID	501
  981 #define OPT_RM_PIDFILE	502
  982 
  983 static void
  984 parse_options(int argc, char * const *argv)
  985 {
  986 	static struct option longopts[] = {
  987 		{ "help",	  0, NULL, 'H'},
  988 		{ "stop",	  0, NULL, 'K'},
  989 		{ "start",	  0, NULL, 'S'},
  990 		{ "status",	  0, NULL, 'T'},
  991 		{ "version",	  0, NULL, 'V'},
  992 		{ "startas",	  1, NULL, 'a'},
  993 		{ "name",	  1, NULL, 'n'},
  994 		{ "oknodo",	  0, NULL, 'o'},
  995 		{ "pid",	  1, NULL, OPT_PID},
  996 		{ "ppid",	  1, NULL, OPT_PPID},
  997 		{ "pidfile",	  1, NULL, 'p'},
  998 		{ "quiet",	  0, NULL, 'q'},
  999 		{ "signal",	  1, NULL, 's'},
 1000 		{ "test",	  0, NULL, 't'},
 1001 		{ "user",	  1, NULL, 'u'},
 1002 		{ "group",	  1, NULL, 'g'},
 1003 		{ "chroot",	  1, NULL, 'r'},
 1004 		{ "verbose",	  0, NULL, 'v'},
 1005 		{ "exec",	  1, NULL, 'x'},
 1006 		{ "chuid",	  1, NULL, 'c'},
 1007 		{ "nicelevel",	  1, NULL, 'N'},
 1008 		{ "procsched",	  1, NULL, 'P'},
 1009 		{ "iosched",	  1, NULL, 'I'},
 1010 		{ "umask",	  1, NULL, 'k'},
 1011 		{ "background",	  0, NULL, 'b'},
 1012 		{ "no-close",	  0, NULL, 'C'},
 1013 		{ "make-pidfile", 0, NULL, 'm'},
 1014 		{ "remove-pidfile", 0, NULL, OPT_RM_PIDFILE},
 1015 		{ "retry",	  1, NULL, 'R'},
 1016 		{ "chdir",	  1, NULL, 'd'},
 1017 		{ NULL,		  0, NULL, 0  }
 1018 	};
 1019 	const char *pid_str = NULL;
 1020 	const char *ppid_str = NULL;
 1021 	const char *umask_str = NULL;
 1022 	const char *signal_str = NULL;
 1023 	const char *schedule_str = NULL;
 1024 	const char *proc_schedule_str = NULL;
 1025 	const char *io_schedule_str = NULL;
 1026 	size_t changeuser_len;
 1027 	int c;
 1028 
 1029 	for (;;) {
 1030 		c = getopt_long(argc, argv,
 1031 		                "HKSVTa:n:op:qr:s:tu:vx:c:N:P:I:k:bCmR:g:d:",
 1032 		                longopts, NULL);
 1033 		if (c == -1)
 1034 			break;
 1035 		switch (c) {
 1036 		case 'H':  /* --help */
 1037 			usage();
 1038 			exit(0);
 1039 		case 'K':  /* --stop */
 1040 			set_action(ACTION_STOP);
 1041 			break;
 1042 		case 'S':  /* --start */
 1043 			set_action(ACTION_START);
 1044 			break;
 1045 		case 'T':  /* --status */
 1046 			set_action(ACTION_STATUS);
 1047 			break;
 1048 		case 'V':  /* --version */
 1049 			do_version();
 1050 			exit(0);
 1051 		case 'a':  /* --startas <pathname> */
 1052 			startas = optarg;
 1053 			break;
 1054 		case 'n':  /* --name <process-name> */
 1055 			cmdname = optarg;
 1056 			break;
 1057 		case 'o':  /* --oknodo */
 1058 			exitnodo = 0;
 1059 			break;
 1060 		case OPT_PID: /* --pid <pid> */
 1061 			pid_str = optarg;
 1062 			break;
 1063 		case OPT_PPID: /* --ppid <ppid> */
 1064 			ppid_str = optarg;
 1065 			break;
 1066 		case 'p':  /* --pidfile <pid-file> */
 1067 			pidfile = optarg;
 1068 			break;
 1069 		case 'q':  /* --quiet */
 1070 			quietmode = true;
 1071 			break;
 1072 		case 's':  /* --signal <signal> */
 1073 			signal_str = optarg;
 1074 			break;
 1075 		case 't':  /* --test */
 1076 			testmode = true;
 1077 			break;
 1078 		case 'u':  /* --user <username>|<uid> */
 1079 			userspec = optarg;
 1080 			break;
 1081 		case 'v':  /* --verbose */
 1082 			quietmode = -1;
 1083 			break;
 1084 		case 'x':  /* --exec <executable> */
 1085 			execname = optarg;
 1086 			break;
 1087 		case 'c':  /* --chuid <username>|<uid> */
 1088 			/* We copy the string just in case we need the
 1089 			 * argument later. */
 1090 			changeuser_len = strcspn(optarg, ":");
 1091 			changeuser = xstrndup(optarg, changeuser_len);
 1092 			if (optarg[changeuser_len] == ':') {
 1093 				if (optarg[changeuser_len + 1] == '\0')
 1094 					fatal("missing group name");
 1095 				changegroup = optarg + changeuser_len + 1;
 1096 			}
 1097 			break;
 1098 		case 'g':  /* --group <group>|<gid> */
 1099 			changegroup = optarg;
 1100 			break;
 1101 		case 'r':  /* --chroot /new/root */
 1102 			changeroot = optarg;
 1103 			break;
 1104 		case 'N':  /* --nice */
 1105 			nicelevel = atoi(optarg);
 1106 			break;
 1107 		case 'P':  /* --procsched */
 1108 			proc_schedule_str = optarg;
 1109 			break;
 1110 		case 'I':  /* --iosched */
 1111 			io_schedule_str = optarg;
 1112 			break;
 1113 		case 'k':  /* --umask <mask> */
 1114 			umask_str = optarg;
 1115 			break;
 1116 		case 'b':  /* --background */
 1117 			background = true;
 1118 			break;
 1119 		case 'C': /* --no-close */
 1120 			close_io = false;
 1121 			break;
 1122 		case 'm':  /* --make-pidfile */
 1123 			mpidfile = true;
 1124 			break;
 1125 		case OPT_RM_PIDFILE: /* --remove-pidfile */
 1126 			rpidfile = true;
 1127 			break;
 1128 		case 'R':  /* --retry <schedule>|<timeout> */
 1129 			schedule_str = optarg;
 1130 			break;
 1131 		case 'd':  /* --chdir /new/dir */
 1132 			changedir = optarg;
 1133 			break;
 1134 		default:
 1135 			/* Message printed by getopt. */
 1136 			badusage(NULL);
 1137 		}
 1138 	}
 1139 
 1140 	if (pid_str != NULL) {
 1141 		if (parse_pid(pid_str, &match_pid) != 0)
 1142 			badusage("pid value must be a number greater than 0");
 1143 	}
 1144 
 1145 	if (ppid_str != NULL) {
 1146 		if (parse_pid(ppid_str, &match_ppid) != 0)
 1147 			badusage("ppid value must be a number greater than 0");
 1148 	}
 1149 
 1150 	if (signal_str != NULL) {
 1151 		if (parse_signal(signal_str, &signal_nr) != 0)
 1152 			badusage("signal value must be numeric or name"
 1153 			         " of signal (KILL, INT, ...)");
 1154 	}
 1155 
 1156 	if (schedule_str != NULL) {
 1157 		parse_schedule(schedule_str);
 1158 	}
 1159 
 1160 	if (proc_schedule_str != NULL)
 1161 		parse_proc_schedule(proc_schedule_str);
 1162 
 1163 	if (io_schedule_str != NULL)
 1164 		parse_io_schedule(io_schedule_str);
 1165 
 1166 	if (umask_str != NULL) {
 1167 		if (parse_umask(umask_str, &umask_value) != 0)
 1168 			badusage("umask value must be a positive number");
 1169 	}
 1170 
 1171 	if (action == ACTION_NONE)
 1172 		badusage("need one of --start or --stop or --status");
 1173 
 1174 	if (!execname && !pid_str && !ppid_str && !pidfile && !userspec &&
 1175 	    !cmdname)
 1176 		badusage("need at least one of --exec, --pid, --ppid, --pidfile, --user or --name");
 1177 
 1178 #ifdef PROCESS_NAME_SIZE
 1179 	if (cmdname && strlen(cmdname) > PROCESS_NAME_SIZE)
 1180 		warning("this system is not able to track process names\n"
 1181 		        "longer than %d characters, please use --exec "
 1182 		        "instead of --name.\n", PROCESS_NAME_SIZE);
 1183 #endif
 1184 
 1185 	if (!startas)
 1186 		startas = execname;
 1187 
 1188 	if (action == ACTION_START && !startas)
 1189 		badusage("--start needs --exec or --startas");
 1190 
 1191 	if (mpidfile && pidfile == NULL)
 1192 		badusage("--make-pidfile requires --pidfile");
 1193 	if (rpidfile && pidfile == NULL)
 1194 		badusage("--remove-pidfile requires --pidfile");
 1195 
 1196 	if (pid_str && pidfile)
 1197 		badusage("need either --pid of --pidfile, not both");
 1198 
 1199 	if (background && action != ACTION_START)
 1200 		badusage("--background is only relevant with --start");
 1201 
 1202 	if (!close_io && !background)
 1203 		badusage("--no-close is only relevant with --background");
 1204 }
 1205 
 1206 static void
 1207 setup_options(void)
 1208 {
 1209 	if (execname) {
 1210 		char *fullexecname;
 1211 
 1212 		/* If it's a relative path, normalize it. */
 1213 		if (execname[0] != '/')
 1214 			execname = newpath(changedir, execname);
 1215 
 1216 		if (changeroot)
 1217 			fullexecname = newpath(changeroot, execname);
 1218 		else
 1219 			fullexecname = execname;
 1220 
 1221 		if (stat(fullexecname, &exec_stat))
 1222 			fatal("unable to stat %s", fullexecname);
 1223 
 1224 		if (fullexecname != execname)
 1225 			free(fullexecname);
 1226 	}
 1227 
 1228 	if (userspec && parse_unsigned(userspec, 10, &user_id) < 0) {
 1229 		struct passwd *pw;
 1230 
 1231 		pw = getpwnam(userspec);
 1232 		if (!pw)
 1233 			fatal("user '%s' not found", userspec);
 1234 
 1235 		user_id = pw->pw_uid;
 1236 	}
 1237 
 1238 	if (changegroup && parse_unsigned(changegroup, 10, &runas_gid) < 0) {
 1239 		struct group *gr;
 1240 
 1241 		gr = getgrnam(changegroup);
 1242 		if (!gr)
 1243 			fatal("group '%s' not found", changegroup);
 1244 		changegroup = gr->gr_name;
 1245 		runas_gid = gr->gr_gid;
 1246 	}
 1247 	if (changeuser) {
 1248 		struct passwd *pw;
 1249 		struct stat st;
 1250 
 1251 		if (parse_unsigned(changeuser, 10, &runas_uid) == 0)
 1252 			pw = getpwuid(runas_uid);
 1253 		else
 1254 			pw = getpwnam(changeuser);
 1255 		if (!pw)
 1256 			fatal("user '%s' not found", changeuser);
 1257 		changeuser = pw->pw_name;
 1258 		runas_uid = pw->pw_uid;
 1259 		if (changegroup == NULL) {
 1260 			/* Pass the default group of this user. */
 1261 			changegroup = ""; /* Just empty. */
 1262 			runas_gid = pw->pw_gid;
 1263 		}
 1264 		if (stat(pw->pw_dir, &st) == 0)
 1265 			setenv("HOME", pw->pw_dir, 1);
 1266 	}
 1267 }
 1268 
 1269 #if defined(OS_Linux)
 1270 static const char *
 1271 proc_status_field(pid_t pid, const char *field)
 1272 {
 1273 	static char *line = NULL;
 1274 	static size_t line_size = 0;
 1275 
 1276 	FILE *fp;
 1277 	char filename[32];
 1278 	char *value = NULL;
 1279 	ssize_t line_len;
 1280 	size_t field_len = strlen(field);
 1281 
 1282 	sprintf(filename, "/proc/%d/status", pid);
 1283 	fp = fopen(filename, "r");
 1284 	if (!fp)
 1285 		return NULL;
 1286 	while ((line_len = getline(&line, &line_size, fp)) >= 0) {
 1287 		if (strncasecmp(line, field, field_len) == 0) {
 1288 			line[line_len - 1] = '\0';
 1289 
 1290 			value = line + field_len;
 1291 			while (isspace(*value))
 1292 				value++;
 1293 
 1294 			break;
 1295 		}
 1296 	}
 1297 	fclose(fp);
 1298 
 1299 	return value;
 1300 }
 1301 #elif defined(OS_AIX)
 1302 static bool
 1303 proc_get_psinfo(pid_t pid, struct psinfo *psinfo)
 1304 {
 1305 	char filename[64];
 1306 	FILE *fp;
 1307 
 1308 	sprintf(filename, "/proc/%d/psinfo", pid);
 1309 	fp = fopen(filename, "r");
 1310 	if (!fp)
 1311 		return false;
 1312 	if (fread(psinfo, sizeof(*psinfo), 1, fp) == 0) {
 1313 		fclose(fp);
 1314 		return false;
 1315 	}
 1316 	if (ferror(fp)) {
 1317 		fclose(fp);
 1318 		return false;
 1319 	}
 1320 
 1321 	fclose(fp);
 1322 
 1323 	return true;
 1324 }
 1325 #elif defined(OS_Hurd)
 1326 static void
 1327 init_procset(void)
 1328 {
 1329 	struct ps_context *context;
 1330 	error_t err;
 1331 
 1332 	err = ps_context_create(getproc(), &context);
 1333 	if (err)
 1334 		error(1, err, "ps_context_create");
 1335 
 1336 	err = proc_stat_list_create(context, &procset);
 1337 	if (err)
 1338 		error(1, err, "proc_stat_list_create");
 1339 
 1340 	err = proc_stat_list_add_all(procset, 0, 0);
 1341 	if (err)
 1342 		error(1, err, "proc_stat_list_add_all");
 1343 }
 1344 
 1345 static struct proc_stat *
 1346 get_proc_stat(pid_t pid, ps_flags_t flags)
 1347 {
 1348 	struct proc_stat *ps;
 1349 	ps_flags_t wanted_flags = PSTAT_PID | flags;
 1350 
 1351 	if (!procset)
 1352 		init_procset();
 1353 
 1354 	ps = proc_stat_list_pid_proc_stat(procset, pid);
 1355 	if (!ps)
 1356 		return NULL;
 1357 	if (proc_stat_set_flags(ps, wanted_flags))
 1358 		return NULL;
 1359 	if ((proc_stat_flags(ps) & wanted_flags) != wanted_flags)
 1360 		return NULL;
 1361 
 1362 	return ps;
 1363 }
 1364 #elif defined(HAVE_KVM_H)
 1365 static kvm_t *
 1366 ssd_kvm_open(void)
 1367 {
 1368 	kvm_t *kd;
 1369 	char errbuf[_POSIX2_LINE_MAX];
 1370 
 1371 	kd = kvm_openfiles(NULL, KVM_MEMFILE, NULL, O_RDONLY, errbuf);
 1372 	if (kd == NULL)
 1373 		errx(1, "%s", errbuf);
 1374 
 1375 	return kd;
 1376 }
 1377 
 1378 static struct kinfo_proc *
 1379 ssd_kvm_get_procs(kvm_t *kd, int op, int arg, int *count)
 1380 {
 1381 	struct kinfo_proc *kp;
 1382 	int lcount;
 1383 
 1384 	if (count == NULL)
 1385 		count = &lcount;
 1386 	*count = 0;
 1387 
 1388 #if defined(OS_OpenBSD)
 1389 	kp = kvm_getprocs(kd, op, arg, sizeof(*kp), count);
 1390 #else
 1391 	kp = kvm_getprocs(kd, op, arg, count);
 1392 #endif
 1393 	if (kp == NULL && errno != ESRCH)
 1394 		errx(1, "%s", kvm_geterr(kd));
 1395 
 1396 	return kp;
 1397 }
 1398 #endif
 1399 
 1400 #if defined(OS_Linux)
 1401 static bool
 1402 pid_is_exec(pid_t pid, const struct stat *esb)
 1403 {
 1404 	char lname[32];
 1405 	char lcontents[_POSIX_PATH_MAX + 1];
 1406 	char *filename;
 1407 	const char deleted[] = " (deleted)";
 1408 	int nread;
 1409 	struct stat sb;
 1410 
 1411 	sprintf(lname, "/proc/%d/exe", pid);
 1412 	nread = readlink(lname, lcontents, sizeof(lcontents) - 1);
 1413 	if (nread == -1)
 1414 		return false;
 1415 
 1416 	filename = lcontents;
 1417 	filename[nread] = '\0';
 1418 
 1419 	/* OpenVZ kernels contain a bogus patch that instead of appending,
 1420 	 * prepends the deleted marker. Workaround those. Otherwise handle
 1421 	 * the normal appended marker. */
 1422 	if (strncmp(filename, deleted, strlen(deleted)) == 0)
 1423 		filename += strlen(deleted);
 1424 	else if (strcmp(filename + nread - strlen(deleted), deleted) == 0)
 1425 		filename[nread - strlen(deleted)] = '\0';
 1426 
 1427 	if (stat(filename, &sb) != 0)
 1428 		return false;
 1429 
 1430 	return (sb.st_dev == esb->st_dev && sb.st_ino == esb->st_ino);
 1431 }
 1432 #elif defined(OS_AIX)
 1433 static bool
 1434 pid_is_exec(pid_t pid, const struct stat *esb)
 1435 {
 1436 	struct stat sb;
 1437 	char filename[64];
 1438 
 1439 	sprintf(filename, "/proc/%d/object/a.out", pid);
 1440 
 1441 	if (stat(filename, &sb) != 0)
 1442 		return false;
 1443 
 1444 	return sb.st_dev == esb->st_dev && sb.st_ino == esb->st_ino;
 1445 }
 1446 #elif defined(OS_Hurd)
 1447 static bool
 1448 pid_is_exec(pid_t pid, const struct stat *esb)
 1449 {
 1450 	struct proc_stat *ps;
 1451 	struct stat sb;
 1452 	const char *filename;
 1453 
 1454 	ps = get_proc_stat(pid, PSTAT_ARGS);
 1455 	if (ps == NULL)
 1456 		return false;
 1457 
 1458 	/* On old Hurd systems we have to use the argv[0] value, because
 1459 	 * there is nothing better. */
 1460 	filename = proc_stat_args(ps);
 1461 #ifdef PSTAT_EXE
 1462 	/* On new Hurd systems we can use the correct value, as long
 1463 	 * as it's not NULL nor empty, as it was the case on the first
 1464 	 * implementation. */
 1465 	if (proc_stat_set_flags(ps, PSTAT_EXE) == 0 &&
 1466 	    proc_stat_flags(ps) & PSTAT_EXE &&
 1467 	    proc_stat_exe(ps) != NULL &&
 1468 	    proc_stat_exe(ps)[0] != '\0')
 1469 		filename = proc_stat_exe(ps);
 1470 #endif
 1471 
 1472 	if (stat(filename, &sb) != 0)
 1473 		return false;
 1474 
 1475 	return (sb.st_dev == esb->st_dev && sb.st_ino == esb->st_ino);
 1476 }
 1477 #elif defined(OS_Darwin)
 1478 static bool
 1479 pid_is_exec(pid_t pid, const struct stat *esb)
 1480 {
 1481 	struct stat sb;
 1482 	char pathname[_POSIX_PATH_MAX];
 1483 
 1484 	if (proc_pidpath(pid, pathname, sizeof(pathname)) < 0)
 1485 		return false;
 1486 
 1487 	if (stat(pathname, &sb) != 0)
 1488 		return false;
 1489 
 1490 	return (sb.st_dev == esb->st_dev && sb.st_ino == esb->st_ino);
 1491 }
 1492 #elif defined(OS_HPUX)
 1493 static bool
 1494 pid_is_exec(pid_t pid, const struct stat *esb)
 1495 {
 1496 	struct pst_status pst;
 1497 
 1498 	if (pstat_getproc(&pst, sizeof(pst), (size_t)0, (int)pid) < 0)
 1499 		return false;
 1500 	return ((dev_t)pst.pst_text.psf_fsid.psfs_id == esb->st_dev &&
 1501 	        (ino_t)pst.pst_text.psf_fileid == esb->st_ino);
 1502 }
 1503 #elif defined(OS_FreeBSD)
 1504 static bool
 1505 pid_is_exec(pid_t pid, const struct stat *esb)
 1506 {
 1507 	struct stat sb;
 1508 	int error, mib[4];
 1509 	size_t len;
 1510 	char pathname[PATH_MAX];
 1511 
 1512 	mib[0] = CTL_KERN;
 1513 	mib[1] = KERN_PROC;
 1514 	mib[2] = KERN_PROC_PATHNAME;
 1515 	mib[3] = pid;
 1516 	len = sizeof(pathname);
 1517 
 1518 	error = sysctl(mib, 4, pathname, &len, NULL, 0);
 1519 	if (error != 0 && errno != ESRCH)
 1520 		return false;
 1521 	if (len == 0)
 1522 		pathname[0] = '\0';
 1523 
 1524 	if (stat(pathname, &sb) != 0)
 1525 		return false;
 1526 
 1527 	return (sb.st_dev == esb->st_dev && sb.st_ino == esb->st_ino);
 1528 }
 1529 #elif defined(HAVE_KVM_H)
 1530 static bool
 1531 pid_is_exec(pid_t pid, const struct stat *esb)
 1532 {
 1533 	kvm_t *kd;
 1534 	int argv_len = 0;
 1535 	struct kinfo_proc *kp;
 1536 	struct stat sb;
 1537 	char buf[_POSIX2_LINE_MAX];
 1538 	char **pid_argv_p;
 1539 	char *start_argv_0_p, *end_argv_0_p;
 1540 	bool res = false;
 1541 
 1542 	kd = ssd_kvm_open();
 1543 	kp = ssd_kvm_get_procs(kd, KERN_PROC_PID, pid, NULL);
 1544 	if (kp == NULL)
 1545 		goto cleanup;
 1546 
 1547 	pid_argv_p = kvm_getargv(kd, kp, argv_len);
 1548 	if (pid_argv_p == NULL)
 1549 		errx(1, "%s", kvm_geterr(kd));
 1550 
 1551 	/* Find and compare string. */
 1552 	start_argv_0_p = *pid_argv_p;
 1553 
 1554 	/* Find end of argv[0] then copy and cut of str there. */
 1555 	end_argv_0_p = strchr(*pid_argv_p, ' ');
 1556 	if (end_argv_0_p == NULL)
 1557 		/* There seems to be no space, so we have the command
 1558 		 * already in its desired form. */
 1559 		start_argv_0_p = *pid_argv_p;
 1560 	else {
 1561 		/* Tests indicate that this never happens, since
 1562 		 * kvm_getargv itself cuts of tailing stuff. This is
 1563 		 * not what the manpage says, however. */
 1564 		strncpy(buf, *pid_argv_p, (end_argv_0_p - start_argv_0_p));
 1565 		buf[(end_argv_0_p - start_argv_0_p) + 1] = '\0';
 1566 		start_argv_0_p = buf;
 1567 	}
 1568 
 1569 	if (stat(start_argv_0_p, &sb) != 0)
 1570 		goto cleanup;
 1571 
 1572 	res = (sb.st_dev == esb->st_dev && sb.st_ino == esb->st_ino);
 1573 
 1574 cleanup:
 1575 	kvm_close(kd);
 1576 
 1577 	return res;
 1578 }
 1579 #endif
 1580 
 1581 #if defined(OS_Linux)
 1582 static bool
 1583 pid_is_child(pid_t pid, pid_t ppid)
 1584 {
 1585 	const char *ppid_str;
 1586 	pid_t proc_ppid;
 1587 	int rc;
 1588 
 1589 	ppid_str = proc_status_field(pid, "PPid:");
 1590 	if (ppid_str == NULL)
 1591 		return false;
 1592 
 1593 	rc = parse_pid(ppid_str, &proc_ppid);
 1594 	if (rc < 0)
 1595 		return false;
 1596 
 1597 	return proc_ppid == ppid;
 1598 }
 1599 #elif defined(OS_Hurd)
 1600 static bool
 1601 pid_is_child(pid_t pid, pid_t ppid)
 1602 {
 1603 	struct proc_stat *ps;
 1604 	struct procinfo *pi;
 1605 
 1606 	ps = get_proc_stat(pid, PSTAT_PROC_INFO);
 1607 	if (ps == NULL)
 1608 		return false;
 1609 
 1610 	pi = proc_stat_proc_info(ps);
 1611 
 1612 	return pi->ppid == ppid;
 1613 }
 1614 #elif defined(OS_Darwin)
 1615 static bool
 1616 pid_is_child(pid_t pid, pid_t ppid)
 1617 {
 1618 	struct proc_bsdinfo info;
 1619 
 1620 	if (proc_pidinfo(pid, PROC_PIDTBSDINFO, 0, &info, sizeof(info)) < 0)
 1621 		return false;
 1622 
 1623 	return (pid_t)info.pbi_ppid == ppid;
 1624 }
 1625 #elif defined(OS_AIX)
 1626 static bool
 1627 pid_is_child(pid_t pid, pid_t ppid)
 1628 {
 1629 	struct psinfo psi;
 1630 
 1631 	if (!proc_get_psinfo(pid, &psi))
 1632 		return false;
 1633 
 1634 	return (pid_t)psi.pr_ppid == ppid;
 1635 }
 1636 #elif defined(OS_HPUX)
 1637 static bool
 1638 pid_is_child(pid_t pid, pid_t ppid)
 1639 {
 1640 	struct pst_status pst;
 1641 
 1642 	if (pstat_getproc(&pst, sizeof(pst), (size_t)0, (int)pid) < 0)
 1643 		return false;
 1644 
 1645 	return pst.pst_ppid == ppid;
 1646 }
 1647 #elif defined(OS_FreeBSD)
 1648 static bool
 1649 pid_is_child(pid_t pid, pid_t ppid)
 1650 {
 1651 	struct kinfo_proc kp;
 1652 	int rc, mib[4];
 1653 	size_t len;
 1654 
 1655 	mib[0] = CTL_KERN;
 1656 	mib[1] = KERN_PROC;
 1657 	mib[2] = KERN_PROC_PID;
 1658 	mib[3] = pid;
 1659 	len = sizeof(kp);
 1660 
 1661 	rc = sysctl(mib, 4, &kp, &len, NULL, 0);
 1662 	if (rc != 0 && errno != ESRCH)
 1663 		return false;
 1664 	if (len == 0 || len != sizeof(kp))
 1665 		return false;
 1666 
 1667 	return kp.ki_ppid == ppid;
 1668 }
 1669 #elif defined(HAVE_KVM_H)
 1670 static bool
 1671 pid_is_child(pid_t pid, pid_t ppid)
 1672 {
 1673 	kvm_t *kd;
 1674 	struct kinfo_proc *kp;
 1675 	pid_t proc_ppid;
 1676 	bool res = false;
 1677 
 1678 	kd = ssd_kvm_open();
 1679 	kp = ssd_kvm_get_procs(kd, KERN_PROC_PID, pid, NULL);
 1680 	if (kp == NULL)
 1681 		goto cleanup;
 1682 
 1683 #if defined(OS_FreeBSD)
 1684 	proc_ppid = kp->ki_ppid;
 1685 #elif defined(OS_OpenBSD)
 1686 	proc_ppid = kp->p_ppid;
 1687 #elif defined(OS_DragonFlyBSD)
 1688 	proc_ppid = kp->kp_ppid;
 1689 #else
 1690 	proc_ppid = kp->kp_proc.p_ppid;
 1691 #endif
 1692 
 1693 	res = (proc_ppid == ppid);
 1694 
 1695 cleanup:
 1696 	kvm_close(kd);
 1697 
 1698 	return res;
 1699 }
 1700 #endif
 1701 
 1702 #if defined(OS_Linux)
 1703 static bool
 1704 pid_is_user(pid_t pid, uid_t uid)
 1705 {
 1706 	struct stat sb;
 1707 	char buf[32];
 1708 
 1709 	sprintf(buf, "/proc/%d", pid);
 1710 	if (stat(buf, &sb) != 0)
 1711 		return false;
 1712 	return (sb.st_uid == uid);
 1713 }
 1714 #elif defined(OS_Hurd)
 1715 static bool
 1716 pid_is_user(pid_t pid, uid_t uid)
 1717 {
 1718 	struct proc_stat *ps;
 1719 
 1720 	ps = get_proc_stat(pid, PSTAT_OWNER_UID);
 1721 	return ps && (uid_t)proc_stat_owner_uid(ps) == uid;
 1722 }
 1723 #elif defined(OS_Darwin)
 1724 static bool
 1725 pid_is_user(pid_t pid, uid_t uid)
 1726 {
 1727 	struct proc_bsdinfo info;
 1728 
 1729 	if (proc_pidinfo(pid, PROC_PIDTBSDINFO, 0, &info, sizeof(info)) < 0)
 1730 		return false;
 1731 
 1732 	return info.pbi_ruid == uid;
 1733 }
 1734 #elif defined(OS_AIX)
 1735 static bool
 1736 pid_is_user(pid_t pid, uid_t uid)
 1737 {
 1738 	struct psinfo psi;
 1739 
 1740 	if (!proc_get_psinfo(pid, &psi))
 1741 		return false;
 1742 
 1743 	return psi.pr_uid == uid;
 1744 }
 1745 #elif defined(OS_HPUX)
 1746 static bool
 1747 pid_is_user(pid_t pid, uid_t uid)
 1748 {
 1749 	struct pst_status pst;
 1750 
 1751 	if (pstat_getproc(&pst, sizeof(pst), (size_t)0, (int)pid) < 0)
 1752 		return false;
 1753 	return ((uid_t)pst.pst_uid == uid);
 1754 }
 1755 #elif defined(OS_FreeBSD)
 1756 static bool
 1757 pid_is_user(pid_t pid, uid_t uid)
 1758 {
 1759 	struct kinfo_proc kp;
 1760 	int rc, mib[4];
 1761 	size_t len;
 1762 
 1763 	mib[0] = CTL_KERN;
 1764 	mib[1] = KERN_PROC;
 1765 	mib[2] = KERN_PROC_PID;
 1766 	mib[3] = pid;
 1767 	len = sizeof(kp);
 1768 
 1769 	rc = sysctl(mib, 4, &kp, &len, NULL, 0);
 1770 	if (rc != 0 && errno != ESRCH)
 1771 		return false;
 1772 	if (len == 0 || len != sizeof(kp))
 1773 		return false;
 1774 
 1775 	return kp.ki_ruid == uid;
 1776 }
 1777 #elif defined(HAVE_KVM_H)
 1778 static bool
 1779 pid_is_user(pid_t pid, uid_t uid)
 1780 {
 1781 	kvm_t *kd;
 1782 	uid_t proc_uid;
 1783 	struct kinfo_proc *kp;
 1784 	bool res = false;
 1785 
 1786 	kd = ssd_kvm_open();
 1787 	kp = ssd_kvm_get_procs(kd, KERN_PROC_PID, pid, NULL);
 1788 	if (kp == NULL)
 1789 		goto cleanup;
 1790 
 1791 #if defined(OS_FreeBSD)
 1792 	proc_uid = kp->ki_ruid;
 1793 #elif defined(OS_OpenBSD)
 1794 	proc_uid = kp->p_ruid;
 1795 #elif defined(OS_DragonFlyBSD)
 1796 	proc_uid = kp->kp_ruid;
 1797 #elif defined(OS_NetBSD)
 1798 	proc_uid = kp->kp_eproc.e_pcred.p_ruid;
 1799 #else
 1800 	if (kp->kp_proc.p_cred)
 1801 		kvm_read(kd, (u_long)&(kp->kp_proc.p_cred->p_ruid),
 1802 		         &proc_uid, sizeof(uid_t));
 1803 	else
 1804 		goto cleanup;
 1805 #endif
 1806 
 1807 	res = (proc_uid == (uid_t)uid);
 1808 
 1809 cleanup:
 1810 	kvm_close(kd);
 1811 
 1812 	return res;
 1813 }
 1814 #endif
 1815 
 1816 #if defined(OS_Linux)
 1817 static bool
 1818 pid_is_cmd(pid_t pid, const char *name)
 1819 {
 1820 	const char *comm;
 1821 
 1822 	comm = proc_status_field(pid, "Name:");
 1823 	if (comm == NULL)
 1824 		return false;
 1825 
 1826 	return strcmp(comm, name) == 0;
 1827 }
 1828 #elif defined(OS_Hurd)
 1829 static bool
 1830 pid_is_cmd(pid_t pid, const char *name)
 1831 {
 1832 	struct proc_stat *ps;
 1833 	size_t argv0_len;
 1834 	const char *argv0;
 1835 	const char *binary_name;
 1836 
 1837 	ps = get_proc_stat(pid, PSTAT_ARGS);
 1838 	if (ps == NULL)
 1839 		return false;
 1840 
 1841 	argv0 = proc_stat_args(ps);
 1842 	argv0_len = strlen(argv0) + 1;
 1843 
 1844 	binary_name = basename(argv0);
 1845 	if (strcmp(binary_name, name) == 0)
 1846 		return true;
 1847 
 1848 	/* XXX: This is all kinds of ugly, but on the Hurd there's no way to
 1849 	 * know the command name of a process, so we have to try to match
 1850 	 * also on argv[1] for the case of an interpreted script. */
 1851 	if (proc_stat_args_len(ps) > argv0_len) {
 1852 		const char *script_name = basename(argv0 + argv0_len);
 1853 
 1854 		return strcmp(script_name, name) == 0;
 1855 	}
 1856 
 1857 	return false;
 1858 }
 1859 #elif defined(OS_AIX)
 1860 static bool
 1861 pid_is_cmd(pid_t pid, const char *name)
 1862 {
 1863 	struct psinfo psi;
 1864 
 1865 	if (!proc_get_psinfo(pid, &psi))
 1866 		return false;
 1867 
 1868 	return strcmp(psi.pr_fname, name) == 0;
 1869 }
 1870 #elif defined(OS_HPUX)
 1871 static bool
 1872 pid_is_cmd(pid_t pid, const char *name)
 1873 {
 1874 	struct pst_status pst;
 1875 
 1876 	if (pstat_getproc(&pst, sizeof(pst), (size_t)0, (int)pid) < 0)
 1877 		return false;
 1878 	return (strcmp(pst.pst_ucomm, name) == 0);
 1879 }
 1880 #elif defined(OS_Darwin)
 1881 static bool
 1882 pid_is_cmd(pid_t pid, const char *name)
 1883 {
 1884 	char pathname[_POSIX_PATH_MAX];
 1885 
 1886 	if (proc_pidpath(pid, pathname, sizeof(pathname)) < 0)
 1887 		return false;
 1888 
 1889 	return strcmp(pathname, name) == 0;
 1890 }
 1891 #elif defined(OS_FreeBSD)
 1892 static bool
 1893 pid_is_cmd(pid_t pid, const char *name)
 1894 {
 1895 	struct kinfo_proc kp;
 1896 	int rc, mib[4];
 1897 	size_t len;
 1898 
 1899 	mib[0] = CTL_KERN;
 1900 	mib[1] = KERN_PROC;
 1901 	mib[2] = KERN_PROC_PID;
 1902 	mib[3] = pid;
 1903 	len = sizeof(kp);
 1904 
 1905 	rc = sysctl(mib, 4, &kp, &len, NULL, 0);
 1906 	if (rc != 0 && errno != ESRCH)
 1907 		return false;
 1908 	if (len == 0 || len != sizeof(kp))
 1909 		return false;
 1910 
 1911 	return strcmp(kp.ki_comm, name) == 0;
 1912 }
 1913 #elif defined(HAVE_KVM_H)
 1914 static bool
 1915 pid_is_cmd(pid_t pid, const char *name)
 1916 {
 1917 	kvm_t *kd;
 1918 	struct kinfo_proc *kp;
 1919 	char *process_name;
 1920 	bool res = false;
 1921 
 1922 	kd = ssd_kvm_open();
 1923 	kp = ssd_kvm_get_procs(kd, KERN_PROC_PID, pid, NULL);
 1924 	if (kp == NULL)
 1925 		goto cleanup;
 1926 
 1927 #if defined(OS_FreeBSD)
 1928 	process_name = kp->ki_comm;
 1929 #elif defined(OS_OpenBSD)
 1930 	process_name = kp->p_comm;
 1931 #elif defined(OS_DragonFlyBSD)
 1932 	process_name = kp->kp_comm;
 1933 #else
 1934 	process_name = kp->kp_proc.p_comm;
 1935 #endif
 1936 
 1937 	res = (strcmp(name, process_name) == 0);
 1938 
 1939 cleanup:
 1940 	kvm_close(kd);
 1941 
 1942 	return res;
 1943 }
 1944 #endif
 1945 
 1946 #if defined(OS_Hurd)
 1947 static bool
 1948 pid_is_running(pid_t pid)
 1949 {
 1950 	return get_proc_stat(pid, 0) != NULL;
 1951 }
 1952 #else /* !OS_Hurd */
 1953 static bool
 1954 pid_is_running(pid_t pid)
 1955 {
 1956 	if (kill(pid, 0) == 0 || errno == EPERM)
 1957 		return true;
 1958 	else if (errno == ESRCH)
 1959 		return false;
 1960 	else
 1961 		fatal("error checking pid %u status", pid);
 1962 }
 1963 #endif
 1964 
 1965 static enum status_code
 1966 pid_check(pid_t pid)
 1967 {
 1968 	if (execname && !pid_is_exec(pid, &exec_stat))
 1969 		return STATUS_DEAD;
 1970 	if (match_ppid > 0 && !pid_is_child(pid, match_ppid))
 1971 		return STATUS_DEAD;
 1972 	if (userspec && !pid_is_user(pid, user_id))
 1973 		return STATUS_DEAD;
 1974 	if (cmdname && !pid_is_cmd(pid, cmdname))
 1975 		return STATUS_DEAD;
 1976 	if (action != ACTION_STOP && !pid_is_running(pid))
 1977 		return STATUS_DEAD;
 1978 
 1979 	pid_list_push(&found, pid);
 1980 
 1981 	return STATUS_OK;
 1982 }
 1983 
 1984 static enum status_code
 1985 do_pidfile(const char *name)
 1986 {
 1987 	FILE *f;
 1988 	static pid_t pid = 0;
 1989 
 1990 	if (pid)
 1991 		return pid_check(pid);
 1992 
 1993 	f = fopen(name, "r");
 1994 	if (f) {
 1995 		enum status_code pid_status;
 1996 
 1997 		if (fscanf(f, "%d", &pid) == 1)
 1998 			pid_status = pid_check(pid);
 1999 		else
 2000 			pid_status = STATUS_UNKNOWN;
 2001 		fclose(f);
 2002 
 2003 		if (pid_status == STATUS_DEAD)
 2004 			return STATUS_DEAD_PIDFILE;
 2005 		else
 2006 			return pid_status;
 2007 	} else if (errno == ENOENT)
 2008 		return STATUS_DEAD;
 2009 	else
 2010 		fatal("unable to open pidfile %s", name);
 2011 }
 2012 
 2013 #if defined(OS_Linux) || defined(OS_Solaris) || defined(OS_AIX)
 2014 static enum status_code
 2015 do_procinit(void)
 2016 {
 2017 	DIR *procdir;
 2018 	struct dirent *entry;
 2019 	int foundany;
 2020 	pid_t pid;
 2021 	enum status_code prog_status = STATUS_DEAD;
 2022 
 2023 	procdir = opendir("/proc");
 2024 	if (!procdir)
 2025 		fatal("unable to opendir /proc");
 2026 
 2027 	foundany = 0;
 2028 	while ((entry = readdir(procdir)) != NULL) {
 2029 		enum status_code pid_status;
 2030 
 2031 		if (sscanf(entry->d_name, "%d", &pid) != 1)
 2032 			continue;
 2033 		foundany++;
 2034 
 2035 		pid_status = pid_check(pid);
 2036 		if (pid_status < prog_status)
 2037 			prog_status = pid_status;
 2038 	}
 2039 	closedir(procdir);
 2040 	if (!foundany)
 2041 		fatal("nothing in /proc - not mounted?");
 2042 
 2043 	return prog_status;
 2044 }
 2045 #elif defined(OS_Hurd)
 2046 static int
 2047 check_proc_stat(struct proc_stat *ps)
 2048 {
 2049 	pid_check(proc_stat_pid(ps));
 2050 	return 0;
 2051 }
 2052 
 2053 static enum status_code
 2054 do_procinit(void)
 2055 {
 2056 	if (!procset)
 2057 		init_procset();
 2058 
 2059 	proc_stat_list_for_each(procset, check_proc_stat);
 2060 
 2061 	if (found)
 2062 		return STATUS_OK;
 2063 	else
 2064 		return STATUS_DEAD;
 2065 }
 2066 #elif defined(OS_Darwin)
 2067 static enum status_code
 2068 do_procinit(void)
 2069 {
 2070 	pid_t *pid_buf;
 2071 	int i, npids, pid_bufsize;
 2072 	enum status_code prog_status = STATUS_DEAD;
 2073 
 2074 	npids = proc_listallpids(NULL, 0);
 2075 	if (npids == 0)
 2076 		return STATUS_UNKNOWN;
 2077 
 2078 	/* Try to avoid sudden changes in number of PIDs. */
 2079 	npids += 4096;
 2080 	pid_bufsize = sizeof(pid_t) * npids;
 2081 	pid_buf = xmalloc(pid_bufsize);
 2082 
 2083 	npids = proc_listallpids(pid_buf, pid_bufsize);
 2084 	if (npids == 0)
 2085 		return STATUS_UNKNOWN;
 2086 
 2087 	for (i = 0; i < npids; i++) {
 2088 		enum status_code pid_status;
 2089 
 2090 		pid_status = pid_check(pid_buf[i]);
 2091 		if (pid_status < prog_status)
 2092 			prog_status = pid_status;
 2093 	}
 2094 
 2095 	free(pid_buf);
 2096 
 2097 	return prog_status;
 2098 }
 2099 #elif defined(OS_HPUX)
 2100 static enum status_code
 2101 do_procinit(void)
 2102 {
 2103 	struct pst_status pst[10];
 2104 	int i, count;
 2105 	int idx = 0;
 2106 	enum status_code prog_status = STATUS_DEAD;
 2107 
 2108 	while ((count = pstat_getproc(pst, sizeof(pst[0]), 10, idx)) > 0) {
 2109 		enum status_code pid_status;
 2110 
 2111 		for (i = 0; i < count; i++) {
 2112 			pid_status = pid_check(pst[i].pst_pid);
 2113 			if (pid_status < prog_status)
 2114 				prog_status = pid_status;
 2115 		}
 2116 		idx = pst[count - 1].pst_idx + 1;
 2117 	}
 2118 
 2119 	return prog_status;
 2120 }
 2121 #elif defined(OS_FreeBSD)
 2122 static enum status_code
 2123 do_procinit(void)
 2124 {
 2125 	struct kinfo_proc *kp;
 2126 	int rc, mib[3];
 2127 	size_t len = 0;
 2128 	int nentries, i;
 2129 	enum status_code prog_status = STATUS_DEAD;
 2130 
 2131 	mib[0] = CTL_KERN;
 2132 	mib[1] = KERN_PROC;
 2133 	mib[2] = KERN_PROC_PROC;
 2134 
 2135 	rc = sysctl(mib, 3, NULL, &len, NULL, 0);
 2136 	if (rc != 0 && errno != ESRCH)
 2137 		return STATUS_UNKNOWN;
 2138 	if (len == 0)
 2139 		return STATUS_UNKNOWN;
 2140 
 2141 	kp = xmalloc(len);
 2142 	rc = sysctl(mib, 3, kp, &len, NULL, 0);
 2143 	if (rc != 0 && errno != ESRCH)
 2144 		return STATUS_UNKNOWN;
 2145 	if (len == 0)
 2146 		return STATUS_UNKNOWN;
 2147 	nentries = len / sizeof(*kp);
 2148 
 2149 	for (i = 0; i < nentries; i++) {
 2150 		enum status_code pid_status;
 2151 
 2152 		pid_status = pid_check(kp[i].ki_pid);
 2153 		if (pid_status < prog_status)
 2154 			prog_status = pid_status;
 2155 	}
 2156 
 2157 	free(kp);
 2158 
 2159 	return prog_status;
 2160 }
 2161 #elif defined(HAVE_KVM_H)
 2162 static enum status_code
 2163 do_procinit(void)
 2164 {
 2165 	kvm_t *kd;
 2166 	int nentries, i;
 2167 	struct kinfo_proc *kp;
 2168 	enum status_code prog_status = STATUS_DEAD;
 2169 
 2170 	kd = ssd_kvm_open();
 2171 	kp = ssd_kvm_get_procs(kd, KERN_PROC_ALL, 0, &nentries);
 2172 
 2173 	for (i = 0; i < nentries; i++) {
 2174 		enum status_code pid_status;
 2175 		pid_t pid;
 2176 
 2177 #if defined(OS_FreeBSD)
 2178 		pid = kp[i].ki_pid;
 2179 #elif defined(OS_OpenBSD)
 2180 		pid = kp[i].p_pid;
 2181 #elif defined(OS_DragonFlyBSD)
 2182 		pid = kp[i].kp_pid;
 2183 #else
 2184 		pid = kp[i].kp_proc.p_pid;
 2185 #endif
 2186 
 2187 		pid_status = pid_check(pid);
 2188 		if (pid_status < prog_status)
 2189 			prog_status = pid_status;
 2190 	}
 2191 
 2192 	kvm_close(kd);
 2193 
 2194 	return prog_status;
 2195 }
 2196 #endif
 2197 
 2198 static enum status_code
 2199 do_findprocs(void)
 2200 {
 2201 	pid_list_free(&found);
 2202 
 2203 	if (match_pid > 0)
 2204 		return pid_check(match_pid);
 2205 	else if (pidfile)
 2206 		return do_pidfile(pidfile);
 2207 	else
 2208 		return do_procinit();
 2209 }
 2210 
 2211 static int
 2212 do_start(int argc, char **argv)
 2213 {
 2214 	int devnull_fd = -1;
 2215 	gid_t rgid;
 2216 	uid_t ruid;
 2217 
 2218 	do_findprocs();
 2219 
 2220 	if (found) {
 2221 		if (quietmode <= 0)
 2222 			printf("%s already running.\n", execname ? execname : "process");
 2223 		return exitnodo;
 2224 	}
 2225 	if (testmode && quietmode <= 0) {
 2226 		printf("Would start %s ", startas);
 2227 		while (argc-- > 0)
 2228 			printf("%s ", *argv++);
 2229 		if (changeuser != NULL) {
 2230 			printf(" (as user %s[%d]", changeuser, runas_uid);
 2231 			if (changegroup != NULL)
 2232 				printf(", and group %s[%d])", changegroup, runas_gid);
 2233 			else
 2234 				printf(")");
 2235 		}
 2236 		if (changeroot != NULL)
 2237 			printf(" in directory %s", changeroot);
 2238 		if (nicelevel)
 2239 			printf(", and add %i to the priority", nicelevel);
 2240 		if (proc_sched)
 2241 			printf(", with scheduling policy %s with priority %i",
 2242 			       proc_sched->policy_name, proc_sched->priority);
 2243 		if (io_sched)
 2244 			printf(", with IO scheduling class %s with priority %i",
 2245 			       io_sched->policy_name, io_sched->priority);
 2246 		printf(".\n");
 2247 	}
 2248 	if (testmode)
 2249 		return 0;
 2250 	if (quietmode < 0)
 2251 		printf("Starting %s...\n", startas);
 2252 	*--argv = startas;
 2253 	if (background)
 2254 		/* Ok, we need to detach this process. */
 2255 		daemonize();
 2256 	else if (mpidfile && pidfile != NULL)
 2257 		/* User wants _us_ to make the pidfile, but detach themself! */
 2258 		write_pidfile(pidfile, getpid());
 2259 	if (background && close_io) {
 2260 		devnull_fd = open("/dev/null", O_RDWR);
 2261 		if (devnull_fd < 0)
 2262 			fatal("unable to open '%s'", "/dev/null");
 2263 	}
 2264 	if (nicelevel) {
 2265 		errno = 0;
 2266 		if ((nice(nicelevel) == -1) && (errno != 0))
 2267 			fatal("unable to alter nice level by %i", nicelevel);
 2268 	}
 2269 	if (proc_sched)
 2270 		set_proc_schedule(proc_sched);
 2271 	if (io_sched)
 2272 		set_io_schedule(io_sched);
 2273 	if (umask_value >= 0)
 2274 		umask(umask_value);
 2275 	if (changeroot != NULL) {
 2276 		if (chdir(changeroot) < 0)
 2277 			fatal("unable to chdir() to %s", changeroot);
 2278 		if (chroot(changeroot) < 0)
 2279 			fatal("unable to chroot() to %s", changeroot);
 2280 	}
 2281 	if (chdir(changedir) < 0)
 2282 		fatal("unable to chdir() to %s", changedir);
 2283 
 2284 	rgid = getgid();
 2285 	ruid = getuid();
 2286 	if (changegroup != NULL) {
 2287 		if (rgid != (gid_t)runas_gid)
 2288 			if (setgid(runas_gid))
 2289 				fatal("unable to set gid to %d", runas_gid);
 2290 	}
 2291 	if (changeuser != NULL) {
 2292 		/* We assume that if our real user and group are the same as
 2293 		 * the ones we should switch to, the supplementary groups
 2294 		 * will be already in place. */
 2295 		if (rgid != (gid_t)runas_gid || ruid != (uid_t)runas_uid)
 2296 			if (initgroups(changeuser, runas_gid))
 2297 				fatal("unable to set initgroups() with gid %d",
 2298 				      runas_gid);
 2299 
 2300 		if (ruid != (uid_t)runas_uid)
 2301 			if (setuid(runas_uid))
 2302 				fatal("unable to set uid to %s", changeuser);
 2303 	}
 2304 
 2305 	if (background && close_io) {
 2306 		int i;
 2307 
 2308 		dup2(devnull_fd, 0); /* stdin */
 2309 		dup2(devnull_fd, 1); /* stdout */
 2310 		dup2(devnull_fd, 2); /* stderr */
 2311 
 2312 		 /* Now close all extra fds. */
 2313 		for (i = get_open_fd_max() - 1; i >= 3; --i)
 2314 			close(i);
 2315 	}
 2316 	execv(startas, argv);
 2317 	fatal("unable to start %s", startas);
 2318 }
 2319 
 2320 static void
 2321 do_stop(int sig_num, int *n_killed, int *n_notkilled)
 2322 {
 2323 	struct pid_list *p;
 2324 
 2325 	do_findprocs();
 2326 
 2327 	*n_killed = 0;
 2328 	*n_notkilled = 0;
 2329 
 2330 	if (!found)
 2331 		return;
 2332 
 2333 	pid_list_free(&killed);
 2334 
 2335 	for (p = found; p; p = p->next) {
 2336 		if (testmode) {
 2337 			if (quietmode <= 0)
 2338 				printf("Would send signal %d to %d.\n",
 2339 				       sig_num, p->pid);
 2340 			(*n_killed)++;
 2341 		} else if (kill(p->pid, sig_num) == 0) {
 2342 			pid_list_push(&killed, p->pid);
 2343 			(*n_killed)++;
 2344 		} else {
 2345 			if (sig_num)
 2346 				warning("failed to kill %d: %s\n",
 2347 				        p->pid, strerror(errno));
 2348 			(*n_notkilled)++;
 2349 		}
 2350 	}
 2351 }
 2352 
 2353 static void
 2354 do_stop_summary(int retry_nr)
 2355 {
 2356 	struct pid_list *p;
 2357 
 2358 	if (quietmode >= 0 || !killed)
 2359 		return;
 2360 
 2361 	printf("Stopped %s (pid", what_stop);
 2362 	for (p = killed; p; p = p->next)
 2363 		printf(" %d", p->pid);
 2364 	putchar(')');
 2365 	if (retry_nr > 0)
 2366 		printf(", retry #%d", retry_nr);
 2367 	printf(".\n");
 2368 }
 2369 
 2370 static void DPKG_ATTR_PRINTF(1)
 2371 set_what_stop(const char *format, ...)
 2372 {
 2373 	va_list arglist;
 2374 	int rc;
 2375 
 2376 	va_start(arglist, format);
 2377 	rc = vasprintf(&what_stop, format, arglist);
 2378 	va_end(arglist);
 2379 
 2380 	if (rc < 0)
 2381 		fatal("cannot allocate formatted string");
 2382 }
 2383 
 2384 /*
 2385  * We want to keep polling for the processes, to see if they've exited, or
 2386  * until the timeout expires.
 2387  *
 2388  * This is a somewhat complicated algorithm to try to ensure that we notice
 2389  * reasonably quickly when all the processes have exited, but don't spend
 2390  * too much CPU time polling. In particular, on a fast machine with
 2391  * quick-exiting daemons we don't want to delay system shutdown too much,
 2392  * whereas on a slow one, or where processes are taking some time to exit,
 2393  * we want to increase the polling interval.
 2394  *
 2395  * The algorithm is as follows: we measure the elapsed time it takes to do
 2396  * one poll(), and wait a multiple of this time for the next poll. However,
 2397  * if that would put us past the end of the timeout period we wait only as
 2398  * long as the timeout period, but in any case we always wait at least
 2399  * MIN_POLL_INTERVAL (20ms). The multiple (‘ratio’) starts out as 2, and
 2400  * increases by 1 for each poll to a maximum of 10; so we use up to between
 2401  * 30% and 10% of the machine's resources (assuming a few reasonable things
 2402  * about system performance).
 2403  */
 2404 static bool
 2405 do_stop_timeout(int timeout, int *n_killed, int *n_notkilled)
 2406 {
 2407 	struct timespec stopat, before, after, interval, maxinterval;
 2408 	int rc, ratio;
 2409 
 2410 	timespec_gettime(&stopat);
 2411 	stopat.tv_sec += timeout;
 2412 	ratio = 1;
 2413 	for (;;) {
 2414 		timespec_gettime(&before);
 2415 		if (timespec_cmp(&before, &stopat, >))
 2416 			return false;
 2417 
 2418 		do_stop(0, n_killed, n_notkilled);
 2419 		if (!*n_killed)
 2420 			return true;
 2421 
 2422 		timespec_gettime(&after);
 2423 
 2424 		if (!timespec_cmp(&after, &stopat, <))
 2425 			return false;
 2426 
 2427 		if (ratio < 10)
 2428 			ratio++;
 2429 
 2430 		timespec_sub(&stopat, &after, &maxinterval);
 2431 		timespec_sub(&after, &before, &interval);
 2432 		timespec_mul(&interval, ratio);
 2433 
 2434 		if (interval.tv_sec < 0 || interval.tv_nsec < 0)
 2435 			interval.tv_sec = interval.tv_nsec = 0;
 2436 
 2437 		if (timespec_cmp(&interval, &maxinterval, >))
 2438 			interval = maxinterval;
 2439 
 2440 		if (interval.tv_sec == 0 &&
 2441 		    interval.tv_nsec <= MIN_POLL_INTERVAL)
 2442 			interval.tv_nsec = MIN_POLL_INTERVAL;
 2443 
 2444 		rc = pselect(0, NULL, NULL, NULL, &interval, NULL);
 2445 		if (rc < 0 && errno != EINTR)
 2446 			fatal("select() failed for pause");
 2447 	}
 2448 }
 2449 
 2450 static int
 2451 finish_stop_schedule(bool anykilled)
 2452 {
 2453 	if (rpidfile && pidfile && !testmode)
 2454 		remove_pidfile(pidfile);
 2455 
 2456 	if (anykilled)
 2457 		return 0;
 2458 
 2459 	if (quietmode <= 0)
 2460 		printf("No %s found running; none killed.\n", what_stop);
 2461 
 2462 	return exitnodo;
 2463 }
 2464 
 2465 static int
 2466 run_stop_schedule(void)
 2467 {
 2468 	int position, n_killed, n_notkilled, value, retry_nr;
 2469 	bool anykilled;
 2470 
 2471 	if (testmode) {
 2472 		if (schedule != NULL) {
 2473 			if (quietmode <= 0)
 2474 				printf("Ignoring --retry in test mode\n");
 2475 			schedule = NULL;
 2476 		}
 2477 	}
 2478 
 2479 	if (cmdname)
 2480 		set_what_stop("%s", cmdname);
 2481 	else if (execname)
 2482 		set_what_stop("%s", execname);
 2483 	else if (pidfile)
 2484 		set_what_stop("process in pidfile '%s'", pidfile);
 2485 	else if (match_pid > 0)
 2486 		set_what_stop("process with pid %d", match_pid);
 2487 	else if (match_ppid > 0)
 2488 		set_what_stop("process(es) with parent pid %d", match_ppid);
 2489 	else if (userspec)
 2490 		set_what_stop("process(es) owned by '%s'", userspec);
 2491 	else
 2492 		BUG("no match option, please report");
 2493 
 2494 	anykilled = false;
 2495 	retry_nr = 0;
 2496 
 2497 	if (schedule == NULL) {
 2498 		do_stop(signal_nr, &n_killed, &n_notkilled);
 2499 		do_stop_summary(0);
 2500 		if (n_notkilled > 0 && quietmode <= 0)
 2501 			printf("%d pids were not killed\n", n_notkilled);
 2502 		if (n_killed)
 2503 			anykilled = true;
 2504 		return finish_stop_schedule(anykilled);
 2505 	}
 2506 
 2507 	for (position = 0; position < schedule_length; position++) {
 2508 	reposition:
 2509 		value = schedule[position].value;
 2510 		n_notkilled = 0;
 2511 
 2512 		switch (schedule[position].type) {
 2513 		case sched_goto:
 2514 			position = value;
 2515 			goto reposition;
 2516 		case sched_signal:
 2517 			do_stop(value, &n_killed, &n_notkilled);
 2518 			do_stop_summary(retry_nr++);
 2519 			if (!n_killed)
 2520 				return finish_stop_schedule(anykilled);
 2521 			else
 2522 				anykilled = true;
 2523 			continue;
 2524 		case sched_timeout:
 2525 			if (do_stop_timeout(value, &n_killed, &n_notkilled))
 2526 				return finish_stop_schedule(anykilled);
 2527 			else
 2528 				continue;
 2529 		default:
 2530 			BUG("schedule[%d].type value %d is not valid",
 2531 			    position, schedule[position].type);
 2532 		}
 2533 	}
 2534 
 2535 	if (quietmode <= 0)
 2536 		printf("Program %s, %d process(es), refused to die.\n",
 2537 		       what_stop, n_killed);
 2538 
 2539 	return 2;
 2540 }
 2541 
 2542 int
 2543 main(int argc, char **argv)
 2544 {
 2545 	progname = argv[0];
 2546 
 2547 	parse_options(argc, argv);
 2548 	setup_options();
 2549 
 2550 	argc -= optind;
 2551 	argv += optind;
 2552 
 2553 	if (action == ACTION_START)
 2554 		return do_start(argc, argv);
 2555 	else if (action == ACTION_STOP)
 2556 		return run_stop_schedule();
 2557 	else if (action == ACTION_STATUS)
 2558 		return do_findprocs();
 2559 
 2560 	return 0;
 2561 }

Generated by cgit