Magellan Linux

Diff of /trunk/magellan-initscripts/src/start-stop-daemon.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 111 by niro, Sat Jul 2 15:46:28 2005 UTC revision 1268 by niro, Fri Mar 11 17:57:28 2011 UTC
# Line 18  Line 18 
18   *                 and Andreas Schuldei <andreas@schuldei.org>   *                 and Andreas Schuldei <andreas@schuldei.org>
19   *   *
20   * Changes by Ian Jackson: added --retry (and associated rearrangements).   * Changes by Ian Jackson: added --retry (and associated rearrangements).
  *  
21   * Modified for Gentoo rc-scripts by Donny Davies <woodchip@gentoo.org>:   * Modified for Gentoo rc-scripts by Donny Davies <woodchip@gentoo.org>:
22   *   I removed the BSD/Hurd/OtherOS stuff, added #include <stddef.h>   *   I removed the BSD/Hurd/OtherOS stuff, added #include <stddef.h>
23   *   and stuck in a #define VERSION "1.9.18".  Now it compiles without   *   and stuck in a #define VERSION "1.9.18".  Now it compiles without
# Line 28  Line 27 
27   *   Fetched updates from Debian's dpkg-1.10.20, including fix for   *   Fetched updates from Debian's dpkg-1.10.20, including fix for
28   *   Gentoo bug 22686 (start-stop-daemon in baselayout doesn't allow   *   Gentoo bug 22686 (start-stop-daemon in baselayout doesn't allow
29   *   altered nicelevel).   *   altered nicelevel).
30     *
31     *
32     * Changes by Quequero <quequero@bitchx.it>:
33     * Added -e|--env for setting an environment variable before starting the
34     * process.
35     * Moved --make-pidfile after chrooting process (pid file will be wrote in
36     * new root if -r option is used!).
37     * Daemon binary will be stat()ed correctly if it's going to be chrooted
38     * with -r|--chroot.
39     *
40   */   */
41    
42  #define VERSION "1.10.20"  #define VERSION "1.13.11"
 #include <stddef.h>  
