2 * Unix SMB/CIFS implementation.
3 * Samba system utilities
4 * Copyright (C) Jeremy Allison 2000
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "system/wait.h"
22 #include "system/filesys.h"
24 #include "lib/util/sys_popen.h"
25 #include "lib/util/debug.h"
27 /**************************************************************************
28 Wrapper for popen. Safer as it doesn't search a path.
29 Modified from the glibc sources.
30 modified by tridge to return a file descriptor. We must kick our FILE* habit
31 ****************************************************************************/
33 typedef struct _popen_list
37 struct _popen_list *next;
40 static popen_list *popen_chain;
42 int sys_popenv(char * const argl[])
44 int parent_end, child_end;
46 popen_list *entry = NULL;
47 const char *command = NULL;
63 DBG_ERR("error opening pipe: %s\n",
68 parent_end = pipe_fds[0];
69 child_end = pipe_fds[1];
71 entry = talloc_zero(NULL, popen_list);
73 DBG_ERR("talloc failed\n");
77 entry->child_pid = fork();
79 if (entry->child_pid == -1) {
80 DBG_ERR("fork failed: %s\n", strerror(errno));
84 if (entry->child_pid == 0) {
90 int child_std_end = STDOUT_FILENO;
94 if (child_end != child_std_end) {
95 dup2 (child_end, child_std_end);
100 * POSIX.2: "popen() shall ensure that any streams from previous
101 * popen() calls that remain open in the parent process are closed
102 * in the new child process."
105 for (p = popen_chain; p; p = p->next)
108 ret = execv(argl[0], argl);
110 DBG_ERR("ERROR executing command "
111 "'%s': %s\n", command, strerror(errno));
122 /* Link into popen_chain. */
123 entry->next = popen_chain;
125 entry->fd = parent_end;
137 /**************************************************************************
138 Wrapper for pclose. Modified from the glibc sources.
139 ****************************************************************************/
141 int sys_pclose(int fd)
144 popen_list **ptr = &popen_chain;
145 popen_list *entry = NULL;
149 /* Unlink from popen_chain. */
150 for ( ; *ptr != NULL; ptr = &(*ptr)->next) {
151 if ((*ptr)->fd == fd) {
159 if (status < 0 || close(entry->fd) < 0)
163 * As Samba is catching and eating child process
164 * exits we don't really care about the child exit
165 * code, a -1 with errno = ECHILD will do fine for us.
169 wait_pid = waitpid (entry->child_pid, &wstatus, 0);
170 } while (wait_pid == -1 && errno == EINTR);