summary refs log tree commit diff
diff options
context:
space:
mode:
authorGerrit Pape <pape@smarden.org>2006-11-02 22:59:14 +0000
committerGerrit Pape <pape@smarden.org>2006-11-02 22:59:14 +0000
commita1bbb6ddcf9119220c509c2e6424cf6a5a20d984 (patch)
treee1691179493adeaa9e59410895afc47b50f2f704
parentc09a0fe2d6721235b106745b03e2992f0d35fc24 (diff)
downloadrunit-a1bbb6ddcf9119220c509c2e6424cf6a5a20d984.tar.gz
runit-a1bbb6ddcf9119220c509c2e6424cf6a5a20d984.tar.xz
runit-a1bbb6ddcf9119220c509c2e6424cf6a5a20d984.zip
* chpst.c, uidgid.c, uidgid.h: support numerical uid gid through
    chpst -[u|U] :uid:gid...
  * man/chpst.8: adapt; clarify that users and groups are looked up in
    /etc/passwd and /etc/group only.
  * sv.c: properly wait for a service to be restarted on 'restart';
    support checks through -v for pause, cont, kill.
-rw-r--r--man/chpst.834
-rw-r--r--package/CHANGES9
-rw-r--r--src/chpst.c26
-rw-r--r--src/sv.c11
-rw-r--r--src/uidgid.c45
-rw-r--r--src/uidgid.h6
6 files changed, 108 insertions, 23 deletions
diff --git a/man/chpst.8 b/man/chpst.8
index 42c23d3..c67ec65 100644
--- a/man/chpst.8
+++ b/man/chpst.8
@@ -38,18 +38,21 @@ changes the process state according to the given options, and runs
 .IR prog .
 .SH OPTIONS
 .TP
-.B \-u \fIuser[:group]
+.B \-u \fI[:]user[:group]
 setuidgid.
 Set uid and gid to the
 .IR user 's
-uid and gid.
+uid and gid, as found in
+.IR /etc/passwd .
 If
 .I user
 is followed by a colon and a
 .IR group ,
 set the gid to
 .IR group 's
-gid instead of
+gid, as found in
+.IR /etc/group ,
+instead of
 .IR user 's
 gid.
 If
@@ -57,22 +60,41 @@ If
 consists of a colon-separated list of group names,
 .B chpst
 sets the group ids of all listed groups.
+If
+.I user
+is prefixed with a colon, the
+.I user
+and all
+.I group
+arguments are interpreted as uid and gids respectivly, and not looked up in
+the password or group file.
 All initial supplementary groups are removed.
 .TP
-.B \-U \fIuser[:group]
+.B \-U \fI[:]user[:group]
 envuidgid.
 Set the environment variables $UID and $GID to the
 .IR user 's
-uid and gid.
+uid and gid, as found in
+.IR /etc/passwd .
 If
 .I user
 is followed by a colon and a
 .IR group ,
 set $GID to the
 .IR group 's
-gid instead of
+gid, as found in
+.IR /etc/group ,
+instead of
 .IR user 's
 gid.
+If
+.I user
+is prefixed with a colon, the
+.I user
+and
+.I group
+arguments are interpreted as uid and gid respectivly, and not looked up in
+the password or group file.
 .TP
 .B \-e \fIdir
 envdir.
diff --git a/package/CHANGES b/package/CHANGES
index 4679a3a..4341bdb 100644
--- a/package/CHANGES
+++ b/package/CHANGES
@@ -1,3 +1,12 @@
+1.8.0
+
+  * chpst.c, uidgid.c, uidgid.h: support numerical uid gid through
+    chpst -[u|U] :uid:gid...
+  * man/chpst.8: adapt; clarify that users and groups are looked up in
+    /etc/passwd and /etc/group only.
+  * sv.c: properly wait for a service to be restarted on 'restart';
+    support checks through -v for pause, cont, kill.
+
 1.7.0
 Sat, 07 Oct 2006 18:24:17 +0000
   * svlogd.c, fmt_ptime.*, man/svlogd.8: new option -ttt: prefix log
diff --git a/src/chpst.c b/src/chpst.c
index ae07e36..9df2fb6 100644
--- a/src/chpst.c
+++ b/src/chpst.c
@@ -61,30 +61,40 @@ const char *lock =0;
 const char *root =0;
 unsigned int lockdelay;
 
