/[cvs]/ccvs/src/run.c
ViewVC logotype

Diff of /ccvs/src/run.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.58 by dprice, Fri May 27 18:07:48 2005 UTC revision 1.59 by dprice, Thu Sep 29 20:20:34 2005 UTC
# Line 444  run_popen (const char *cmd, const char * Line 444  run_popen (const char *cmd, const char *
444    
445    
446    
447    /* Work around an OpenSSH problem: it can put its standard file
448       descriptors into nonblocking mode, which will mess us up if we
449       share file descriptions with it.  The simplest workaround is
450       to create an intervening process between OpenSSH and the
451       actual stderr.  */
452    
453    static void
454    work_around_openssh_glitch (void)
455    {
456        pid_t pid;
457        int stderr_pipe[2];
458        struct stat sb;
459    
460        /* Do nothing unless stderr is a file that is affected by
461           nonblocking mode.  */
462        if (!(fstat (STDERR_FILENO, &sb) == 0
463              && (S_ISFIFO (sb.st_mode) || S_ISSOCK (sb.st_mode)
464                  || S_ISCHR (sb.st_mode) || S_ISBLK (sb.st_mode))))
465           return;
466    
467        if (pipe (stderr_pipe) < 0)
468           error (1, errno, "cannot create pipe");
469        pid = fork ();
470        if (pid < 0)
471           error (1, errno, "cannot fork");
472        if (pid != 0)
473        {
474           /* Still in child of original process.  Act like "cat -u".  */
475           char buf[1 << 13];
476           ssize_t inbytes;
477           pid_t w;
478           int status;
479    
480           if (close (stderr_pipe[1]) < 0)
481               error (1, errno, "cannot close pipe");
482    
483           while ((inbytes = read (stderr_pipe[0], buf, sizeof buf)) != 0)
484           {
485               size_t outbytes = 0;
486    
487               if (inbytes < 0)
488               {
489                   if (errno == EINTR)
490                       continue;
491                   error (1, errno, "reading from pipe");
492               }
493    
494               do
495               {
496                   ssize_t w = write (STDERR_FILENO,
497                                      buf + outbytes, inbytes - outbytes);
498                   if (w < 0)
499                   {
500                       if (errno == EINTR)
501                         w = 0;
502                       if (w < 0)
503                         _exit (1);
504                   }
505                   outbytes += w;
506               }
507               while (inbytes != outbytes);
508           }
509    
510           /* Done processing output from grandchild.  Propagate
511              its exit status back to the parent.  */
512           while ((w = waitpid (pid, &status, 0)) == -1 && errno == EINTR)
513               continue;
514           if (w < 0)
515               error (1, errno, "waiting for child");
516           if (!WIFEXITED (status))
517           {
518               if (WIFSIGNALED (status))
519                   raise (WTERMSIG (status));
520               error (1, errno, "child did not exit cleanly");
521           }
522           _exit (WEXITSTATUS (status));
523        }
524    
525        /* Grandchild of original process.  */
526        if (close (stderr_pipe[0]) < 0)
527           error (1, errno, "cannot close pipe");
528    
529        if (stderr_pipe[1] != STDERR_FILENO)
530        {
531           if (dup2 (stderr_pipe[1], STDERR_FILENO) < 0)
532               error (1, errno, "cannot dup2 pipe");
533           if (close (stderr_pipe[1]) < 0)
534               error (1, errno, "cannot close pipe");
535        }
536    }
537    
538    
539    
540  int  int
541  piped_child (char *const *command, int *tofdp, int *fromfdp)  piped_child (char *const *command, int *tofdp, int *fromfdp, bool fix_stderr)
542  {  {
543      int pid;      int pid;
544      int to_child_pipe[2];      int to_child_pipe[2];
# Line 463  piped_child (char *const *command, int * Line 556  piped_child (char *const *command, int *
556      setmode (from_child_pipe[1], O_BINARY);      setmode (from_child_pipe[1], O_BINARY);
557  #endif  #endif
558    
 #ifdef HAVE_VFORK  
     pid = vfork ();  
 #else  
559      pid = fork ();      pid = fork ();
 #endif  
560      if (pid < 0)      if (pid < 0)
561          error (1, errno, "cannot fork");          error (1, errno, "cannot fork");
562      if (pid == 0)      if (pid == 0)
# Line 481  piped_child (char *const *command, int * Line 570  piped_child (char *const *command, int *
570          if (dup2 (from_child_pipe[1], STDOUT_FILENO) < 0)          if (dup2 (from_child_pipe[1], STDOUT_FILENO) < 0)
571              error (1, errno, "cannot dup2 pipe");              error (1, errno, "cannot dup2 pipe");
572    
573          /* Okay to cast out const below - execvp don't return anyhow.  */          if (fix_stderr)
574                work_around_openssh_glitch ();
575    
576            /* Okay to cast out const below - execvp don't return nohow.  */
577          execvp ((char *)command[0], (char **)command);          execvp ((char *)command[0], (char **)command);
578          error (1, errno, "cannot exec %s", command[0]);          error (1, errno, "cannot exec %s", command[0]);
579      }      }
# Line 501  int Line 593  int
593  run_piped (int *tofdp, int *fromfdp)  run_piped (int *tofdp, int *fromfdp)
594  {  {
595      run_add_arg (NULL);      run_add_arg (NULL);
596      return piped_child (run_argv, tofdp, fromfdp);      return piped_child (run_argv, tofdp, fromfdp, false);
597  }  }
598    
599    

Legend:
Removed from v.1.58  
changed lines
  Added in v.1.59

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26