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, &copy, 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