43    
44  #define NONRETURNPRINTFFORMAT(x, y) \  #define NONRETURNPRINTFFORMAT(x, y) \
45   __attribute__((noreturn, format(printf, x, y)))   __attribute__((noreturn, format(printf, x, y)))
# Line 52  Line 60 
60  #  define OSFreeBSD  #  define OSFreeBSD
61  #elif defined(__NetBSD__)  #elif defined(__NetBSD__)
62  #  define OSNetBSD  #  define OSNetBSD
63    #elif defined(__APPLE__)
64    #  define OSDarwin
65  #else  #else
66  #  error Unknown architecture - cannot build start-stop-daemon  #  error Unknown architecture - cannot build start-stop-daemon
67  #endif  #endif
# Line 63  Line 73 
73  #  include <ps.h>  #  include <ps.h>
74  #endif  #endif
75    
76  #if defined(OSOpenBSD) || defined(OSFreeBSD) || defined(OSNetBSD)  #if defined(OSOpenBSD) || defined(OSFreeBSD) || defined(OSNetBSD) || defined(OSDarwin)
77  #include <sys/param.h>  #include <sys/param.h>
78  #include <sys/user.h>  #include <sys/user.h>
79  #include <sys/proc.h>  #include <sys/proc.h>
80  #include <sys/stat.h>  #include <sys/stat.h>
81  #include <sys/sysctl.h>  #include <sys/sysctl.h>
82  #include <sys/types.h>  #include <sys/types.h>
83    
84  #include <err.h>  #include <err.h>
85  #include <kvm.h>  #include <kvm.h>
86  #include <limits.h>  #include <limits.h>
# Line 102  Line 112 
112  #include <assert.h>  #include <assert.h>
113  #include <ctype.h>  #include <ctype.h>
114    
115    #include <stddef.h>
116    
117  #include "headers.h"  #include "headers.h"
118    
119  #ifdef HURD_IHASH_H  #ifdef HURD_IHASH_H
# Line 120  static const char *signal_str = NULL; Line 132  static const char *signal_str = NULL;
132  static int user_id = -1;  static int user_id = -1;
133  static int runas_uid = -1;  static int runas_uid = -1;
134  static int runas_gid = -1;  static int runas_gid = -1;
135    static char *env = NULL;
136  static const char *userspec = NULL;  static const char *userspec = NULL;
137  static char *changeuser = NULL;  static char *changeuser = NULL;
138  static const char *changegroup = NULL;  static const char *changegroup = NULL;
139  static char *changeroot = NULL;  static char *changeroot = NULL;
140  static const char *changedir = NULL;  static const char *changedir = "/";
141  static const char *cmdname = NULL;  static const char *cmdname = NULL;
142  static char *execname = NULL;  static char *execname = NULL;
143  static char *startas = NULL;  static char *startas = NULL;
# Line 136  static int nicelevel = 0; Line 149  static int nicelevel = 0;
149    
150  static struct stat exec_stat;  static struct stat exec_stat;
151  #if defined(OSHURD)  #if defined(OSHURD)
152  static struct proc_stat_list *procset;  static struct proc_stat_list *procset = NULL;
153  #endif  #endif
154    
155    
# Line 197  static void badusage(const char *msg); Line 210  static void badusage(const char *msg);
210  typedef long tvselector(const struct timeval*);  typedef long tvselector(const struct timeval*);
211  static long tvselector_sec(const struct timeval *tv) { return tv->tv_sec; }  static long tvselector_sec(const struct timeval *tv) { return tv->tv_sec; }
212  static long tvselector_usec(const struct timeval *tv) { return tv->tv_usec; }  static long tvselector_usec(const struct timeval *tv) { return tv->tv_usec; }
213  #define TVCALC_ELEM(result, expr, sec, adj)                           \  #define TVCALC_ELEM(result, expr, sec, adj) \
214  {      \  { \
215    const long TVADJUST = adj;      \    const long TVADJUST = adj; \
216    long (*const TVELEM)(const struct timeval*) = tvselector_##sec;     \    long (*const TVELEM)(const struct timeval*) = tvselector_##sec; \
217    (result).tv_##sec = (expr);      \    (result).tv_##sec = (expr); \
218  }  }
219  #define TVCALC(result,expr)      \  #define TVCALC(result,expr) \
220  do {      \  do { \
221    TVCALC_ELEM(result, expr, sec, (-1));      \    TVCALC_ELEM(result, expr, sec, (-1)); \
222    TVCALC_ELEM(result, expr, usec, (+1000000));      \    TVCALC_ELEM(result, expr, usec, (+1000000)); \
223    (result).tv_sec += (result).tv_usec / 1000000;      \    (result).tv_sec += (result).tv_usec / 1000000; \
224    (result).tv_usec %= 1000000;      \    (result).tv_usec %= 1000000; \
225  } while(0)  } while(0)
226    
227    
# Line 221  fatal(const char *format, ...) Line 234  fatal(const char *format, ...)
234   va_start(arglist, format);   va_start(arglist, format);
235   vfprintf(stderr, format, arglist);   vfprintf(stderr, format, arglist);
236   va_end(arglist);   va_end(arglist);
237   putc('\n', stderr);   fprintf(stderr, " (%s)\n", strerror (errno));
238   exit(2);   exit(2);
239  }  }
240    
# Line 298  do_help(void) Line 311  do_help(void)
311  "  -b|--background               force the process to detach\n"  "  -b|--background               force the process to detach\n"
312  "  -m|--make-pidfile             create the pidfile before starting\n"  "  -m|--make-pidfile             create the pidfile before starting\n"
313  "  -R|--retry <schedule>         check whether processes die, and retry\n"  "  -R|--retry <schedule>         check whether processes die, and retry\n"
314    "  -e|--env <env-name>           set an environment variable (PWD=\"/\")\n"
315    "  -r|--chroot <path>            chroot process to given directory\n"
316  "  -t|--test                     test mode, don't do anything\n"  "  -t|--test                     test mode, don't do anything\n"
317  "  -o|--oknodo                   exit status 0 (not 1) if nothing done\n"  "  -o|--oknodo                   exit status 0 (not 1) if nothing done\n"
318  "  -q|--quiet                    be more quiet\n"  "  -q|--quiet                    be more quiet\n"
# Line 461  static void Line 476  static void
476  parse_options(int argc, char * const *argv)  parse_options(int argc, char * const *argv)
477  {  {
478   static struct option longopts[] = {   static struct option longopts[] = {
479   { "help",  0, NULL, 'H'},   { "help",         0, NULL, 'H'},
480   { "stop",  0, NULL, 'K'},   { "stop",         0, NULL, 'K'},
481   { "start",  0, NULL, 'S'},   { "start",        0, NULL, 'S'},
482   { "version",  0, NULL, 'V'},   { "version",      0, NULL, 'V'},
483   { "startas",  1, NULL, 'a'},   { "startas",      1, NULL, 'a'},
484   { "name",  1, NULL, 'n'},   { "env",          1, NULL, 'e'},
485   { "oknodo",  0, NULL, 'o'},   { "name",         1, NULL, 'n'},
486   { "pidfile",  1, NULL, 'p'},   { "oknodo",       0, NULL, 'o'},
487   { "quiet",  0, NULL, 'q'},   { "pidfile",      1, NULL, 'p'},
488   { "signal",  1, NULL, 's'},   { "quiet",        0, NULL, 'q'},
489   { "test",  0, NULL, 't'},   { "signal",       1, NULL, 's'},
490   { "user",  1, NULL, 'u'},   { "test",         0, NULL, 't'},
491   { "group",  1, NULL, 'g'},   { "user",         1, NULL, 'u'},
492   { "chroot",  1, NULL, 'r'},   { "group",        1, NULL, 'g'},
493   { "verbose",  0, NULL, 'v'},   { "chroot",       1, NULL, 'r'},
494   { "exec",  1, NULL, 'x'},   { "verbose",      0, NULL, 'v'},
495   { "chuid",  1, NULL, 'c'},   { "exec",         1, NULL, 'x'},
496   { "nicelevel",  1, NULL, 'N'},   { "chuid",        1, NULL, 'c'},
497     { "nicelevel",    1, NULL, 'N'},
498   { "background",   0, NULL, 'b'},   { "background",   0, NULL, 'b'},
499   { "make-pidfile", 0, NULL, 'm'},   { "make-pidfile", 0, NULL, 'm'},
500   { "retry",        1, NULL, 'R'},   { "retry",        1, NULL, 'R'},
501   { "chdir",        1, NULL, 'd'},   { "chdir",        1, NULL, 'd'},
502   { NULL, 0, NULL, 0}   { NULL,           0, NULL, 0}
503   };   };
504   int c;   int c;
505    
506   for (;;) {   for (;;) {
507   c = getopt_long(argc, argv, "HKSV:a:n:op:qr:s:tu:vx:c:N:bmR:g:d:",   c = getopt_long(argc, argv, "HKSVa:n:op:qr:e:s:tu:vx:c:N:bmR:g:d:",
508   longopts, (int *) 0);   longopts, (int *) 0);
509   if (c == -1)   if (c == -1)
510   break;   break;
# Line 548  parse_options(int argc, char * const *ar Line 564  parse_options(int argc, char * const *ar
564   case 'r':  /* --chroot /new/root */   case 'r':  /* --chroot /new/root */
565   changeroot = optarg;   changeroot = optarg;
566   break;   break;
567     case 'e':  /* --env <env-name> */
568     if (env)
569     badusage("Only one --env option is supported, use /usr/bin/env if you need more");
570     env = optarg;
571     break;
572   case 'N':  /* --nice */   case 'N':  /* --nice */
573   nicelevel = atoi(optarg);   nicelevel = atoi(optarg);
574   break;   break;
# Line 652  pid_is_cmd(pid_t pid, const char *name) Line 673  pid_is_cmd(pid_t pid, const char *name)
673    
674    
675  #if defined(OSHURD)  #if defined(OSHURD)
676    static void
677    init_procset(void)
678    {
679     struct ps_context *context;
680     error_t err;
681    
682     err = ps_context_create(getproc(), &context);
683     if (err)
684     error(1, err, "ps_context_create");
685    
686     err = proc_stat_list_create(context, &procset);
687     if (err)
688     error(1, err, "proc_stat_list_create");
689    
690     err = proc_stat_list_add_all(procset, 0, 0);
691     if (err)
692     error(1, err, "proc_stat_list_add_all");
693    }
694    
695    static struct proc_stat *
696    get_proc_stat (pid_t pid, ps_flags_t flags)
697    {
698     struct proc_stat *ps;
699     ps_flags_t wanted_flags = PSTAT_PID | flags;
700    
701     if (!procset)
702     init_procset();
703    
704     ps = proc_stat_list_pid_proc_stat(procset, pid);
705     if (!ps)
706     return NULL;
707     if (proc_stat_set_flags(ps, wanted_flags))
708     return NULL;
709     if ((proc_stat_flags(ps) & wanted_flags) != wanted_flags)
710     return NULL;
711    
712     return ps;
713    }
714    
715  static int  static int
716  pid_is_user(pid_t pid, uid_t uid)  pid_is_user(pid_t pid, uid_t uid)
717  {  {
718   struct stat sb;   struct proc_stat *ps;
  char buf[32];  
  struct proc_stat *pstat;  
719    
720   sprintf(buf, "/proc/%d", pid);   ps = get_proc_stat(pid, PSTAT_OWNER_UID);
721   if (stat(buf, &sb) != 0)   return ps && proc_stat_owner_uid(ps) == uid;
  return 0;  
  return (sb.st_uid == uid);  
  pstat = proc_stat_list_pid_proc_stat (procset, pid);  
  if (pstat == NULL)  
  fatal ("Error getting process information: NULL proc_stat struct");  
  proc_stat_set_flags (pstat, PSTAT_PID | PSTAT_OWNER_UID);  
  return (pstat->owner_uid == uid);  
722  }  }
723    
724  static int  static int
725  pid_is_cmd(pid_t pid, const char *name)  pid_is_cmd(pid_t pid, const char *name)
726  {  {
727   struct proc_stat *pstat;   struct proc_stat *ps;
728   pstat = proc_stat_list_pid_proc_stat (procset, pid);  
729   if (pstat == NULL)   ps = get_proc_stat(pid, PSTAT_ARGS);
730   fatal ("Error getting process information: NULL proc_stat struct");   return ps && !strcmp(proc_stat_args(ps), name);
731   proc_stat_set_flags (pstat, PSTAT_PID | PSTAT_ARGS);  }
732   return (!strcmp (name, pstat->args));  
733    static int
734    pid_is_running(pid_t pid)
735    {
736     return get_proc_stat(pid, 0) != NULL;
737  }  }
 #endif /* OSHURD */  
738    
739    #else /* !OSHURD */
740    
741  static int  static int
742  pid_is_running(pid_t pid)  pid_is_running(pid_t pid)
# Line 699  pid_is_running(pid_t pid) Line 754  pid_is_running(pid_t pid)
754   return 1;   return 1;
755  }  }
756    
757    #endif /* OSHURD */
758    
759  static void  static void
760  check(pid_t pid)  check(pid_t pid)
761  {  {
762  #if defined(OSLinux) || defined(OShpux)  #if defined(OSLinux) || defined(OShpux)
763   if (execname && !pid_is_exec(pid, &exec_stat))   if (execname && !pid_is_exec(pid, &exec_stat))
764  #elif defined(OSHURD) || defined(OSFreeBSD) || defined(OSNetBSD)   return;
765      /* I will try this to see if it works */  #elif defined(OSHURD) || defined(OSFreeBSD) || defined(OSNetBSD) || defined(OSDarwin)
766     /* I will try this to see if it works */
767   if (execname && !pid_is_cmd(pid, execname))   if (execname && !pid_is_cmd(pid, execname))
 #endif  
768   return;   return;
769    #endif
770   if (userspec && !pid_is_user(pid, user_id))   if (userspec && !pid_is_user(pid, user_id))
771   return;   return;
772   if (cmdname && !pid_is_cmd(pid, cmdname))   if (cmdname && !pid_is_cmd(pid, cmdname))
# Line 765  do_procinit(void) Line 823  do_procinit(void)
823    
824    
825  #if defined(OSHURD)  #if defined(OSHURD)
826  error_t  static int
827  check_all(void *ptr)  check_proc_stat (struct proc_stat *ps)
828  {  {
829   struct proc_stat *pstat = ptr;   check(ps->pid);
   
  check(pstat->pid);  
830   return 0;   return 0;
831  }  }
832    
833  static void  static void
834  do_procinit(void)  do_procinit(void)
835  {  {
836   struct ps_context *context;   if (!procset)
837   error_t err;   init_procset();
838    
839   err = ps_context_create(getproc(), &context);   proc_stat_list_for_each (procset, check_proc_stat);
  if (err)  
  error(1, err, "ps_context_create");  
   
  err = proc_stat_list_create(context, &procset);  
  if (err)  
  error(1, err, "proc_stat_list_create");  
   
  err = proc_stat_list_add_all(procset, 0, 0);  
  if (err)  
  error(1, err, "proc_stat_list_add_all");  
   
  /* Check all pids */  
  ihash_iterate(context->procs, check_all);  
840  }  }
841  #endif /* OSHURD */  #endif /* OSHURD */
842    
843    
844  #if defined(OSOpenBSD) || defined(OSFreeBSD) || defined(OSNetBSD)  #if defined(OSOpenBSD) || defined(OSFreeBSD) || defined(OSNetBSD)
845    
846    # if defined(OSNetBSD)
847    #  define _KINFO_PROC2 kinfo_proc2
848    #  define _GET_KINFO_UID(kp) (kp->p_ruid)
849    #  define _GET_KINFO_COMM(kp) (kp->p_comm)
850    # else
851    #  define _KINFO_PROC2 kinfo_proc
852    #  define _GET_KINFO_UID(kp) (kp->ki_ruid)
853    #  define _GET_KINFO_COMM(kp) (kp->ki_comm)
854    # endif
855    
856  static int  static int
857  pid_is_cmd(pid_t pid, const char *name)  pid_is_cmd(pid_t pid, const char *name)
858  {  {
859          kvm_t *kd;   kvm_t *kd;
860          int nentries, argv_len=0;   int nentries, argv_len=0;
861          struct kinfo_proc *kp;   struct kinfo_proc *kp;
862          char  errbuf[_POSIX2_LINE_MAX], buf[_POSIX2_LINE_MAX];   char  errbuf[_POSIX2_LINE_MAX], buf[_POSIX2_LINE_MAX];
863   char  **pid_argv_p;   char  **pid_argv_p;
864   char  *start_argv_0_p, *end_argv_0_p;   char  *start_argv_0_p, *end_argv_0_p;
865    
866     kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
867          kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);   if (kd == 0)
868          if (kd == 0)   errx(1, "%s", errbuf);
869                  errx(1, "%s", errbuf);   if ((kp = kvm_getprocs(kd, KERN_PROC_PID, pid, &nentries)) == 0)
870          if ((kp = kvm_getprocs(kd, KERN_PROC_PID, pid, &nentries)) == 0)   errx(1, "%s", kvm_geterr(kd));
                 errx(1, "%s", kvm_geterr(kd));  
871   if ((pid_argv_p = kvm_getargv(kd, kp, argv_len)) == 0)   if ((pid_argv_p = kvm_getargv(kd, kp, argv_len)) == 0)
872   errx(1, "%s", kvm_geterr(kd));   errx(1, "%s", kvm_geterr(kd));
873    
874   start_argv_0_p = *pid_argv_p;   start_argv_0_p = *pid_argv_p;
875   /* find and compare string */   /* find and compare string */
876      
877   /* find end of argv[0] then copy and cut of str there. */   /* find end of argv[0] then copy and cut of str there. */
878   if ((end_argv_0_p = strchr(*pid_argv_p, ' ')) == 0 )   if ((end_argv_0_p = strchr(*pid_argv_p, ' ')) == 0 )
879   /* There seems to be no space, so we have the command   /* There seems to be no space, so we have the command
880   * allready in its desired form. */   * allready in its desired form. */
881    start_argv_0_p = *pid_argv_p;   start_argv_0_p = *pid_argv_p;
882   else {   else {
883    /* Tests indicate that this never happens, since   /* Tests indicate that this never happens, since
884     * kvm_getargv itselfe cuts of tailing stuff. This is   * kvm_getargv itselfe cuts of tailing stuff. This is
885     * not what the manpage says, however. */   * not what the manpage says, however. */
886    strncpy(buf, *pid_argv_p, (end_argv_0_p - start_argv_0_p));   strncpy(buf, *pid_argv_p, (end_argv_0_p - start_argv_0_p));
887    buf[(end_argv_0_p - start_argv_0_p) + 1] = '\0';   buf[(end_argv_0_p - start_argv_0_p) + 1] = '\0';
888    start_argv_0_p = buf;   start_argv_0_p = buf;
889   }   }
890            
891   if (strlen(name) != strlen(start_argv_0_p))   if (strlen(name) != strlen(start_argv_0_p))
892                 return 0;   return 0;
893          return (strcmp(name, start_argv_0_p) == 0) ? 1 : 0;   return (strcmp(name, start_argv_0_p) == 0) ? 1 : 0;
894  }  }
895    
896  static int  static int
897  pid_is_user(pid_t pid, uid_t uid)  pid_is_user(pid_t pid, uid_t uid)
898  {  {
899   kvm_t *kd;   kvm_t *kd;
900   int nentries;   /* Value not used */   int nentries;   /* Value not used */
901   uid_t proc_uid;   uid_t proc_uid;
902   struct kinfo_proc *kp;   struct _KINFO_PROC2 *kp;
903   char  errbuf[_POSIX2_LINE_MAX];   char  errbuf[_POSIX2_LINE_MAX];
904    
   
905   kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);   kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
906   if (kd == 0)   if (kd == 0)
907   errx(1, "%s", errbuf);   errx(1, "%s", errbuf);
908   if ((kp = kvm_getprocs(kd, KERN_PROC_PID, pid, &nentries)) == 0)   if ((kp = kvm_getprocs(kd, KERN_PROC_PID, pid, &nentries)) == 0)
909   errx(1, "%s", kvm_geterr(kd));   errx(1, "%s", kvm_geterr(kd));
910   if (kp->ki_ruid )   if (_GET_KINFO_UID(kp))
911   kvm_read(kd, (u_long)&(kp->ki_ruid),   kvm_read(kd, (u_long)&(_GET_KINFO_UID(kp)),
912   &proc_uid, sizeof(uid_t));   &proc_uid, sizeof(uid_t));
913   else   else
914   return 0;   return 0;
# Line 868  pid_is_exec(pid_t pid, const char *name) Line 920  pid_is_exec(pid_t pid, const char *name)
920  {  {
921   kvm_t *kd;   kvm_t *kd;
922   int nentries;   int nentries;
923   struct kinfo_proc *kp;   struct _KINFO_PROC2 *kp;
924   char errbuf[_POSIX2_LINE_MAX], *pidexec;   char errbuf[_POSIX2_LINE_MAX], *pidexec;
925    
926   kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);   kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
# Line 876  pid_is_exec(pid_t pid, const char *name) Line 928  pid_is_exec(pid_t pid, const char *name)
928   errx(1, "%s", errbuf);   errx(1, "%s", errbuf);
929   if ((kp = kvm_getprocs(kd, KERN_PROC_PID, pid, &nentries)) == 0)   if ((kp = kvm_getprocs(kd, KERN_PROC_PID, pid, &nentries)) == 0)
930   errx(1, "%s", kvm_geterr(kd));   errx(1, "%s", kvm_geterr(kd));
931   pidexec = kp->ki_comm;   pidexec = _GET_KINFO_COMM(kp);
932   if (strlen(name) != strlen(pidexec))   if (strlen(name) != strlen(pidexec))
933   return 0;   return 0;
934   return (strcmp(name, pidexec) == 0) ? 1 : 0;   return (strcmp(name, pidexec) == 0) ? 1 : 0;
# Line 891  do_procinit(void) Line 943  do_procinit(void)
943    
944  #endif /* OSOpenBSD */  #endif /* OSOpenBSD */
945    
946    #if defined(OSDarwin)
947    int
948    pid_is_user(pid_t pid, uid_t uid)
949    {
950     int mib[4];
951     size_t size;
952     struct kinfo_proc ki;
953    
954     size = sizeof(ki);
955     mib[0] = CTL_KERN;
956     mib[1] = KERN_PROC;
957     mib[2] = KERN_PROC_PID;
958     mib[3] = pid;
959     if (sysctl(mib, 4, &ki, &size, NULL, 0) < 0)
960     errx(1, "%s", "Failure calling sysctl");
961     return (uid == ki.kp_eproc.e_pcred.p_ruid);
962    }
963    
964    static int
965    pid_is_cmd(pid_t pid, const char *name)
966    {
967     int mib[4];
968     size_t size;
969     struct kinfo_proc ki;
970    
971     size = sizeof(ki);
972     mib[0] = CTL_KERN;
973     mib[1] = KERN_PROC;
974     mib[2] = KERN_PROC_PID;
975     mib[3] = pid;
976     if (sysctl(mib, 4, &ki, &size, NULL, 0) < 0)
977     errx(1, "%s", "Failure calling sysctl");
978     return (!strncmp(name, ki.kp_proc.p_comm, MAXCOMLEN));
979    }
980    
981    static void
982    do_procinit(void)
983    {
984     int mib[3];
985     size_t size;
986     int nprocs, ret, i;
987     struct kinfo_proc *procs = NULL, *newprocs;
988    
989     mib[0] = CTL_KERN;
990     mib[1] = KERN_PROC;
991     mib[2] = KERN_PROC_ALL;
992     ret = sysctl(mib, 3, NULL, &size, NULL, 0);
993     /* Allocate enough memory for entire process table */
994     do {
995     size += size / 10;
996     newprocs = realloc(procs, size);
997     if (newprocs == NULL) {
998     if (procs)
999     free(procs);
1000     errx(1, "%s", "Could not reallocate memory");
1001     }
1002     procs = newprocs;
1003     ret = sysctl(mib, 3, procs, &size, NULL, 0);
1004     } while (ret >= 0 && errno == ENOMEM);
1005    
1006     if (ret < 0)
1007     errx(1, "%s", "Failure calling sysctl");
1008    
1009     /* Verify size of proc structure */
1010     if (size % sizeof(struct kinfo_proc) != 0)
1011     errx(1, "%s", "proc size mismatch, userland out of sync with kernel");
1012     nprocs = size / sizeof(struct kinfo_proc);
1013     for (i = 0; i < nprocs; i++) {
1014     check(procs[i].kp_proc.p_pid);
1015     }
1016    }
1017    #endif /* OSDarwin */
1018    
1019  #if defined(OShpux)  #if defined(OShpux)
1020  static int  static int
# Line 932  do_procinit(void) Line 1056  do_procinit(void)
1056   int idx = 0;   int idx = 0;
1057    
1058   while ((count = pstat_getproc(pst, sizeof(pst[0]), 10, idx)) > 0) {   while ((count = pstat_getproc(pst, sizeof(pst[0]), 10, idx)) > 0) {
1059                  for (i = 0; i < count; i++)   for (i = 0; i < count; i++)
1060   check(pst[i].pst_pid);   check(pst[i].pst_pid);
1061                  idx = pst[count - 1].pst_idx + 1;   idx = pst[count - 1].pst_idx + 1;
1062   }   }
1063  }  }
1064  #endif /* OShpux */  #endif /* OShpux */
# Line 944  static void Line 1068  static void
1068  do_findprocs(void)  do_findprocs(void)
1069  {  {
1070   clear(&found);   clear(&found);
1071    
1072   if (pidfile)   if (pidfile)
1073   do_pidfile(pidfile);   do_pidfile(pidfile);
1074   else   else
# Line 957  do_stop(int signal_nr, int quietmode, in Line 1081  do_stop(int signal_nr, int quietmode, in
1081  {  {
1082   struct pid_list *p;   struct pid_list *p;
1083    
1084   do_findprocs();   do_findprocs();
1085    
1086   *n_killed = 0;   *n_killed = 0;
1087   *n_notkilled = 0;   *n_notkilled = 0;
1088    
1089   if (!found)   if (!found)
1090   return;   return;
1091    
1092   clear(&killed);   clear(&killed);
1093    
1094   for (p = found; p; p = p->next) {   for (p = found; p; p = p->next) {
1095   if (testmode) {   if (testmode) {
# Line 974  do_stop(int signal_nr, int quietmode, in Line 1098  do_stop(int signal_nr, int quietmode, in
1098   (*n_killed)++;   (*n_killed)++;
1099   } else if (kill(p->pid, signal_nr) == 0) {   } else if (kill(p->pid, signal_nr) == 0) {
1100   push(&killed, p->pid);   push(&killed, p->pid);
1101   (*n_killed)++;   (*n_killed)++;
1102   } else {   } else {
1103   printf("%s: warning: failed to kill %d: %s\n",   printf("%s: warning: failed to kill %d: %s\n",
1104         progname, p->pid, strerror(errno));         progname, p->pid, strerror(errno));
1105   (*n_notkilled)++;   (*n_notkilled)++;
1106   }   }
1107   }   }
1108   if (quietmode < 0 && killed) {   if (quietmode < 0 && killed) {
1109   printf("Stopped %s (pid", what_stop);   printf("Stopped %s (pid", what_stop);
1110   for (p = killed; p; p = p->next)   for (p = killed; p; p = p->next)
1111   printf(" %d", p->pid);   printf(" %d", p->pid);
1112   putchar(')');   putchar(')');
1113   if (retry_nr > 0)   if (retry_nr > 0)
1114   printf(", retry #%d", retry_nr);   printf(", retry #%d", retry_nr);
1115   printf(".\n");   printf(".\n");
1116   }   }
1117  }  }
1118    
# Line 1104  run_stop_schedule(void) Line 1228  run_stop_schedule(void)
1228    
1229   if (interval.tv_sec == 0 &&   if (interval.tv_sec == 0 &&
1230      interval.tv_usec <= MIN_POLL_INTERVAL)      interval.tv_usec <= MIN_POLL_INTERVAL)
1231          interval.tv_usec = MIN_POLL_INTERVAL;   interval.tv_usec = MIN_POLL_INTERVAL;
1232    
1233   r = select(0,0,0,0,&interval);   r = select(0,0,0,0,&interval);
1234   if (r < 0 && errno != EINTR)   if (r < 0 && errno != EINTR)
# Line 1138  x_finished: Line 1262  x_finished:
1262  }  }
1263    
1264    
 int main(int argc, char **argv) NONRETURNING;  
1265  int  int
1266  main(int argc, char **argv)  main(int argc, char **argv)
1267  {  {
# Line 1152  main(int argc, char **argv) Line 1275  main(int argc, char **argv)
1275   argc -= optind;   argc -= optind;
1276   argv += optind;   argv += optind;
1277    
1278   if (execname && stat(execname, &exec_stat))   if (changeroot == NULL) {
1279   fatal("stat %s: %s", execname, strerror(errno));   if (execname && stat(execname, &exec_stat))
1280     fatal("stat %s: %s", execname, strerror(errno));
1281     } else {
1282     if (execname) {
1283     char *tmp = NULL;
1284    
1285     tmp = malloc(strlen(changeroot) + strlen(execname) + 1);
1286     strncpy(tmp, changeroot, strlen(changeroot));
1287     strncat(tmp, execname, strlen(execname));
1288    
1289     if (stat(tmp, &exec_stat)) {
1290     fatal("stat %s: %s", tmp, strerror(errno));
1291     free(tmp);
1292     } else {
1293     free(tmp);
1294     }
1295     }
1296     }
1297    
1298   if (userspec && sscanf(userspec, "%d", &user_id) != 1) {   if (userspec && sscanf(userspec, "%d", &user_id) != 1) {
1299   struct passwd *pw;   struct passwd *pw;
# Line 1218  main(int argc, char **argv) Line 1358  main(int argc, char **argv)
1358   if (background) { /* ok, we need to detach this process */   if (background) { /* ok, we need to detach this process */
1359   int i;   int i;
1360   if (quietmode < 0)   if (quietmode < 0)
1361   printf("Detatching to start %s...", startas);   printf("Detaching to start %s...", startas);
1362   i = fork();   i = fork();
1363   if (i<0) {   if (i<0) {
1364   fatal("Unable to fork.\n");   fatal("Unable to fork.\n");
# Line 1241  main(int argc, char **argv) Line 1381  main(int argc, char **argv)
1381   fatal("Unable to alter nice level by %i: %s", nicelevel,   fatal("Unable to alter nice level by %i: %s", nicelevel,
1382   strerror(errno));   strerror(errno));
1383   }   }
  if (mpidfile && pidfile != NULL) { /* user wants _us_ to make the pidfile :) */  
  FILE *pidf = fopen(pidfile, "w");  
  pid_t pidt = getpid();  
  if (pidf == NULL)  
  fatal("Unable to open pidfile `%s' for writing: %s", pidfile,  
  strerror(errno));  
  fprintf(pidf, "%d\n", pidt);  
  fclose(pidf);  
  }  
1384   if (changeroot != NULL) {   if (changeroot != NULL) {
1385   if (chdir(changeroot) < 0)   if (chdir(changeroot) < 0)
1386   fatal("Unable to chdir() to %s", changeroot);   fatal("Unable to chdir() to %s", changeroot);
1387   if (chroot(changeroot) < 0)   if (chroot(changeroot) < 0)
1388   fatal("Unable to chroot() to %s", changeroot);   fatal("Unable to chroot() to %s", changeroot);
1389   }   }
1390   if (changedir != NULL && chdir(changedir) < 0)   if (chdir(changedir) < 0)
1391   fatal("Unable to chdir() to %s", changedir);   fatal("Unable to chdir() to %s", changedir);
1392            if (mpidfile && pidfile != NULL) { /* user wants _us_ to make the pidfile :) */
1393                    FILE *pidf = fopen(pidfile, "w");
1394                    pid_t pidt = getpid();
1395                    if (pidf == NULL)
1396                            fatal("Unable to open pidfile `%s' for writing: %s", pidfile,
1397                                    strerror(errno));
1398                    fprintf(pidf, "%d\n", pidt);
1399                    fclose(pidf);
1400            }
1401   if (changeuser != NULL) {   if (changeuser != NULL) {
1402   if (setgid(runas_gid))   if (setgid(runas_gid))
1403   fatal("Unable to set gid to %d", runas_gid);   fatal("Unable to set gid to %d", runas_gid);
1404   if (initgroups(changeuser, runas_gid))   if (initgroups(changeuser, runas_gid))
1405   fatal("Unable to set initgroups() with gid %d", runas_gid);   fatal("Unable to set initgroups() with gid %d", runas_gid);
1406   if (setuid(runas_uid))   if (setuid(runas_uid))
1407   fatal("Unable to set uid to %s", changeuser);   fatal("Unable to set uid to %s", changeuser);
1408   }   }
1409     if (env != NULL) {
1410     if(putenv(env))
1411     fatal("Unable to set variable: %s", env);
1412     }
1413   if (background) { /* continue background setup */   if (background) { /* continue background setup */
1414   int i;   int i;
1415  #ifdef HAVE_TIOCNOTTY  #ifdef HAVE_TIOCNOTTY
# Line 1295  main(int argc, char **argv) Line 1439  main(int argc, char **argv)
1439   execv(startas, argv);   execv(startas, argv);
1440   fatal("Unable to start %s: %s", startas, strerror(errno));   fatal("Unable to start %s: %s", startas, strerror(errno));
1441  }  }
   

Legend:
Removed from v.111  
changed lines
  Added in v.1268