]> mj.ucw.cz Git - libucw.git/blob - ucw/utils/ucw-daemon-control.c
Macros: CLAMP now accepts arbitrary types, not only ints
[libucw.git] / ucw / utils / ucw-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: ucw-daemon-control --start <options> -- <daemon> <args>\n\
43    or: ucw-daemon-control --stop <options>\n\
44    or: ucw-daemon-control --reload <options>\n\
45    or: ucw-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 103                     The daemon was in an undefined state (e.g., stale PID file)\n\
60 ", stderr);
61   exit(1);
62 }
63
64 int
65 main(int argc, char **argv)
66 {
67   int c, sig;
68   struct daemon_control_params dc = { };
69
70   while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
71     switch (c)
72       {
73       case 0:
74         break;
75       case 'p':
76         dc.pid_file = optarg;
77         break;
78       case 'g':
79         dc.guard_file = optarg;
80         break;
81       case 's':
82         sig = sig_name_to_number(optarg);
83         if (sig < 0)
84           {
85             fprintf(stderr, "%s: Unknown signal %s\n", argv[0], optarg);
86             return 1;
87           }
88         dc.signal = sig;
89         break;
90       default:
91         usage();
92       }
93   if (!dc.pid_file || !action)
94     usage();
95   dc.action = action;
96
97   if (action == DAEMON_CONTROL_START)
98     {
99       if (optind >= argc)
100         usage();
101       dc.argv = argv + optind;
102     }
103   else if (optind < argc)
104     usage();
105
106   if (!dc.guard_file)
107     {
108       if (!str_has_suffix(dc.pid_file, ".pid"))
109         {
110           fprintf(stderr, "%s: For automatic choice of --guard-file, the --pid-file must end with `.pid'\n", argv[0]);
111           return 1;
112         }
113       int len = strlen(dc.pid_file);
114       char *buf = xmalloc(len + 2);
115       sprintf(buf, "%.*s.lock", len-4, dc.pid_file);
116       dc.guard_file = buf;
117     }
118
119   int err = daemon_control(&dc);
120   if (err == DAEMON_STATUS_ERROR)
121     fprintf(stderr, "%s: %s\n", argv[0], dc.error_msg);
122   return err;
123 }