summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--doc/runscripts.html2
-rw-r--r--man/chpst.813
-rw-r--r--man/sv.824
-rw-r--r--package/CHANGES10
-rw-r--r--src/chpst.c5
-rw-r--r--src/runsv.c5
-rw-r--r--src/sv.c61
-rw-r--r--src/uidgid.c28
-rw-r--r--src/uidgid.h3
9 files changed, 123 insertions, 28 deletions
diff --git a/doc/runscripts.html b/doc/runscripts.html
index 9d274f6..793f2ed 100644
--- a/doc/runscripts.html
+++ b/doc/runscripts.html
@@ -282,7 +282,7 @@ this page</a>.
 (<i>Linux</i>, DHCP Client Daemon v.scriptconfig-0.1)
 <pre>
  #!/bin/sh
- dhcpcd -a -d -D -H eth0
+ exec dhcpcd -a -d -D -H eth0
 </pre>
 <hr>
 <h3><a name="dhcpd">A <tt>dhcpd</tt> run script</a></h3>
diff --git a/man/chpst.8 b/man/chpst.8
index ae158cb..7594fa8 100644
--- a/man/chpst.8
+++ b/man/chpst.8
@@ -50,7 +50,12 @@ set the gid to
 gid instead of
 .IR user 's
 gid.
-All supplementary groups are removed.
+If
+.I group
+consists of a colon-separated list of group names,
+.B chpst
+sets the group ids of all listed groups.
+All initial supplementary groups are removed.
 .TP
 .B \-U \fIuser[:group]
 envuidgid.
@@ -66,6 +71,12 @@ set $GID to the
 gid instead of
 .IR user 's
 gid.
+If
+.I group
+consists of a colon-separated list of group names,
+.B chpst
+sets the group ids of all listed groups.
+All initial supplementary groups are removed.
 .TP
 .B \-e \fIdir
 envdir.
diff --git a/man/sv.8 b/man/sv.8
index 49d21b2..8cb1bc7 100644
--- a/man/sv.8
+++ b/man/sv.8
@@ -95,6 +95,14 @@ Same as
 .IR up ,
 but wait up to 7 seconds for the command to take effect.
 Then report the status or timeout.
+If the script
+.I ./check
+exists in the service directory,
+.B sv
+runs this script to check whether the service is up and available;
+it's considered to be available if
+.I ./check
+exits with 0.
 .TP
 .B stop
 Same as
@@ -110,6 +118,14 @@ and
 .I up
 to the service, and wait up to 7 seconds for the service to restart.
 Then report the status or timeout.
+If the script
+.I ./check
+exists in the service directory,
+.B sv
+runs this script to check whether the service is up and available again;
+it's considered to be available if
+.I ./check
+exits with 0.
 .TP
 .B shutdown
 Same as
@@ -147,6 +163,14 @@ commands, and wait up to 7 seconds for the service to restart.
 Then report the status, and on timeout send the service the
 .I kill
 command.
+If the script
+.I ./check
+exists in the service directory,
+.B sv
+runs this script to check whether the service is up and available again;
+it's considered to be available if
+.I ./check
+exits with 0.
 .TP
 .B force-shutdown
 Same as
diff --git a/package/CHANGES b/package/CHANGES
index dda8c0e..983da59 100644
--- a/package/CHANGES
+++ b/package/CHANGES
@@ -1,4 +1,12 @@
-  * doc/runscripts.html: typo; openssh needs absolute path (thx Kevin Berry).
+runit 1.3.1
+Tue, 23 Aug 2005 22:35:14 +0000
+  * doc/runscripts.html: typo; openssh needs absolute path (thx Kevin Berry);
+    exec into dhcpcd.
+  * uidgid.c, uidgid.h, chpst.c: support colon-separated list of groups.
+  * sv.c: utilize optional ./check script in service directory to check for
+    availablity of service.
+  * runsv.c: wait_pid() might be interupted.
+  * man/chpst.8, man/sv.8: adapt.
 
 runit 1.3.0
 Sun, 24 Jul 2005 16:50:55 +0000
diff --git a/src/chpst.c b/src/chpst.c
index cbf34eb..3381a3b 100644
--- a/src/chpst.c
+++ b/src/chpst.c
@@ -70,7 +70,8 @@ void suidgid(char *user, unsigned int dogrp) {
     else
       fatalx("unknown account", user);
   }
