aboutsummaryrefslogtreecommitdiffstats
path: root/src/alias/s6-frontend-alias-chpst.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/alias/s6-frontend-alias-chpst.c')
-rw-r--r--src/alias/s6-frontend-alias-chpst.c347
1 files changed, 347 insertions, 0 deletions
diff --git a/src/alias/s6-frontend-alias-chpst.c b/src/alias/s6-frontend-alias-chpst.c
new file mode 100644
index 0000000..860654e
--- /dev/null
+++ b/src/alias/s6-frontend-alias-chpst.c
@@ -0,0 +1,347 @@
+ /* ISC license. */
+
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <errno.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include <skalibs/uint64.h>
+#include <skalibs/types.h>
+#include <skalibs/bytestr.h>
+#include <skalibs/sgetopt.h>
+#include <skalibs/buffer.h>
+#include <skalibs/strerr2.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/genalloc.h>
+#include <skalibs/env.h>
+#include <skalibs/djbunix.h>
+
+#include <execline/config.h>
+
+#include <s6/config.h>
+
+#define USAGE "s6-frontend-alias-chpst [ -v ] [ -P ] [ -0 ] [ -1 ] [ -2 ] [ -u user ] [ -U user ] [ -b argv0 ] [ -e dir ] [ -n niceness ] [ -l lock | -L lock ] [ -m bytes ] [ -d bytes ] [ -o n ] [ -p n ] [ -f bytes ] [ -c bytes ] prog..."
+
+#define dienomem() strerr_diefu1sys(111, "stralloc_catb")
+#define dieusage() strerr_dieusage(100, USAGE)
+
+static unsigned int verbosity = 0 ;
+
+static void printit (char const *const *argv)
+{
+ buffer_puts(buffer_2, PROG) ;
+ buffer_puts(buffer_2, ": info: executing the following command line:") ;
+ for (; *argv ; argv++)
+ {
+ buffer_puts(buffer_2, " ") ;
+ buffer_puts(buffer_2, *argv) ;
+ }
+ buffer_putsflush(buffer_2, "\n") ;
+}
+
+static inline size_t parseuggnum (char const *s, uint32_t *flags, uid_t *uid, gid_t *gid, gid_t *tab)
+{
+ size_t n = 0 ;
+ size_t pos = uid_scan(s, uid) ;
+ if (!pos) dieusage() ;
+ if (!s[pos]) return 0 ;
+ if (s[pos] != ':') dieusage() ;
+ s += pos+1 ;
+ pos = gid_scan(s, gid) ;
+ if (!pos) dieusage() ;
+ *flags |= 32768 ;
+ if (!s[pos]) return 0 ;
+ if (s[pos] != ':') dieusage() ;
+ s += pos+1 ;
+ if (!gid_scanlist(tab, NGROUPS_MAX, s, &n)) dieusage() ;
+ return n ;
+}
+
+static struct passwd *do_getpwnam (char const *s)
+{
+ struct passwd *pw = getpwnam(s) ;
+ if (!pw)
+ {
+ if (errno) strerr_diefu1sys(111, "read user database") ;
+ else strerr_dief2x(100, "user not found in user database: ", s) ;
+ }
+ return pw ;
+}
+
+static struct group *do_getgrnam (char const *s)
+{
+ struct group *gr = getgrnam(s) ;
+ if (!gr)
+ {
+ if (errno) strerr_diefu1sys(111, "read group database") ;
+ else strerr_dief2x(100, "group not found in group database: ", s) ;
+ }
+ return gr ;
+}
+
+static inline size_t parseuggsym (char const *s, uint32_t *flags, uid_t *uid, gid_t *gid, gid_t *tab)
+{
+ size_t n = 0 ;
+ struct passwd *pw ;
+ struct group *gr ;
+ size_t pos = str_chr(s, ':') ;
+ *flags |= 32768 ;
+ errno = 0 ;
+ if (!s[pos]) pw = do_getpwnam(s) ;
+ else
+ {
+ char tmp[pos+1] ;
+ memcpy(tmp, s, pos) ;
+ tmp[pos] = 0 ;
+ pw = do_getpwnam(tmp) ;
+ }
+ *uid = pw->pw_uid ;
+ if (!s[pos])
+ {
+ *gid = pw->pw_gid ;
+ return 0 ;
+ }
+ s += pos+1 ;
+ pos = str_chr(s, ':') ;
+ errno = 0 ;
+ if (!s[pos]) gr = do_getgrnam(s) ;
+ else
+ {
+ char tmp[pos+1] ;
+ memcpy(tmp, s, pos) ;
+ tmp[pos] = 0 ;
+ gr = do_getgrnam(tmp) ;
+ }
+ *gid = gr->gr_gid ;
+ if (!s[pos]) return 0 ;
+ s += pos+1 ;
+ while (*s)
+ {
+ if (n >= NGROUPS_MAX)
+ strerr_dief1x(100, "too many supplementary groups listed for the -u option") ;
+ pos = str_chr(s, ':') ;
+ errno = 0 ;
+ if (!s[pos]) gr = do_getgrnam(s) ;
+ else
+ {
+ char tmp[pos+1] ;
+ memcpy(tmp, s, pos) ;
+ tmp[pos] = 0 ;
+ gr = do_getgrnam(tmp) ;
+ }
+ tab[n++] = gr->gr_gid ;
+ s += s[pos] ? pos+1 : pos ;
+ }
+ return n ;
+}
+
+int main (int argc, char const *const *argv, char const *const *envp)
+{
+ static char const *valopt[6] = { "-m", "-d", "-o", "-p", "-f", "-c" } ;
+ genalloc envdirs = GENALLOC_ZERO ; /* char const * */
+ stralloc newroot = STRALLOC_ZERO ;
+ unsigned int newargc = 0 ;
+ char const *argv0 = 0 ;
+ char const *lockfile = 0 ;
+ char const *envug = 0 ;
+ uint32_t flags = 0 ;
+ int niceval = 0 ;
+ char valfmt[6][UINT64_FMT] ;
+ char nicefmt[INT_FMT] ;
+ char uidfmt[UID_FMT] ;
+ char gidfmt[GID_FMT] ;
+ char gidlistfmt[GID_FMT * NGROUPS_MAX] ;
+ PROG = "s6-frontend-alias-chpst" ;
+
+ {
+ subgetopt_t l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "vP012u:U:b:e:/:n:l:L:m:d:o:p:f:c:", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'v' : verbosity++ ; break ;
+ case '0' : flags |= 1 ; newargc += 2 ; break ;
+ case '1' : flags |= 2 ; newargc += 2 ; break ;
+ case '2' : flags |= 4 ; newargc += 2 ; break ;
+ case 'P' : flags |= 8 ; newargc += 2 ; break ;
+ case 'b' : argv0 = l.arg ; newargc += 4 ; break ;
+ case 'u' :
+ {
+ size_t n ;
+ uid_t uid ;
+ gid_t gid ;
+ gid_t tab[NGROUPS_MAX] ;
+ newargc += 6 ;
+ flags |= 16384 ; flags &= ~32768 ;
+ n = l.arg[0] == ':' ?
+ parseuggnum(l.arg + 1, &flags, &uid, &gid, tab) :
+ parseuggsym(l.arg, &flags, &uid, &gid, tab) ;
+ uidfmt[uid_fmt(uidfmt, uid)] = 0 ;
+ if (flags & 32768)
+ {
+ newargc += 2 ;
+ gidfmt[gid_fmt(gidfmt, gid)] = 0 ;
+ }
+ gidlistfmt[gid_fmtlist(gidlistfmt, tab, n)] = 0 ;
+ break ;
+ }
+ case 'U' :
+ envug = l.arg ;
+ newargc += 3 ;
+ if (envug[0] == ':') { flags |= 4096 ; envug++ ; newargc++ ; } else flags &= ~4096 ;
+ if (strchr(envug, ':')) { flags |= 8192 ; newargc++ ; } else flags &= ~8192 ;
+ break ;
+ case 'e' :
+ if (!genalloc_append(char const *, &envdirs, &l.arg)) dienomem() ;
+ newargc += 3 ;
+ break ;
+ case '/' :
+ newroot.len = 0 ;
+ if (sarealpath(&newroot, l.arg) < 0 || !stralloc_0(&newroot)) dienomem() ;
+ newargc += 2 ;
+ break ;
+ case 'n' :
+ if (!int0_scan(l.arg, &niceval)) dieusage() ;
+ newargc += 3 ;
+ break ;
+ case 'l' : lockfile = l.arg ; flags &= ~16 ; newargc += 4 ; break ;
+ case 'L' : lockfile = l.arg ; flags |= 16 ; newargc += 4 ; break ;
+ case 'm' :
+ case 'd' :
+ case 'o' :
+ case 'p' :
+ case 'f' :
+ case 'c' :
+ {
+ uint64_t val ;
+ size_t pos = byte_chr("mdopfc", 6, opt) ;
+ if (!uint640_scan(l.arg, &val)) dieusage() ;
+ valfmt[pos][uint64_fmt(valfmt[pos], val)] = 0 ;
+ flags |= 32 | (1 << (6 + pos)) ;
+ newargc += 2 ;
+ break ;
+ }
+ default : dieusage() ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+
+ if (flags & 32) newargc += 2 ;
+ newargc += argc ;
+
+ {
+ unsigned int m = 0 ;
+ char const *newargv[newargc + 1] ;
+
+ if (niceval)
+ {
+ nicefmt[int_fmt(nicefmt, niceval)] = 0 ;
+ newargv[m++] = "nice" ;
+ newargv[m++] = "-n" ;
+ newargv[m++] = nicefmt ;
+ newargv[m++] = "--" ;
+ }
+
+ if (flags & 8)
+ {
+ newargv[m++] = S6_EXTBINPREFIX "s6-setsid" ;
+ newargv[m++] = "--" ;
+ }
+
+ if (genalloc_len(char const *, &envdirs))
+ {
+ for (size_t i = 0 ; i < genalloc_len(char const *, &envdirs) ; i++)
+ {
+ newargv[m++] = S6_EXTBINPREFIX "s6-envdir" ;
+ newargv[m++] = "--" ;
+ newargv[m++] = genalloc_s(char const *, &envdirs)[i] ;
+ }
+ }
+
+ if (lockfile)
+ {
+ newargv[m++] = S6_EXTBINPREFIX "s6-setlock" ;
+ newargv[m++] = flags & 16 ? "-n" : "-N" ;
+ newargv[m++] = "--" ;
+ newargv[m++] = lockfile ;
+ }
+
+ if (flags & 16384)
+ {
+ newargv[m++] = S6_EXTBINPREFIX "s6-applyuidgid" ;
+ newargv[m++] = "-u" ;
+ newargv[m++] = uidfmt ;
+ if (flags & 32768)
+ {
+ newargv[m++] = "-g" ;
+ newargv[m++] = gidfmt ;
+ }
+ newargv[m++] = "-G" ;
+ newargv[m++] = gidlistfmt ;
+ newargv[m++] = "--" ;
+ }
+
+ if (envug)
+ {
+ newargv[m++] = S6_EXTBINPREFIX "s6-envuidgid" ;
+ if (flags & 4096) newargv[m++] = "-n" ;
+ if (flags & 8192) newargv[m++] = "-B" ;
+ newargv[m++] = "--" ;
+ newargv[m++] = envug ;
+ }
+
+ if (flags & 32)
+ {
+ newargv[m++] = S6_EXTBINPREFIX "s6-softlimit" ;
+ for (unsigned int i = 0 ; i < 6 ; i++) if (flags & (1 << (i + 6)))
+ {
+ newargv[m++] = valopt[i] ;
+ newargv[m++] = valfmt[i] ;
+ }
+ newargv[m++] = "--" ;
+ }
+
+ if (flags & 1)
+ {
+ newargv[m++] = EXECLINE_EXTBINPREFIX "fdclose" ;
+ newargv[m++] = "0" ;
+ }
+
+ if (flags & 2)
+ {
+ newargv[m++] = EXECLINE_EXTBINPREFIX "fdclose" ;
+ newargv[m++] = "1" ;
+ }
+
+ if (flags & 4)
+ {
+ newargv[m++] = EXECLINE_EXTBINPREFIX "fdclose" ;
+ newargv[m++] = "2" ;
+ }
+
+ if (argv0)
+ {
+ newargv[m++] = EXECLINE_BINPREFIX "exec" ;
+ newargv[m++] = "-a" ;
+ newargv[m++] = argv0 ;
+ newargv[m++] = "--" ;
+ }
+
+ if (newroot.s)
+ {
+ newargv[m++] = "chroot" ;
+ newargv[m++] = newroot.s ;
+ if (argv0) strerr_warnw1x("the -b option is ineffective when the -/ option is also given") ;
+ }
+
+ for (int i = 0 ; i < argc+1 ; i++) newargv[m++] = argv[i] ;
+ if (verbosity) printit(newargv) ;
+ xpathexec0_run(newargv, envp) ;
+ }
+}