chiark / gitweb /
Up to halfway down rhs p.12, inc builtin services, but not working yet.
[userv.git] / client.c
index bee10a1a3a5857d95b5a2491b46bf1c31939fab5..7a810b534aa98d42da10dad7135d4b5810a825a2 100644 (file)
--- a/client.c
+++ b/client.c
@@ -135,15 +135,17 @@ struct fdsetupstate {
 enum signalsexitspecials { se_number=-100, se_numbernocore, se_highbit, se_stdout };
 enum overridetypes { ot_none, ot_string, ot_file };
 
-static const char *serviceuser=0;
+struct constkeyvaluepair { const char *key, *value; };
+
+static const char *serviceuser;
 static uid_t serviceuid, myuid;
-static struct fdsetupstate *fdsetup=0;
-static int fdsetupsize=0;
-static const char *(*defvarsarray)[2];
-static int defvarsavail=0, defvarsused=0;
-static unsigned long timeout=0;
+static struct fdsetupstate *fdsetup;
+static int fdsetupsize, builtin;
+static struct constkeyvaluepair *defvararray;
+static int defvaravail, defvarused;
+static unsigned long timeout;
 static int signalsexit=254;
-static int sigpipeok=0, hidecwd=0;
+static int sigpipeok, hidecwd;
 static int overridetype= ot_none;
 static const char *overridevalue, *spoofuser=0;
 
@@ -276,6 +278,7 @@ static void xfflush(FILE *file) {
 static void usage(void) {
   if (fprintf(stderr,
     "usage: userv <options> [--] <service-user> <service-name> [<argument> ...]\n"
+    "usage: userv <options> -B|--builtin [--] <builtin-service> [<info-argument> ...]\n"
     "options: -f|--file <fd>[<fdmodifiers>]=<filename>\n"
     "         -D|--defvar <name>=<value>\n"
     "         -t|--timeout <seconds>\n"
@@ -420,19 +423,21 @@ static void of_fdwait(const struct optioninfo *oip, const char *value, char *key
 static void of_defvar(const struct optioninfo *oip, const char *value, char *key) {
   int i;
 
+  if (!key[0])
+    usageerror("empty string not allowed as variable name");
   if (strlen(key)>MAX_GENERAL_STRING)
     usageerror("variable name `%s' is far too long",key);
   if (strlen(value)>MAX_GENERAL_STRING)
     usageerror("variable `%s' has value `%s' which is far too long",key,value);
-  for (i=0; i<defvarsused && strcmp(defvarsarray[i][0],key); i++);
-  if (defvarsused >= MAX_ARGSDEFVARS) usageerror("far too many --defvar or -D options");
-  if (i>=defvarsavail) {
-    defvarsavail+=10; defvarsavail<<=1;
-    defvarsarray= xrealloc(defvarsarray,sizeof(const char*)*2*defvarsavail);
+  for (i=0; i<defvarused && strcmp(defvararray[i].key,key); i++);
+  if (defvarused >= MAX_ARGSDEFVAR) usageerror("far too many --defvar or -D options");
+  if (i>=defvaravail) {
+    defvaravail+=10; defvaravail<<=1;
+    defvararray= xrealloc(defvararray,sizeof(struct constkeyvaluepair)*defvaravail);
   }
-  if (i==defvarsused) defvarsused++;
-  defvarsarray[i][0]= key;
-  defvarsarray[i][1]= value;
+  if (i==defvarused) defvarused++;
+  defvararray[i].key= key;
+  defvararray[i].value= value;
 }
 
 static void of_timeout(const struct optioninfo *oip, const char *value, char *key) {
@@ -467,6 +472,10 @@ static void of_hidecwd(const struct optioninfo *oip, const char *value, char *ke
   hidecwd=1;
 }
 
+static void of_builtin(const struct optioninfo *oip, const char *value, char *key) {
+  builtin=1;
+}
+
 static void of_help(const struct optioninfo *oip, const char *value, char *key) {
   usage();
   exit(0);
@@ -515,6 +524,7 @@ const struct optioninfo optioninfos[]= {
   { 'S', "signals",       1, of_signals      },
   { 'P', "sigpipe",       0, of_sigpipe      },
   { 'H', "hidecwd",       0, of_hidecwd      },
+  { 'B', "builtin",       0, of_builtin      },
   { 'h', "help",          0, of_help         },
   {  0,  "copyright",     0, of_copyright    },
   {  0,  "override",      1, of_override     },
@@ -676,7 +686,7 @@ int main(int argc, char *const *argv) {
   char *argp;
   const struct optioninfo *oip;
   struct sockaddr_un ssockname;
-  int sfd, ngids, i, j, tempfd, l, c, reading, fd, r, status, ngidssize;
+  int sfd, ngids, i, tempfd, l, c, reading, fd, r, status, ngidssize;
   sigset_t sset;
   unsigned long ul;
   size_t cwdbufsize;
@@ -715,7 +725,7 @@ int main(int argc, char *const *argv) {
   of_file(0,"stderr",fd2key);
 
   for (argpp= argv+1;
-       (argp= *argpp) && *argp == '-';
+       (argp= *argpp) && *argp == '-' && argp[1];
        argpp++) {
     if (!*++argp) usageerror("unknown option/argument `%s'",*argpp);
     if (*argp == '-') { /* Two hyphens */
@@ -749,9 +759,15 @@ int main(int argc, char *const *argv) {
       }
     }
   }
-  if (!*argpp) usageerror("no service user given after options");
-  serviceuser= *argpp++;
-  if (!*argpp) usageerror("no service name given after options and service user");
+  if (builtin) {
+    serviceuser= "-";
+  } else {
+    if (!*argpp) usageerror("no service user given after options");
+    serviceuser= *argpp++;
+  }
+  if (!*argpp) usageerror(builtin ?
+                         "no service name given after options and service user" :
+                         "no builtin service given after options");
   
   for (fd=0; fd<fdsetupsize; fd++) {
     if (!fdsetup[fd].filename) continue;
@@ -767,9 +783,23 @@ int main(int argc, char *const *argv) {
 
   argc-= (argpp-argv);
   argv= argpp;
-  if (argc > MAX_ARGSDEFVARS) usageerror("far too many arguments");
+  if (argc > MAX_ARGSDEFVAR) usageerror("far too many arguments");
   if (ngids > MAX_GIDS) miscerror("caller is in far too many gids");
   
+  spoofuid= myuid;
+  spoofgid= mygid;
+  logname= getenv("LOGNAME");
+  if (!logname) logname= getenv("USER");
+  if (logname) {
+    pw= getpwnam(logname);
+    if (!pw || pw->pw_uid != myuid) logname= 0;
+  }
+  if (!logname) {
+    pw= getpwuid(myuid); if (!pw) miscerror("cannot determine your login name");
+    logname= pw->pw_name;
+  }
+
+  if (!strcmp(serviceuser,"-")) serviceuser= logname;
   pw= getpwnam(serviceuser);
   if (!pw) miscerror("requested service user `%s' is not a user",serviceuser);
   serviceuid= pw->pw_uid;
@@ -799,19 +829,6 @@ int main(int argc, char *const *argv) {
       }
       gidarray[ngids++]= gr->gr_gid;
     }
-  } else {
-    spoofuid= myuid;
-    spoofgid= mygid;
-    logname= getenv("LOGNAME");
-    if (!logname) logname= getenv("USER");
-    if (logname) {
-      pw= getpwnam(logname);
-      if (!pw || pw->pw_uid != myuid) logname= 0;
-    }
-    if (!logname) {
-      pw= getpwuid(myuid); if (!pw) miscerror("cannot determine your login name");
-      logname= pw->pw_name;
-    }
   }
 
   cwdbufsize= 0; cwdbuf= 0;
@@ -931,7 +948,7 @@ int main(int argc, char *const *argv) {
     else request_mbuf.nreadfds++;
   }
   request_mbuf.nargs= argc-1;
-  request_mbuf.nvars= defvarsused;
+  request_mbuf.nvars= defvarused;
   request_mbuf.overridelen= ovused;
   xfwrite(&request_mbuf,sizeof(request_mbuf),swfile);
   xfwrite(serviceuser,sizeof(*serviceuser)*request_mbuf.serviceuserlen,swfile);
@@ -945,9 +962,10 @@ int main(int argc, char *const *argv) {
   xfwritefds(fdm_write,request_mbuf.nwritefds,swfile);
   for (i=1; i<argc; i++)
     xfwritestring(argv[i],swfile);
-  for (i=0; i<defvarsused; i++)
-    for (j=0; j<2; j++)
-      xfwritestring(defvarsarray[i][j],swfile);
+  for (i=0; i<defvarused; i++) {
+    xfwritestring(defvararray[i].key,swfile);
+    xfwritestring(defvararray[i].value,swfile);
+  }
   ul= REQUEST_END_MAGIC; xfwrite(&ul,sizeof(ul),swfile);
   xfflush(swfile);