chiark / gitweb /
Call it beta.
[userv.git] / client.c
index 4fbb710..740aac5 100644 (file)
--- a/client.c
+++ b/client.c
@@ -2,7 +2,7 @@
  * userv - client.c
  * client code
  *
- * Copyright (C)1996-1997 Ian Jackson
+ * Copyright (C)1996-1997,1999 Ian Jackson
  *
  * This is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by
@@ -72,6 +72,7 @@
 
 #include "config.h"
 #include "common.h"
+#include "both.h"
 #include "version.h"
 
 enum fdmodifiervalues {
@@ -127,7 +128,7 @@ static uid_t myuid, spoofuid;
 static gid_t mygid, spoofgid, *gidarray;
 static int ngids;
 static struct opening_msg opening_mbuf;
-static const char *logname;
+static const char *loginname;
 static char *cwdbuf;
 static size_t cwdbufsize;
 static char *ovbuf;
@@ -213,7 +214,7 @@ static void NONRETURNPRINTFFORMAT(1,2) protoerror(const char *fmt, ...) {
 
 static void xfread(void *p, size_t sz, FILE *file) {
   size_t nr;
-  nr= fread(p,1,sz,file);
+  nr= working_fread(p,sz,file);
   if (nr != sz) protoreaderror(file,"in data");
 }
 
@@ -277,7 +278,8 @@ static void getprogress(struct progress_msg *progress_r, FILE *file) {
        protoerror("stderr message length %d is far too long",
                   progress_r->data.errmsg.messagelen);
       for (i=0; i<progress_r->data.errmsg.messagelen; i++) {
-       c= getc(file); if (c==EOF) protoreaderror(file,"in error message");
+       c= working_getc(file);
+       if (c==EOF) protoreaderror(file,"in error message");
        if (isprint(c)) putc(c,stderr);
        else fprintf(stderr,"\\x%02x",(unsigned char)c);
       }
@@ -378,6 +380,7 @@ static void sighandler_chld(int ignored) /* DOES return, unlike in daemon */ {
        memset(&event_mbuf,0,sizeof(event_mbuf));
        event_mbuf.magic= EVENT_MAGIC;
        event_mbuf.type= et_closereadfd;
+        event_mbuf.data.closereadfd.fd= fd;
        r= fwrite(&event_mbuf,1,sizeof(event_mbuf),swfile);
        if (r != sizeof(event_mbuf) || fflush(swfile))
          if (errno != EPIPE) syscallerror("inform service of closed read fd");
@@ -433,8 +436,10 @@ static void usage(void) {
     "         --override-file <filename>      }  to root\n"
     "         --spoof-user <username>         }  or same user\n"
     "fdmodifiers:            read    write  overwrite    trunc[ate]\n"
-    "(separate with commas)  append  sync   excl[usive]  creat[e]  fd\n\n"
-    "userv and uservd version " VERSION "; copyright (C)1996-1997 Ian Jackson.\n"
+    "(separate with commas)  append  sync   excl[usive]  creat[e]  fd\n"
+    "userv -B 'X' ... is same as userv --override 'execute-builtin X' - 'X' ...\n"
+    "         for help, type `userv -B help'; remember to quote multi-word X\n"
+    "userv and uservd version " VERSION VEREXT "; copyright (C)1996-1999 Ian Jackson.\n"
     "there is NO WARRANTY; type `userv --copyright' for details.\n",
             stderr) < 0)
     syscallerror("write usage to stderr");
@@ -679,7 +684,7 @@ static void of_help(const struct optioninfo *oip, const char *value, char *key)
 
 static void of_copyright(const struct optioninfo *oip, const char *value, char *key) {
   if (fputs(
-" userv - user service daemon and client; copyright (C)1996-1997 Ian Jackson\n\n"
+" userv - user service daemon and client; copyright (C)1996-1999 Ian Jackson\n\n"
 " This is free software; you can redistribute it and/or modify it under the\n"
 " terms of the GNU General Public License as published by the Free Software\n"
 " Foundation; either version 2 of the License, or (at your option) any\n"
@@ -737,13 +742,14 @@ static void callvalueoption(const struct optioninfo *oip, char *arg) {
   char *equals;
   if (oip->values == 2) {
     equals= strchr(arg,'=');
-    if (!equals)
+    if (!equals) {
       if (oip->abbrev)
         usageerror("option --%s (-%c) passed argument `%s' with no `='",
                    oip->full,oip->abbrev,arg);
       else
         usageerror("option --%s passed argument `%s' with no `='",
                    oip->full,arg);
+    }
     *equals++= 0;
     (oip->fn)(oip,equals,arg);
   } else {
@@ -851,18 +857,18 @@ static void determine_users(void) {
   
   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;
+  loginname= getenv("LOGNAME");
+  if (!loginname) loginname= getenv("USER");
+  if (loginname) {
+    pw= getpwnam(loginname);
+    if (!pw || pw->pw_uid != myuid) loginname= 0;
   }
-  if (!logname) {
+  if (!loginname) {
     pw= getpwuid(myuid); if (!pw) miscerror("cannot determine your login name");
-    logname= pw->pw_name;
+    loginname= pw->pw_name;
   }
 
-  if (!strcmp(serviceuser,"-")) serviceuser= logname;
+  if (!strcmp(serviceuser,"-")) serviceuser= loginname;
   pw= getpwnam(serviceuser);
   if (!pw) miscerror("requested service user `%s' is not a user",serviceuser);
   serviceuid= pw->pw_uid;
@@ -872,9 +878,9 @@ static void determine_users(void) {
               " the user who will be providing the service");
 
   if (spoofuser) {
-    logname= spoofuser;
-    pw= getpwnam(logname);
-    if (!pw) miscerror("spoofed login name `%s' is not valid",logname);
+    loginname= spoofuser;
+    pw= getpwnam(loginname);
+    if (!pw) miscerror("spoofed login name `%s' is not valid",loginname);
     spoofuid= pw->pw_uid;
     spoofgid= pw->pw_gid;
     ngidssize= ngids; ngids= 0;
@@ -884,7 +890,7 @@ static void determine_users(void) {
     }
     gidarray[ngids++]= spoofgid;
     while ((gr= getgrent())) { /* ouch! getgrent has no error behaviour! */
-      for (mem= gr->gr_mem; *mem && strcmp(*mem,logname); mem++);
+      for (mem= gr->gr_mem; *mem && strcmp(*mem,loginname); mem++);
       if (!*mem) continue;
       if (ngids>=ngidssize) {
       if (ngids>=MAX_GIDS) miscerror("spoofed user is member of too many groups");
@@ -1046,7 +1052,8 @@ static void server_sendrequest(int argc, char *const *argv) {
   request_mbuf.clientpid= getpid();
   request_mbuf.serviceuserlen= strlen(serviceuser);
   request_mbuf.servicelen= strlen(argv[0]);
-  request_mbuf.lognamelen= strlen(logname);
+  request_mbuf.loginnamelen= strlen(loginname);
+  request_mbuf.spoofed= spoofuser ? 1 : 0;
   request_mbuf.cwdlen= cwdbufsize;
   request_mbuf.callinguid= spoofuid;
   request_mbuf.ngids= ngids+1;
@@ -1064,7 +1071,7 @@ static void server_sendrequest(int argc, char *const *argv) {
   xfwrite(&request_mbuf,sizeof(request_mbuf),swfile);
   xfwrite(serviceuser,sizeof(*serviceuser)*request_mbuf.serviceuserlen,swfile);
   xfwrite(argv[0],sizeof(*argv[0])*request_mbuf.servicelen,swfile);
-  xfwrite(logname,sizeof(*logname)*request_mbuf.lognamelen,swfile);
+  xfwrite(loginname,sizeof(*loginname)*request_mbuf.loginnamelen,swfile);
   xfwrite(cwdbuf,sizeof(*cwdbuf)*request_mbuf.cwdlen,swfile);
   if (ovused>=0) xfwrite(ovbuf,sizeof(*ovbuf)*ovused,swfile);
   xfwrite(&spoofgid,sizeof(gid_t),swfile);
@@ -1127,6 +1134,7 @@ static void connect_pipes(void) {
   struct sigaction sig;
   char catnamebuf[sizeof(int)*3+30];
   int fd, reading;
+  pid_t child;
   
   for (fd=0; fd<fdsetupsize; fd++) {
     if (!fdsetup[fd].filename) continue;
@@ -1136,9 +1144,12 @@ static void connect_pipes(void) {
       if (fdsetup[fd].copyfd<0)
        syscallerror("open file `%s' for fd %d",fdsetup[fd].filename,fd);
     }
-    fdsetup[fd].catpid= fork();
-    if (fdsetup[fd].catpid==-1) syscallerror("fork for cat for fd %d",fd);
-    if (!fdsetup[fd].catpid) {
+    blocksignals(SIG_BLOCK);
+    child= fork();
+    fdsetup[fd].catpid= child;
+    blocksignals(SIG_UNBLOCK);
+    if (child==-1) syscallerror("fork for cat for fd %d",fd);
+    if (!child) {
       snprintf(catnamebuf,sizeof(catnamebuf),"cat fd%d",fd);
       catnamebuf[sizeof(catnamebuf)-1]= 0;
       sig.sa_handler= SIG_DFL;