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.
15 * NOTE: This utility is obsolete and has been replaced by ucw-daemon-control.
16 * You need to enable CONFIG_UCW_OBSOLETE_DAEMON_HELPER to compile it.
42 static struct option options[] = {
43 { "pid-file", required_argument, NULL, 'p' },
44 { "status-file", required_argument, NULL, 's' },
45 { "start", no_argument, &action, ACTION_START },
46 { "stop", no_argument, &action, ACTION_STOP },
47 { "force-stop", no_argument, &action, ACTION_FORCE_STOP },
48 { "check", no_argument, &action, ACTION_CHECK },
49 { "reload", no_argument, &action, ACTION_RELOAD },
50 { NULL, no_argument, NULL, 0 }
57 Usage: ucw-daemon-helper --start <options> -- <daemon> <args>\n\
58 or: ucw-daemon-helper --stop <options>\n\
59 or: ucw-daemon-helper --force-stop <options>\n\
60 or: ucw-daemon-helper --reload <options>\n\
61 or: ucw-daemon-helper --check <options>\n\
64 --pid-file <name> Name of PID file for this daemon (mandatory)\n\
65 --status-file <name> Status file used by the daemon (deleted just before starting)\n\
71 main(int argc, char **argv)
75 char *statfile = NULL;
79 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
96 bzero(&fl, sizeof(fl));
98 fl.l_whence = SEEK_SET;
105 fd = open(pidfile, O_RDWR | O_CREAT, 0666);
107 die("Unable to create %s: %m", pidfile);
108 if ((c = fcntl(fd, F_SETLK, &fl)) < 0)
110 if (errno == EAGAIN || errno == EACCES)
113 die("fcntl lock on %s failed: %m", pidfile);
115 c = sprintf(buf, "%d\n", getpid());
116 if (write(fd, buf, c) != c)
117 die("write on %s failed: %m", pidfile);
118 if (ftruncate(fd, c) < 0)
119 die("truncate on %s failed: %m", pidfile);
120 if (statfile && unlink(statfile) < 0 && errno != ENOENT)
121 die("unlink(%s) failed: %m", statfile);
123 /* Disconnect from stdin and stdout, leave stderr to the daemon. */
125 open("/dev/null", O_RDWR, 0);
129 char **a = alloca(sizeof(char *) * (argc+1));
130 memcpy(a, argv, sizeof(char *) * argc);
133 die("Cannot execute %s: %m", a[0]);
135 case ACTION_FORCE_STOP:
140 fd = open(pidfile, O_RDWR);
146 die("Unable to open %s: %m", pidfile);
148 if ((c = fcntl(fd, F_SETLK, &fl)) >= 0)
154 if (errno != EAGAIN && errno != EACCES)
155 die("fcntl lock on %s failed: %m", pidfile);
156 if ((c = read(fd, buf, sizeof(buf))) < 0)
157 die("read on %s failed: %m", pidfile);
160 if (c >= (int) sizeof(buf) || sscanf(buf, "%d", &c) != 1)
161 die("PID file syntax error");
163 if (action == ACTION_CHECK || action == ACTION_RELOAD)
165 if (action == ACTION_RELOAD)
167 if (kill(c, sig) < 0 && errno == ESRCH)
171 sig = (action == ACTION_STOP) ? SIGTERM : SIGQUIT;
172 if (kill(c, sig) < 0)
176 die("Cannot kill process %d: %m", c);
178 if ((c = fcntl(fd, F_SETLKW, &fl)) < 0)
179 die("Cannot lock %s: %m", pidfile);
182 if (unlink(pidfile) < 0)
183 die("Cannot unlink %s: %m", pidfile);