-  if (prot_gid(ugid.gid) == -1) fatal("unable to setgid");
+  if (setgroups(ugid.gids, ugid.gid) == -1) fatal("unable to setgroups");
+  if (setgid(*ugid.gid) == -1) fatal("unable to setgid");
   if (prot_uid(ugid.uid) == -1) fatal("unable to setuid");
 }
 
@@ -84,7 +85,7 @@ void euidgid(char *user, unsigned int dogrp) {
     else
       fatalx("unknown account", user);
   }
-  bufnum[fmt_ulong(bufnum, ugid.gid)] =0;
+  bufnum[fmt_ulong(bufnum, *ugid.gid)] =0;
   if (! pathexec_env("GID", bufnum)) die_nomem();
   bufnum[fmt_ulong(bufnum, ugid.uid)] =0;
   if (! pathexec_env("UID", bufnum)) die_nomem();
diff --git a/src/runsv.c b/src/runsv.c
index 2323f0b..342354f 100644
--- a/src/runsv.c
+++ b/src/runsv.c
@@ -226,9 +226,10 @@ unsigned int custom(struct svdir *s, char c) {
         prog[0] =a;
         prog[1] =0;
         execve(a, prog, environ);
-	fatal("unable to run control/?");
+        fatal("unable to run control/?");
       }
