commit 993c4102e0594ffbda6199b2b014f7e3e4ef8334
parent 480651ade4426ecd92171ed33324e98843696b63
Author: Gerrit Pape <pape@smarden.org>
Date: Thu, 2 Nov 2006 22:59:14 +0000
* 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.
Diffstat:
6 files changed, 108 insertions(+), 23 deletions(-)
diff --git 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
@@ -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
@@ -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
@@ -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 =✓ break;
case 'c':
- if (!str_diff(action, "check")) { act =0; acts ="c"; cbk =✓ break; }
+ if (!str_diff(action, "check")) { act =0; acts ="C"; cbk =✓ 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
@@ -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
@@ -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