chiark / gitweb /
Fixed spurious failure with Interrupted system call; Fixed race when fd closed at...
[userv.git] / client.c
index 4fbb710..4987073 100644 (file)
--- a/client.c
+++ b/client.c
@@ -72,6 +72,7 @@
 
 #include "config.h"
 #include "common.h"
+#include "both.h"
 #include "version.h"
 
 enum fdmodifiervalues {
@@ -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);
       }
@@ -370,6 +372,7 @@ static void sighandler_chld(int ignored) /* DOES return, unlike in daemon */ {
     if (child == 0 || (child == -1 && errno == ECHILD)) break;
     if (child == -1) syscallerror("wait for child process (in sigchld handler)");
     for (fd=0; fd<fdsetupsize && fdsetup[fd].catpid != child; fd++);
+fprintf(stderr,"chld found pid=%ld fd=%d setupsize=%d\n",(long)child,fd,fdsetupsize);
     if (fd>=fdsetupsize) continue; /* perhaps the caller gave us children */
     if ((WIFEXITED(status) && WEXITSTATUS(status)==0) ||
        (WIFSIGNALED(status) && WTERMSIG(status)==SIGPIPE) ||
@@ -378,6 +381,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");
@@ -434,7 +438,7 @@ static void usage(void) {
     "         --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"
+    "userv and uservd version " VERSION VEREXT "; copyright (C)1996-1997 Ian Jackson.\n"
     "there is NO WARRANTY; type `userv --copyright' for details.\n",
             stderr) < 0)
     syscallerror("write usage to stderr");
@@ -737,13 +741,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 {
@@ -1047,6 +1052,7 @@ static void server_sendrequest(int argc, char *const *argv) {
   request_mbuf.serviceuserlen= strlen(serviceuser);
   request_mbuf.servicelen= strlen(argv[0]);
   request_mbuf.lognamelen= strlen(logname);
+  request_mbuf.spoofed= spoofuser ? 1 : 0;
   request_mbuf.cwdlen= cwdbufsize;
   request_mbuf.callinguid= spoofuid;
   request_mbuf.ngids= ngids+1;
@@ -1127,6 +1133,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 +1143,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;