[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Cvs-cvs] Changes to ccvs/src/run.c
From: |
Derek Robert Price |
Subject: |
[Cvs-cvs] Changes to ccvs/src/run.c |
Date: |
Thu, 29 Sep 2005 16:20:38 -0400 |
Index: ccvs/src/run.c
diff -u ccvs/src/run.c:1.58 ccvs/src/run.c:1.59
--- ccvs/src/run.c:1.58 Fri May 27 18:07:48 2005
+++ ccvs/src/run.c Thu Sep 29 20:20:34 2005
@@ -444,8 +444,101 @@
+/* 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 (char *const *command, int *tofdp, int *fromfdp)
+piped_child (char *const *command, int *tofdp, int *fromfdp, bool fix_stderr)
{
int pid;
int to_child_pipe[2];
@@ -463,11 +556,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)
@@ -481,7 +570,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]);
}
@@ -501,7 +593,7 @@
run_piped (int *tofdp, int *fromfdp)
{
run_add_arg (NULL);
- return piped_child (run_argv, tofdp, fromfdp);
+ return piped_child (run_argv, tofdp, fromfdp, false);
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Cvs-cvs] Changes to ccvs/src/run.c,
Derek Robert Price <=