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
);