commit 426478b5f171376139665c40bf0f9ff90dcc52cb
parent 0529f2ba7ef7e7709a291ea400ced1870f7a482d
Author: Gerrit Pape <pape@smarden.org>
Date: Tue, 23 Aug 2005 22:36:27 +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.
Diffstat:
9 files changed, 123 insertions(+), 28 deletions(-)
diff --git 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);