-      if (wait_pid(&w, pid) == -1) {
+      while (wait_pid(&w, pid) == -1) {
+        if (errno == error_intr) continue;
         warn("unable to wait for child control/?");
         return(0);
       }
diff --git a/src/sv.c b/src/sv.c
index 37d338b..197ffa1 100644
--- a/src/sv.c
+++ b/src/sv.c
@@ -12,6 +12,7 @@
 #include "scan.h"
 #include "tai.h"
 #include "taia.h"
+#include "wait.h"
 
 #define USAGE " [-v] [-w sec] action service ..."
 #define USAGELSB " [-w sec] action"
@@ -113,7 +114,8 @@ unsigned int svstatus_print(char *m) {
  
   if (stat("down", &s) == -1) {
     if (errno != error_noent) {
-      outs(WARN); outs("unable to stat down: "); outs(error_str(errno));
+      outs(WARN); outs("unable to stat "); outs(*service); outs("/down: ");
+      outs(error_str(errno)); flush("\n");
       return(0);
     }
     normallyup =1;
@@ -164,28 +166,65 @@ int status(char *unused) {
   if (lsb) switch(r) { case 1: done(0); case 2: done(3); case 0: done(4); }
   return(r);
 }
- 
+
+int checkscript() {
+  char *prog[2];
+  struct stat s;
+  int pid, w;
+
+  if (stat("check", &s) == -1) {
+    if (errno == error_noent) return(1);
+    outs(WARN); outs("unable to stat "); outs(*service); outs("/check: ");
+    outs(error_str(errno)); flush("\n");
+    return(0);
+  }
+  /* if (!(s.st_mode & S_IXUSR)) return(1); */
+  if ((pid =fork()) == -1) {
+    outs(WARN); outs("unable to fork for "); outs(*service); outs("/check: ");
+    outs(error_str(errno)); flush("\n");
+    return(0);
+  }
+  if (!pid) {
+    prog[0] ="./check";
+    prog[1] =0;
+    close(1); close(2);
+    execve("check", prog, environ);
+    outs(WARN); outs("unable to run "); outs(*service); outs("/check: ");
+    outs(error_str(errno)); flush("\n");
+    _exit(0);
+  }
+  while (wait_pid(&w, pid) == -1) {
+    if (errno == error_intr) continue;
+    outs(WARN); outs("unable to wait for child "); outs(*service);
+    outs("/check: "); outs(error_str(errno)); flush("\n");
+    return(0);
+  }
+  return(!wait_exitcode(w));
+}
+
 int check(char *a) {
   unsigned int pid;
 
+  if (!a || !*a) return(-1);
+  while(*(a +1)) ++a;
   if ((r =svstatus_get()) == -1) return(-1);
   if (r == 0) { if (*a == 'x') return(1); return(-1); }
-  pid =(unsigned char) svstatus[15];
+  pid =(unsigned char)svstatus[15];
   pid <<=8; pid +=(unsigned char)svstatus[14];
   pid <<=8; pid +=(unsigned char)svstatus[13];
   pid <<=8; pid +=(unsigned char)svstatus[12];
   switch (*a) {
   case 'x': return(0);
-  case 'u': if (!pid) return(0); break;
+  case 'u': if (!pid) return(0); if (!checkscript()) return(0); break;
   case 'd': if (pid) return(0); break;
   case 't':
     if (!pid && svstatus[17] == 'd') break;
     tai_unpack(svstatus, &tstatus);
-    if ((tstart.sec.x > tstatus.x) || ! pid || svstatus[18]) return(0);
+    if ((tstart.sec.x > tstatus.x) || !pid || svstatus[18]) return(0);
     break;
   case 'o':
     tai_unpack(svstatus, &tstatus);
-    if ((! pid && tstart.sec.x > tstatus.x) || (pid && svstatus[17] != 'd'))
+    if ((!pid && tstart.sec.x > tstatus.x) || (pid && svstatus[17] != 'd'))
       return(0);
   }
   outs(OK); svstatus_print(*service); flush("\n");
@@ -235,7 +274,7 @@ int main(int argc, char **argv) {
   argv +=optind; argc -=optind;
   if (!(action =*argv++)) usage(); --argc;
   if (!lsb) { service =argv; services =argc; }
-  if (! *service) usage();
+  if (!*service) usage();
 
   taia_now(&tnow); tstart =tnow;
   if ((curdir =open_read(".")) == -1)
@@ -300,7 +339,7 @@ int main(int argc, char **argv) {
       taia_sub(&tdiff, &tnow, &tstart);
       service =servicex; done =1;
       for (i =0; i < services; ++i, ++service) {
-        if (! *service) continue;
+        if (!*service) continue;
         if ((**service != '/') && (**service != '.')) {
           if ((chdir(varservice) == -1) || (chdir(*service) == -1)) {
             fail("unable to change to service directory");
@@ -314,17 +353,17 @@ int main(int argc, char **argv) {
           }
         if (*service) { if (cbk(acts) != 0) *service =0; else done =0; }
         if (*service && taia_approx(&tdiff) > wait) {
-	  kll ? outs(KILL) : outs(TIMEOUT);
+          kll ? outs(KILL) : outs(TIMEOUT);
           if (svstatus_get() > 0) { svstatus_print(*service); ++rc; }
           flush("\n");
-	  if (kll) control("k");
+          if (kll) control("k");
           *service =0;
         }
         if (fchdir(curdir) == -1)
           fatal("unable to change to original directory");
       }
       if (done) break;
-      usleep(250000);
+      usleep(420000);
       taia_now(&tnow);
     }
   return(rc > 99 ? 99 : rc);
diff --git a/src/uidgid.c b/src/uidgid.c
index 84429d0..b467069 100644
--- a/src/uidgid.c
+++ b/src/uidgid.c
@@ -8,24 +8,34 @@ unsigned int uidgid_get(struct uidgid *u, char *ug, unsigned int dogrp) {
   char *g =0;
   struct passwd *pwd =0;
   struct group *gr =0;
-  int d =0;
+  int i, d =0;
 
   if (dogrp)
     if (ug[(d =str_chr(ug, ':'))] == ':') {
       ug[d] =0;
       g =ug +d +1;
     }
-  pwd =getpwnam(ug);
+  if (! (pwd =getpwnam(ug))) { ug[d] =':'; return(0); }
   if (g) {
-    gr =getgrnam(g);
     ug[d] =':';
+    for (i =0; i < 60; ++i) {
+      if (g[(d =str_chr(g, ':'))] == ':') {
+        g[d] =0;
+        if (! (gr =getgrnam(g))) { g[d] =':'; return(0); }
+        g[d] =':';
+        u->gid[i] =gr->gr_gid;
+        g +=d +1;
+      }
+      else {
+        if (! (gr =getgrnam(g))) return(0);
+        u->gid[i++] =gr->gr_gid;
+        break;
+      }
+    }
+    u->gid[i] =0;
+    u->gids =i;
   }
-  if (! pwd) return(0);
-  if (g && ! gr) return(0);
-  if (gr)
-    u->gid =gr->gr_gid;
-  else
-    u->gid =pwd->pw_gid;
+  if (! g) { u->gid[0] =pwd->pw_gid; u->gids =1; }
   u->uid =pwd->pw_uid;
   return(1);
 }
diff --git a/src/uidgid.h b/src/uidgid.h
index 54f6686..a612edd 100644
--- a/src/uidgid.h
+++ b/src/uidgid.h
@@ -3,7 +3,8 @@
 
 struct uidgid {
   int uid;
-  int gid;
+  int gid[61];
+  int gids;
 };
 
 extern unsigned int uidgid_get(struct uidgid *, char *, unsigned int);