lib: Fix CID 1306765 Unchecked return value from library
[samba.git] / lib / util / util_runcmd.c
index 8a475ef301d01dad1feb54c4bb6c518e3b00d106..f18e37bcb2d46839c41cf590a03113504e9a6e88 100644 (file)
@@ -33,7 +33,6 @@
 struct samba_runcmd_state {
        int stdout_log_level;
        int stderr_log_level;
-       struct tevent_fd *fde_stdin;
        struct tevent_fd *fde_stdout;
        struct tevent_fd *fde_stderr;
        int fd_stdin, fd_stdout, fd_stderr;
@@ -50,6 +49,10 @@ static int samba_runcmd_state_destructor(struct samba_runcmd_state *state)
                waitpid(state->pid, NULL, 0);
                state->pid = -1;
        }
+
+       if (state->fd_stdin != -1) {
+               close(state->fd_stdin);
+       }
        return 0;
 }
 
@@ -77,6 +80,10 @@ struct tevent_req *samba_runcmd_send(TALLOC_CTX *mem_ctx,
        char **argv;
        va_list ap;
 
+       if (argv0 == NULL) {
+               return NULL;
+       }
+
        req = tevent_req_create(mem_ctx, &state,
                                struct samba_runcmd_state);
        if (req == NULL) {
@@ -85,6 +92,7 @@ struct tevent_req *samba_runcmd_send(TALLOC_CTX *mem_ctx,
 
        state->stdout_log_level = stdout_log_level;
        state->stderr_log_level = stderr_log_level;
+       state->fd_stdin = -1;
 
        state->arg0 = talloc_strdup(state, argv0[0]);
        if (tevent_req_nomem(state->arg0, req)) {
@@ -135,6 +143,10 @@ struct tevent_req *samba_runcmd_send(TALLOC_CTX *mem_ctx,
                set_blocking(state->fd_stderr, false);
                set_blocking(state->fd_stdin,  false);
 
+               smb_set_close_on_exec(state->fd_stdin);
+               smb_set_close_on_exec(state->fd_stdout);
+               smb_set_close_on_exec(state->fd_stderr);
+
                talloc_set_destructor(state, samba_runcmd_state_destructor);
 
                state->fde_stdout = tevent_add_fd(ev, state,
@@ -145,7 +157,6 @@ struct tevent_req *samba_runcmd_send(TALLOC_CTX *mem_ctx,
                if (tevent_req_nomem(state->fde_stdout, req)) {
                        close(state->fd_stdout);
                        close(state->fd_stderr);
-                       close(state->fd_stdin);
                        return tevent_req_post(req, ev);
                }
                tevent_fd_set_auto_close(state->fde_stdout);
@@ -157,22 +168,10 @@ struct tevent_req *samba_runcmd_send(TALLOC_CTX *mem_ctx,
                                                  req);
                if (tevent_req_nomem(state->fde_stdout, req)) {
                        close(state->fd_stderr);
-                       close(state->fd_stdin);
                        return tevent_req_post(req, ev);
                }
                tevent_fd_set_auto_close(state->fde_stderr);
 
-               state->fde_stdin = tevent_add_fd(ev, state,
-                                                state->fd_stdin,
-                                                0,
-                                                samba_runcmd_io_handler,
-                                                req);
-               if (tevent_req_nomem(state->fde_stdin, req)) {
-                       close(state->fd_stdin);
-                       return tevent_req_post(req, ev);
-               }
-               tevent_fd_set_auto_close(state->fde_stdin);
-
                if (!timeval_is_zero(&endtime)) {
                        tevent_req_set_endtime(req, ev, endtime);
                }
@@ -197,6 +196,10 @@ struct tevent_req *samba_runcmd_send(TALLOC_CTX *mem_ctx,
        dup2(p1[1], 1);
        dup2(p2[1], 2);
 
+       close(p1[1]);
+       close(p2[1]);
+       close(p3[0]);
+
        argv = str_list_copy(state, discard_const_p(const char *, argv0));
        if (!argv) {
                fprintf(stderr, "Out of memory in child\n");
@@ -205,13 +208,16 @@ struct tevent_req *samba_runcmd_send(TALLOC_CTX *mem_ctx,
 
        va_start(ap, argv0);
        while (1) {
+               const char **l;
                char *arg = va_arg(ap, char *);
                if (arg == NULL) break;
-               argv = discard_const_p(char *, str_list_add((const char **)argv, arg));
-               if (!argv) {
+               l = discard_const_p(const char *, argv);
+               l = str_list_add(l, arg);
+               if (l == NULL) {
                        fprintf(stderr, "Out of memory in child\n");
                        _exit(255);
                }
+               argv = discard_const_p(char *, l);
        }
        va_end(ap);
 
@@ -243,14 +249,6 @@ static void samba_runcmd_io_handler(struct tevent_context *ev,
        } else if (fde == state->fde_stderr) {
                level = state->stderr_log_level;
                fd = state->fd_stderr;
-       } else if (fde == state->fde_stdin) {
-               char c;
-               if (read(state->fd_stdin, &c, 1) != 1) {
-                       /* the child has closed its stdin */
-                       talloc_free(fde);
-                       state->fde_stdin = NULL;
-                       return;
-               }
        } else {
                return;
        }
@@ -290,7 +288,11 @@ static void samba_runcmd_io_handler(struct tevent_context *ev,
                                           SIGCHLD in the standard
                                           process model.
                                        */
-                                       tevent_req_done(req);
+                                       DEBUG(0, ("Error in waitpid() unexpectedly got ECHILD "
+                                                 "for %s child %d - %s, "
+                                                 "someone has set SIGCHLD to SIG_IGN!\n",
+                                       state->arg0, (int)state->pid, strerror(errno)));
+                                       tevent_req_error(req, errno);
                                        return;
                                }
                                DEBUG(0,("Error in waitpid() for child %s - %s \n",