summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/daemontools-extras/s6-envuidgid.c108
1 files changed, 68 insertions, 40 deletions
diff --git a/src/daemontools-extras/s6-envuidgid.c b/src/daemontools-extras/s6-envuidgid.c
index 2971e6a..57c178f 100644
--- a/src/daemontools-extras/s6-envuidgid.c
+++ b/src/daemontools-extras/s6-envuidgid.c
@@ -16,17 +16,48 @@
#define USAGE "s6-envuidgid [ -i | -D defaultuid:defaultgid ] [ -u | -g | -B ] [ -n ] account prog..."
#define dieusage() strerr_dieusage(100, USAGE)
+static inline unsigned int scan_defaults (char const *s, uint64 *uid, gid_t *gid, unsigned int *n, gid_t *tab)
+{
+ unsigned int pos = uint64_scan(s, uid) ;
+ if (!pos)
+ {
+ if (*s != ':') return 0 ;
+ *uid = 0 ;
+ }
+ s += pos ;
+ if (!*s) goto zgid ;
+ if (*s++ != ':') return 0 ;
+ if (!*s) goto zgid ;
+ pos = gid_scan(s, gid) ;
+ if (!pos)
+ {
+ if (*s != ':') return 0 ;
+ *gid = 0 ;
+ }
+ s += pos ;
+ if (!*s) goto zn ;
+ if (*s++ != ':') return 0 ;
+ if (!*s) goto zn ;
+ return gid_scanlist(tab, NGROUPS_MAX, s, n) ;
+
+ zgid:
+ *gid = 0 ;
+ zn:
+ *n = 0 ;
+ return 1 ;
+}
+
int main (int argc, char *const *argv, char const *const *envp)
{
char const *user = 0 ;
char const *group = 0 ;
- int what = 0 ;
+ unsigned int what = 7 ;
int numfallback = 0 ;
int insist = 1 ;
- unsigned int pos ;
uint64 uid ;
gid_t gid ;
- char fmt[19 + UINT64_FMT + (NGROUPS_MAX+1) * GID_FMT] ;
+ unsigned int n ;
+ gid_t tab[NGROUPS_MAX] ;
PROG = "s6-envuidgid" ;
{
subgetopt_t l = SUBGETOPT_ZERO ;
@@ -39,27 +70,12 @@ int main (int argc, char *const *argv, char const *const *envp)
case 'u' : what = 1 ; break ;
case 'g' : what = 2 ; break ;
case 'B' : what = 3 ; break ;
- case 'n' : what = 3 ; numfallback = 1 ; break ;
+ case 'n' : what &= 3 ; numfallback = 1 ; break ;
case 'i' : insist = 1 ; break ;
case 'D' :
- {
- unsigned int pos = uint64_scan(l.arg, &uid) ;
- if (!pos)
- {
- if (l.arg[pos] != ':') dieusage() ;
- uid = 0 ;
- }
- if (!l.arg[pos]) gid = 0 ;
- else
- {
- if (l.arg[pos++] != ':') dieusage() ;
- if (!l.arg[pos]) gid = 0 ;
- else if (!gid0_scan(l.arg + pos, &gid)) dieusage() ;
- }
+ if (!scan_defaults(l.arg, &uid, &gid, &n, tab)) dieusage() ;
insist = 0 ;
- what = 3 ;
break ;
- }
default : dieusage() ;
}
}
@@ -69,7 +85,7 @@ int main (int argc, char *const *argv, char const *const *envp)
switch (what)
{
- case 0 : /* account */
+ case 7 : /* account */
case 1 : /* user */
user = argv[0] ;
break ;
@@ -77,8 +93,9 @@ int main (int argc, char *const *argv, char const *const *envp)
group = argv[0] ;
break ;
case 3 : /* both */
+ {
+ unsigned int pos = str_chr(argv[0], ':') ;
user = argv[0] ;
- pos = str_chr(argv[0], ':') ;
if (argv[0][pos])
{
argv[0][pos] = 0 ;
@@ -87,20 +104,16 @@ int main (int argc, char *const *argv, char const *const *envp)
if (!group[0]) group = 0 ;
}
break ;
+ }
default : strerr_dief1x(101, "inconsistent option management - please submit a bug-report") ;
}
- pos = 0 ;
-
if (group)
{
struct group *gr = getgrnam(group) ;
if (gr) gid = gr->gr_gid ;
else if (numfallback && gid_scan(group, &gid)) ;
else if (insist) strerr_dief2x(1, "unknown group: ", group) ;
- byte_copy(fmt + pos, 4, "GID=") ; pos += 4 ;
- pos += gid_fmt(fmt + pos, gid) ;
- fmt[pos++] = 0 ;
}
if (user)
@@ -109,26 +122,41 @@ int main (int argc, char *const *argv, char const *const *envp)
if (pw)
{
uid = pw->pw_uid ;
- if (!what)
+ if (what == 7)
{
- gid_t tab[NGROUPS_MAX] ;
- int n = prot_readgroups(argv[0], tab, NGROUPS_MAX) ;
- if (n < 0)
+ int r = prot_readgroups(argv[0], tab, NGROUPS_MAX) ;
+ if (r < 0)
strerr_diefu2sys(111, "get supplementary groups for ", argv[0]) ;
- byte_copy(fmt + pos, 4, "GID=") ; pos += 4 ;
- pos += gid_fmt(fmt + pos, pw->pw_gid) ;
- byte_copy(fmt + pos, 9, "\0GIDLIST=") ; pos += 9 ;
- pos += gid_fmtlist(fmt + pos, tab, n) ;
- fmt[pos++] = 0 ;
+ n = r ;
+ gid = pw->pw_gid ;
}
}
else if (numfallback && uint64_scan(user, &uid)) ;
else if (insist) strerr_dief2x(1, "unknown user: ", user) ;
- byte_copy(fmt + pos, 4, "UID=") ; pos += 4 ;
- pos += uint64_fmt(fmt + pos, uid) ;
- fmt[pos++] = 0 ;
}
- pathexec_r((char const *const *)argv + 1, envp, env_len(envp), fmt, pos) ;
+ {
+ unsigned int pos = 0 ;
+ char fmt[19 + UINT64_FMT + (NGROUPS_MAX+1) * GID_FMT] ;
+ if (what & 1)
+ {
+ byte_copy(fmt + pos, 4, "UID=") ; pos += 4 ;
+ pos += uint64_fmt(fmt + pos, uid) ;
+ fmt[pos++] = 0 ;
+ }
+ if (what & 2)
+ {
+ byte_copy(fmt + pos, 4, "GID=") ; pos += 4 ;
+ pos += gid_fmt(fmt + pos, gid) ;
+ fmt[pos++] = 0 ;
+ }
+ if (what & 4)
+ {
+ byte_copy(fmt + pos, 8, "GIDLIST=") ; pos += 8 ;
+ pos += gid_fmtlist(fmt + pos, tab, n) ;
+ fmt[pos++] = 0 ;
+ }
+ pathexec_r((char const *const *)argv + 1, envp, env_len(envp), fmt, pos) ;
+ }
strerr_dieexec(111, argv[1]) ;
}