source: tools/start-stop-daemon/start-stop-daemon.c @ 6

Last change on this file since 6 was 6, checked in by alloc, 9 years ago

Renamed ssd

File size: 33.8 KB
Line 
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/*
24 * MODIFIED TO NOT DEPEND ON EXTERNAL HEADERS!
25 * By Christian Illy <christian@illy.bz>
26 * Used dpkg source package from https://packages.debian.org/stable/dpkg
27 * Version 1.16.14
28 */
29
30// from config.h, generated by configure:
31#define VERSION "1.16.14_01"
32
33//*****************************************
34// Stuff from dpkg/macros.h
35#define DPKG_ATTR_NORET
36#define DPKG_ATTR_PRINTF(n)
37/**
38 * @def array_count
39 *
40 * Returns the amount of items in an array.
41 */
42#ifndef array_count
43#define array_count(a) (sizeof(a) / sizeof((a)[0]))
44#endif
45// End of stuff from dpkg/macros.h
46//*****************************************
47
48
49#define OSLinux
50
51#define MIN_POLL_INTERVAL 20000 /* µs */
52
53#include <sys/syscall.h>
54
55#include <sys/types.h>
56#include <sys/time.h>
57#include <sys/stat.h>
58#include <sys/ioctl.h>
59#include <sys/termios.h>
60
61#include <assert.h>
62#include <errno.h>
63#include <limits.h>
64#include <fcntl.h>
65#include <dirent.h>
66#include <ctype.h>
67#include <string.h>
68#include <pwd.h>
69#include <grp.h>
70#include <signal.h>
71#include <unistd.h>
72#include <stddef.h>
73#include <stdbool.h>
74#include <stdarg.h>
75#include <stdlib.h>
76#include <stdio.h>
77#include <getopt.h>
78
79#include <error.h>
80
81#ifdef _POSIX_PRIORITY_SCHEDULING
82#include <sched.h>
83#else
84#define SCHED_OTHER -1
85#define SCHED_FIFO -1
86#define SCHED_RR -1
87#endif
88
89/* This comes from TASK_COMM_LEN defined in Linux' include/linux/sched.h. */
90#define PROCESS_NAME_SIZE 15
91
92#if defined(SYS_ioprio_set)
93#define HAVE_IOPRIO_SET
94#endif
95
96enum {
97        IOPRIO_WHO_PROCESS = 1,
98        IOPRIO_WHO_PGRP,
99        IOPRIO_WHO_USER,
100};
101
102enum {
103        IOPRIO_CLASS_NONE,
104        IOPRIO_CLASS_RT,
105        IOPRIO_CLASS_BE,
106        IOPRIO_CLASS_IDLE,
107};
108
109enum action_code {
110        action_none,
111        action_start,
112        action_stop,
113        action_status,
114};
115
116static enum action_code action;
117static int testmode = 0;
118static int quietmode = 0;
119static int exitnodo = 1;
120static int background = 0;
121static int close_io = 1;
122static int mpidfile = 0;
123static int signal_nr = SIGTERM;
124static int user_id = -1;
125static int runas_uid = -1;
126static int runas_gid = -1;
127static const char *userspec = NULL;
128static char *changeuser = NULL;
129static const char *changegroup = NULL;
130static char *changeroot = NULL;
131static const char *changedir = "/";
132static const char *cmdname = NULL;
133static char *execname = NULL;
134static char *startas = NULL;
135static const char *pidfile = NULL;
136static char what_stop[1024];
137static const char *progname = "";
138static int nicelevel = 0;
139static int umask_value = -1;
140
141#define IOPRIO_CLASS_SHIFT 13
142#define IOPRIO_PRIO_VALUE(class, prio) (((class) << IOPRIO_CLASS_SHIFT) | (prio))
143#define IO_SCHED_PRIO_MIN 0
144#define IO_SCHED_PRIO_MAX 7
145
146static struct stat exec_stat;
147
148/* LSB Init Script process status exit codes. */
149enum status_code {
150        status_ok = 0,
151        status_dead_pidfile = 1,
152        status_dead_lockfile = 2,
153        status_dead = 3,
154        status_unknown = 4,
155};
156
157struct pid_list {
158        struct pid_list *next;
159        pid_t pid;
160};
161
162static struct pid_list *found = NULL;
163static struct pid_list *killed = NULL;
164
165/* Resource scheduling policy. */
166struct res_schedule {
167        const char *policy_name;
168        int policy;
169        int priority;
170};
171
172struct schedule_item {
173        enum {
174                sched_timeout,
175                sched_signal,
176                sched_goto,
177                /* Only seen within parse_schedule and callees. */
178                sched_forever,
179        } type;
180        /* Seconds, signal no., or index into array. */
181        int value;
182};
183
184static struct res_schedule *proc_sched = NULL;
185static struct res_schedule *io_sched = NULL;
186
187static int schedule_length;
188static struct schedule_item *schedule = NULL;
189
190
191static void DPKG_ATTR_PRINTF(1)
192warning(const char *format, ...)
193{
194        va_list arglist;
195
196        fprintf(stderr, "%s: warning: ", progname);
197        va_start(arglist, format);
198        vfprintf(stderr, format, arglist);
199        va_end(arglist);
200}
201
202static void DPKG_ATTR_NORET DPKG_ATTR_PRINTF(1)
203fatal(const char *format, ...)
204{
205        va_list arglist;
206        int errno_fatal = errno;
207
208        fprintf(stderr, "%s: ", progname);
209        va_start(arglist, format);
210        vfprintf(stderr, format, arglist);
211        va_end(arglist);
212        if (errno_fatal)
213                fprintf(stderr, " (%s)\n", strerror(errno_fatal));
214        else
215                fprintf(stderr, "\n");
216
217        if (action == action_status)
218                exit(status_unknown);
219        else
220                exit(2);
221}
222
223static void *
224xmalloc(int size)
225{
226        void *ptr;
227
228        ptr = malloc(size);
229        if (ptr)
230                return ptr;
231        fatal("malloc(%d) failed", size);
232}
233
234static char *
235xstrdup(const char *str)
236{
237        char *new_str;
238
239        new_str = strdup(str);
240        if (new_str)
241                return new_str;
242        fatal("strdup(%s) failed", str);
243}
244
245static void
246xgettimeofday(struct timeval *tv)
247{
248        if (gettimeofday(tv, NULL) != 0)
249                fatal("gettimeofday failed");
250}
251
252static void
253tmul(struct timeval *a, int b)
254{
255        a->tv_sec *= b;
256        a->tv_usec *= b;
257        a->tv_sec = a->tv_sec + a->tv_usec / 1000000;
258        a->tv_usec %= 1000000;
259}
260
261static char *
262newpath(const char *dirname, const char *filename)
263{
264        char *path;
265        size_t path_len;
266
267        path_len = strlen(dirname) + 1 + strlen(filename) + 1;
268        path = xmalloc(path_len);
269        snprintf(path, path_len, "%s/%s", dirname, filename);
270
271        return path;
272}
273
274static long
275get_open_fd_max(void)
276{
277        return getdtablesize();
278}
279
280static void
281daemonize(void)
282{
283        pid_t pid;
284
285        if (quietmode < 0)
286                printf("Detaching to start %s...", startas);
287
288        pid = fork();
289        if (pid < 0)
290                fatal("unable to do first fork");
291        else if (pid) /* Parent. */
292                _exit(0);
293
294        /* Create a new session. */
295        setsid();
296
297        pid = fork();
298        if (pid < 0)
299                fatal("unable to do second fork");
300        else if (pid) /* Parent. */
301                _exit(0);
302
303        if (quietmode < 0)
304                printf("done.\n");
305}
306
307static void
308write_pidfile(const char *filename, pid_t pid)
309{
310        FILE *fp;
311        int fd;
312
313        fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW, 0666);
314        if (fd < 0)
315                fp = NULL;
316        else
317                fp = fdopen(fd, "w");
318
319        if (fp == NULL)
320                fatal("unable to open pidfile '%s' for writing", filename);
321
322        fprintf(fp, "%d\n", pid);
323
324        if (fclose(fp))
325                fatal("unable to close pidfile '%s'", filename);
326}
327
328static void
329pid_list_push(struct pid_list **list, pid_t pid)
330{
331        struct pid_list *p;
332
333        p = xmalloc(sizeof(*p));
334        p->next = *list;
335        p->pid = pid;
336        *list = p;
337}
338
339static void
340pid_list_free(struct pid_list **list)
341{
342        struct pid_list *here, *next;
343
344        for (here = *list; here != NULL; here = next) {
345                next = here->next;
346                free(here);
347        }
348
349        *list = NULL;
350}
351
352static void
353usage(void)
354{
355        printf(
356"Usage: start-stop-daemon [<option> ...] <command>\n"
357"\n"
358"Commands:\n"
359"  -S|--start -- <argument> ...  start a program and pass <arguments> to it\n"
360"  -K|--stop                     stop a program\n"
361"  -T|--status                   get the program status\n"
362"  -H|--help                     print help information\n"
363"  -V|--version                  print version\n"
364"\n"
365"Matching options (at least one is required):\n"
366"  -p|--pidfile <pid-file>       pid file to check\n"
367"  -x|--exec <executable>        program to start/check if it is running\n"
368"  -n|--name <process-name>      process name to check\n"
369"  -u|--user <username|uid>      process owner to check\n"
370"\n"
371"Options:\n"
372"  -g|--group <group|gid>        run process as this group\n"
373"  -c|--chuid <name|uid[:group|gid]>\n"
374"                                change to this user/group before starting\n"
375"                                  process\n"
376"  -s|--signal <signal>          signal to send (default TERM)\n"
377"  -a|--startas <pathname>       program to start (default is <executable>)\n"
378"  -r|--chroot <directory>       chroot to <directory> before starting\n"
379"  -d|--chdir <directory>        change to <directory> (default is /)\n"
380"  -N|--nicelevel <incr>         add incr to the process' nice level\n"
381"  -P|--procsched <policy[:prio]>\n"
382"                                use <policy> with <prio> for the kernel\n"
383"                                  process scheduler (default prio is 0)\n"
384"  -I|--iosched <class[:prio]>   use <class> with <prio> to set the IO\n"
385"                                  scheduler (default prio is 4)\n"
386"  -k|--umask <mask>             change the umask to <mask> before starting\n"
387"  -b|--background               force the process to detach\n"
388"  -C|--no-close                 do not close any file descriptor\n"
389"  -m|--make-pidfile             create the pidfile before starting\n"
390"  -R|--retry <schedule>         check whether processes die, and retry\n"
391"  -t|--test                     test mode, don't do anything\n"
392"  -o|--oknodo                   exit status 0 (not 1) if nothing done\n"
393"  -q|--quiet                    be more quiet\n"
394"  -v|--verbose                  be more verbose\n"
395"\n"
396"Retry <schedule> is <item>|/<item>/... where <item> is one of\n"
397" -<signal-num>|[-]<signal-name>  send that signal\n"
398" <timeout>                       wait that many seconds\n"
399" forever                         repeat remainder forever\n"
400"or <schedule> may be just <timeout>, meaning <signal>/<timeout>/KILL/<timeout>\n"
401"\n"
402"The process scheduler <policy> can be one of:\n"
403"  other, fifo or rr\n"
404"\n"
405"The IO scheduler <class> can be one of:\n"
406"  real-time, best-effort or idle\n"
407"\n"
408"Exit status:\n"
409"  0 = done\n"
410"  1 = nothing done (=> 0 if --oknodo)\n"
411"  2 = with --retry, processes would not die\n"
412"  3 = trouble\n"
413"Exit status with --status:\n"
414"  0 = program is running\n"
415"  1 = program is not running and the pid file exists\n"
416"  3 = program is not running\n"
417"  4 = unable to determine status\n");
418}
419
420static void
421do_version(void)
422{
423        printf("start-stop-daemon %s for non-Debian\n\n", VERSION);
424
425        printf("Written by Marek Michalkiewicz, public domain.\n");
426}
427
428static void DPKG_ATTR_NORET
429badusage(const char *msg)
430{
431        if (msg)
432                fprintf(stderr, "%s: %s\n", progname, msg);
433        fprintf(stderr, "Try '%s --help' for more information.\n", progname);
434
435        if (action == action_status)
436                exit(status_unknown);
437        else
438                exit(3);
439}
440
441struct sigpair {
442        const char *name;
443        int signal;
444};
445
446static const struct sigpair siglist[] = {
447        { "ABRT",       SIGABRT },
448        { "ALRM",       SIGALRM },
449        { "FPE",        SIGFPE  },
450        { "HUP",        SIGHUP  },
451        { "ILL",        SIGILL  },
452        { "INT",        SIGINT  },
453        { "KILL",       SIGKILL },
454        { "PIPE",       SIGPIPE },
455        { "QUIT",       SIGQUIT },
456        { "SEGV",       SIGSEGV },
457        { "TERM",       SIGTERM },
458        { "USR1",       SIGUSR1 },
459        { "USR2",       SIGUSR2 },
460        { "CHLD",       SIGCHLD },
461        { "CONT",       SIGCONT },
462        { "STOP",       SIGSTOP },
463        { "TSTP",       SIGTSTP },
464        { "TTIN",       SIGTTIN },
465        { "TTOU",       SIGTTOU }
466};
467
468static int
469parse_unsigned(const char *string, int base, int *value_r)
470{
471        long value;
472        char *endptr;
473
474        if (!string[0])
475                return -1;
476
477        errno = 0;
478        value = strtol(string, &endptr, base);
479        if (string == endptr || *endptr != '\0' || errno != 0)
480                return -1;
481        if (value < 0 || value > INT_MAX)
482                return -1;
483
484        *value_r = value;
485        return 0;
486}
487
488static int
489parse_signal(const char *sig_str, int *sig_num)
490{
491        unsigned int i;
492
493        if (parse_unsigned(sig_str, 10, sig_num) == 0)
494                return 0;
495
496        for (i = 0; i < array_count(siglist); i++) {
497                if (strcmp(sig_str, siglist[i].name) == 0) {
498                        *sig_num = siglist[i].signal;
499                        return 0;
500                }
501        }
502        return -1;
503}
504
505static int
506parse_umask(const char *string, int *value_r)
507{
508        return parse_unsigned(string, 0, value_r);
509}
510
511static void
512validate_proc_schedule(void)
513{
514#ifdef _POSIX_PRIORITY_SCHEDULING
515        int prio_min, prio_max;
516
517        prio_min = sched_get_priority_min(proc_sched->policy);
518        prio_max = sched_get_priority_max(proc_sched->policy);
519
520        if (proc_sched->priority < prio_min)
521                badusage("process scheduler priority less than min");
522        if (proc_sched->priority > prio_max)
523                badusage("process scheduler priority greater than max");
524#endif
525}
526
527static void
528parse_proc_schedule(const char *string)
529{
530        char *policy_str, *prio_str;
531        int prio = 0;
532
533        policy_str = xstrdup(string);
534        policy_str = strtok(policy_str, ":");
535        prio_str = strtok(NULL, ":");
536
537        if (prio_str && parse_unsigned(prio_str, 10, &prio) != 0)
538                fatal("invalid process scheduler priority");
539
540        proc_sched = xmalloc(sizeof(*proc_sched));
541        proc_sched->policy_name = policy_str;
542
543        if (strcmp(policy_str, "other") == 0) {
544                proc_sched->policy = SCHED_OTHER;
545                proc_sched->priority = 0;
546        } else if (strcmp(policy_str, "fifo") == 0) {
547                proc_sched->policy = SCHED_FIFO;
548                proc_sched->priority = prio;
549        } else if (strcmp(policy_str, "rr") == 0) {
550                proc_sched->policy = SCHED_RR;
551                proc_sched->priority = prio;
552        } else
553                badusage("invalid process scheduler policy");
554
555        validate_proc_schedule();
556}
557
558static void
559parse_io_schedule(const char *string)
560{
561        char *class_str, *prio_str;
562        int prio = 4;
563
564        class_str = xstrdup(string);
565        class_str = strtok(class_str, ":");
566        prio_str = strtok(NULL, ":");
567
568        if (prio_str && parse_unsigned(prio_str, 10, &prio) != 0)
569                fatal("invalid IO scheduler priority");
570
571        io_sched = xmalloc(sizeof(*io_sched));
572        io_sched->policy_name = class_str;
573
574        if (strcmp(class_str, "real-time") == 0) {
575                io_sched->policy = IOPRIO_CLASS_RT;
576                io_sched->priority = prio;
577        } else if (strcmp(class_str, "best-effort") == 0) {
578                io_sched->policy = IOPRIO_CLASS_BE;
579                io_sched->priority = prio;
580        } else if (strcmp(class_str, "idle") == 0) {
581                io_sched->policy = IOPRIO_CLASS_IDLE;
582                io_sched->priority = 7;
583        } else
584                badusage("invalid IO scheduler policy");
585
586        if (io_sched->priority < IO_SCHED_PRIO_MIN)
587                badusage("IO scheduler priority less than min");
588        if (io_sched->priority > IO_SCHED_PRIO_MAX)
589                badusage("IO scheduler priority greater than max");
590}
591
592static void
593set_proc_schedule(struct res_schedule *sched)
594{
595#ifdef _POSIX_PRIORITY_SCHEDULING
596        struct sched_param param;
597
598        param.sched_priority = sched->priority;
599
600        if (sched_setscheduler(getpid(), sched->policy, &param) == -1)
601                fatal("unable to set process scheduler");
602#endif
603}
604
605#ifdef HAVE_IOPRIO_SET
606static inline int
607ioprio_set(int which, int who, int ioprio)
608{
609        return syscall(SYS_ioprio_set, which, who, ioprio);
610}
611#endif
612
613static void
614set_io_schedule(struct res_schedule *sched)
615{
616#ifdef HAVE_IOPRIO_SET
617        int io_sched_mask;
618
619        io_sched_mask = IOPRIO_PRIO_VALUE(sched->policy, sched->priority);
620        if (ioprio_set(IOPRIO_WHO_PROCESS, getpid(), io_sched_mask) == -1)
621                warning("unable to alter IO priority to mask %i (%s)\n",
622                        io_sched_mask, strerror(errno));
623#endif
624}
625
626static void
627parse_schedule_item(const char *string, struct schedule_item *item)
628{
629        const char *after_hyph;
630
631        if (strcmp(string, "forever") == 0) {
632                item->type = sched_forever;
633        } else if (isdigit(string[0])) {
634                item->type = sched_timeout;
635                if (parse_unsigned(string, 10, &item->value) != 0)
636                        badusage("invalid timeout value in schedule");
637        } else if ((after_hyph = string + (string[0] == '-')) &&
638                   parse_signal(after_hyph, &item->value) == 0) {
639                item->type = sched_signal;
640        } else {
641                badusage("invalid schedule item (must be [-]<signal-name>, "
642                         "-<signal-number>, <timeout> or 'forever'");
643        }
644}
645
646static void
647parse_schedule(const char *schedule_str)
648{
649        char item_buf[20];
650        const char *slash;
651        int count, repeatat;
652        size_t str_len;
653
654        count = 0;
655        for (slash = schedule_str; *slash; slash++)
656                if (*slash == '/')
657                        count++;
658
659        schedule_length = (count == 0) ? 4 : count + 1;
660        schedule = xmalloc(sizeof(*schedule) * schedule_length);
661
662        if (count == 0) {
663                schedule[0].type = sched_signal;
664                schedule[0].value = signal_nr;
665                parse_schedule_item(schedule_str, &schedule[1]);
666                if (schedule[1].type != sched_timeout) {
667                        badusage ("--retry takes timeout, or schedule list"
668                                  " of at least two items");
669                }
670                schedule[2].type = sched_signal;
671                schedule[2].value = SIGKILL;
672                schedule[3] = schedule[1];
673        } else {
674                count = 0;
675                repeatat = -1;
676                while (schedule_str != NULL) {
677                        slash = strchr(schedule_str, '/');
678                        str_len = slash ? (size_t)(slash - schedule_str) : strlen(schedule_str);
679                        if (str_len >= sizeof(item_buf))
680                                badusage("invalid schedule item: far too long"
681                                         " (you must delimit items with slashes)");
682                        memcpy(item_buf, schedule_str, str_len);
683                        item_buf[str_len] = '\0';
684                        schedule_str = slash ? slash + 1 : NULL;
685
686                        parse_schedule_item(item_buf, &schedule[count]);
687                        if (schedule[count].type == sched_forever) {
688                                if (repeatat >= 0)
689                                        badusage("invalid schedule: 'forever'"
690                                                 " appears more than once");
691                                repeatat = count;
692                                continue;
693                        }
694                        count++;
695                }
696                if (repeatat == count)
697                        badusage("invalid schedule: 'forever' appears last, "
698                                 "nothing to repeat");
699                if (repeatat >= 0) {
700                        schedule[count].type = sched_goto;
701                        schedule[count].value = repeatat;
702                        count++;
703                }
704                assert(count == schedule_length);
705        }
706}
707
708static void
709set_action(enum action_code new_action)
710{
711        if (action == new_action)
712                return;
713
714        if (action != action_none)
715                badusage("only one command can be specified");
716
717        action = new_action;
718}
719
720static void
721parse_options(int argc, char * const *argv)
722{
723        static struct option longopts[] = {
724                { "help",         0, NULL, 'H'},
725                { "stop",         0, NULL, 'K'},
726                { "start",        0, NULL, 'S'},
727                { "status",       0, NULL, 'T'},
728                { "version",      0, NULL, 'V'},
729                { "startas",      1, NULL, 'a'},
730                { "name",         1, NULL, 'n'},
731                { "oknodo",       0, NULL, 'o'},
732                { "pidfile",      1, NULL, 'p'},
733                { "quiet",        0, NULL, 'q'},
734                { "signal",       1, NULL, 's'},
735                { "test",         0, NULL, 't'},
736                { "user",         1, NULL, 'u'},
737                { "group",        1, NULL, 'g'},
738                { "chroot",       1, NULL, 'r'},
739                { "verbose",      0, NULL, 'v'},
740                { "exec",         1, NULL, 'x'},
741                { "chuid",        1, NULL, 'c'},
742                { "nicelevel",    1, NULL, 'N'},
743                { "procsched",    1, NULL, 'P'},
744                { "iosched",      1, NULL, 'I'},
745                { "umask",        1, NULL, 'k'},
746                { "background",   0, NULL, 'b'},
747                { "no-close",     0, NULL, 'C'},
748                { "make-pidfile", 0, NULL, 'm'},
749                { "retry",        1, NULL, 'R'},
750                { "chdir",        1, NULL, 'd'},
751                { NULL,           0, NULL, 0  }
752        };
753        const char *umask_str = NULL;
754        const char *signal_str = NULL;
755        const char *schedule_str = NULL;
756        const char *proc_schedule_str = NULL;
757        const char *io_schedule_str = NULL;
758        int c;
759
760        for (;;) {
761                c = getopt_long(argc, argv,
762                                "HKSVTa:n:op:qr:s:tu:vx:c:N:P:I:k:bCmR:g:d:",
763                                longopts, NULL);
764                if (c == -1)
765                        break;
766                switch (c) {
767                case 'H':  /* --help */
768                        usage();
769                        exit(0);
770                case 'K':  /* --stop */
771                        set_action(action_stop);
772                        break;
773                case 'S':  /* --start */
774                        set_action(action_start);
775                        break;
776                case 'T':  /* --status */
777                        set_action(action_status);
778                        break;
779                case 'V':  /* --version */
780                        do_version();
781                        exit(0);
782                case 'a':  /* --startas <pathname> */
783                        startas = optarg;
784                        break;
785                case 'n':  /* --name <process-name> */
786                        cmdname = optarg;
787                        break;
788                case 'o':  /* --oknodo */
789                        exitnodo = 0;
790                        break;
791                case 'p':  /* --pidfile <pid-file> */
792                        pidfile = optarg;
793                        break;
794                case 'q':  /* --quiet */
795                        quietmode = 1;
796                        break;
797                case 's':  /* --signal <signal> */
798                        signal_str = optarg;
799                        break;
800                case 't':  /* --test */
801                        testmode = 1;
802                        break;
803                case 'u':  /* --user <username>|<uid> */
804                        userspec = optarg;
805                        break;
806                case 'v':  /* --verbose */
807                        quietmode = -1;
808                        break;
809                case 'x':  /* --exec <executable> */
810                        execname = optarg;
811                        break;
812                case 'c':  /* --chuid <username>|<uid> */
813                        /* We copy the string just in case we need the
814                         * argument later. */
815                        changeuser = xstrdup(optarg);
816                        changeuser = strtok(changeuser, ":");
817                        changegroup = strtok(NULL, ":");
818                        break;
819                case 'g':  /* --group <group>|<gid> */
820                        changegroup = optarg;
821                        break;
822                case 'r':  /* --chroot /new/root */
823                        changeroot = optarg;
824                        break;
825                case 'N':  /* --nice */
826                        nicelevel = atoi(optarg);
827                        break;
828                case 'P':  /* --procsched */
829                        proc_schedule_str = optarg;
830                        break;
831                case 'I':  /* --iosched */
832                        io_schedule_str = optarg;
833                        break;
834                case 'k':  /* --umask <mask> */
835                        umask_str = optarg;
836                        break;
837                case 'b':  /* --background */
838                        background = 1;
839                        break;
840                case 'C': /* --no-close */
841                        close_io = 0;
842                        break;
843                case 'm':  /* --make-pidfile */
844                        mpidfile = 1;
845                        break;
846                case 'R':  /* --retry <schedule>|<timeout> */
847                        schedule_str = optarg;
848                        break;
849                case 'd':  /* --chdir /new/dir */
850                        changedir = optarg;
851                        break;
852                default:
853                        /* Message printed by getopt. */
854                        badusage(NULL);
855                }
856        }
857
858        if (signal_str != NULL) {
859                if (parse_signal(signal_str, &signal_nr) != 0)
860                        badusage("signal value must be numeric or name"
861                                 " of signal (KILL, INT, ...)");
862        }
863
864        if (schedule_str != NULL) {
865                parse_schedule(schedule_str);
866        }
867
868        if (proc_schedule_str != NULL)
869                parse_proc_schedule(proc_schedule_str);
870
871        if (io_schedule_str != NULL)
872                parse_io_schedule(io_schedule_str);
873
874        if (umask_str != NULL) {
875                if (parse_umask(umask_str, &umask_value) != 0)
876                        badusage("umask value must be a positive number");
877        }
878
879        if (action == action_none)
880                badusage("need one of --start or --stop or --status");
881
882        if (!execname && !pidfile && !userspec && !cmdname)
883                badusage("need at least one of --exec, --pidfile, --user or --name");
884
885        if (cmdname && strlen(cmdname) > PROCESS_NAME_SIZE)
886                warning("this system is not able to track process names\n"
887                        "longer than %d characters, please use --exec "
888                        "instead of --name.\n", PROCESS_NAME_SIZE);
889
890        if (!startas)
891                startas = execname;
892
893        if (action == action_start && !startas)
894                badusage("--start needs --exec or --startas");
895
896        if (mpidfile && pidfile == NULL)
897                badusage("--make-pidfile requires --pidfile");
898
899        if (background && action != action_start)
900                badusage("--background is only relevant with --start");
901
902        if (!close_io && !background)
903                badusage("--no-close is only relevant with --background");
904}
905
906static bool
907pid_is_exec(pid_t pid, const struct stat *esb)
908{
909        char lname[32];
910        char lcontents[_POSIX_PATH_MAX];
911        const char deleted[] = " (deleted)";
912        int nread;
913        struct stat sb;
914
915        sprintf(lname, "/proc/%d/exe", pid);
916        nread = readlink(lname, lcontents, sizeof(lcontents));
917        if (nread == -1)
918                return false;
919
920        lcontents[nread] = '\0';
921        if (strcmp(lcontents + nread - strlen(deleted), deleted) == 0)
922                lcontents[nread - strlen(deleted)] = '\0';
923
924        if (stat(lcontents, &sb) != 0)
925                return false;
926
927        return (sb.st_dev == esb->st_dev && sb.st_ino == esb->st_ino);
928}
929
930static bool
931pid_is_user(pid_t pid, uid_t uid)
932{
933        struct stat sb;
934        char buf[32];
935
936        sprintf(buf, "/proc/%d", pid);
937        if (stat(buf, &sb) != 0)
938                return false;
939        return (sb.st_uid == uid);
940}
941
942static bool
943pid_is_cmd(pid_t pid, const char *name)
944{
945        char buf[32];
946        FILE *f;
947        int c;
948
949        sprintf(buf, "/proc/%d/stat", pid);
950        f = fopen(buf, "r");
951        if (!f)
952                return false;
953        while ((c = getc(f)) != EOF && c != '(')
954                ;
955        if (c != '(') {
956                fclose(f);
957                return false;
958        }
959        /* This hopefully handles command names containing ‘)’. */
960        while ((c = getc(f)) != EOF && c == *name)
961                name++;
962        fclose(f);
963        return (c == ')' && *name == '\0');
964}
965
966static bool
967pid_is_running(pid_t pid)
968{
969        if (kill(pid, 0) == 0 || errno == EPERM)
970                return true;
971        else if (errno == ESRCH)
972                return false;
973        else
974                fatal("error checking pid %u status", pid);
975}
976
977static enum status_code
978pid_check(pid_t pid)
979{
980        if (execname && !pid_is_exec(pid, &exec_stat))
981                return status_dead;
982        if (userspec && !pid_is_user(pid, user_id))
983                return status_dead;
984        if (cmdname && !pid_is_cmd(pid, cmdname))
985                return status_dead;
986        if (action != action_stop && !pid_is_running(pid))
987                return status_dead;
988
989        pid_list_push(&found, pid);
990
991        return status_ok;
992}
993
994static enum status_code
995do_pidfile(const char *name)
996{
997        FILE *f;
998        static pid_t pid = 0;
999
1000        if (pid)
1001                return pid_check(pid);
1002
1003        f = fopen(name, "r");
1004        if (f) {
1005                enum status_code pid_status;
1006
1007                if (fscanf(f, "%d", &pid) == 1)
1008                        pid_status = pid_check(pid);
1009                else
1010                        pid_status = status_unknown;
1011                fclose(f);
1012
1013                if (pid_status == status_dead)
1014                        return status_dead_pidfile;
1015                else
1016                        return pid_status;
1017        } else if (errno == ENOENT)
1018                return status_dead;
1019        else
1020                fatal("unable to open pidfile %s", name);
1021}
1022
1023static enum status_code
1024do_procinit(void)
1025{
1026        DIR *procdir;
1027        struct dirent *entry;
1028        int foundany;
1029        pid_t pid;
1030        enum status_code prog_status = status_dead;
1031
1032        procdir = opendir("/proc");
1033        if (!procdir)
1034                fatal("unable to opendir /proc");
1035
1036        foundany = 0;
1037        while ((entry = readdir(procdir)) != NULL) {
1038                enum status_code pid_status;
1039
1040                if (sscanf(entry->d_name, "%d", &pid) != 1)
1041                        continue;
1042                foundany++;
1043
1044                pid_status = pid_check(pid);
1045                if (pid_status < prog_status)
1046                        prog_status = pid_status;
1047        }
1048        closedir(procdir);
1049        if (!foundany)
1050                fatal("nothing in /proc - not mounted?");
1051
1052        return prog_status;
1053}
1054
1055static enum status_code
1056do_findprocs(void)
1057{
1058        pid_list_free(&found);
1059
1060        if (pidfile)
1061                return do_pidfile(pidfile);
1062        else
1063                return do_procinit();
1064}
1065
1066static void
1067do_stop(int sig_num, int *n_killed, int *n_notkilled)
1068{
1069        struct pid_list *p;
1070
1071        do_findprocs();
1072
1073        *n_killed = 0;
1074        *n_notkilled = 0;
1075
1076        if (!found)
1077                return;
1078
1079        pid_list_free(&killed);
1080
1081        for (p = found; p; p = p->next) {
1082                if (testmode) {
1083                        if (quietmode <= 0)
1084                                printf("Would send signal %d to %d.\n",
1085                                       sig_num, p->pid);
1086                        (*n_killed)++;
1087                } else if (kill(p->pid, sig_num) == 0) {
1088                        pid_list_push(&killed, p->pid);
1089                        (*n_killed)++;
1090                } else {
1091                        if (sig_num)
1092                                warning("failed to kill %d: %s\n",
1093                                        p->pid, strerror(errno));
1094                        (*n_notkilled)++;
1095                }
1096        }
1097}
1098
1099static void
1100do_stop_summary(int retry_nr)
1101{
1102        struct pid_list *p;
1103
1104        if (quietmode >= 0 || !killed)
1105                return;
1106
1107        printf("Stopped %s (pid", what_stop);
1108        for (p = killed; p; p = p->next)
1109                printf(" %d", p->pid);
1110        putchar(')');
1111        if (retry_nr > 0)
1112                printf(", retry #%d", retry_nr);
1113        printf(".\n");
1114}
1115
1116static void
1117set_what_stop(const char *str)
1118{
1119        strncpy(what_stop, str, sizeof(what_stop));
1120        what_stop[sizeof(what_stop) - 1] = '\0';
1121}
1122
1123/*
1124 * We want to keep polling for the processes, to see if they've exited, or
1125 * until the timeout expires.
1126 *
1127 * This is a somewhat complicated algorithm to try to ensure that we notice
1128 * reasonably quickly when all the processes have exited, but don't spend
1129 * too much CPU time polling. In particular, on a fast machine with
1130 * quick-exiting daemons we don't want to delay system shutdown too much,
1131 * whereas on a slow one, or where processes are taking some time to exit,
1132 * we want to increase the polling interval.
1133 *
1134 * The algorithm is as follows: we measure the elapsed time it takes to do
1135 * one poll(), and wait a multiple of this time for the next poll. However,
1136 * if that would put us past the end of the timeout period we wait only as
1137 * long as the timeout period, but in any case we always wait at least
1138 * MIN_POLL_INTERVAL (20ms). The multiple (‘ratio’) starts out as 2, and
1139 * increases by 1 for each poll to a maximum of 10; so we use up to between
1140 * 30% and 10% of the machine's resources (assuming a few reasonable things
1141 * about system performance).
1142 */
1143static bool
1144do_stop_timeout(int timeout, int *n_killed, int *n_notkilled)
1145{
1146        struct timeval stopat, before, after, interval, maxinterval;
1147        int r, ratio;
1148
1149        xgettimeofday(&stopat);
1150        stopat.tv_sec += timeout;
1151        ratio = 1;
1152        for (;;) {
1153                xgettimeofday(&before);
1154                if (timercmp(&before, &stopat, >))
1155                        return false;
1156
1157                do_stop(0, n_killed, n_notkilled);
1158                if (!*n_killed)
1159                        return true;
1160
1161                xgettimeofday(&after);
1162
1163                if (!timercmp(&after, &stopat, <))
1164                        return false;
1165
1166                if (ratio < 10)
1167                        ratio++;
1168
1169                timersub(&stopat, &after, &maxinterval);
1170                timersub(&after, &before, &interval);
1171                tmul(&interval, ratio);
1172
1173                if (interval.tv_sec < 0 || interval.tv_usec < 0)
1174                        interval.tv_sec = interval.tv_usec = 0;
1175
1176                if (timercmp(&interval, &maxinterval, >))
1177                        interval = maxinterval;
1178
1179                if (interval.tv_sec == 0 &&
1180                    interval.tv_usec <= MIN_POLL_INTERVAL)
1181                        interval.tv_usec = MIN_POLL_INTERVAL;
1182
1183                r = select(0, NULL, NULL, NULL, &interval);
1184                if (r < 0 && errno != EINTR)
1185                        fatal("select() failed for pause");
1186        }
1187}
1188
1189static int
1190finish_stop_schedule(bool anykilled)
1191{
1192        if (anykilled)
1193                return 0;
1194
1195        if (quietmode <= 0)
1196                printf("No %s found running; none killed.\n", what_stop);
1197
1198        return exitnodo;
1199}
1200
1201static int
1202run_stop_schedule(void)
1203{
1204        int position, n_killed, n_notkilled, value, retry_nr;
1205        bool anykilled;
1206
1207        if (testmode) {
1208                if (schedule != NULL) {
1209                        if (quietmode <= 0)
1210                                printf("Ignoring --retry in test mode\n");
1211                        schedule = NULL;
1212                }
1213        }
1214
1215        if (cmdname)
1216                set_what_stop(cmdname);
1217        else if (execname)
1218                set_what_stop(execname);
1219        else if (pidfile)
1220                sprintf(what_stop, "process in pidfile '%.200s'", pidfile);
1221        else if (userspec)
1222                sprintf(what_stop, "process(es) owned by '%.200s'", userspec);
1223        else
1224                fatal("internal error, no match option, please report");
1225
1226        anykilled = false;
1227        retry_nr = 0;
1228
1229        if (schedule == NULL) {
1230                do_stop(signal_nr, &n_killed, &n_notkilled);
1231                do_stop_summary(0);
1232                if (n_notkilled > 0 && quietmode <= 0)
1233                        printf("%d pids were not killed\n", n_notkilled);
1234                if (n_killed)
1235                        anykilled = true;
1236                return finish_stop_schedule(anykilled);
1237        }
1238
1239        for (position = 0; position < schedule_length; position++) {
1240        reposition:
1241                value = schedule[position].value;
1242                n_notkilled = 0;
1243
1244                switch (schedule[position].type) {
1245                case sched_goto:
1246                        position = value;
1247                        goto reposition;
1248                case sched_signal:
1249                        do_stop(value, &n_killed, &n_notkilled);
1250                        do_stop_summary(retry_nr++);
1251                        if (!n_killed)
1252                                return finish_stop_schedule(anykilled);
1253                        else
1254                                anykilled = true;
1255                        continue;
1256                case sched_timeout:
1257                        if (do_stop_timeout(value, &n_killed, &n_notkilled))
1258                                return finish_stop_schedule(anykilled);
1259                        else
1260                                continue;
1261                default:
1262                        assert(!"schedule[].type value must be valid");
1263                }
1264        }
1265
1266        if (quietmode <= 0)
1267                printf("Program %s, %d process(es), refused to die.\n",
1268                       what_stop, n_killed);
1269
1270        return 2;
1271}
1272
1273int
1274main(int argc, char **argv)
1275{
1276        enum status_code prog_status;
1277        int devnull_fd = -1;
1278        gid_t rgid;
1279        uid_t ruid;
1280        progname = argv[0];
1281
1282        parse_options(argc, argv);
1283        argc -= optind;
1284        argv += optind;
1285
1286        if (execname) {
1287                char *fullexecname;
1288
1289                /* If it's a relative path, normalize it. */
1290                if (execname[0] != '/')
1291                        execname = newpath(changedir, execname);
1292
1293                if (changeroot)
1294                        fullexecname = newpath(changeroot, execname);
1295                else
1296                        fullexecname = execname;
1297
1298                if (stat(fullexecname, &exec_stat))
1299                        fatal("unable to stat %s", fullexecname);
1300
1301                if (fullexecname != execname)
1302                        free(fullexecname);
1303        }
1304
1305        if (userspec && sscanf(userspec, "%d", &user_id) != 1) {
1306                struct passwd *pw;
1307
1308                pw = getpwnam(userspec);
1309                if (!pw)
1310                        fatal("user '%s' not found", userspec);
1311
1312                user_id = pw->pw_uid;
1313        }
1314
1315        if (changegroup && sscanf(changegroup, "%d", &runas_gid) != 1) {
1316                struct group *gr = getgrnam(changegroup);
1317                if (!gr)
1318                        fatal("group '%s' not found", changegroup);
1319                changegroup = gr->gr_name;
1320                runas_gid = gr->gr_gid;
1321        }
1322        if (changeuser) {
1323                struct passwd *pw;
1324                struct stat st;
1325
1326                if (sscanf(changeuser, "%d", &runas_uid) == 1)
1327                        pw = getpwuid(runas_uid);
1328                else
1329                        pw = getpwnam(changeuser);
1330                if (!pw)
1331                        fatal("user '%s' not found", changeuser);
1332                changeuser = pw->pw_name;
1333                runas_uid = pw->pw_uid;
1334                if (changegroup == NULL) {
1335                        /* Pass the default group of this user. */
1336                        changegroup = ""; /* Just empty. */
1337                        runas_gid = pw->pw_gid;
1338                }
1339                if (stat(pw->pw_dir, &st) == 0)
1340                        setenv("HOME", pw->pw_dir, 1);
1341        }
1342
1343        if (action == action_stop) {
1344                int i = run_stop_schedule();
1345                exit(i);
1346        }
1347
1348        prog_status = do_findprocs();
1349
1350        if (action == action_status)
1351                exit(prog_status);
1352
1353        if (found) {
1354                if (quietmode <= 0)
1355                        printf("%s already running.\n", execname ? execname : "process");
1356                exit(exitnodo);
1357        }
1358        if (testmode && quietmode <= 0) {
1359                printf("Would start %s ", startas);
1360                while (argc-- > 0)
1361                        printf("%s ", *argv++);
1362                if (changeuser != NULL) {
1363                        printf(" (as user %s[%d]", changeuser, runas_uid);
1364                        if (changegroup != NULL)
1365                                printf(", and group %s[%d])", changegroup, runas_gid);
1366                        else
1367                                printf(")");
1368                }
1369                if (changeroot != NULL)
1370                        printf(" in directory %s", changeroot);
1371                if (nicelevel)
1372                        printf(", and add %i to the priority", nicelevel);
1373                if (proc_sched)
1374                        printf(", with scheduling policy %s with priority %i",
1375                               proc_sched->policy_name, proc_sched->priority);
1376                if (io_sched)
1377                        printf(", with IO scheduling class %s with priority %i",
1378                               io_sched->policy_name, io_sched->priority);
1379                printf(".\n");
1380        }
1381        if (testmode)
1382                exit(0);
1383        if (quietmode < 0)
1384                printf("Starting %s...\n", startas);
1385        *--argv = startas;
1386        if (background)
1387                /* Ok, we need to detach this process. */
1388                daemonize();
1389        if (background && close_io) {
1390                devnull_fd = open("/dev/null", O_RDWR);
1391                if (devnull_fd < 0)
1392                        fatal("unable to open '%s'", "/dev/null");
1393        }
1394        if (nicelevel) {
1395                errno = 0;
1396                if ((nice(nicelevel) == -1) && (errno != 0))
1397                        fatal("unable to alter nice level by %i", nicelevel);
1398        }
1399        if (proc_sched)
1400                set_proc_schedule(proc_sched);
1401        if (io_sched)
1402                set_io_schedule(io_sched);
1403        if (umask_value >= 0)
1404                umask(umask_value);
1405        if (mpidfile && pidfile != NULL)
1406                /* User wants _us_ to make the pidfile. */
1407                write_pidfile(pidfile, getpid());
1408        if (changeroot != NULL) {
1409                if (chdir(changeroot) < 0)
1410                        fatal("unable to chdir() to %s", changeroot);
1411                if (chroot(changeroot) < 0)
1412                        fatal("unable to chroot() to %s", changeroot);
1413        }
1414        if (chdir(changedir) < 0)
1415                fatal("unable to chdir() to %s", changedir);
1416
1417        rgid = getgid();
1418        ruid = getuid();
1419        if (changegroup != NULL) {
1420                if (rgid != (gid_t)runas_gid)
1421                        if (setgid(runas_gid))
1422                                fatal("unable to set gid to %d", runas_gid);
1423        }
1424        if (changeuser != NULL) {
1425                /* We assume that if our real user and group are the same as
1426                 * the ones we should switch to, the supplementary groups
1427                 * will be already in place. */
1428                if (rgid != (gid_t)runas_gid || ruid != (uid_t)runas_uid)
1429                        if (initgroups(changeuser, runas_gid))
1430                                fatal("unable to set initgroups() with gid %d",
1431                                      runas_gid);
1432
1433                if (ruid != (uid_t)runas_uid)
1434                        if (setuid(runas_uid))
1435                                fatal("unable to set uid to %s", changeuser);
1436        }
1437
1438        /* Set a default umask for dumb programs. */
1439        if (background && umask_value < 0)
1440                umask(022);
1441
1442        if (background && close_io) {
1443                int i;
1444
1445                dup2(devnull_fd, 0); /* stdin */
1446                dup2(devnull_fd, 1); /* stdout */
1447                dup2(devnull_fd, 2); /* stderr */
1448
1449                 /* Now close all extra fds. */
1450                for (i = get_open_fd_max() - 1; i >= 3; --i)
1451                        close(i);
1452        }
1453        execv(startas, argv);
1454        fatal("unable to start %s", startas);
1455}
Note: See TracBrowser for help on using the repository browser.