1*76404edcSAsim Jamshed #include "proc_open.h"
2*76404edcSAsim Jamshed
3*76404edcSAsim Jamshed #include <stdlib.h>
4*76404edcSAsim Jamshed #include <stdio.h>
5*76404edcSAsim Jamshed #include <ctype.h>
6*76404edcSAsim Jamshed #include <string.h>
7*76404edcSAsim Jamshed #include <errno.h>
8*76404edcSAsim Jamshed
9*76404edcSAsim Jamshed #ifdef WIN32
10*76404edcSAsim Jamshed # include <io.h>
11*76404edcSAsim Jamshed # include <fcntl.h>
12*76404edcSAsim Jamshed #else
13*76404edcSAsim Jamshed # include <sys/wait.h>
14*76404edcSAsim Jamshed # include <unistd.h>
15*76404edcSAsim Jamshed #endif
16*76404edcSAsim Jamshed
17*76404edcSAsim Jamshed
18*76404edcSAsim Jamshed #ifdef WIN32
19*76404edcSAsim Jamshed /* {{{ win32 stuff */
20*76404edcSAsim Jamshed # define SHELLENV "ComSpec"
21*76404edcSAsim Jamshed # define SECURITY_DC , SECURITY_ATTRIBUTES *security
22*76404edcSAsim Jamshed # define SECURITY_CC , security
23*76404edcSAsim Jamshed # define pipe(pair) (CreatePipe(&pair[0], &pair[1], security, 2048L) ? 0 : -1)
dup_handle(HANDLE src,BOOL inherit,BOOL closeorig)24*76404edcSAsim Jamshed static inline HANDLE dup_handle(HANDLE src, BOOL inherit, BOOL closeorig)
25*76404edcSAsim Jamshed {
26*76404edcSAsim Jamshed HANDLE copy, self = GetCurrentProcess();
27*76404edcSAsim Jamshed
28*76404edcSAsim Jamshed if (!DuplicateHandle(self, src, self, ©, 0, inherit, DUPLICATE_SAME_ACCESS |
29*76404edcSAsim Jamshed (closeorig ? DUPLICATE_CLOSE_SOURCE : 0)))
30*76404edcSAsim Jamshed return NULL;
31*76404edcSAsim Jamshed return copy;
32*76404edcSAsim Jamshed }
33*76404edcSAsim Jamshed # define close_descriptor(fd) CloseHandle(fd)
pipe_close_parent(pipe_t * p)34*76404edcSAsim Jamshed static void pipe_close_parent(pipe_t *p) {
35*76404edcSAsim Jamshed /* don't let the child inherit the parent side of the pipe */
36*76404edcSAsim Jamshed p->parent = dup_handle(p->parent, FALSE, TRUE);
37*76404edcSAsim Jamshed }
pipe_close_child(pipe_t * p)38*76404edcSAsim Jamshed static void pipe_close_child(pipe_t *p) {
39*76404edcSAsim Jamshed close_descriptor(p->child);
40*76404edcSAsim Jamshed p->fd = _open_osfhandle((long)p->parent,
41*76404edcSAsim Jamshed (p->fd == 0 ? O_RDONLY : O_WRONLY)|O_BINARY);
42*76404edcSAsim Jamshed }
43*76404edcSAsim Jamshed /* }}} */
44*76404edcSAsim Jamshed #else /* WIN32 */
45*76404edcSAsim Jamshed /* {{{ unix way */
46*76404edcSAsim Jamshed # define SHELLENV "SHELL"
47*76404edcSAsim Jamshed # define SECURITY_DC
48*76404edcSAsim Jamshed # define SECURITY_CC
49*76404edcSAsim Jamshed # define close_descriptor(fd) close(fd)
pipe_close_parent(pipe_t * p)50*76404edcSAsim Jamshed static void pipe_close_parent(pipe_t *p) {
51*76404edcSAsim Jamshed /* don't close stdin */
52*76404edcSAsim Jamshed close_descriptor(p->parent);
53*76404edcSAsim Jamshed if (dup2(p->child, p->fd) != p->fd) {
54*76404edcSAsim Jamshed perror("pipe_child dup2");
55*76404edcSAsim Jamshed } else {
56*76404edcSAsim Jamshed close_descriptor(p->child);
57*76404edcSAsim Jamshed p->child = p->fd;
58*76404edcSAsim Jamshed }
59*76404edcSAsim Jamshed }
pipe_close_child(pipe_t * p)60*76404edcSAsim Jamshed static void pipe_close_child(pipe_t *p) {
61*76404edcSAsim Jamshed close_descriptor(p->child);
62*76404edcSAsim Jamshed p->fd = p->parent;
63*76404edcSAsim Jamshed }
64*76404edcSAsim Jamshed /* }}} */
65*76404edcSAsim Jamshed #endif /* WIN32 */
66*76404edcSAsim Jamshed
67*76404edcSAsim Jamshed /* {{{ pipe_close */
pipe_close(pipe_t * p)68*76404edcSAsim Jamshed static void pipe_close(pipe_t *p) {
69*76404edcSAsim Jamshed close_descriptor(p->parent);
70*76404edcSAsim Jamshed close_descriptor(p->child);
71*76404edcSAsim Jamshed #ifdef WIN32
72*76404edcSAsim Jamshed close(p->fd);
73*76404edcSAsim Jamshed #endif
74*76404edcSAsim Jamshed }
75*76404edcSAsim Jamshed /* }}} */
76*76404edcSAsim Jamshed /* {{{ pipe_open */
pipe_open(pipe_t * p,int fd SECURITY_DC)77*76404edcSAsim Jamshed static int pipe_open(pipe_t *p, int fd SECURITY_DC) {
78*76404edcSAsim Jamshed descriptor_t newpipe[2];
79*76404edcSAsim Jamshed
80*76404edcSAsim Jamshed if (0 != pipe(newpipe)) {
81*76404edcSAsim Jamshed fprintf(stderr, "can't open pipe");
82*76404edcSAsim Jamshed return -1;
83*76404edcSAsim Jamshed }
84*76404edcSAsim Jamshed if (0 == fd) {
85*76404edcSAsim Jamshed p->parent = newpipe[1]; /* write */
86*76404edcSAsim Jamshed p->child = newpipe[0]; /* read */
87*76404edcSAsim Jamshed } else {
88*76404edcSAsim Jamshed p->parent = newpipe[0]; /* read */
89*76404edcSAsim Jamshed p->child = newpipe[1]; /* write */
90*76404edcSAsim Jamshed }
91*76404edcSAsim Jamshed p->fd = fd;
92*76404edcSAsim Jamshed
93*76404edcSAsim Jamshed return 0;
94*76404edcSAsim Jamshed }
95*76404edcSAsim Jamshed /* }}} */
96*76404edcSAsim Jamshed
97*76404edcSAsim Jamshed /* {{{ proc_open_pipes */
proc_open_pipes(proc_handler_t * proc SECURITY_DC)98*76404edcSAsim Jamshed static int proc_open_pipes(proc_handler_t *proc SECURITY_DC) {
99*76404edcSAsim Jamshed if (pipe_open(&(proc->in), 0 SECURITY_CC) != 0) {
100*76404edcSAsim Jamshed return -1;
101*76404edcSAsim Jamshed }
102*76404edcSAsim Jamshed if (pipe_open(&(proc->out), 1 SECURITY_CC) != 0) {
103*76404edcSAsim Jamshed return -1;
104*76404edcSAsim Jamshed }
105*76404edcSAsim Jamshed if (pipe_open(&(proc->err), 2 SECURITY_CC) != 0) {
106*76404edcSAsim Jamshed return -1;
107*76404edcSAsim Jamshed }
108*76404edcSAsim Jamshed return 0;
109*76404edcSAsim Jamshed }
110*76404edcSAsim Jamshed /* }}} */
111*76404edcSAsim Jamshed /* {{{ proc_close_pipes */
proc_close_pipes(proc_handler_t * proc)112*76404edcSAsim Jamshed static void proc_close_pipes(proc_handler_t *proc) {
113*76404edcSAsim Jamshed pipe_close(&proc->in);
114*76404edcSAsim Jamshed pipe_close(&proc->out);
115*76404edcSAsim Jamshed pipe_close(&proc->err);
116*76404edcSAsim Jamshed }
117*76404edcSAsim Jamshed /* }}} */
118*76404edcSAsim Jamshed /* {{{ proc_close_parents */
proc_close_parents(proc_handler_t * proc)119*76404edcSAsim Jamshed static void proc_close_parents(proc_handler_t *proc) {
120*76404edcSAsim Jamshed pipe_close_parent(&proc->in);
121*76404edcSAsim Jamshed pipe_close_parent(&proc->out);
122*76404edcSAsim Jamshed pipe_close_parent(&proc->err);
123*76404edcSAsim Jamshed }
124*76404edcSAsim Jamshed /* }}} */
125*76404edcSAsim Jamshed /* {{{ proc_close_childs */
proc_close_childs(proc_handler_t * proc)126*76404edcSAsim Jamshed static void proc_close_childs(proc_handler_t *proc) {
127*76404edcSAsim Jamshed pipe_close_child(&proc->in);
128*76404edcSAsim Jamshed pipe_close_child(&proc->out);
129*76404edcSAsim Jamshed pipe_close_child(&proc->err);
130*76404edcSAsim Jamshed }
131*76404edcSAsim Jamshed /* }}} */
132*76404edcSAsim Jamshed
133*76404edcSAsim Jamshed #ifdef WIN32
134*76404edcSAsim Jamshed /* {{{ proc_close */
proc_close(proc_handler_t * proc)135*76404edcSAsim Jamshed int proc_close(proc_handler_t *proc) {
136*76404edcSAsim Jamshed proc_pid_t child = proc->child;
137*76404edcSAsim Jamshed DWORD wstatus;
138*76404edcSAsim Jamshed
139*76404edcSAsim Jamshed proc_close_pipes(proc);
140*76404edcSAsim Jamshed WaitForSingleObject(child, INFINITE);
141*76404edcSAsim Jamshed GetExitCodeProcess(child, &wstatus);
142*76404edcSAsim Jamshed CloseHandle(child);
143*76404edcSAsim Jamshed
144*76404edcSAsim Jamshed return wstatus;
145*76404edcSAsim Jamshed }
146*76404edcSAsim Jamshed /* }}} */
147*76404edcSAsim Jamshed /* {{{ proc_open */
proc_open(proc_handler_t * proc,const char * command)148*76404edcSAsim Jamshed int proc_open(proc_handler_t *proc, const char *command) {
149*76404edcSAsim Jamshed PROCESS_INFORMATION pi;
150*76404edcSAsim Jamshed STARTUPINFO si;
151*76404edcSAsim Jamshed BOOL procok;
152*76404edcSAsim Jamshed SECURITY_ATTRIBUTES security;
153*76404edcSAsim Jamshed const char *shell = NULL;
154*76404edcSAsim Jamshed const char *windir = NULL;
155*76404edcSAsim Jamshed buffer *cmdline;
156*76404edcSAsim Jamshed
157*76404edcSAsim Jamshed if (NULL == (shell = getenv(SHELLENV)) &&
158*76404edcSAsim Jamshed NULL == (windir = getenv("SystemRoot")) &&
159*76404edcSAsim Jamshed NULL == (windir = getenv("windir"))) {
160*76404edcSAsim Jamshed fprintf(stderr, "One of %s,%%SystemRoot,%%windir is required", SHELLENV);
161*76404edcSAsim Jamshed return -1;
162*76404edcSAsim Jamshed }
163*76404edcSAsim Jamshed
164*76404edcSAsim Jamshed /* we use this to allow the child to inherit handles */
165*76404edcSAsim Jamshed memset(&security, 0, sizeof(security));
166*76404edcSAsim Jamshed security.nLength = sizeof(security);
167*76404edcSAsim Jamshed security.bInheritHandle = TRUE;
168*76404edcSAsim Jamshed security.lpSecurityDescriptor = NULL;
169*76404edcSAsim Jamshed
170*76404edcSAsim Jamshed if (proc_open_pipes(proc, &security) != 0) {
171*76404edcSAsim Jamshed return -1;
172*76404edcSAsim Jamshed }
173*76404edcSAsim Jamshed proc_close_parents(proc);
174*76404edcSAsim Jamshed
175*76404edcSAsim Jamshed memset(&si, 0, sizeof(si));
176*76404edcSAsim Jamshed si.cb = sizeof(si);
177*76404edcSAsim Jamshed si.dwFlags = STARTF_USESTDHANDLES;
178*76404edcSAsim Jamshed si.hStdInput = proc->in.child;
179*76404edcSAsim Jamshed si.hStdOutput = proc->out.child;
180*76404edcSAsim Jamshed si.hStdError = proc->err.child;
181*76404edcSAsim Jamshed
182*76404edcSAsim Jamshed memset(&pi, 0, sizeof(pi));
183*76404edcSAsim Jamshed
184*76404edcSAsim Jamshed cmdline = buffer_init();
185*76404edcSAsim Jamshed if (shell) {
186*76404edcSAsim Jamshed buffer_append_string(cmdline, shell);
187*76404edcSAsim Jamshed } else {
188*76404edcSAsim Jamshed buffer_append_string(cmdline, windir);
189*76404edcSAsim Jamshed buffer_append_string_len(cmdline, CONST_STR_LEN("\\system32\\cmd.exe"));
190*76404edcSAsim Jamshed }
191*76404edcSAsim Jamshed buffer_append_string_len(cmdline, CONST_STR_LEN(" /c "));
192*76404edcSAsim Jamshed buffer_append_string(cmdline, command);
193*76404edcSAsim Jamshed procok = CreateProcess(NULL, cmdline->ptr, &security, &security, TRUE,
194*76404edcSAsim Jamshed NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
195*76404edcSAsim Jamshed
196*76404edcSAsim Jamshed if (FALSE == procok) {
197*76404edcSAsim Jamshed fprintf(stderr, "failed to CreateProcess: %s", cmdline->ptr);
198*76404edcSAsim Jamshed buffer_free(cmdline);
199*76404edcSAsim Jamshed return -1;
200*76404edcSAsim Jamshed }
201*76404edcSAsim Jamshed buffer_free(cmdline);
202*76404edcSAsim Jamshed
203*76404edcSAsim Jamshed proc->child = pi.hProcess;
204*76404edcSAsim Jamshed CloseHandle(pi.hThread);
205*76404edcSAsim Jamshed
206*76404edcSAsim Jamshed proc_close_childs(proc);
207*76404edcSAsim Jamshed
208*76404edcSAsim Jamshed return 0;
209*76404edcSAsim Jamshed }
210*76404edcSAsim Jamshed /* }}} */
211*76404edcSAsim Jamshed #else /* WIN32 */
212*76404edcSAsim Jamshed /* {{{ proc_close */
proc_close(proc_handler_t * proc)213*76404edcSAsim Jamshed int proc_close(proc_handler_t *proc) {
214*76404edcSAsim Jamshed pid_t child = proc->child;
215*76404edcSAsim Jamshed int wstatus;
216*76404edcSAsim Jamshed pid_t wait_pid;
217*76404edcSAsim Jamshed
218*76404edcSAsim Jamshed proc_close_pipes(proc);
219*76404edcSAsim Jamshed
220*76404edcSAsim Jamshed do {
221*76404edcSAsim Jamshed wait_pid = waitpid(child, &wstatus, 0);
222*76404edcSAsim Jamshed } while (wait_pid == -1 && errno == EINTR);
223*76404edcSAsim Jamshed
224*76404edcSAsim Jamshed if (wait_pid == -1) {
225*76404edcSAsim Jamshed return -1;
226*76404edcSAsim Jamshed } else {
227*76404edcSAsim Jamshed if (WIFEXITED(wstatus))
228*76404edcSAsim Jamshed wstatus = WEXITSTATUS(wstatus);
229*76404edcSAsim Jamshed }
230*76404edcSAsim Jamshed
231*76404edcSAsim Jamshed return wstatus;
232*76404edcSAsim Jamshed }
233*76404edcSAsim Jamshed /* }}} */
234*76404edcSAsim Jamshed /* {{{ proc_open */
proc_open(proc_handler_t * proc,const char * command)235*76404edcSAsim Jamshed int proc_open(proc_handler_t *proc, const char *command) {
236*76404edcSAsim Jamshed pid_t child;
237*76404edcSAsim Jamshed const char *shell;
238*76404edcSAsim Jamshed
239*76404edcSAsim Jamshed if (NULL == (shell = getenv(SHELLENV))) {
240*76404edcSAsim Jamshed shell = "/bin/sh";
241*76404edcSAsim Jamshed }
242*76404edcSAsim Jamshed
243*76404edcSAsim Jamshed if (proc_open_pipes(proc) != 0) {
244*76404edcSAsim Jamshed return -1;
245*76404edcSAsim Jamshed }
246*76404edcSAsim Jamshed
247*76404edcSAsim Jamshed /* the unix way */
248*76404edcSAsim Jamshed
249*76404edcSAsim Jamshed child = fork();
250*76404edcSAsim Jamshed
251*76404edcSAsim Jamshed if (child == 0) {
252*76404edcSAsim Jamshed /* this is the child process */
253*76404edcSAsim Jamshed
254*76404edcSAsim Jamshed /* close those descriptors that we just opened for the parent stuff,
255*76404edcSAsim Jamshed * dup new descriptors into required descriptors and close the original
256*76404edcSAsim Jamshed * cruft
257*76404edcSAsim Jamshed */
258*76404edcSAsim Jamshed proc_close_parents(proc);
259*76404edcSAsim Jamshed
260*76404edcSAsim Jamshed execl(shell, shell, "-c", command, (char *)NULL);
261*76404edcSAsim Jamshed fprintf(stderr, "failed to execute shell: %s -c %s: %s\n", shell, command, strerror(errno));
262*76404edcSAsim Jamshed _exit(127);
263*76404edcSAsim Jamshed
264*76404edcSAsim Jamshed } else if (child < 0) {
265*76404edcSAsim Jamshed fprintf(stderr, "failed to forking");
266*76404edcSAsim Jamshed proc_close(proc);
267*76404edcSAsim Jamshed return -1;
268*76404edcSAsim Jamshed
269*76404edcSAsim Jamshed } else {
270*76404edcSAsim Jamshed proc->child = child;
271*76404edcSAsim Jamshed proc_close_childs(proc);
272*76404edcSAsim Jamshed return 0;
273*76404edcSAsim Jamshed }
274*76404edcSAsim Jamshed }
275*76404edcSAsim Jamshed /* }}} */
276*76404edcSAsim Jamshed #endif /* WIN32 */
277*76404edcSAsim Jamshed
278*76404edcSAsim Jamshed /* {{{ proc_read_fd_to_buffer */
proc_read_fd_to_buffer(int fd,buffer * b)279*76404edcSAsim Jamshed static void proc_read_fd_to_buffer(int fd, buffer *b) {
280*76404edcSAsim Jamshed ssize_t s;
281*76404edcSAsim Jamshed
282*76404edcSAsim Jamshed for (;;) {
283*76404edcSAsim Jamshed buffer_prepare_append(b, 512);
284*76404edcSAsim Jamshed if ((s = read(fd, (void *)(b->ptr + b->used), 512 - 1)) <= 0) {
285*76404edcSAsim Jamshed break;
286*76404edcSAsim Jamshed }
287*76404edcSAsim Jamshed b->used += s;
288*76404edcSAsim Jamshed }
289*76404edcSAsim Jamshed b->ptr[b->used] = '\0';
290*76404edcSAsim Jamshed }
291*76404edcSAsim Jamshed /* }}} */
292*76404edcSAsim Jamshed /* {{{ proc_open_buffer */
proc_open_buffer(const char * command,buffer * in,buffer * out,buffer * err)293*76404edcSAsim Jamshed int proc_open_buffer(const char *command, buffer *in, buffer *out, buffer *err) {
294*76404edcSAsim Jamshed proc_handler_t proc;
295*76404edcSAsim Jamshed
296*76404edcSAsim Jamshed if (proc_open(&proc, command) != 0) {
297*76404edcSAsim Jamshed return -1;
298*76404edcSAsim Jamshed }
299*76404edcSAsim Jamshed
300*76404edcSAsim Jamshed if (in) {
301*76404edcSAsim Jamshed if (write(proc.in.fd, (void *)in->ptr, in->used) < 0) {
302*76404edcSAsim Jamshed perror("error writing pipe");
303*76404edcSAsim Jamshed return -1;
304*76404edcSAsim Jamshed }
305*76404edcSAsim Jamshed }
306*76404edcSAsim Jamshed pipe_close(&proc.in);
307*76404edcSAsim Jamshed
308*76404edcSAsim Jamshed if (out) {
309*76404edcSAsim Jamshed proc_read_fd_to_buffer(proc.out.fd, out);
310*76404edcSAsim Jamshed }
311*76404edcSAsim Jamshed pipe_close(&proc.out);
312*76404edcSAsim Jamshed
313*76404edcSAsim Jamshed if (err) {
314*76404edcSAsim Jamshed proc_read_fd_to_buffer(proc.err.fd, err);
315*76404edcSAsim Jamshed } else {
316*76404edcSAsim Jamshed buffer *tmp = buffer_init();
317*76404edcSAsim Jamshed proc_read_fd_to_buffer(proc.err.fd, tmp);
318*76404edcSAsim Jamshed if (tmp->used > 0 && write(2, (void*)tmp->ptr, tmp->used) < 0) {
319*76404edcSAsim Jamshed perror("error writing pipe");
320*76404edcSAsim Jamshed return -1;
321*76404edcSAsim Jamshed }
322*76404edcSAsim Jamshed buffer_free(tmp);
323*76404edcSAsim Jamshed }
324*76404edcSAsim Jamshed pipe_close(&proc.err);
325*76404edcSAsim Jamshed
326*76404edcSAsim Jamshed proc_close(&proc);
327*76404edcSAsim Jamshed
328*76404edcSAsim Jamshed return 0;
329*76404edcSAsim Jamshed }
330*76404edcSAsim Jamshed /* }}} */
331*76404edcSAsim Jamshed
332*76404edcSAsim Jamshed /* {{{ test */
333*76404edcSAsim Jamshed #ifdef DEBUG_PROC_OPEN
main(void)334*76404edcSAsim Jamshed int main(void) {
335*76404edcSAsim Jamshed proc_handler_t proc;
336*76404edcSAsim Jamshed buffer *in = buffer_init(), *out = buffer_init(), *err = buffer_init();
337*76404edcSAsim Jamshed int wstatus;
338*76404edcSAsim Jamshed
339*76404edcSAsim Jamshed #define FREE() do { \
340*76404edcSAsim Jamshed buffer_free(in); \
341*76404edcSAsim Jamshed buffer_free(out); \
342*76404edcSAsim Jamshed buffer_free(err); \
343*76404edcSAsim Jamshed } while (0)
344*76404edcSAsim Jamshed
345*76404edcSAsim Jamshed #define RESET() do { \
346*76404edcSAsim Jamshed buffer_reset(in); \
347*76404edcSAsim Jamshed buffer_reset(out); \
348*76404edcSAsim Jamshed buffer_reset(err); \
349*76404edcSAsim Jamshed wstatus = proc_close(&proc); \
350*76404edcSAsim Jamshed if (0&&wstatus != 0) { \
351*76404edcSAsim Jamshed fprintf(stdout, "exitstatus %d\n", wstatus); \
352*76404edcSAsim Jamshed return __LINE__ - 200; \
353*76404edcSAsim Jamshed } \
354*76404edcSAsim Jamshed } while (0)
355*76404edcSAsim Jamshed
356*76404edcSAsim Jamshed #define ERROR_OUT() do { \
357*76404edcSAsim Jamshed fprintf(stdout, "failed opening proc\n"); \
358*76404edcSAsim Jamshed wstatus = proc_close(&proc); \
359*76404edcSAsim Jamshed fprintf(stdout, "exitstatus %d\n", wstatus); \
360*76404edcSAsim Jamshed FREE(); \
361*76404edcSAsim Jamshed return __LINE__ - 300; \
362*76404edcSAsim Jamshed } while (0)
363*76404edcSAsim Jamshed
364*76404edcSAsim Jamshed #ifdef WIN32
365*76404edcSAsim Jamshed #define CMD_CAT "pause"
366*76404edcSAsim Jamshed #else
367*76404edcSAsim Jamshed #define CMD_CAT "cat"
368*76404edcSAsim Jamshed #endif
369*76404edcSAsim Jamshed
370*76404edcSAsim Jamshed do {
371*76404edcSAsim Jamshed fprintf(stdout, "test: echo 123 without read\n");
372*76404edcSAsim Jamshed if (proc_open(&proc, "echo 321") != 0) {
373*76404edcSAsim Jamshed ERROR_OUT();
374*76404edcSAsim Jamshed }
375*76404edcSAsim Jamshed close_descriptor(proc.in.parent);
376*76404edcSAsim Jamshed close_descriptor(proc.out.parent);
377*76404edcSAsim Jamshed close_descriptor(proc.err.parent);
378*76404edcSAsim Jamshed RESET();
379*76404edcSAsim Jamshed
380*76404edcSAsim Jamshed fprintf(stdout, "test: echo 321 with read\n"); fflush(stdout);
381*76404edcSAsim Jamshed if (proc_open_buffer("echo 321", NULL, out, err) != 0) {
382*76404edcSAsim Jamshed ERROR_OUT();
383*76404edcSAsim Jamshed }
384*76404edcSAsim Jamshed fprintf(stdout, "result: ->%s<-\n\n", out->ptr); fflush(stdout);
385*76404edcSAsim Jamshed RESET();
386*76404edcSAsim Jamshed
387*76404edcSAsim Jamshed fprintf(stdout, "test: echo 123 | " CMD_CAT "\n"); fflush(stdout);
388*76404edcSAsim Jamshed buffer_copy_string_len(in, CONST_STR_LEN("123\n"));
389*76404edcSAsim Jamshed if (proc_open_buffer(CMD_CAT, in, out, err) != 0) {
390*76404edcSAsim Jamshed ERROR_OUT();
391*76404edcSAsim Jamshed }
392*76404edcSAsim Jamshed fprintf(stdout, "result: ->%s<-\n\n", out->ptr); fflush(stdout);
393*76404edcSAsim Jamshed RESET();
394*76404edcSAsim Jamshed } while (0);
395*76404edcSAsim Jamshed
396*76404edcSAsim Jamshed #undef RESET
397*76404edcSAsim Jamshed #undef ERROR_OUT
398*76404edcSAsim Jamshed
399*76404edcSAsim Jamshed fprintf(stdout, "ok\n");
400*76404edcSAsim Jamshed
401*76404edcSAsim Jamshed FREE();
402*76404edcSAsim Jamshed return 0;
403*76404edcSAsim Jamshed }
404*76404edcSAsim Jamshed #endif /* DEBUG_PROC_OPEN */
405*76404edcSAsim Jamshed /* }}} */
406*76404edcSAsim Jamshed
407