]> TLD Linux GIT Repositories - rc-scripts.git/blob - src/start-stop-daemon.c
- from PLD
[rc-scripts.git] / src / start-stop-daemon.c
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 aswell.
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 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #if defined(linux)
28 #  define OSLinux
29 #elif defined(__GNU__)
30 #  define OSHURD
31 #elif defined(__sparc__)
32 #  define OSsunos
33 #elif defined(OPENBSD) || defined(__OpenBSD__)
34 #  define OSOpenBSD
35 #elif defined(hpux)
36 #  define OShpux
37 #elif defined(__FreeBSD__)
38 #  define OSFreeBSD
39 #elif defined(__NetBSD__)
40 #  define OSNetBSD
41 #else
42 #  error Unknown architecture - cannot build start-stop-daemon
43 #endif
44
45 #define MIN_POLL_INTERVAL 20000 /*us*/
46
47 #if defined(OSHURD)
48 #  include <hurd.h>
49 #  include <ps.h>
50 #endif
51
52 #if defined(OSOpenBSD) || defined(OSFreeBSD) || defined(OSNetBSD)
53 #include <sys/param.h>
54 #include <sys/user.h>
55 #include <sys/proc.h>
56 #include <sys/stat.h>
57 #include <sys/sysctl.h>
58 #include <sys/types.h>
59  
60 #include <err.h>
61 #include <kvm.h>
62 #include <limits.h>
63 #endif
64
65 #if HAVE_SYS_CAPABILITY_H
66 #include <sys/prctl.h>
67 #include <sys/capability.h>
68 #endif
69
70 #if defined(OShpux)
71 #include <sys/param.h>
72 #include <sys/pstat.h>
73 #endif
74
75 #include <errno.h>
76 #include <stdio.h>
77 #include <stdlib.h>
78 #include <string.h>
79 #include <stdarg.h>
80 #include <signal.h>
81 #include <sys/stat.h>
82 #include <dirent.h>
83 #include <sys/time.h>
84 #include <unistd.h>
85 #include <getopt.h>
86 #include <pwd.h>
87 #include <grp.h>
88 #include <sys/ioctl.h>
89 #include <sys/types.h>
90 #include <sys/termios.h>
91 #include <fcntl.h>
92 #include <limits.h>
93 #include <assert.h>
94 #include <ctype.h>
95
96 #ifdef HAVE_ERROR_H
97 #  include <error.h>
98 #endif
99
100 static int testmode = 0;
101 static int quietmode = 0;
102 static int exitnodo = 1;
103 static int start = 0;
104 static int stop = 0;
105 static int background = 0;
106 static int mpidfile = 0;
107 static int signal_nr = 15;
108 static const char *signal_str = NULL;
109 static int user_id = -1;
110 static int runas_uid = -1;
111 static int runas_gid = -1;
112 static const char *userspec = NULL;
113 static char *changeuser = NULL;
114 static const char *changegroup = NULL;
115 static char *changeroot = NULL;
116 static const char *changedir = "/";
117 static const char *cmdname = NULL;
118 static char *execname = NULL;
119 static char *startas = NULL;
120 static const char *pidfile = NULL;
121 static char what_stop[1024];
122 static const char *schedule_str = NULL;
123 static const char *progname = "";
124 static int nicelevel = 0;
125 static char *caplist = NULL;
126
127 static struct stat exec_stat;
128 #if defined(OSHURD)
129 static struct proc_stat_list *procset = NULL;
130 #endif
131
132
133 struct pid_list {
134         struct pid_list *next;
135         pid_t pid;
136 };
137
138 static struct pid_list *found = NULL;
139 static struct pid_list *killed = NULL;
140
141 struct schedule_item {
142         enum { sched_timeout, sched_signal, sched_goto, sched_forever } type;
143         int value; /* seconds, signal no., or index into array */
144         /* sched_forever is only seen within parse_schedule and callees */
145 };
146
147 static int schedule_length;
148 static struct schedule_item *schedule = NULL;
149
150 static void *xmalloc(int size);
151 static void push(struct pid_list **list, pid_t pid);
152 static void do_help(void);
153 static void parse_options(int argc, char * const *argv);
154 static int pid_is_user(pid_t pid, uid_t uid);
155 static int pid_is_cmd(pid_t pid, const char *name);
156 static void check(pid_t pid);
157 static void do_pidfile(const char *name);
158 static void do_stop(int signal_nr, int quietmode,
159                     int *n_killed, int *n_notkilled, int retry_nr);
160 #if defined(OSLinux) || defined(OShpux)
161 static int pid_is_exec(pid_t pid, const struct stat *esb);
162 #endif
163
164
165 #ifdef __GNUC__
166 static void fatal(const char *format, ...)
167         NONRETURNPRINTFFORMAT(1, 2);
168 static void badusage(const char *msg)
169         NONRETURNING;
170 #else
171 static void fatal(const char *format, ...);
172 static void badusage(const char *msg);
173 #endif
174
175 /* This next part serves only to construct the TVCALC macro, which
176  * is used for doing arithmetic on struct timeval's.  It works like this:
177  *   TVCALC(result, expression);
178  * where result is a struct timeval (and must be an lvalue) and
179  * expression is the single expression for both components.  In this
180  * expression you can use the special values TVELEM, which when fed a
181  * const struct timeval* gives you the relevant component, and
182  * TVADJUST.  TVADJUST is necessary when subtracting timevals, to make
183  * it easier to renormalise.  Whenver you subtract timeval elements,
184  * you must make sure that TVADJUST is added to the result of the
185  * subtraction (before any resulting multiplication or what have you).
186  * TVELEM must be linear in TVADJUST.
187  */
188 typedef long tvselector(const struct timeval*);
189 static long tvselector_sec(const struct timeval *tv) { return tv->tv_sec; }
190 static long tvselector_usec(const struct timeval *tv) { return tv->tv_usec; }
191 #define TVCALC_ELEM(result, expr, sec, adj)                           \
192 {                                                                     \
193   const long TVADJUST = adj;                                          \
194   long (*const TVELEM)(const struct timeval*) = tvselector_##sec;     \
195   (result).tv_##sec = (expr);                                         \
196 }
197 #define TVCALC(result,expr)                                           \
198 do {                                                                  \
199   TVCALC_ELEM(result, expr, sec, (-1));                               \
200   TVCALC_ELEM(result, expr, usec, (+1000000));                        \
201   (result).tv_sec += (result).tv_usec / 1000000;                      \
202   (result).tv_usec %= 1000000;                                        \
203 } while(0)
204
205
206 static void
207 fatal(const char *format, ...)
208 {
209         va_list arglist;
210
211         fprintf(stderr, "%s: ", progname);
212         va_start(arglist, format);
213         vfprintf(stderr, format, arglist);
214         va_end(arglist);
215         putc('\n', stderr);
216         exit(2);
217 }
218
219
220 static void *
221 xmalloc(int size)
222 {
223         void *ptr;
224
225         ptr = malloc(size);
226         if (ptr)
227                 return ptr;
228         fatal("malloc(%d) failed", size);
229 }
230
231
232 static void
233 xgettimeofday(struct timeval *tv)
234 {
235         if (gettimeofday(tv,0) != 0)
236                 fatal("gettimeofday failed: %s", strerror(errno));
237 }
238
239
240 static void
241 push(struct pid_list **list, pid_t pid)
242 {
243         struct pid_list *p;
244
245         p = xmalloc(sizeof(*p));
246         p->next = *list;
247         p->pid = pid;
248         *list = p;
249 }
250
251 static void
252 clear(struct pid_list **list)
253 {
254         struct pid_list *here, *next;
255
256         for (here = *list; here != NULL; here = next) {
257                 next = here->next;
258                 free(here);
259         }
260
261         *list = NULL;
262 }
263
264 static void
265 do_help(void)
266 {
267         printf(
268 "start-stop-daemon VERSION for Debian - small and fast C version written by\n"
269 "Marek Michalkiewicz <marekm@i17linuxb.ists.pwr.wroc.pl>, public domain.\n"
270 "\n"
271 "Usage:\n"
272 "  start-stop-daemon -S|--start options ... -- arguments ...\n"
273 "  start-stop-daemon -K|--stop options ...\n"
274 "  start-stop-daemon -H|--help\n"
275 "  start-stop-daemon -V|--version\n"
276 "\n"
277 "Options (at least one of --exec|--pidfile|--user is required):\n"
278 "  -x|--exec <executable>        program to start/check if it is running\n"
279 "  -p|--pidfile <pid-file>       pid file to check\n"
280 "  -c|--chuid <name|uid[:group|gid]>\n"
281 "               change to this user/group before starting process\n"
282 "  -u|--user <username>|<uid>    stop processes owned by this user\n"
283 "  -g|--group <group|gid>        run process as this group\n"
284 "  -n|--name <process-name>      stop processes with this name\n"
285 "  -s|--signal <signal>          signal to send (default TERM)\n"
286 "  -a|--startas <pathname>       program to start (default is <executable>)\n"
287 "  -D|--dropcap <capbilities>    drop theses capabilities\n"
288 "  -C|--chdir <directory>        Change to <directory>(default is /)\n"
289 "  -N|--nicelevel <incr>         add incr to the process's nice level\n"
290 "  -b|--background               force the process to detach\n"
291 "  -m|--make-pidfile             create the pidfile before starting\n"
292 "  -R|--retry <schedule>         check whether processes die, and retry\n"
293 "  -t|--test                     test mode, don't do anything\n"
294 "  -o|--oknodo                   exit status 0 (not 1) if nothing done\n"
295 "  -q|--quiet                    be more quiet\n"
296 "  -v|--verbose                  be more verbose\n"
297 "Retry <schedule> is <item>|/<item>/... where <item> is one of\n"
298 " -<signal-num>|[-]<signal-name>  send that signal\n"
299 " <timeout>                       wait that many seconds\n"
300 " forever                         repeat remainder forever\n"
301 "or <schedule> may be just <timeout>, meaning <signal>/<timeout>/KILL/<timeout>\n"
302 "\n"
303 "Exit status:  0 = done      1 = nothing done (=> 0 if --oknodo)\n"
304 "              3 = trouble   2 = with --retry, processes wouldn't die\n");
305 }
306
307
308 static void
309 badusage(const char *msg)
310 {
311         if (msg)
312                 fprintf(stderr, "%s: %s\n", progname, msg);
313         fprintf(stderr, "Try `%s --help' for more information.\n", progname);
314         exit(3);
315 }
316
317 struct sigpair {
318         const char *name;
319         int signal;
320 };
321
322 const struct sigpair siglist[] = {
323         { "ABRT",       SIGABRT },
324         { "ALRM",       SIGALRM },
325         { "FPE",        SIGFPE  },
326         { "HUP",        SIGHUP  },
327         { "ILL",        SIGILL  },
328         { "INT",        SIGINT  },
329         { "KILL",       SIGKILL },
330         { "PIPE",       SIGPIPE },
331         { "QUIT",       SIGQUIT },
332         { "SEGV",       SIGSEGV },
333         { "TERM",       SIGTERM },
334         { "USR1",       SIGUSR1 },
335         { "USR2",       SIGUSR2 },
336         { "CHLD",       SIGCHLD },
337         { "CONT",       SIGCONT },
338         { "STOP",       SIGSTOP },
339         { "TSTP",       SIGTSTP },
340         { "TTIN",       SIGTTIN },
341         { "TTOU",       SIGTTOU }
342 };
343
344 static int parse_integer(const char *string, int *value_r) {
345         unsigned long ul;
346         char *ep;
347
348         if (!string[0])
349                 return -1;
350
351         ul= strtoul(string,&ep,10);
352         if (ul > INT_MAX || *ep != '\0')
353                 return -1;
354
355         *value_r= ul;
356         return 0;
357 }
358
359 static int parse_signal(const char *signal_str, int *signal_nr)
360 {
361         unsigned int i;
362
363         if (parse_integer(signal_str, signal_nr) == 0)
364                 return 0;
365
366         for (i = 0; i < sizeof (siglist) / sizeof (siglist[0]); i++) {
367                 if (strcmp (signal_str, siglist[i].name) == 0) {
368                         *signal_nr = siglist[i].signal;
369                         return 0;
370                 }
371         }
372         return -1;
373 }
374
375 static void
376 parse_schedule_item(const char *string, struct schedule_item *item) {
377         const char *after_hyph;
378
379         if (!strcmp(string,"forever")) {
380                 item->type = sched_forever;
381         } else if (isdigit(string[0])) {
382                 item->type = sched_timeout;
383                 if (parse_integer(string, &item->value) != 0)
384                         badusage("invalid timeout value in schedule");
385         } else if ((after_hyph = string + (string[0] == '-')) &&
386                    parse_signal(after_hyph, &item->value) == 0) {
387                 item->type = sched_signal;
388         } else {
389                 badusage("invalid schedule item (must be [-]<signal-name>, "
390                          "-<signal-number>, <timeout> or `forever'");
391         }
392 }
393
394 static void
395 parse_schedule(const char *schedule_str) {
396         char item_buf[20];
397         const char *slash;
398         int count, repeatat;
399         ptrdiff_t str_len;
400
401         count = 0;
402         for (slash = schedule_str; *slash; slash++)
403                 if (*slash == '/')
404                         count++;
405
406         schedule_length = (count == 0) ? 4 : count+1;
407         schedule = xmalloc(sizeof(*schedule) * schedule_length);
408
409         if (count == 0) {
410                 schedule[0].type = sched_signal;
411                 schedule[0].value = signal_nr;
412                 parse_schedule_item(schedule_str, &schedule[1]);
413                 if (schedule[1].type != sched_timeout) {
414                         badusage ("--retry takes timeout, or schedule list"
415                                   " of at least two items");
416                 }
417                 schedule[2].type = sched_signal;
418                 schedule[2].value = SIGKILL;
419                 schedule[3]= schedule[1];
420         } else {
421                 count = 0;
422                 repeatat = -1;
423                 while (schedule_str != NULL) {
424                         slash = strchr(schedule_str,'/');
425                         str_len = slash ? slash - schedule_str : strlen(schedule_str);
426                         if (str_len >= (ptrdiff_t)sizeof(item_buf))
427                                 badusage("invalid schedule item: far too long"
428                                          " (you must delimit items with slashes)");
429                         memcpy(item_buf, schedule_str, str_len);
430                         item_buf[str_len] = 0;
431                         schedule_str = slash ? slash+1 : NULL;
432
433                         parse_schedule_item(item_buf, &schedule[count]);
434                         if (schedule[count].type == sched_forever) {
435                                 if (repeatat >= 0)
436                                         badusage("invalid schedule: `forever'"
437                                                  " appears more than once");
438                                 repeatat = count;
439                                 continue;
440                         }
441                         count++;
442                 }
443                 if (repeatat >= 0) {
444                         schedule[count].type = sched_goto;
445                         schedule[count].value = repeatat;
446                         count++;
447                 }
448                 assert(count == schedule_length);
449         }
450 }
451
452 #ifdef HAVE_SYS_CAPABILITY_H
453 static void
454 remove_capabilities(char *capstr) {
455         cap_value_t capval;
456         char *savedptr, *ptr;
457         cap_t caps;
458
459         caps = cap_get_proc();
460         if (caps == NULL) {
461                 fatal("Unable to retrieve my capabilities");
462         }
463
464         ptr = strtok_r(capstr, ",", &savedptr);
465         while (ptr) {
466                 if (cap_from_name(ptr, &capval) != 0) {
467                         errno = EINVAL;
468                         fatal("Unable to parse this capability : \"%s\"", ptr);
469                 }
470
471                 if (prctl(PR_CAPBSET_DROP, capval, 0, 0) != 0) {
472                         fatal("Unable to drop this capability: %s", ptr);
473                 }
474
475                 if (cap_set_flag(caps, CAP_INHERITABLE, 1, (cap_value_t *)&capval, CAP_CLEAR) != 0) {
476                         fatal("Unable to clear the capability %s", ptr);
477                 }
478
479                 ptr = strtok_r(NULL, ",", &savedptr);
480         }
481
482         if (cap_set_proc(caps) != 0) {
483                 fatal("Unable to remove theses capabilities from the inherited set\n");
484         }
485
486         if (cap_free(caps) == -1) {
487                 fatal("Cannot free the capability");
488         }
489 }
490 #endif
491
492 static void
493 parse_options(int argc, char * const *argv)
494 {
495         static struct option longopts[] = {
496                 { "help",         0, NULL, 'H'},
497                 { "stop",         0, NULL, 'K'},
498                 { "start",        0, NULL, 'S'},
499                 { "version",      0, NULL, 'V'},
500                 { "startas",      1, NULL, 'a'},
501                 { "name",         1, NULL, 'n'},
502                 { "oknodo",       0, NULL, 'o'},
503                 { "pidfile",      1, NULL, 'p'},
504                 { "quiet",        0, NULL, 'q'},
505                 { "signal",       1, NULL, 's'},
506                 { "test",         0, NULL, 't'},
507                 { "user",         1, NULL, 'u'},
508                 { "group",        1, NULL, 'g'},
509                 { "chroot",       1, NULL, 'r'},
510                 { "dropcap",      1, NULL, 'D'},
511                 { "verbose",      0, NULL, 'v'},
512                 { "exec",         1, NULL, 'x'},
513                 { "chuid",        1, NULL, 'c'},
514                 { "nicelevel",    1, NULL, 'N'},
515                 { "background",   0, NULL, 'b'},
516                 { "make-pidfile", 0, NULL, 'm'},
517                 { "retry",        1, NULL, 'R'},
518                 { "chdir",        1, NULL, 'd'},
519                 { NULL,         0, NULL, 0}
520         };
521         int c;
522
523         for (;;) {
524                 c = getopt_long(argc, argv, "HKSVa:n:op:qr:s:tu:vx:c:N:bmR:g:d:D",
525                                 longopts, (int *) 0);
526                 if (c == -1)
527                         break;
528                 switch (c) {
529                 case 'H':  /* --help */
530                         do_help();
531                         exit(0);
532                 case 'K':  /* --stop */
533                         stop = 1;
534                         break;
535                 case 'S':  /* --start */
536                         start = 1;
537                         break;
538                 case 'V':  /* --version */
539                         printf("start-stop-daemon " VERSION "\n");
540                         exit(0);
541                 case 'a':  /* --startas <pathname> */
542                         startas = optarg;
543                         break;
544                 case 'n':  /* --name <process-name> */
545                         cmdname = optarg;
546                         break;
547                 case 'o':  /* --oknodo */
548                         exitnodo = 0;
549                         break;
550                 case 'p':  /* --pidfile <pid-file> */
551                         pidfile = optarg;
552                         break;
553                 case 'q':  /* --quiet */
554                         quietmode = 1;
555                         break;
556                 case 's':  /* --signal <signal> */
557                         signal_str = optarg;
558                         break;
559                 case 't':  /* --test */
560                         testmode = 1;
561                         break;
562                 case 'u':  /* --user <username>|<uid> */
563                         userspec = optarg;
564                         break;
565                 case 'v':  /* --verbose */
566                         quietmode = -1;
567                         break;
568                 case 'x':  /* --exec <executable> */
569                         execname = optarg;
570                         break;
571                 case 'c':  /* --chuid <username>|<uid> */
572                         /* we copy the string just in case we need the
573                          * argument later. */
574                         changeuser = strdup(optarg);
575                         changeuser = strtok(changeuser, ":");
576                         changegroup = strtok(NULL, ":");
577                         break;
578                 case 'g':  /* --group <group>|<gid> */
579                         changegroup = optarg;
580                         break;
581                 case 'r':  /* --chroot /new/root */
582                         changeroot = optarg;
583                         break;
584                 case 'D':  /* --dropcap cap_net_raw,cap_mac_admin */
585 #ifdef HAVE_SYS_CAPABILITY_H
586                         caplist = optarg;
587 #else
588                         badusage("Capabilities are not supported on your OS");
589 #endif
590                         break;
591                 case 'N':  /* --nice */
592                         nicelevel = atoi(optarg);
593                         break;
594                 case 'b':  /* --background */
595                         background = 1;
596                         break;
597                 case 'm':  /* --make-pidfile */
598                         mpidfile = 1;
599                         break;
600                 case 'R':  /* --retry <schedule>|<timeout> */
601                         schedule_str = optarg;
602                         break;
603                 case 'd':  /* --chdir /new/dir */
604                         changedir = optarg;
605                         break;
606                 default:
607                         badusage(NULL);  /* message printed by getopt */
608                 }
609         }
610
611         if (signal_str != NULL) {
612                 if (parse_signal (signal_str, &signal_nr) != 0)
613                         badusage("signal value must be numeric or name"
614                                  " of signal (KILL, INT, ...)");
615         }
616
617         if (schedule_str != NULL) {
618                 parse_schedule(schedule_str);
619         }
620
621         if (start == stop)
622                 badusage("need one of --start or --stop");
623
624         if (!execname && !pidfile && !userspec && !cmdname)
625                 badusage("need at least one of --exec, --pidfile, --user or --name");
626
627         if (!startas)
628                 startas = execname;
629
630         if (start && !startas)
631                 badusage("--start needs --exec or --startas");
632
633         if (mpidfile && pidfile == NULL)
634                 badusage("--make-pidfile is only relevant with --pidfile");
635
636         if (background && !start)
637                 badusage("--background is only relevant with --start");
638
639 }
640
641 #if defined(OSLinux)
642 static int
643 pid_is_exec(pid_t pid, const struct stat *esb)
644 {
645         struct stat sb;
646         char buf[32];
647
648         sprintf(buf, "/proc/%d/exe", pid);
649         if (stat(buf, &sb) != 0)
650                 return 0;
651         return (sb.st_dev == esb->st_dev && sb.st_ino == esb->st_ino);
652 }
653
654
655 static int
656 pid_is_user(pid_t pid, uid_t uid)
657 {
658         struct stat sb;
659         char buf[32];
660
661         sprintf(buf, "/proc/%d", pid);
662         if (stat(buf, &sb) != 0)
663                 return 0;
664         return (sb.st_uid == uid);
665 }
666
667
668 static int
669 pid_is_cmd(pid_t pid, const char *name)
670 {
671         char buf[32];
672         FILE *f;
673         int c;
674
675         sprintf(buf, "/proc/%d/stat", pid);
676         f = fopen(buf, "r");
677         if (!f)
678                 return 0;
679         while ((c = getc(f)) != EOF && c != '(')
680                 ;
681         if (c != '(') {
682                 fclose(f);
683                 return 0;
684         }
685         /* this hopefully handles command names containing ')' */
686         while ((c = getc(f)) != EOF && c == *name)
687                 name++;
688         fclose(f);
689         return (c == ')' && *name == '\0');
690 }
691 #endif /* OSLinux */
692
693
694 #if defined(OSHURD)
695 static void
696 init_procset(void)
697 {
698         struct ps_context *context;
699         error_t err;
700
701         err = ps_context_create(getproc(), &context);
702         if (err)
703                 error(1, err, "ps_context_create");
704
705         err = proc_stat_list_create(context, &procset);
706         if (err)
707                 error(1, err, "proc_stat_list_create");
708
709         err = proc_stat_list_add_all(procset, 0, 0);
710         if (err)
711                 error(1, err, "proc_stat_list_add_all");
712 }
713
714 static struct proc_stat *
715 get_proc_stat (pid_t pid, ps_flags_t flags)
716 {
717         struct proc_stat *ps;
718         ps_flags_t wanted_flags = PSTAT_PID | flags;
719
720         if (!procset)
721                 init_procset();
722
723         ps = proc_stat_list_pid_proc_stat(procset, pid);
724         if (!ps)
725                 return NULL;
726         if (proc_stat_set_flags(ps, wanted_flags))
727                 return NULL;
728         if ((proc_stat_flags(ps) & wanted_flags) != wanted_flags)
729                 return NULL;
730
731         return ps;
732 }
733
734 static int
735 pid_is_user(pid_t pid, uid_t uid)
736 {
737         struct proc_stat *ps;
738
739         ps = get_proc_stat(pid, PSTAT_OWNER_UID);
740         return ps && proc_stat_owner_uid(ps) == uid;
741 }
742
743 static int
744 pid_is_cmd(pid_t pid, const char *name)
745 {
746         struct proc_stat *ps;
747
748         ps = get_proc_stat(pid, PSTAT_ARGS);
749         return ps && !strcmp(proc_stat_args(ps), name);
750 }
751
752 static int
753 pid_is_running(pid_t pid)
754 {
755         return get_proc_stat(pid, 0) != NULL;
756 }
757
758 #else /* !OSHURD */
759
760 static int
761 pid_is_running(pid_t pid)
762 {
763         struct stat sb;
764         char buf[32];
765
766         sprintf(buf, "/proc/%d", pid);
767         if (stat(buf, &sb) != 0) {
768                 if (errno!=ENOENT)
769                         fatal("Error stating %s: %s", buf, strerror(errno));
770                 return 0;
771         }
772
773         return 1;
774 }
775
776 #endif /* OSHURD */
777
778 static void
779 check(pid_t pid)
780 {
781 #if defined(OSLinux) || defined(OShpux)
782         if (execname && !pid_is_exec(pid, &exec_stat))
783 #elif defined(OSHURD) || defined(OSFreeBSD) || defined(OSNetBSD)
784     /* I will try this to see if it works */
785         if (execname && !pid_is_cmd(pid, execname))
786 #endif
787                 return;
788         if (userspec && !pid_is_user(pid, user_id))
789                 return;
790         if (cmdname && !pid_is_cmd(pid, cmdname))
791                 return;
792         if (start && !pid_is_running(pid))
793                 return;
794         if (stop && pid_is_running(pid))
795                 push(&found, pid);
796 }
797
798 static void
799 do_pidfile(const char *name)
800 {
801         FILE *f;
802         pid_t pid;
803
804         f = fopen(name, "r");
805         if (f) {
806                 if (fscanf(f, "%d", &pid) == 1)
807                         check(pid);
808                 fclose(f);
809         } else if (errno != ENOENT)
810                 fatal("open pidfile %s: %s", name, strerror(errno));
811
812 }
813
814 /* WTA: this  needs to be an autoconf check for /proc/pid existance.
815  */
816
817 #if defined(OSLinux) || defined (OSsunos) || defined(OSfreebsd)
818 static void
819 do_procinit(void)
820 {
821         DIR *procdir;
822         struct dirent *entry;
823         int foundany;
824         pid_t pid;
825
826         procdir = opendir("/proc");
827         if (!procdir)
828                 fatal("opendir /proc: %s", strerror(errno));
829
830         foundany = 0;
831         while ((entry = readdir(procdir)) != NULL) {
832                 if (sscanf(entry->d_name, "%d", &pid) != 1)
833                         continue;
834                 foundany++;
835                 check(pid);
836         }
837         closedir(procdir);
838         if (!foundany)
839                 fatal("nothing in /proc - not mounted?");
840 }
841 #endif /* OSLinux */
842
843
844 #if defined(OSHURD)
845 static int
846 check_proc_stat (struct proc_stat *ps)
847 {
848         check(ps->pid);
849         return 0;
850 }
851
852 static void
853 do_procinit(void)
854 {
855         if (!procset)
856                 init_procset();
857
858         proc_stat_list_for_each (procset, check_proc_stat);
859 }
860 #endif /* OSHURD */
861
862
863 #if defined(OSOpenBSD) || defined(OSFreeBSD) || defined(OSNetBSD)
864 static int
865 pid_is_cmd(pid_t pid, const char *name)
866 {
867         kvm_t *kd;
868         int nentries, argv_len=0;
869         struct kinfo_proc *kp;
870         char  errbuf[_POSIX2_LINE_MAX], buf[_POSIX2_LINE_MAX];
871         char  **pid_argv_p;
872         char  *start_argv_0_p, *end_argv_0_p;
873  
874  
875         kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
876         if (kd == 0)
877                 errx(1, "%s", errbuf);
878         if ((kp = kvm_getprocs(kd, KERN_PROC_PID, pid, &nentries)) == 0)
879                 errx(1, "%s", kvm_geterr(kd));
880         if ((pid_argv_p = kvm_getargv(kd, kp, argv_len)) == 0)
881                 errx(1, "%s", kvm_geterr(kd)); 
882
883         start_argv_0_p = *pid_argv_p;
884         /* find and compare string */
885           
886         /* find end of argv[0] then copy and cut of str there. */
887         if ((end_argv_0_p = strchr(*pid_argv_p, ' ')) == 0 )    
888         /* There seems to be no space, so we have the command
889          * allready in its desired form. */
890           start_argv_0_p = *pid_argv_p;
891         else {
892           /* Tests indicate that this never happens, since
893            * kvm_getargv itselfe cuts of tailing stuff. This is
894            * not what the manpage says, however. */
895           strncpy(buf, *pid_argv_p, (end_argv_0_p - start_argv_0_p));
896           buf[(end_argv_0_p - start_argv_0_p) + 1] = '\0';
897           start_argv_0_p = buf;
898         }
899         
900         if (strlen(name) != strlen(start_argv_0_p))
901                return 0;
902         return (strcmp(name, start_argv_0_p) == 0) ? 1 : 0;
903 }
904  
905 static int
906 pid_is_user(pid_t pid, uid_t uid)
907 {
908         kvm_t *kd;
909         int nentries;   /* Value not used */
910         uid_t proc_uid;
911         struct kinfo_proc *kp;
912         char  errbuf[_POSIX2_LINE_MAX];
913
914
915         kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
916         if (kd == 0)
917                 errx(1, "%s", errbuf);
918         if ((kp = kvm_getprocs(kd, KERN_PROC_PID, pid, &nentries)) == 0)
919                 errx(1, "%s", kvm_geterr(kd));
920         if (kp->kp_proc.p_cred )
921                 kvm_read(kd, (u_long)&(kp->kp_proc.p_cred->p_ruid),
922                         &proc_uid, sizeof(uid_t));
923         else
924                 return 0;
925         return (proc_uid == (uid_t)uid);
926 }
927
928 static int
929 pid_is_exec(pid_t pid, const char *name)
930 {
931         kvm_t *kd;
932         int nentries;
933         struct kinfo_proc *kp;
934         char errbuf[_POSIX2_LINE_MAX], *pidexec;
935
936         kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
937         if (kd == 0)
938                 errx(1, "%s", errbuf);
939         if ((kp = kvm_getprocs(kd, KERN_PROC_PID, pid, &nentries)) == 0)
940                 errx(1, "%s", kvm_geterr(kd));
941         pidexec = (&kp->kp_proc)->p_comm;
942         if (strlen(name) != strlen(pidexec))
943                 return 0;
944         return (strcmp(name, pidexec) == 0) ? 1 : 0;
945 }
946
947
948 static void
949 do_procinit(void)
950 {
951         /* Nothing to do */
952 }
953
954 #endif /* OSOpenBSD */
955
956
957 #if defined(OShpux)
958 static int
959 pid_is_user(pid_t pid, uid_t uid)
960 {
961         struct pst_status pst;
962
963         if (pstat_getproc(&pst, sizeof(pst), (size_t) 0, (int) pid) < 0)
964                 return 0;
965         return ((uid_t) pst.pst_uid == uid);
966 }
967
968 static int
969 pid_is_cmd(pid_t pid, const char *name)
970 {
971         struct pst_status pst;
972
973         if (pstat_getproc(&pst, sizeof(pst), (size_t) 0, (int) pid) < 0)
974                 return 0;
975         return (strcmp(pst.pst_ucomm, name) == 0);
976 }
977
978 static int
979 pid_is_exec(pid_t pid, const struct stat *esb)
980 {
981         struct pst_status pst;
982
983         if (pstat_getproc(&pst, sizeof(pst), (size_t) 0, (int) pid) < 0)
984                 return 0;
985         return ((dev_t) pst.pst_text.psf_fsid.psfs_id == esb->st_dev
986                 && (ino_t) pst.pst_text.psf_fileid == esb->st_ino);
987 }
988
989 static void
990 do_procinit(void)
991 {
992         struct pst_status pst[10];
993         int i, count;
994         int idx = 0;
995
996         while ((count = pstat_getproc(pst, sizeof(pst[0]), 10, idx)) > 0) {
997                 for (i = 0; i < count; i++)
998                         check(pst[i].pst_pid);
999                 idx = pst[count - 1].pst_idx + 1;
1000         }
1001 }
1002 #endif /* OShpux */
1003
1004
1005 static void
1006 do_findprocs(void)
1007 {
1008         clear(&found);
1009         
1010         if (pidfile)
1011                 do_pidfile(pidfile);
1012         else
1013                 do_procinit();
1014 }
1015
1016 /* return 1 on failure */
1017 static void
1018 do_stop(int signal_nr, int quietmode, int *n_killed, int *n_notkilled, int retry_nr)
1019 {
1020         struct pid_list *p;
1021
1022         do_findprocs();
1023  
1024         *n_killed = 0;
1025         *n_notkilled = 0;
1026  
1027         if (!found)
1028                 return;
1029  
1030         clear(&killed);
1031
1032         for (p = found; p; p = p->next) {
1033                 if (testmode) {
1034                         printf("Would send signal %d to %d.\n",
1035                                signal_nr, p->pid);
1036                         (*n_killed)++;
1037                 } else if (kill(p->pid, signal_nr) == 0) {
1038                         push(&killed, p->pid);
1039                         (*n_killed)++;
1040                 } else {
1041                         printf("%s: warning: failed to kill %d: %s\n",
1042                                progname, p->pid, strerror(errno));
1043                         (*n_notkilled)++;
1044                 }
1045         }
1046         if (quietmode < 0 && killed) {
1047                 printf("Stopped %s (pid", what_stop);
1048                 for (p = killed; p; p = p->next)
1049                         printf(" %d", p->pid);
1050                 putchar(')');
1051                 if (retry_nr > 0)
1052                         printf(", retry #%d", retry_nr);
1053                 printf(".\n");
1054         }
1055 }
1056
1057
1058 static void
1059 set_what_stop(const char *str)
1060 {
1061         strncpy(what_stop, str, sizeof(what_stop));
1062         what_stop[sizeof(what_stop)-1] = '\0';
1063 }
1064
1065 static int
1066 run_stop_schedule(void)
1067 {
1068         int r, position, n_killed, n_notkilled, value, ratio, anykilled, retry_nr;
1069         struct timeval stopat, before, after, interval, maxinterval;
1070
1071         if (testmode) {
1072                 if (schedule != NULL) {
1073                         printf("Ignoring --retry in test mode\n");
1074                         schedule = NULL;
1075                 }
1076         }
1077
1078         if (cmdname)
1079                 set_what_stop(cmdname);
1080         else if (execname)
1081                 set_what_stop(execname);
1082         else if (pidfile)
1083                 sprintf(what_stop, "process in pidfile `%.200s'", pidfile);
1084         else if (userspec)
1085                 sprintf(what_stop, "process(es) owned by `%.200s'", userspec);
1086         else
1087                 fatal("internal error, please report");
1088
1089         anykilled = 0;
1090         retry_nr = 0;
1091
1092         if (schedule == NULL) {
1093                 do_stop(signal_nr, quietmode, &n_killed, &n_notkilled, 0);
1094                 if (n_notkilled > 0 && quietmode <= 0)
1095                         printf("%d pids were not killed\n", n_notkilled);
1096                 if (n_killed)
1097                         anykilled = 1;
1098                 goto x_finished;
1099         }
1100
1101         for (position = 0; position < schedule_length; ) {
1102                 value= schedule[position].value;
1103                 n_notkilled = 0;
1104
1105                 switch (schedule[position].type) {
1106
1107                 case sched_goto:
1108                         position = value;
1109                         continue;
1110
1111                 case sched_signal:
1112                         do_stop(value, quietmode, &n_killed, &n_notkilled, retry_nr++);
1113                         if (!n_killed)
1114                                 goto x_finished;
1115                         else
1116                                 anykilled = 1;
1117                         goto next_item;
1118
1119                 case sched_timeout:
1120  /* We want to keep polling for the processes, to see if they've exited,
1121   * or until the timeout expires.
1122   *
1123   * This is a somewhat complicated algorithm to try to ensure that we
1124   * notice reasonably quickly when all the processes have exited, but
1125   * don't spend too much CPU time polling.  In particular, on a fast
1126   * machine with quick-exiting daemons we don't want to delay system
1127   * shutdown too much, whereas on a slow one, or where processes are
1128   * taking some time to exit, we want to increase the polling
1129   * interval.
1130   *
1131   * The algorithm is as follows: we measure the elapsed time it takes
1132   * to do one poll(), and wait a multiple of this time for the next
1133   * poll.  However, if that would put us past the end of the timeout
1134   * period we wait only as long as the timeout period, but in any case
1135   * we always wait at least MIN_POLL_INTERVAL (20ms).  The multiple
1136   * (`ratio') starts out as 2, and increases by 1 for each poll to a
1137   * maximum of 10; so we use up to between 30% and 10% of the
1138   * machine's resources (assuming a few reasonable things about system
1139   * performance).
1140   */
1141                         xgettimeofday(&stopat);
1142                         stopat.tv_sec += value;
1143                         ratio = 1;
1144                         for (;;) {
1145                                 xgettimeofday(&before);
1146                                 if (timercmp(&before,&stopat,>))
1147                                         goto next_item;
1148
1149                                 do_stop(0, 1, &n_killed, &n_notkilled, 0);
1150                                 if (!n_killed)
1151                                         goto x_finished;
1152
1153                                 xgettimeofday(&after);
1154
1155                                 if (!timercmp(&after,&stopat,<))
1156                                         goto next_item;
1157
1158                                 if (ratio < 10)
1159                                         ratio++;
1160
1161  TVCALC(interval,    ratio * (TVELEM(&after) - TVELEM(&before) + TVADJUST));
1162  TVCALC(maxinterval,          TVELEM(&stopat) - TVELEM(&after) + TVADJUST);
1163
1164                                 if (timercmp(&interval,&maxinterval,>))
1165                                         interval = maxinterval;
1166
1167                                 if (interval.tv_sec == 0 &&
1168                                     interval.tv_usec <= MIN_POLL_INTERVAL)
1169                                         interval.tv_usec = MIN_POLL_INTERVAL;
1170
1171                                 r = select(0,0,0,0,&interval);
1172                                 if (r < 0 && errno != EINTR)
1173                                         fatal("select() failed for pause: %s",
1174                                               strerror(errno));
1175                         }
1176
1177                 default:
1178                         assert(!"schedule[].type value must be valid");
1179
1180                 }
1181
1182         next_item:
1183                 position++;
1184         }
1185
1186         if (quietmode <= 0)
1187                 printf("Program %s, %d process(es), refused to die.\n",
1188                        what_stop, n_killed);
1189
1190         return 2;
1191
1192 x_finished:
1193         if (!anykilled) {
1194                 if (quietmode <= 0)
1195                         printf("No %s found running; none killed.\n", what_stop);
1196                 return exitnodo;
1197         } else {
1198                 return 0;
1199         }
1200 }
1201
1202
1203 int main(int argc, char **argv) NONRETURNING;
1204 int
1205 main(int argc, char **argv)
1206 {
1207         int devnull_fd = -1;
1208 #ifdef HAVE_TIOCNOTTY
1209         int tty_fd = -1;
1210 #endif
1211         progname = argv[0];
1212
1213         parse_options(argc, argv);
1214         argc -= optind;
1215         argv += optind;
1216
1217         if (execname && stat(execname, &exec_stat))
1218                 fatal("stat %s: %s", execname, strerror(errno));
1219
1220         if (userspec && sscanf(userspec, "%d", &user_id) != 1) {
1221                 struct passwd *pw;
1222
1223                 pw = getpwnam(userspec);
1224                 if (!pw)
1225                         fatal("user `%s' not found\n", userspec);
1226
1227                 user_id = pw->pw_uid;
1228         }
1229
1230         if (changegroup && sscanf(changegroup, "%d", &runas_gid) != 1) {
1231                 struct group *gr = getgrnam(changegroup);
1232                 if (!gr)
1233                         fatal("group `%s' not found\n", changegroup);
1234                 runas_gid = gr->gr_gid;
1235         }
1236         if (changeuser && sscanf(changeuser, "%d", &runas_uid) != 1) {
1237                 struct passwd *pw = getpwnam(changeuser);
1238                 if (!pw)
1239                         fatal("user `%s' not found\n", changeuser);
1240                 runas_uid = pw->pw_uid;
1241                 if (changegroup == NULL) { /* pass the default group of this user */
1242                         changegroup = ""; /* just empty */
1243                         runas_gid = pw->pw_gid;
1244                 }
1245         }
1246
1247         if (stop) {
1248                 int i = run_stop_schedule();
1249                 exit(i);
1250         }
1251
1252         do_findprocs();
1253
1254         if (found) {
1255                 if (quietmode <= 0)
1256                         printf("%s already running.\n", execname ? execname : "process");
1257                 exit(exitnodo);
1258         }
1259         if (testmode) {
1260                 printf("Would start %s ", startas);
1261                 while (argc-- > 0)
1262                         printf("%s ", *argv++);
1263                 if (changeuser != NULL) {
1264                         printf(" (as user %s[%d]", changeuser, runas_uid);
1265                         if (changegroup != NULL)
1266                                 printf(", and group %s[%d])", changegroup, runas_gid);
1267                         else
1268                                 printf(")");
1269                 }
1270                 if (changeroot != NULL)
1271                         printf(" in directory %s", changeroot);
1272                 if (nicelevel)
1273                         printf(", and add %i to the priority", nicelevel);
1274                 printf(".\n");
1275                 exit(0);
1276         }
1277         if (quietmode < 0)
1278                 printf("Starting %s...\n", startas);
1279         *--argv = startas;
1280         if (background) { /* ok, we need to detach this process */
1281                 int i;
1282                 if (quietmode < 0)
1283                         printf("Detaching to start %s...", startas);
1284                 i = fork();
1285                 if (i<0) {
1286                         fatal("Unable to fork.\n");
1287                 }
1288                 if (i) { /* parent */
1289                         if (quietmode < 0)
1290                                 printf("done.\n");
1291                         exit(0);
1292                 }
1293                  /* child continues here */
1294
1295 #ifdef HAVE_TIOCNOTTY
1296                 tty_fd=open("/dev/tty", O_RDWR);
1297 #endif
1298                 devnull_fd=open("/dev/null", O_RDWR);
1299         }
1300         if (nicelevel) {
1301                 errno=0;
1302                 if ((nice(nicelevel)==-1) && (errno!=0))
1303                         fatal("Unable to alter nice level by %i: %s", nicelevel,
1304                                 strerror(errno));
1305         }
1306         if (mpidfile && pidfile != NULL) { /* user wants _us_ to make the pidfile :) */
1307                 FILE *pidf = fopen(pidfile, "w");
1308                 pid_t pidt = getpid();
1309                 if (pidf == NULL)
1310                         fatal("Unable to open pidfile `%s' for writing: %s", pidfile,
1311                                 strerror(errno));
1312                 fprintf(pidf, "%d\n", pidt);
1313                 fclose(pidf);
1314         }
1315         if (changeroot != NULL) {
1316                 if (chdir(changeroot) < 0)
1317                         fatal("Unable to chdir() to %s", changeroot);
1318                 if (chroot(changeroot) < 0)
1319                         fatal("Unable to chroot() to %s", changeroot);
1320         }
1321         if (chdir(changedir) < 0)
1322                 fatal("Unable to chdir() to %s", changedir);
1323         if (changeuser != NULL) {
1324                 if (setgid(runas_gid))
1325                         fatal("Unable to set gid to %d", runas_gid);
1326                 if (initgroups(changeuser, runas_gid))
1327                         fatal("Unable to set initgroups() with gid %d", runas_gid);
1328                 if (setuid(runas_uid))
1329                         fatal("Unable to set uid to %s", changeuser);
1330         }
1331         if (background) { /* continue background setup */
1332                 int i;
1333 #ifdef HAVE_TIOCNOTTY
1334                  /* change tty */
1335                 ioctl(tty_fd, TIOCNOTTY, 0);
1336                 close(tty_fd);
1337 #endif
1338                 umask(022); /* set a default for dumb programs */
1339                 dup2(devnull_fd,0); /* stdin */
1340                 dup2(devnull_fd,1); /* stdout */
1341                 dup2(devnull_fd,2); /* stderr */
1342 #if defined(OShpux)
1343                  /* now close all extra fds */
1344                 for (i=sysconf(_SC_OPEN_MAX)-1; i>=3; --i) close(i);
1345 #else
1346                  /* now close all extra fds */
1347                 for (i=getdtablesize()-1; i>=3; --i) close(i);
1348 #endif
1349
1350                 /* create a new session */
1351 #ifdef HAVE_SETSID
1352                 setsid();
1353 #else
1354                 setpgid(0,0);
1355 #endif
1356         }
1357
1358 #ifdef HAVE_SYS_CAPABILITY_H
1359         if (caplist) {
1360                 remove_capabilities(caplist);
1361         }
1362 #endif
1363
1364         execv(startas, argv);
1365         fatal("Unable to start %s: %s", startas, strerror(errno));
1366 }
1367