Re: [REQUEST FOR VOTES] snmpd: Drop support for pass_persist on uClinux

Bart Van Assche <[email protected]>
Newsgroups gmane.network.net-snmp.devel
Message-ID <[email protected]>
On 2020-08-16 15:58, Wes Hardaker wrote:
> Magnus Fromreide <[email protected]> writes:
> 
>> That is a more lenient option than just dropping it so I think 'happy with
>> dropping it' covers this variant. On the other hand I usually am far from
>> the most conservative one in discussions like  this one.
> 
> I think off by default makes a lot more sense than an out-right removal.

How about restoring uClinux support with the patch below? parse_cmd() and
dup() are called before fork(). That change makes it possible to use a
regular pipe between the parent and the child, even when using vfork(). The
patch below has been tested on Linux (but not on uClinux).

Thanks,

Bart.


diff --git a/agent/mibgroup/util_funcs.c b/agent/mibgroup/util_funcs.c
index f39ea1adcd89..d42277b18f7e 100644
--- a/agent/mibgroup/util_funcs.c
+++ b/agent/mibgroup/util_funcs.c
@@ -458,53 +458,60 @@ int
 get_exec_pipes(const char *cmd, int *fdIn, int *fdOut, netsnmp_pid_t *pid)
 {
 #if defined(HAVE_EXECV)
-    int             fd[2][2];
+    int             fd[2][2], stdin_fd, stdout_fd, stderr_fd;
     char           **argv, *args;

+    argv = parse_cmd(&args, cmd);
+    if (!argv) {
+        DEBUGMSGTL(("util_funcs", "get_exec_pipes(): argv == NULL\n"));
+        return 0;
+    }
     /*
-     * Setup our pipes
+     * Setup pipes
      */
     if (pipe(fd[0]) || pipe(fd[1])) {
         setPerrorstatus("pipe");
         return 0;
     }
-    if ((*pid = fork()) == 0) { /* First handle for the child */
-        close(fd[0][1]);
-        close(fd[1][0]);
-        close(0);
-        if (dup(fd[0][0]) != 0) {
-            setPerrorstatus("dup 0");
-            return 0;
-        }
-        close(fd[0][0]);
-        close(1);
-        if (dup(fd[1][1]) != 1) {
-            setPerrorstatus("dup 1");
-            return 0;
-        }
-        close(fd[1][1]);
-
-        /*
-         * write standard output and standard error to pipe.
-         */
+    /* Save stdin, stdout and stderr */
+    stdin_fd = dup(STDIN_FILENO);
+    stdout_fd = dup(STDOUT_FILENO);
+    stderr_fd = dup(STDERR_FILENO);
+    /* Redirect stdin, stdout and stderr to the child side of the pipe */
+    if (dup2(fd[0][0], STDIN_FILENO) != 0) {
+        setPerrorstatus("dup 0");
+        return 0;
+    }
+    if (dup2(fd[1][1], STDOUT_FILENO) != 1) {
+        setPerrorstatus("dup 1");
+        return 0;
+    }
+    NETSNMP_IGNORE_RESULT(dup2(STDOUT_FILENO, STDERR_FILENO));
+#ifdef __uClinux__
+    if ((*pid = vfork()) == 0) {
+#else
+    if ((*pid = fork()) == 0) {
         /*
          * close all non-standard open file descriptors
          */
-        netsnmp_close_fds(1);
-        NETSNMP_IGNORE_RESULT(dup(1));  /* stderr */
+        netsnmp_close_fds(STDOUT_FILENO);
+#endif

-        argv = parse_cmd(&args, cmd);
-        if (!argv) {
-            DEBUGMSGTL(("util_funcs", "get_exec_pipes(): argv == NULL\n"));
-            return 0;
-        }
-        DEBUGMSGTL(("util_funcs", "get_exec_pipes(): argv[0] = %s\n", argv[0]));
+        /* Child process */
         execv(argv[0], argv);
         perror(argv[0]);
         free(argv);
         free(args);
-        exit(1);
+        return 1;
     } else {
+        /* Parent process. */
+        /* Restore stdin, stdout and stderr */
+        dup2(stdin_fd, STDIN_FILENO);
+        close(stdin_fd);
+        dup2(stdout_fd, STDOUT_FILENO);
+        close(stdout_fd);
+        dup2(stderr_fd, STDERR_FILENO);
+        close(stderr_fd);
         close(fd[0][0]);
         close(fd[1][1]);
         if (*pid < 0) {
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.