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