diff options
-rw-r--r-- | doc/runscripts.html | 2 | ||||
-rw-r--r-- | man/chpst.8 | 13 | ||||
-rw-r--r-- | man/sv.8 | 24 | ||||
-rw-r--r-- | package/CHANGES | 10 | ||||
-rw-r--r-- | src/chpst.c | 5 | ||||
-rw-r--r-- | src/runsv.c | 5 | ||||
-rw-r--r-- | src/sv.c | 61 | ||||
-rw-r--r-- | src/uidgid.c | 28 | ||||
-rw-r--r-- | src/uidgid.h | 3 |
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); |