-void suidgid(char *user, unsigned int dogrp) {
+void suidgid(char *user, unsigned int ext) {
   struct uidgid ugid;
 
-  if (! uidgid_get(&ugid, user, dogrp)) {
-    if (dogrp)
+  if (ext) {
+    if (! uidgids_get(&ugid, user)) {
+      if (*user == ':')
+        fatalx("invalid uid/gids", user +1);
+      else
       fatalx("unknown user/group", user);
+    }
+  }
     else
+    if (! uidgid_get(&ugid, user))
       fatalx("unknown account", user);
-  }
   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");
 }
 
-void euidgid(char *user, unsigned int dogrp) {
+void euidgid(char *user, unsigned int ext) {
   struct uidgid ugid;
   char bufnum[FMT_ULONG];
 
-  if (! uidgid_get(&ugid, user, dogrp)) {
-    if (dogrp)
+  if (ext) {
+    if (! uidgids_get(&ugid, user)) {
+      if (*user == ':')
+        fatalx("invalid uid/gids", user +1);
+      else
       fatalx("unknown user/group", user);
+    }
+  }
     else
+    if (! uidgid_get(&ugid, user))
       fatalx("unknown account", user);
-  }
   bufnum[fmt_ulong(bufnum, *ugid.gid)] =0;
   if (! pathexec_env("GID", bufnum)) die_nomem();
   bufnum[fmt_ulong(bufnum, ugid.uid)] =0;
diff --git a/src/sv.c b/src/sv.c
index a9592f4..c8126a3 100644
--- a/src/sv.c
+++ b/src/sv.c
@@ -208,6 +208,7 @@ int check(char *a) {
   unsigned int pid;
 
   if ((r =svstatus_get()) == -1) return(-1);
+  while (*a) {
   if (r == 0) { if (*a == 'x') return(1); return(-1); }
   pid =(unsigned char)svstatus[15];
   pid <<=8; pid +=(unsigned char)svstatus[14];
@@ -220,8 +221,9 @@ int check(char *a) {
     if (!checkscript()) return(0);
     break;
   case 'd': if (pid) return(0); break;
-  case 'c': if (pid) if (!checkscript()) return(0); break;
+    case 'C': if (pid) if (!checkscript()) return(0); break;
   case 't':
+    case 'k':
     if (!pid && svstatus[17] == 'd') break;
     tai_unpack(svstatus, &tstatus);
     if ((tstart.sec.x > tstatus.x) || !pid || svstatus[18] || !checkscript())
@@ -231,6 +233,11 @@ int check(char *a) {
     tai_unpack(svstatus, &tstatus);
     if ((!pid && tstart.sec.x > tstatus.x) || (pid && svstatus[17] != 'd'))
       return(0);
+      break;
+    case 'p': if (pid && !svstatus[16]) return(0); break;
+    case 'c': if (pid && svstatus[16]) return(0); break;
+    }
+    ++a;
   }
   outs(OK); svstatus_print(*service); flush("\n");
   return(1);
@@ -297,7 +304,7 @@ int main(int argc, char **argv) {
   case 'T':
     acts ="tc"; kll =1; cbk =&check; break;
   case 'c':
-    if (!str_diff(action, "check")) { act =0; acts ="c"; cbk =&check; break; }
+    if (!str_diff(action, "check")) { act =0; acts ="C"; cbk =&check; break; }
   case 'u': case 'd': case 'o': case 't': case 'p': case 'h':
   case 'a': case 'i': case 'k': case 'q': case '1': case '2':
     action[1] =0; acts =action; break;
diff --git a/src/uidgid.c b/src/uidgid.c
index 720d2ff..718d7a9 100644
--- a/src/uidgid.c
+++ b/src/uidgid.c
@@ -3,20 +3,56 @@
 #include <grp.h>
 #include "uidgid.h"
 #include "str.h"
+#include "scan.h"
 
-unsigned int uidgid_get(struct uidgid *u, char *ug, unsigned int dogrp) {
+/* user */
+unsigned int uidgid_get(struct uidgid *u, char *ug) {
+  struct passwd *pwd =0;
+
+  if (! (pwd =getpwnam(ug))) return(0);
+  u->gid[0] =pwd->pw_gid; u->gids =1;
+  u->uid =pwd->pw_uid;
+  return(1);
+}
+
+/* uid:gid[:gid[:gid]...] */
+unsigned int uidgids_set(struct uidgid *u, char *ug) {
+  unsigned long id;
+  int i;
+
+  if (*(ug +=scan_ulong(ug, &id)) != ':') return(0);
+  u->uid =(uid_t)id;
+  ++ug;
+  for (i =0; i < 60; ++i, ++ug) {
+    ug +=scan_ulong(ug, &id);
+    u->gid[i] =(gid_t)id;
+    if (*ug != ':') { ++i; break; }
+  }
+  u->gid[i] =0;
+  u->gids =i;
+  if (*ug) return(0);
+  return(1);
+}
+
+/* [:]user[:group[:group]...] */
+unsigned int uidgids_get(struct uidgid *u, char *ug) {
   char *g =0;
   struct passwd *pwd =0;
   struct group *gr =0;
   int i, d =0;
 
-  if (dogrp)
+  if (*ug == ':') return(uidgids_set(u, ug +1));
     if (ug[(d =str_chr(ug, ':'))] == ':') {
       ug[d] =0;
       g =ug +d +1;
     }
   if (! (pwd =getpwnam(ug))) { if (g) ug[d] =':'; return(0); }
-  if (g) {
+  u->uid =pwd->pw_uid;
+  if (! g) {
+    u->gid[0] =pwd->pw_gid;
+    u->gids =1;
+    return(1);
+  }
     ug[d] =':';
     for (i =0; i < 60; ++i) {
       if (g[(d =str_chr(g, ':'))] == ':') {
@@ -34,8 +70,5 @@ unsigned int uidgid_get(struct uidgid *u, char *ug, unsigned int dogrp) {
     }
     u->gid[i] =0;
     u->gids =i;
-  }
-  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 f8599a1..13cacbc 100644
--- a/src/uidgid.h
+++ b/src/uidgid.h
@@ -9,6 +9,10 @@ struct uidgid {
   int gids;
 };
 
-extern unsigned int uidgid_get(struct uidgid *, char *, unsigned int);
+/* user */
+extern unsigned int uidgid_get(struct uidgid *, char *);
+
+/* [:]user[:group[:group]...] */
+extern unsigned int uidgids_get(struct uidgid *, char *);
 
 #endif