Intergrate our standard options

This commit is contained in:
Roy Marples 2007-08-17 11:01:18 +00:00
parent d1a1e3a3c9
commit bc90e41b76

View File

@ -9,6 +9,8 @@
system so we can monitor daemons a little. system so we can monitor daemons a little.
*/ */
#define APPLET "start-stop-daemon"
/* nano seconds */ /* nano seconds */
#define POLL_INTERVAL 20000000 #define POLL_INTERVAL 20000000
#define START_WAIT 100000000 #define START_WAIT 100000000
@ -63,7 +65,7 @@ typedef struct schedulelist
} schedulelist_t; } schedulelist_t;
static schedulelist_t *schedule; static schedulelist_t *schedule;
static char *progname; static char *applet;
static char *changeuser; static char *changeuser;
static char **newenv; static char **newenv;
@ -133,7 +135,7 @@ static int parse_signal (const char *sig)
if (sscanf (sig, "%u", &i) == 1) { if (sscanf (sig, "%u", &i) == 1) {
if (i > 0 && i < sizeof (signallist) / sizeof (signallist[0])) if (i > 0 && i < sizeof (signallist) / sizeof (signallist[0]))
return (i); return (i);
eerrorx ("%s: `%s' is not a valid signal", progname, sig); eerrorx ("%s: `%s' is not a valid signal", applet, sig);
} }
if (strncmp (sig, "SIG", 3) == 0) if (strncmp (sig, "SIG", 3) == 0)
@ -146,7 +148,7 @@ static int parse_signal (const char *sig)
(s && strcmp (s, signallist[i].name) == 0)) (s && strcmp (s, signallist[i].name) == 0))
return (signallist[i].signal); return (signallist[i].signal);
eerrorx ("%s: `%s' is not a valid signal", progname, sig); eerrorx ("%s: `%s' is not a valid signal", applet, sig);
} }
static void parse_schedule_item (schedulelist_t *item, const char *string) static void parse_schedule_item (schedulelist_t *item, const char *string)
@ -160,7 +162,7 @@ static void parse_schedule_item (schedulelist_t *item, const char *string)
item->type = schedule_timeout; item->type = schedule_timeout;
errno = 0; errno = 0;
if (sscanf (string, "%d", &item->value) != 1) if (sscanf (string, "%d", &item->value) != 1)
eerrorx ("%s: invalid timeout value in schedule `%s'", progname, eerrorx ("%s: invalid timeout value in schedule `%s'", applet,
string); string);
} else if ((after_hyph = string + (string[0] == '-')) && } else if ((after_hyph = string + (string[0] == '-')) &&
((sig = parse_signal (after_hyph)) != -1)) ((sig = parse_signal (after_hyph)) != -1))
@ -169,7 +171,7 @@ static void parse_schedule_item (schedulelist_t *item, const char *string)
item->value = (int) sig; item->value = (int) sig;
} }
else else
eerrorx ("%s: invalid schedule item `%s'", progname, string); eerrorx ("%s: invalid schedule item `%s'", applet, string);
} }
static void parse_schedule (const char *string, int default_signal) static void parse_schedule (const char *string, int default_signal)
@ -201,7 +203,7 @@ static void parse_schedule (const char *string, int default_signal)
next->gotolist = NULL; next->gotolist = NULL;
if (string) { if (string) {
if (sscanf (string, "%d", &next->value) != 1) if (sscanf (string, "%d", &next->value) != 1)
eerrorx ("%s: invalid timeout value in schedule", progname); eerrorx ("%s: invalid timeout value in schedule", applet);
} }
else else
next->value = 5; next->value = 5;
@ -218,7 +220,7 @@ static void parse_schedule (const char *string, int default_signal)
len = strlen (string); len = strlen (string);
if (len >= (ptrdiff_t) sizeof (buffer)) if (len >= (ptrdiff_t) sizeof (buffer))
eerrorx ("%s: invalid schedule item, far too long", progname); eerrorx ("%s: invalid schedule item, far too long", applet);
memcpy (buffer, string, len); memcpy (buffer, string, len);
buffer[len] = 0; buffer[len] = 0;
@ -228,7 +230,7 @@ static void parse_schedule (const char *string, int default_signal)
if (next->type == schedule_forever) { if (next->type == schedule_forever) {
if (repeatat) if (repeatat)
eerrorx ("%s: invalid schedule, `forever' appears more than once", eerrorx ("%s: invalid schedule, `forever' appears more than once",
progname); applet);
repeatat = next; repeatat = next;
continue; continue;
@ -263,13 +265,13 @@ static pid_t get_pid (const char *pidfile, bool quiet)
if ((fp = fopen (pidfile, "r")) == NULL) { if ((fp = fopen (pidfile, "r")) == NULL) {
if (! quiet) if (! quiet)
eerror ("%s: fopen `%s': %s", progname, pidfile, strerror (errno)); eerror ("%s: fopen `%s': %s", applet, pidfile, strerror (errno));
return (-1); return (-1);
} }
if (fscanf (fp, "%d", &pid) != 1) { if (fscanf (fp, "%d", &pid) != 1) {
if (! quiet) if (! quiet)
eerror ("%s: no pid found in `%s'", progname, pidfile); eerror ("%s: no pid found in `%s'", applet, pidfile);
fclose (fp); fclose (fp);
return (-1); return (-1);
} }
@ -311,7 +313,7 @@ static int do_stop (const char *exec, const char *cmd,
if (! killed) { if (! killed) {
if (! quiet) if (! quiet)
eerror ("%s: failed to send signal %d to PID %d: %s", eerror ("%s: failed to send signal %d to PID %d: %s",
progname, sig, pids[i], strerror (errno)); applet, sig, pids[i], strerror (errno));
if (verbose) if (verbose)
eend (1, NULL); eend (1, NULL);
nkilled = -1; nkilled = -1;
@ -362,7 +364,7 @@ static int run_stop_schedule (const char *exec, const char *cmd,
if (nkilled == 0) { if (nkilled == 0) {
if (tkilled == 0) { if (tkilled == 0) {
if (! quiet) if (! quiet)
eerror ("%s: no matching processes found", progname); eerror ("%s: no matching processes found", applet);
} }
return (tkilled); return (tkilled);
} }
@ -388,9 +390,9 @@ static int run_stop_schedule (const char *exec, const char *cmd,
if (nanosleep (&ts, NULL) == -1) { if (nanosleep (&ts, NULL) == -1) {
if (errno == EINTR) if (errno == EINTR)
eerror ("%s: caught an interupt", progname); eerror ("%s: caught an interupt", applet);
else { else {
eerror ("%s: nanosleep: %s", progname, strerror (errno)); eerror ("%s: nanosleep: %s", applet, strerror (errno));
return (0); return (0);
} }
} }
@ -399,7 +401,7 @@ static int run_stop_schedule (const char *exec, const char *cmd,
break; break;
default: default:
eerror ("%s: invalid schedule item `%d'", progname, item->type); eerror ("%s: invalid schedule item `%d'", applet, item->type);
return (0); return (0);
} }
@ -412,9 +414,9 @@ static int run_stop_schedule (const char *exec, const char *cmd,
if (! quiet) { if (! quiet) {
if (nrunning == 1) if (nrunning == 1)
eerror ("%s: %d process refused to stop", progname, nrunning); eerror ("%s: %d process refused to stop", applet, nrunning);
else else
eerror ("%s: %d process(es) refused to stop", progname, nrunning); eerror ("%s: %d process(es) refused to stop", applet, nrunning);
} }
return (-nrunning); return (-nrunning);
@ -437,64 +439,69 @@ static void handle_signal (int sig)
case SIGQUIT: case SIGQUIT:
if (! signame[0]) if (! signame[0])
snprintf (signame, sizeof (signame), "SIGQUIT"); snprintf (signame, sizeof (signame), "SIGQUIT");
eerrorx ("%s: caught %s, aborting", progname, signame); eerrorx ("%s: caught %s, aborting", applet, signame);
case SIGCHLD: case SIGCHLD:
while (1) { while (1) {
if ((pid = waitpid (-1, &status, WNOHANG)) < 0) { if ((pid = waitpid (-1, &status, WNOHANG)) < 0) {
if (errno != ECHILD) if (errno != ECHILD)
eerror ("%s: waitpid: %s", progname, strerror (errno)); eerror ("%s: waitpid: %s", applet, strerror (errno));
break; break;
} }
} }
break; break;
default: default:
eerror ("%s: caught unknown signal %d", progname, sig); eerror ("%s: caught unknown signal %d", applet, sig);
} }
/* Restore errno */ /* Restore errno */
errno = serrno; errno = serrno;
} }
#include "_usage.h"
#define getoptstring "KN:R:Sbc:d:g:mn:op:qs:tu:r:vx:1:2:" getoptstring_COMMON
static struct option longopts[] = {
{ "stop", 0, NULL, 'K'},
{ "nicelevel", 1, NULL, 'N'},
{ "retry", 1, NULL, 'R'},
{ "start", 0, NULL, 'S'},
{ "startas", 1, NULL, 'a'},
{ "background", 0, NULL, 'b'},
{ "chuid", 1, NULL, 'c'},
{ "chdir", 1, NULL, 'd'},
{ "group", 1, NULL, 'g'},
{ "make-pidfile", 0, NULL, 'm'},
{ "name", 1, NULL, 'n'},
{ "oknodo", 0, NULL, 'o'},
{ "pidfile", 1, NULL, 'p'},
{ "quiet", 0, NULL, 'q'},
{ "signal", 1, NULL, 's'},
{ "test", 0, NULL, 't'},
{ "user", 1, NULL, 'u'},
{ "chroot", 1, NULL, 'r'},
{ "verbose", 0, NULL, 'v'},
{ "exec", 1, NULL, 'x'},
{ "stdout", 1, NULL, '1'},
{ "stderr", 1, NULL, '2'},
longopts_COMMON
{ NULL, 0, NULL, 0}
};
#include "_usage.c"
int start_stop_daemon (int argc, char **argv) int start_stop_daemon (int argc, char **argv)
{ {
int devnull_fd = -1; int devnull_fd = -1;
#ifdef TIOCNOTTY #ifdef TIOCNOTTY
int tty_fd = -1; int tty_fd = -1;
#endif #endif
#ifdef HAVE_PAM #ifdef HAVE_PAM
pam_handle_t *pamh = NULL; pam_handle_t *pamh = NULL;
int pamr; int pamr;
#endif #endif
static struct option longopts[] = {
{ "stop", 0, NULL, 'K'},
{ "nicelevel", 1, NULL, 'N'},
{ "retry", 1, NULL, 'R'},
{ "start", 0, NULL, 'S'},
{ "startas", 1, NULL, 'a'},
{ "background", 0, NULL, 'b'},
{ "chuid", 1, NULL, 'c'},
{ "chdir", 1, NULL, 'd'},
{ "group", 1, NULL, 'g'},
{ "make-pidfile", 0, NULL, 'm'},
{ "name", 1, NULL, 'n'},
{ "oknodo", 0, NULL, 'o'},
{ "pidfile", 1, NULL, 'p'},
{ "quiet", 0, NULL, 'q'},
{ "signal", 1, NULL, 's'},
{ "test", 0, NULL, 't'},
{ "user", 1, NULL, 'u'},
{ "chroot", 1, NULL, 'r'},
{ "verbose", 0, NULL, 'v'},
{ "exec", 1, NULL, 'x'},
{ "stdout", 1, NULL, '1'},
{ "stderr", 1, NULL, '2'},
{ NULL, 0, NULL, 0}
};
int opt; int opt;
bool start = false; bool start = false;
bool stop = false; bool stop = false;
@ -523,7 +530,7 @@ int start_stop_daemon (int argc, char **argv)
char *svcname = getenv ("SVCNAME"); char *svcname = getenv ("SVCNAME");
char *env; char *env;
progname = argv[0]; applet = argv[0];
atexit (cleanup); atexit (cleanup);
signal (SIGINT, handle_signal); signal (SIGINT, handle_signal);
@ -532,11 +539,10 @@ int start_stop_daemon (int argc, char **argv)
if ((env = getenv ("SSD_NICELEVEL"))) if ((env = getenv ("SSD_NICELEVEL")))
if (sscanf (env, "%d", &nicelevel) != 1) if (sscanf (env, "%d", &nicelevel) != 1)
eerror ("%s: invalid nice level `%s' (SSD_NICELEVEL)", progname, env); eerror ("%s: invalid nice level `%s' (SSD_NICELEVEL)", applet, env);
while ((opt = getopt_long (argc, argv, while ((opt = getopt_long (argc, argv, getoptstring, longopts,
"KN:R:Sbc:d:g:mn:op:qs:tu:r:vx:1:2:", (int *) 0)) != -1)
longopts, (int *) 0)) != -1)
switch (opt) { switch (opt) {
case 'K': /* --stop */ case 'K': /* --stop */
stop = true; stop = true;
@ -544,7 +550,7 @@ int start_stop_daemon (int argc, char **argv)
case 'N': /* --nice */ case 'N': /* --nice */
if (sscanf (optarg, "%d", &nicelevel) != 1) if (sscanf (optarg, "%d", &nicelevel) != 1)
eerrorx ("%s: invalid nice level `%s'", progname, optarg); eerrorx ("%s: invalid nice level `%s'", applet, optarg);
break; break;
case 'R': /* --retry <schedule>|<timeout> */ case 'R': /* --retry <schedule>|<timeout> */
@ -572,7 +578,7 @@ int start_stop_daemon (int argc, char **argv)
pw = getpwuid (tid); pw = getpwuid (tid);
if (! pw) if (! pw)
eerrorx ("%s: user `%s' not found", progname, cu); eerrorx ("%s: user `%s' not found", applet, cu);
uid = pw->pw_uid; uid = pw->pw_uid;
if (! gid) if (! gid)
gid = pw->pw_gid; gid = pw->pw_gid;
@ -587,7 +593,7 @@ int start_stop_daemon (int argc, char **argv)
gr = getgrgid (tid); gr = getgrgid (tid);
if (! gr) if (! gr)
eerrorx ("%s: group `%s' not found", progname, cg); eerrorx ("%s: group `%s' not found", applet, cg);
gid = gr->gr_gid; gid = gr->gr_gid;
} }
} }
@ -607,7 +613,7 @@ int start_stop_daemon (int argc, char **argv)
gr = getgrgid (tid); gr = getgrgid (tid);
if (! gr) if (! gr)
eerrorx ("%s: group `%s' not found", progname, optarg); eerrorx ("%s: group `%s' not found", applet, optarg);
gid = gr->gr_gid; gid = gr->gr_gid;
} }
break; break;
@ -644,7 +650,7 @@ int start_stop_daemon (int argc, char **argv)
if (sscanf (optarg, "%d", &tid) != 1) { if (sscanf (optarg, "%d", &tid) != 1) {
struct passwd *pw = getpwnam (optarg); struct passwd *pw = getpwnam (optarg);
if (! pw) if (! pw)
eerrorx ("%s: user `%s' not found", progname, optarg); eerrorx ("%s: user `%s' not found", applet, optarg);
uid = pw->pw_uid; uid = pw->pw_uid;
} else } else
uid = tid; uid = tid;
@ -671,8 +677,7 @@ int start_stop_daemon (int argc, char **argv)
redirect_stderr = optarg; redirect_stderr = optarg;
break; break;
default: case_RC_COMMON_GETOPT
exit (EXIT_FAILURE);
} }
/* Respect RC as well as how we are called */ /* Respect RC as well as how we are called */
@ -692,23 +697,23 @@ int start_stop_daemon (int argc, char **argv)
} }
if (start == stop) if (start == stop)
eerrorx ("%s: need one of --start or --stop", progname); eerrorx ("%s: need one of --start or --stop", applet);
if (start && ! exec) if (start && ! exec)
eerrorx ("%s: --start needs --exec", progname); eerrorx ("%s: --start needs --exec", applet);
if (stop && ! exec && ! pidfile && ! cmd && ! uid) if (stop && ! exec && ! pidfile && ! cmd && ! uid)
eerrorx ("%s: --stop needs --exec, --pidfile, --name or --user", progname); eerrorx ("%s: --stop needs --exec, --pidfile, --name or --user", applet);
if (makepidfile && ! pidfile) if (makepidfile && ! pidfile)
eerrorx ("%s: --make-pidfile is only relevant with --pidfile", progname); eerrorx ("%s: --make-pidfile is only relevant with --pidfile", applet);
if (background && ! start) if (background && ! start)
eerrorx ("%s: --background is only relevant with --start", progname); eerrorx ("%s: --background is only relevant with --start", applet);
if ((redirect_stdout || redirect_stderr) && ! background) if ((redirect_stdout || redirect_stderr) && ! background)
eerrorx ("%s: --stdout and --stderr are only relevant with --background", eerrorx ("%s: --stdout and --stderr are only relevant with --background",
progname); applet);
argc -= optind; argc -= optind;
argv += optind; argv += optind;
@ -721,7 +726,7 @@ int start_stop_daemon (int argc, char **argv)
else else
tmp = exec; tmp = exec;
if (! rc_is_file (tmp)) { if (! rc_is_file (tmp)) {
eerror ("%s: %s does not exist", progname, tmp); eerror ("%s: %s does not exist", applet, tmp);
if (ch_root) if (ch_root)
free (tmp); free (tmp);
exit (EXIT_FAILURE); exit (EXIT_FAILURE);
@ -756,7 +761,7 @@ int start_stop_daemon (int argc, char **argv)
} }
if (do_stop (exec, cmd, pidfile, uid, 0, true, false, true) > 0) if (do_stop (exec, cmd, pidfile, uid, 0, true, false, true) > 0)
eerrorx ("%s: %s is already running", progname, exec); eerrorx ("%s: %s is already running", applet, exec);
if (test) { if (test) {
if (quiet) if (quiet)
@ -795,7 +800,7 @@ int start_stop_daemon (int argc, char **argv)
*--argv = exec; *--argv = exec;
if ((pid = fork ()) == -1) if ((pid = fork ()) == -1)
eerrorx ("%s: fork: %s", progname, strerror (errno)); eerrorx ("%s: fork: %s", applet, strerror (errno));
/* Child process - lets go! */ /* Child process - lets go! */
if (pid == 0) { if (pid == 0) {
@ -809,20 +814,20 @@ int start_stop_daemon (int argc, char **argv)
if (nicelevel) { if (nicelevel) {
if (setpriority (PRIO_PROCESS, mypid, nicelevel) == -1) if (setpriority (PRIO_PROCESS, mypid, nicelevel) == -1)
eerrorx ("%s: setpritory %d: %s", progname, nicelevel, eerrorx ("%s: setpritory %d: %s", applet, nicelevel,
strerror(errno)); strerror(errno));
} }
if (ch_root && chroot (ch_root) < 0) if (ch_root && chroot (ch_root) < 0)
eerrorx ("%s: chroot `%s': %s", progname, ch_root, strerror (errno)); eerrorx ("%s: chroot `%s': %s", applet, ch_root, strerror (errno));
if (ch_dir && chdir (ch_dir) < 0) if (ch_dir && chdir (ch_dir) < 0)
eerrorx ("%s: chdir `%s': %s", progname, ch_dir, strerror (errno)); eerrorx ("%s: chdir `%s': %s", applet, ch_dir, strerror (errno));
if (makepidfile && pidfile) { if (makepidfile && pidfile) {
FILE *fp = fopen (pidfile, "w"); FILE *fp = fopen (pidfile, "w");
if (! fp) if (! fp)
eerrorx ("%s: fopen `%s': %s", progname, pidfile, strerror eerrorx ("%s: fopen `%s': %s", applet, pidfile, strerror
(errno)); (errno));
fprintf (fp, "%d\n", mypid); fprintf (fp, "%d\n", mypid);
fclose (fp); fclose (fp);
@ -841,15 +846,15 @@ int start_stop_daemon (int argc, char **argv)
if (pamr == PAM_SUCCESS) if (pamr == PAM_SUCCESS)
pamr = pam_open_session (pamh, PAM_SILENT); pamr = pam_open_session (pamh, PAM_SILENT);
if (pamr != PAM_SUCCESS) if (pamr != PAM_SUCCESS)
eerrorx ("%s: pam error: %s", progname, pam_strerror(pamh, pamr)); eerrorx ("%s: pam error: %s", applet, pam_strerror(pamh, pamr));
#endif #endif
if (gid && setgid (gid)) if (gid && setgid (gid))
eerrorx ("%s: unable to set groupid to %d", progname, gid); eerrorx ("%s: unable to set groupid to %d", applet, gid);
if (changeuser && initgroups (changeuser, gid)) if (changeuser && initgroups (changeuser, gid))
eerrorx ("%s: initgroups (%s, %d)", progname, changeuser, gid); eerrorx ("%s: initgroups (%s, %d)", applet, changeuser, gid);
if (uid && setuid (uid)) if (uid && setuid (uid))
eerrorx ("%s: unable to set userid to %d", progname, uid); eerrorx ("%s: unable to set userid to %d", applet, uid);
else { else {
struct passwd *passwd = getpwuid (uid); struct passwd *passwd = getpwuid (uid);
if (passwd) { if (passwd) {
@ -898,13 +903,13 @@ int start_stop_daemon (int argc, char **argv)
if ((stdout_fd = open (redirect_stdout, O_WRONLY | O_CREAT | O_APPEND, if ((stdout_fd = open (redirect_stdout, O_WRONLY | O_CREAT | O_APPEND,
S_IRUSR | S_IWUSR)) == -1) S_IRUSR | S_IWUSR)) == -1)
eerrorx ("%s: unable to open the logfile for stdout `%s': %s", eerrorx ("%s: unable to open the logfile for stdout `%s': %s",
progname, redirect_stdout, strerror (errno)); applet, redirect_stdout, strerror (errno));
} }
if (redirect_stderr) { if (redirect_stderr) {
if ((stderr_fd = open (redirect_stderr, O_WRONLY | O_CREAT | O_APPEND, if ((stderr_fd = open (redirect_stderr, O_WRONLY | O_CREAT | O_APPEND,
S_IRUSR | S_IWUSR)) == -1) S_IRUSR | S_IWUSR)) == -1)
eerrorx ("%s: unable to open the logfile for stderr `%s': %s", eerrorx ("%s: unable to open the logfile for stderr `%s': %s",
progname, redirect_stderr, strerror (errno)); applet, redirect_stderr, strerror (errno));
} }
if (background) { if (background) {
@ -924,7 +929,7 @@ int start_stop_daemon (int argc, char **argv)
if (pamr == PAM_SUCCESS) if (pamr == PAM_SUCCESS)
pam_close_session (pamh, PAM_SILENT); pam_close_session (pamh, PAM_SILENT);
#endif #endif
eerrorx ("%s: failed to exec `%s': %s", progname, exec, strerror (errno)); eerrorx ("%s: failed to exec `%s': %s", applet, exec, strerror (errno));
} }
/* Parent process */ /* Parent process */
@ -944,7 +949,7 @@ int start_stop_daemon (int argc, char **argv)
if (! WIFEXITED (status) || WEXITSTATUS (status) != 0) { if (! WIFEXITED (status) || WEXITSTATUS (status) != 0) {
if (! quiet) if (! quiet)
eerrorx ("%s: failed to start `%s'", progname, exec); eerrorx ("%s: failed to start `%s'", applet, exec);
exit (EXIT_FAILURE); exit (EXIT_FAILURE);
} }
@ -965,9 +970,9 @@ int start_stop_daemon (int argc, char **argv)
while (nloops) { while (nloops) {
if (nanosleep (&ts, NULL) == -1) { if (nanosleep (&ts, NULL) == -1) {
if (errno == EINTR) if (errno == EINTR)
eerror ("%s: caught an interupt", progname); eerror ("%s: caught an interupt", applet);
else { else {
eerror ("%s: nanosleep: %s", progname, strerror (errno)); eerror ("%s: nanosleep: %s", applet, strerror (errno));
return (0); return (0);
} }
} }
@ -1002,13 +1007,13 @@ int start_stop_daemon (int argc, char **argv)
} }
if (! alive) if (! alive)
eerrorx ("%s: %s died", progname, exec); eerrorx ("%s: %s died", applet, exec);
} }
if (retestpid) { if (retestpid) {
if (do_stop (NULL, NULL, pidfile, uid, 0, true, if (do_stop (NULL, NULL, pidfile, uid, 0, true,
false, true) < 1) false, true) < 1)
eerrorx ("%s: %s died", progname, exec); eerrorx ("%s: %s died", applet, exec);
} }
} }