]> mj.ucw.cz Git - libucw.git/blob - ucw/utils/daemon-control.c
85fb450121fae750f75592c25024ec60876162f4
[libucw.git] / ucw / utils / daemon-control.c
1 /*
2  *      A Simple Utility for Controlling Daemons
3  *
4  *      (c) 2012 Martin Mares <mj@ucw.cz>
5  *
6  *      For more information, see ucw/doc/daemon.txt.
7  *
8  *      Return codes:
9  *      100     already done
10  *      101     not running
11  *      102     error
12  */
13
14 #include <ucw/lib.h>
15 #include <ucw/daemon.h>
16 #include <ucw/signames.h>
17 #include <ucw/string.h>
18
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <signal.h>
23 #include <getopt.h>
24
25 static int action;
26
27 static struct option options[] = {
28   { "pid-file",         required_argument,      NULL,           'p' },
29   { "guard-file",       required_argument,      NULL,           'g' },
30   { "signal",           required_argument,      NULL,           's' },
31   { "start",            no_argument,            &action,        DAEMON_CONTROL_START },
32   { "stop",             no_argument,            &action,        DAEMON_CONTROL_STOP },
33   { "check",            no_argument,            &action,        DAEMON_CONTROL_CHECK },
34   { "reload",           no_argument,            &action,        DAEMON_CONTROL_SIGNAL },
35   { NULL,               no_argument,            NULL,           0 }
36 };
37
38 static void NONRET
39 usage(void)
40 {
41   fputs("\n\
42 Usage: daemon-control --start <options> -- <daemon> <args>\n\
43    or: daemon-control --stop <options>\n\
44    or: daemon-control --reload <options>\n\
45    or: daemon-control --check <options>\n\
46 \n\
47 Options:\n\
48 --pid-file <name>       Name of PID file for this daemon (mandatory)\n\
49 --guard-file <name>     Name of guard file (default: derived from --pid-file)\n\
50 --signal <sig>          Send a signal of a given name or number\n\
51                         Default: SIGTERM for --stop, SIGHUP for --reload\n\
52 \n\
53 Exit codes:\n\
54 0                       Successfully completed\n\
55 1                       Invalid arguments\n\
56 100                     The action was null (e.g., --stop on a stopped daemon)\n\
57 101                     The daemon was not running (on --reload or --check)\n\
58 102                     The action has failed (error message was printed to stderr)\n\
59 ", stderr);
60   exit(1);
61 }
62
63 int
64 main(int argc, char **argv)
65 {
66   int c, sig;
67   struct daemon_control_params dc = { };
68
69   while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
70     switch (c)
71       {
72       case 0:
73         break;
74       case 'p':
75         dc.pid_file = optarg;
76         break;
77       case 'g':
78         dc.guard_file = optarg;
79         break;
80       case 's':
81         sig = sig_name_to_number(optarg);
82         if (sig < 0)
83           {
84             fprintf(stderr, "%s: Unknown signal %s\n", argv[0], optarg);
85             return 1;
86           }
87         dc.signal = sig;
88         break;
89       default:
90         usage();
91       }
92   if (!dc.pid_file || !action)
93     usage();
94   dc.action = action;
95
96   if (action == DAEMON_CONTROL_START)
97     {
98       if (optind >= argc)
99         usage();
100       dc.argv = argv + optind;
101     }
102   else if (optind < argc)
103     usage();
104
105   if (!dc.guard_file)
106     {
107       if (!str_has_suffix(dc.pid_file, ".pid"))
108         {
109           fprintf(stderr, "%s: For automatic choice of --guard-file, the --pid-file must end with `.pid'\n", argv[0]);
110           return 1;
111         }
112       int len = strlen(dc.pid_file);
113       char *buf = xmalloc(len + 2);
114       sprintf(buf, "%.*s.lock", len-4, dc.pid_file);
115       dc.guard_file = buf;
116     }
117
118   int err = daemon_control(&dc);
119   if (err == DAEMON_STATUS_ERROR)
120     fprintf(stderr, "%s: %s\n", argv[0], dc.error_msg);
121   return err;
122 }