2 * A Simple Wrapper for Starting and Stopping of Daemons
4 * (c) 2003 Martin Mares <mj@ucw.cz>
6 * It would seem that we are reinventing the wheel and the
7 * start-stop-daemon command present in most Linux distributions
8 * is just what we need, but the usual "does the process already
9 * exist?" strategies fail in presence of multiple running daemons.
39 static struct option options[] = {
40 { "pid-file", required_argument, NULL, 'p' },
41 { "status-file", required_argument, NULL, 's' },
42 { "start", no_argument, &action, ACTION_START },
43 { "stop", no_argument, &action, ACTION_STOP },
44 { "force-stop", no_argument, &action, ACTION_FORCE_STOP },
45 { "check", no_argument, &action, ACTION_CHECK },
46 { "reload", no_argument, &action, ACTION_RELOAD },
47 { NULL, no_argument, NULL, 0 }
54 Usage: daemon-helper --start <options> -- <daemon> <args>\n\
55 or: daemon-helper --stop <options>\n\
56 or: daemon-helper --force-stop <options>\n\
57 or: daemon-helper --reload <options>\n\
58 or: daemon-helper --check <options>\n\
61 --pid-file <name> Name of PID file for this daemon (mandatory)\n\
62 --status-file <name> Status file used by the daemon (deleted just before starting)\n\
68 main(int argc, char **argv)
72 char *statfile = NULL;
76 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
93 bzero(&fl, sizeof(fl));
95 fl.l_whence = SEEK_SET;
102 fd = open(pidfile, O_RDWR | O_CREAT, 0666);
104 die("Unable to create %s: %m", pidfile);
105 if ((c = fcntl(fd, F_SETLK, &fl)) < 0)
107 if (errno == EAGAIN || errno == EACCES)
110 die("fcntl lock on %s failed: %m", pidfile);
112 c = sprintf(buf, "%d\n", getpid());
113 if (write(fd, buf, c) != c)
114 die("write on %s failed: %m", pidfile);
115 if (ftruncate(fd, c) < 0)
116 die("truncate on %s failed: %m", pidfile);
117 if (statfile && unlink(statfile) < 0 && errno != ENOENT)
118 die("unlink(%s) failed: %m", statfile);
120 /* Disconnect from stdin and stdout, leave stderr to the daemon. */
122 open("/dev/null", O_RDWR, 0);
126 char **a = alloca(sizeof(char *) * (argc+1));
127 memcpy(a, argv, sizeof(char *) * argc);
130 die("Cannot execute %s: %m", a[0]);
132 case ACTION_FORCE_STOP:
137 fd = open(pidfile, O_RDWR);
143 die("Unable to open %s: %m", pidfile);
145 if ((c = fcntl(fd, F_SETLK, &fl)) >= 0)
151 if (errno != EAGAIN && errno != EACCES)
152 die("fcntl lock on %s failed: %m", pidfile);
153 if ((c = read(fd, buf, sizeof(buf))) < 0)
154 die("read on %s failed: %m", pidfile);
157 if (c >= (int) sizeof(buf) || sscanf(buf, "%d", &c) != 1)
158 die("PID file syntax error");
160 if (action == ACTION_CHECK || action == ACTION_RELOAD)
162 if (action == ACTION_RELOAD)
164 if (kill(c, sig) < 0 && errno == ESRCH)
168 sig = (action == ACTION_STOP) ? SIGTERM : SIGQUIT;
169 if (kill(c, sig) < 0)
173 die("Cannot kill process %d: %m", c);
175 if ((c = fcntl(fd, F_SETLKW, &fl)) < 0)
176 die("Cannot lock %s: %m", pidfile);
179 if (unlink(pidfile) < 0)
180 die("Cannot unlink %s: %m", pidfile);