83 #include "gw-config.h" 87 #elif defined(__GNU__) 90 #elif defined(__CYGWIN__) 91 #elif defined(__FreeBSD__) || defined(__APPLE__) 94 #error Unknown architecture - cannot build start-stop-daemon 110 #include <sys/stat.h> 119 #include <sys/ioctl.h> 120 #include <sys/types.h> 121 #include <sys/termios.h> 126 #define _STRUCTURED_PROC 1 128 #include <sys/procfs.h> 136 #include <hurd/ihash.h> 163 static struct ps_context *
context;
164 static struct proc_stat_list *procset;
180 #if defined(OSLinux) || defined(OSHURD) || defined(SunOS) || defined(FreeBSD) 181 static int pid_is_user(
int pid,
int uid);
182 static int pid_is_cmd(
int pid,
const char *
name);
188 static int pid_is_exec(
int pid,
const struct stat *esb);
191 static void do_psinit(
void);
197 __attribute__((noreturn,
format(printf, 1, 2)));
199 __attribute__((noreturn));
211 va_start(arglist,
format);
212 vfprintf(stderr,
format, arglist);
252 start-stop-daemon for Debian GNU/Linux - small and fast C version written by\n\ 253 Marek Michalkiewicz <marekm@i17linuxb.ists.pwr.wroc.pl>, public domain.\n" 257 start-stop-daemon -S|--start options ... -- arguments ...\n\ 258 start-stop-daemon -K|--stop options ...\n\ 259 start-stop-daemon -H|--help\n\ 260 start-stop-daemon -V|--version\n\ 262 Options (at least one of --exec|--pidfile|--user is required):\n\ 263 -x|--exec <executable> program to start/check if it is running\n\ 264 -p|--pidfile <pid-file> pid file to check\n\ 265 -c|--chuid <name|uid[:group|gid]>\n\ 266 change to this user/group before starting process\n\ 267 -u|--user <username>|<uid> stop processes owned by this user\n\ 268 -n|--name <process-name> stop processes with this name\n\ 269 -s|--signal <signal> signal to send (default TERM)\n\ 270 -a|--startas <pathname> program to start (default is <executable>)\n\ 271 -b|--background force the process to detach\n\ 272 -m|--make-pidfile create the pidfile before starting\n\ 273 -t|--test test mode, don't do anything\n\ 274 -o|--oknodo exit status 0 (not 1) if nothing done\n\ 275 -q|--quiet be more quiet\n\ 276 -v|--verbose be more verbose\n\ 278 Exit status: 0 = done 1 = nothing done (=> 0 if --oknodo) 2 = trouble\n");
283 start-stop-daemon for Debian GNU/Linux - small and fast C version written by\n\ 284 Marek Michalkiewicz <marekm@i17linuxb.ists.pwr.wroc.pl>, public domain.\n" 288 start-stop-daemon -S options ... -- arguments ...\n\ 289 start-stop-daemon -K options ...\n\ 290 start-stop-daemon -H\n\ 291 start-stop-daemon -V\n\ 293 Options (at least one of --exec|--pidfile|--user is required):\n\ 294 -x <executable> program to start/check if it is running\n\ 295 -p <pid-file> pid file to check\n\ 296 -c <name|uid[:group|gid]> change to this user/group before starting process\n\ 297 -u <username>|<uid> stop processes owned by this user\n\ 298 -n <process-name> stop processes with this name\n\ 299 -s <signal> signal to send (default TERM)\n\ 300 -a <pathname> program to start (default is <executable>)\n\ 301 -b force the process to detach\n\ 302 -m create the pidfile before starting\n\ 303 -t test mode, don't do anything\n\ 304 -o exit status 0 (not 1) if nothing done\n\ 306 -v be more verbose\n\ 308 Exit status: 0 = done 1 = nothing done (=> 0 if -o) 2 = trouble\n");
320 fprintf(stderr,
"Try `%s --help' for more information.\n",
progname);
322 fprintf(stderr,
"Try `%s -H' for more information.\n",
progname);
373 static struct option longopts[] = {
374 {
"help", 0, NULL,
'H'},
375 {
"stop", 0, NULL,
'K'},
376 {
"start", 0, NULL,
'S'},
377 {
"version", 0, NULL,
'V'},
378 {
"startas", 1, NULL,
'a'},
379 {
"name", 1, NULL,
'n'},
380 {
"oknodo", 0, NULL,
'o'},
381 {
"pidfile", 1, NULL,
'p'},
382 {
"quiet", 0, NULL,
'q'},
383 {
"signal", 1, NULL,
's'},
384 {
"test", 0, NULL,
't'},
385 {
"user", 1, NULL,
'u'},
386 {
"chroot", 1, NULL,
'r'},
387 {
"verbose", 0, NULL,
'v'},
388 {
"exec", 1, NULL,
'x'},
389 {
"chuid", 1, NULL,
'c'},
390 {
"background", 0, NULL,
'b'},
391 {
"make-pidfile", 0, NULL,
'm'},
399 c = getopt_long(argc, argv,
"HKSVa:n:op:qr:s:tu:vx:c:bm",
400 longopts, (
int *) 0);
402 c =
getopt(argc, argv,
"HKSVa:n:op:qr:s:tu:vx:c:bm");
417 printf(
"start-stop-daemon " GW_VERSION
"\n");
473 badusage (
"--signal takes a numeric argument or name of signal (KILL, INTR, ...)");
480 badusage(
"need one of --start or --stop");
482 badusage(
"need one of -S (start) or -K (stop)");
486 badusage(
"need at least one of --exec, --pidfile or --user");
492 badusage(
"--start needs --exec or --startas");
495 badusage(
"--make-pidfile is only relevant with --pidfile");
498 badusage(
"--background is only relevant with --start");
504 pid_is_exec(
int pid,
const struct stat *esb)
509 sprintf(buf,
"/proc/%d/exe", pid);
510 if (stat(buf, &sb) != 0)
512 return (sb.st_dev == esb->st_dev && sb.st_ino == esb->st_ino);
517 pid_is_user(
int pid,
int uid)
522 sprintf(buf,
"/proc/%d", pid);
523 if (stat(buf, &sb) != 0)
525 return ((
int) sb.st_uid == uid);
530 pid_is_cmd(
int pid,
const char *
name)
536 sprintf(buf,
"/proc/%d/stat", pid);
540 while ((c = getc(f)) != EOF && c !=
'(')
547 while ((c = getc(f)) != EOF && c == *
name)
550 return (c ==
')' && *
name ==
'\0');
556 pid_is_user(
int pid,
int uid)
560 struct proc_stat *pstat;
562 sprintf(buf,
"/proc/%d", pid);
563 if (stat(buf, &sb) != 0)
565 return (sb.st_uid == uid);
566 pstat = proc_stat_list_pid_proc_stat (procset, pid);
568 fatal (
"Error getting process information: NULL proc_stat struct");
569 proc_stat_set_flags (pstat, PSTAT_PID | PSTAT_OWNER_UID);
570 return (pstat->owner_uid == uid);
574 pid_is_cmd(
int pid,
const char *
name)
576 struct proc_stat *pstat;
577 pstat = proc_stat_list_pid_proc_stat (procset, pid);
579 fatal (
"Error getting process information: NULL proc_stat struct");
580 proc_stat_set_flags (pstat, PSTAT_PID | PSTAT_ARGS);
581 return (!strcmp (
name, pstat->args));
598 pid_is_user(
int pid,
int uid)
603 sprintf(buf,
"/proc/%d", pid);
604 if (stat(buf, &sb) != 0)
606 return ((
int) sb.st_uid == uid);
615 pid_is_cmd(
int pid,
const char *
name)
621 sprintf(buf,
"/proc/%d/psinfo", pid);
625 fread(&pid_info,
sizeof(psinfo_t),1,f);
626 return (!strcmp(
name,pid_info.pr_fname));
631 static int pid_is_user(
int pid,
int uid)
636 sprintf(buf,
"/proc/%d", pid);
637 if (stat(buf, &sb) != 0)
639 return ((
int) sb.st_uid == uid);
643 pid_is_cmd(
int pid,
const char *
name)
649 sprintf(buf,
"/proc/%d/stat", pid);
653 while ((c = getc(f)) != EOF && c !=
'(')
660 while ((c = getc(f)) != EOF && c == *
name)
663 return (c ==
')' && *
name ==
'\0');
673 #elif defined(OSHURD) 692 f = fopen(
name,
"r");
694 if (fscanf(f,
"%d", &pid) == 1)
702 #if defined(OSLinux) || defined (SunOS) || defined(FreeBSD) 707 struct dirent *entry;
710 procdir = opendir(
"/proc");
712 fatal(
"opendir /proc: %s", strerror(errno));
715 while ((entry = readdir(procdir)) != NULL) {
716 if (sscanf(entry->d_name,
"%d", &pid) != 1)
723 fatal(
"nothing in /proc - not mounted?");
730 check_all (
void *ptr)
732 struct proc_stat *pstat = ptr;
742 err = ps_context_create (getproc (), &
context);
744 error (1, err,
"ps_context_create");
746 err = proc_stat_list_create (
context, &procset);
748 error (1, err,
"proc_stat_list_create");
750 err = proc_stat_list_add_all (procset, 0, 0);
752 error (1, err,
"proc_stat_list_add_all");
755 ihash_iterate (
context->procs, check_all);
772 sprintf(what,
"process in pidfile `%s'",
pidfile);
774 sprintf(what,
"process(es) owned by `%s'",
userspec);
776 fatal(
"internal error, please report");
780 printf(
"No %s found running; none killed.\n", what);
785 printf(
"Would send signal %d to %d.\n",
790 printf(
"%s: warning: failed to kill %d: %s\n",
796 printf(
"Stopped %s (pid", what);
798 printf(
" %d", p->
pid);
853 printf(
"%d pids were not killed\n", i);
861 printf(
"%s already running.\n",
execname);
865 printf(
"Would start %s ",
startas);
867 printf(
"%s ", *argv++);
881 printf(
"Starting %s...\n",
startas);
901 printf(
"Detatching to start %s...",
startas);
904 fatal(
"Unable to fork.\n");
913 for (i=getdtablesize()-1; i>=0; --i) close(i);
915 fd = open(
"/dev/tty", O_RDWR);
916 ioctl(fd, TIOCNOTTY, 0);
930 fd=open(
"/dev/null", O_RDWR);
935 FILE *pidf = fopen(
pidfile,
"w");
936 pid_t pidt = getpid();
938 fatal(
"Unable to open pidfile `%s' for writing: %s",
pidfile,
940 fprintf(pidf,
"%d\n", (
int)pidt);
944 fatal(
"Unable to start %s: %s",
startas, strerror(errno));
void error(int err, const char *fmt,...)
static char * changegroup
static const char * signal_str
static struct stat exec_stat
static const char * progname
static const char * pidfile
static void push(struct pid_list **list, int pid)
static void do_pidfile(const char *name)
static struct pid_list * found
static struct pid_list * killed
static void parse_options(int argc, char *const *argv)
static void badusage(const char *msg)
int getopt(int argc, char **argv, char *opts)
static const struct sigpair siglist[]
static void do_help(void)
static const char * cmdname
static void * xmalloc(int size)
int main(int argc, char **argv)
static int parse_signal(const char *signal_str, int *signal_nr)
static const char * userspec
static void fatal(const char *format,...)
static void check(int pid)
static XMLRPCDocument * msg