[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Cvs-cvs] Changes to ccvs/src/run.c [cvs1-11-x-branch]
From: |
Derek Robert Price |
Subject: |
[Cvs-cvs] Changes to ccvs/src/run.c [cvs1-11-x-branch] |
Date: |
Thu, 29 Sep 2005 14:32:14 -0400 |
Index: ccvs/src/run.c
diff -u ccvs/src/run.c:1.33.6.6 ccvs/src/run.c:1.33.6.7
--- ccvs/src/run.c:1.33.6.6 Mon Jun 6 21:32:50 2005
+++ ccvs/src/run.c Thu Sep 29 18:32:08 2005
@@ -417,11 +417,107 @@
return (popen (cmd, mode));
}
+
+
+/* Work around an OpenSSH problem: it can put its standard file
+ descriptors into nonblocking mode, which will mess us up if we
+ share file descriptions with it. The simplest workaround is
+ to create an intervening process between OpenSSH and the
+ actual stderr. */
+
+static void
+work_around_openssh_glitch (void)
+{
+ pid_t pid;
+ int stderr_pipe[2];
+ struct stat sb;
+
+ /* Do nothing unless stderr is a file that is affected by
+ nonblocking mode. */
+ if (!(fstat (STDERR_FILENO, &sb) == 0
+ && (S_ISFIFO (sb.st_mode) || S_ISSOCK (sb.st_mode)
+ || S_ISCHR (sb.st_mode) || S_ISBLK (sb.st_mode))))
+ return;
+
+ if (pipe (stderr_pipe) < 0)
+ error (1, errno, "cannot create pipe");
+ pid = fork ();
+ if (pid < 0)
+ error (1, errno, "cannot fork");
+ if (pid != 0)
+ {
+ /* Still in child of original process. Act like "cat -u". */
+ char buf[1 << 13];
+ ssize_t inbytes;
+ pid_t w;
+ int status;
+
+ if (close (stderr_pipe[1]) < 0)
+ error (1, errno, "cannot close pipe");
+
+ while ((inbytes = read (stderr_pipe[0], buf, sizeof buf)) != 0)
+ {
+ size_t outbytes = 0;
+
+ if (inbytes < 0)
+ {
+ if (errno == EINTR)
+ continue;
+ error (1, errno, "reading from pipe");
+ }
+
+ do
+ {
+ ssize_t w = write (STDERR_FILENO,
+ buf + outbytes, inbytes - outbytes);
+ if (w < 0)
+ {
+ if (errno == EINTR)
+ w = 0;
+ if (w < 0)
+ _exit (1);
+ }
+ outbytes += w;
+ }
+ while (inbytes != outbytes);
+ }
+
+ /* Done processing output from grandchild. Propagate
+ its exit status back to the parent. */
+ while ((w = waitpid (pid, &status, 0)) == -1 && errno == EINTR)
+ continue;
+ if (w < 0)
+ error (1, errno, "waiting for child");
+ if (!WIFEXITED (status))
+ {
+ if (WIFSIGNALED (status))
+ raise (WTERMSIG (status));
+ error (1, errno, "child did not exit cleanly");
+ }
+ _exit (WEXITSTATUS (status));
+ }
+
+ /* Grandchild of original process. */
+ if (close (stderr_pipe[0]) < 0)
+ error (1, errno, "cannot close pipe");
+
+ if (stderr_pipe[1] != STDERR_FILENO)
+ {
+ if (dup2 (stderr_pipe[1], STDERR_FILENO) < 0)
+ error (1, errno, "cannot dup2 pipe");
+ if (close (stderr_pipe[1]) < 0)
+ error (1, errno, "cannot close pipe");
+ }
+}
+
+
+
int
-piped_child (command, tofdp, fromfdp)
+piped_child (command, tofdp, fromfdp, fix_stderr)
const char **command;
int *tofdp;
int *fromfdp;
+ int fix_stderr;
{
int pid;
int to_child_pipe[2];
@@ -439,11 +535,7 @@
setmode (from_child_pipe[1], O_BINARY);
#endif
-#ifdef HAVE_VFORK
- pid = vfork ();
-#else
pid = fork ();
-#endif
if (pid < 0)
error (1, errno, "cannot fork");
if (pid == 0)
@@ -457,7 +549,10 @@
if (dup2 (from_child_pipe[1], STDOUT_FILENO) < 0)
error (1, errno, "cannot dup2 pipe");
- /* Okay to cast out const below - execvp don't return anyhow. */
+ if (fix_stderr)
+ work_around_openssh_glitch ();
+
+ /* Okay to cast out const below - execvp don't return nohow. */
execvp ((char *)command[0], (char **)command);
error (1, errno, "cannot exec %s", command[0]);
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Cvs-cvs] Changes to ccvs/src/run.c [cvs1-11-x-branch],
Derek Robert Price <=