3 #include <process.h> /* for msvc _beginthreadex, _endthreadex */
12 static char *make_command_line(char *shell_name
, char *exec_path
, char **argv
);
14 typedef struct sub_process_t
{
22 volatile DWORD outcnt
;
24 volatile DWORD errcnt
;
32 /* keep track of children so we can implement a waitpid-like routine */
33 static sub_process
*proc_array
[256];
34 static int proc_index
= 0;
35 static int fake_exits_pending
= 0;
38 * When a process has been waited for, adjust the wait state
39 * array so that we don't wait for it again
42 process_adjust_wait_state(sub_process
* pproc
)
49 for (i
= 0; i
< proc_index
; i
++)
50 if (proc_array
[i
]->pid
== pproc
->pid
)
56 memmove(&proc_array
[i
], &proc_array
[i
+1],
57 (proc_index
-i
) * sizeof(sub_process
*));
58 proc_array
[proc_index
] = NULL
;
63 * Waits for any of the registered child processes to finish.
66 process_wait_for_any_private(void)
75 /* build array of handles to wait for */
76 for (i
= 0; i
< proc_index
; i
++) {
77 handles
[i
] = (HANDLE
) proc_array
[i
]->pid
;
79 if (fake_exits_pending
&& proc_array
[i
]->exit_code
)
83 /* wait for someone to exit */
84 if (!fake_exits_pending
) {
85 retval
= WaitForMultipleObjects(proc_index
, handles
, FALSE
, INFINITE
);
86 which
= retval
- WAIT_OBJECT_0
;
89 retval
= !WAIT_FAILED
;
93 /* return pointer to process */
94 if (retval
!= WAIT_FAILED
) {
95 sub_process
* pproc
= proc_array
[which
];
96 process_adjust_wait_state(pproc
);
103 * Terminate a process.
106 process_kill(HANDLE proc
, int signal
)
108 sub_process
* pproc
= (sub_process
*) proc
;
109 pproc
->signal
= signal
;
110 return (TerminateProcess((HANDLE
) pproc
->pid
, signal
));
114 * Use this function to register processes you wish to wait for by
115 * calling process_file_io(NULL) or process_wait_any(). This must be done
116 * because it is possible for callers of this library to reuse the same
117 * handle for multiple processes launches :-(
120 process_register(HANDLE proc
)
122 proc_array
[proc_index
++] = (sub_process
*) proc
;
126 * Public function which works kind of like waitpid(). Wait for any
127 * of the children to die and return results. To call this function,
128 * you must do 1 of things:
130 * x = process_easy(...);
134 * x = process_init_fd();
135 * process_register(x);
139 * x = process_init();
140 * process_register(x);
142 * You must NOT then call process_pipe_io() because this function is
143 * not capable of handling automatic notification of any child
148 process_wait_for_any(void)
150 sub_process
* pproc
= process_wait_for_any_private();
156 * Ouch! can't tell caller if this fails directly. Caller
157 * will have to use process_last_err()
159 (void) process_file_io(pproc
);
160 return ((HANDLE
) pproc
);
165 process_errno(HANDLE proc
)
167 return (((sub_process
*)proc
)->lerrno
);
171 process_signal(HANDLE proc
)
173 return (((sub_process
*)proc
)->signal
);
177 process_last_err(HANDLE proc
)
179 return (((sub_process
*)proc
)->last_err
);
183 process_exit_code(HANDLE proc
)
185 return (((sub_process
*)proc
)->exit_code
);
189 process_outbuf(HANDLE proc
)
191 return (((sub_process
*)proc
)->outp
);
195 process_errbuf(HANDLE proc
)
197 return (((sub_process
*)proc
)->errp
);
201 process_outcnt(HANDLE proc
)
203 return (((sub_process
*)proc
)->outcnt
);
207 process_errcnt(HANDLE proc
)
209 return (((sub_process
*)proc
)->errcnt
);
213 process_pipes(HANDLE proc
, int pipes
[3])
215 pipes
[0] = ((sub_process
*)proc
)->sv_stdin
[0];
216 pipes
[1] = ((sub_process
*)proc
)->sv_stdout
[0];
217 pipes
[2] = ((sub_process
*)proc
)->sv_stderr
[0];
227 * open file descriptors for attaching stdin/stdout/sterr
229 HANDLE stdin_pipes
[2];
230 HANDLE stdout_pipes
[2];
231 HANDLE stderr_pipes
[2];
232 SECURITY_ATTRIBUTES inherit
;
233 BYTE sd
[SECURITY_DESCRIPTOR_MIN_LENGTH
];
235 pproc
= malloc(sizeof(*pproc
));
236 memset(pproc
, 0, sizeof(*pproc
));
238 /* We can't use NULL for lpSecurityDescriptor because that
239 uses the default security descriptor of the calling process.
240 Instead we use a security descriptor with no DACL. This
241 allows nonrestricted access to the associated objects. */
243 if (!InitializeSecurityDescriptor((PSECURITY_DESCRIPTOR
)(&sd
),
244 SECURITY_DESCRIPTOR_REVISION
)) {
245 pproc
->last_err
= GetLastError();
246 pproc
->lerrno
= E_SCALL
;
247 return((HANDLE
)pproc
);
250 inherit
.nLength
= sizeof(inherit
);
251 inherit
.lpSecurityDescriptor
= (PSECURITY_DESCRIPTOR
)(&sd
);
252 inherit
.bInheritHandle
= TRUE
;
254 // By convention, parent gets pipe[0], and child gets pipe[1]
255 // This means the READ side of stdin pipe goes into pipe[1]
256 // and the WRITE side of the stdout and stderr pipes go into pipe[1]
257 if (CreatePipe( &stdin_pipes
[1], &stdin_pipes
[0], &inherit
, 0) == FALSE
||
258 CreatePipe( &stdout_pipes
[0], &stdout_pipes
[1], &inherit
, 0) == FALSE
||
259 CreatePipe( &stderr_pipes
[0], &stderr_pipes
[1], &inherit
, 0) == FALSE
) {
261 pproc
->last_err
= GetLastError();
262 pproc
->lerrno
= E_SCALL
;
263 return((HANDLE
)pproc
);
267 // Mark the parent sides of the pipes as non-inheritable
269 if (SetHandleInformation(stdin_pipes
[0],
270 HANDLE_FLAG_INHERIT
, 0) == FALSE
||
271 SetHandleInformation(stdout_pipes
[0],
272 HANDLE_FLAG_INHERIT
, 0) == FALSE
||
273 SetHandleInformation(stderr_pipes
[0],
274 HANDLE_FLAG_INHERIT
, 0) == FALSE
) {
276 pproc
->last_err
= GetLastError();
277 pproc
->lerrno
= E_SCALL
;
278 return((HANDLE
)pproc
);
280 pproc
->sv_stdin
[0] = (int) stdin_pipes
[0];
281 pproc
->sv_stdin
[1] = (int) stdin_pipes
[1];
282 pproc
->sv_stdout
[0] = (int) stdout_pipes
[0];
283 pproc
->sv_stdout
[1] = (int) stdout_pipes
[1];
284 pproc
->sv_stderr
[0] = (int) stderr_pipes
[0];
285 pproc
->sv_stderr
[1] = (int) stderr_pipes
[1];
287 pproc
->using_pipes
= 1;
291 return((HANDLE
)pproc
);
296 process_init_fd(HANDLE stdinh
, HANDLE stdouth
, HANDLE stderrh
)
300 pproc
= malloc(sizeof(*pproc
));
301 memset(pproc
, 0, sizeof(*pproc
));
304 * Just pass the provided file handles to the 'child side' of the
305 * pipe, bypassing pipes altogether.
307 pproc
->sv_stdin
[1] = (int) stdinh
;
308 pproc
->sv_stdout
[1] = (int) stdouth
;
309 pproc
->sv_stderr
[1] = (int) stderrh
;
311 pproc
->last_err
= pproc
->lerrno
= 0;
313 return((HANDLE
)pproc
);
318 find_file(char *exec_path
, LPOFSTRUCT file_info
)
324 fname
= malloc(strlen(exec_path
) + 5);
325 strcpy(fname
, exec_path
);
326 ext
= fname
+ strlen(fname
);
329 if ((exec_handle
= (HANDLE
)OpenFile(fname
, file_info
,
330 OF_READ
| OF_SHARE_COMPAT
)) != (HANDLE
)HFILE_ERROR
) {
336 if ((exec_handle
= (HANDLE
)OpenFile(fname
, file_info
,
337 OF_READ
| OF_SHARE_COMPAT
)) != (HANDLE
)HFILE_ERROR
) {
343 if ((exec_handle
= (HANDLE
)OpenFile(fname
, file_info
,
344 OF_READ
| OF_SHARE_COMPAT
)) != (HANDLE
)HFILE_ERROR
) {
349 /* should .com come before this case? */
350 if ((exec_handle
= (HANDLE
)OpenFile(exec_path
, file_info
,
351 OF_READ
| OF_SHARE_COMPAT
)) != (HANDLE
)HFILE_ERROR
) {
357 if ((exec_handle
= (HANDLE
)OpenFile(fname
, file_info
,
358 OF_READ
| OF_SHARE_COMPAT
)) != (HANDLE
)HFILE_ERROR
) {
369 * Description: Create the child process to be helped
373 * Notes/Dependencies:
383 sub_process
*pproc
= (sub_process
*)proc
;
384 char *shell_name
= 0;
385 int file_not_found
=0;
388 DWORD bytes_returned
;
391 STARTUPINFO startInfo
;
392 PROCESS_INFORMATION procInfo
;
398 * Shell script detection... if the exec_path starts with #! then
399 * we want to exec shell-script-name exec-path, not just exec-path
400 * NT doesn't recognize #!/bin/sh or #!/etc/Tivoli/bin/perl. We do not
401 * hard-code the path to the shell or perl or whatever: Instead, we
402 * assume it's in the path somewhere (generally, the NT tools
404 * We use OpenFile here because it is capable of searching the Path.
407 exec_handle
= find_file(exec_path
, &file_info
);
410 * If we couldn't open the file, just assume that Windows32 will be able
411 * to find and execute it.
413 if (exec_handle
== (HANDLE
)HFILE_ERROR
) {
417 /* Attempt to read the first line of the file */
418 if (ReadFile( exec_handle
,
419 buf
, sizeof(buf
) - 1, /* leave room for trailing NULL */
420 &bytes_returned
, 0) == FALSE
|| bytes_returned
< 2) {
422 pproc
->last_err
= GetLastError();
423 pproc
->lerrno
= E_IO
;
424 CloseHandle(exec_handle
);
427 if (buf
[0] == '#' && buf
[1] == '!') {
429 * This is a shell script... Change the command line from
430 * exec_path args to shell_name exec_path args
434 /* Make sure buf is NULL terminated */
435 buf
[bytes_returned
] = 0;
437 * Depending on the file system type, etc. the first line
438 * of the shell script may end with newline or newline-carriage-return
439 * Whatever it ends with, cut it off.
441 p
= strchr(buf
, '\n');
444 p
= strchr(buf
, '\r');
449 * Find base name of shell
451 shell_name
= strrchr( buf
, '/');
455 shell_name
= &buf
[2];/* skipping "#!" */
459 CloseHandle(exec_handle
);
465 command_line
= make_command_line( shell_name
, exec_path
, argv
);
467 command_line
= make_command_line( shell_name
, file_info
.szPathName
,
470 if ( command_line
== NULL
) {
472 pproc
->lerrno
= E_NO_MEM
;
477 if (arr2envblk(envp
, &envblk
) ==FALSE
) {
479 pproc
->lerrno
= E_NO_MEM
;
480 free( command_line
);
485 if ((shell_name
) || (file_not_found
)) {
486 exec_path
= 0; /* Search for the program in %Path% */
488 exec_path
= file_info
.szPathName
;
492 * Set up inherited stdin, stdout, stderr for child
494 GetStartupInfo(&startInfo
);
495 startInfo
.dwFlags
= STARTF_USESTDHANDLES
;
496 startInfo
.lpReserved
= 0;
497 startInfo
.cbReserved2
= 0;
498 startInfo
.lpReserved2
= 0;
499 startInfo
.lpTitle
= shell_name
? shell_name
: exec_path
;
500 startInfo
.hStdInput
= (HANDLE
)pproc
->sv_stdin
[1];
501 startInfo
.hStdOutput
= (HANDLE
)pproc
->sv_stdout
[1];
502 startInfo
.hStdError
= (HANDLE
)pproc
->sv_stderr
[1];
505 if (envblk
) free(envblk
);
508 DB (DB_JOBS
, ("CreateProcess(%s,%s,...)\n",
509 exec_path
? exec_path
: "NULL",
510 command_line
? command_line
: "NULL"));
515 0, /* default security attributes for thread */
516 TRUE
, /* inherit handles (e.g. helper pipes, oserv socket) */
519 0, /* default starting directory */
521 &procInfo
) == FALSE
) {
523 pproc
->last_err
= GetLastError();
524 pproc
->lerrno
= E_FORK
;
525 fprintf(stderr
, "process_begin: CreateProcess(%s, %s, ...) failed.\n", exec_path
, command_line
);
526 if (envblk
) free(envblk
);
527 free( command_line
);
532 pproc
->pid
= (int)procInfo
.hProcess
;
533 /* Close the thread handle -- we'll just watch the process */
534 CloseHandle(procInfo
.hThread
);
536 /* Close the halves of the pipes we don't need */
537 if (pproc
->sv_stdin
) {
538 CloseHandle((HANDLE
)pproc
->sv_stdin
[1]);
539 (HANDLE
)pproc
->sv_stdin
[1] = 0;
541 if (pproc
->sv_stdout
) {
542 CloseHandle((HANDLE
)pproc
->sv_stdout
[1]);
543 (HANDLE
)pproc
->sv_stdout
[1] = 0;
545 if (pproc
->sv_stderr
) {
546 CloseHandle((HANDLE
)pproc
->sv_stderr
[1]);
547 (HANDLE
)pproc
->sv_stderr
[1] = 0;
550 free( command_line
);
551 if (envblk
) free(envblk
);
559 proc_stdin_thread(sub_process
*pproc
)
563 if (WriteFile( (HANDLE
) pproc
->sv_stdin
[0], pproc
->inp
, pproc
->incnt
,
564 &in_done
, NULL
) == FALSE
)
566 // This if should never be true for anonymous pipes, but gives
567 // us a chance to change I/O mechanisms later
568 if (in_done
< pproc
->incnt
) {
569 pproc
->incnt
-= in_done
;
570 pproc
->inp
+= in_done
;
575 return 0; // for compiler warnings only.. not reached
579 proc_stdout_thread(sub_process
*pproc
)
581 DWORD bufsize
= 1024;
584 pproc
->outp
= malloc(bufsize
);
585 if (pproc
->outp
== NULL
)
590 if (ReadFile( (HANDLE
)pproc
->sv_stdout
[0], &c
, 1, &nread
, NULL
)
592 /* map_windows32_error_to_string(GetLastError());*/
597 if (pproc
->outcnt
+ nread
> bufsize
) {
598 bufsize
+= nread
+ 512;
599 pproc
->outp
= realloc(pproc
->outp
, bufsize
);
600 if (pproc
->outp
== NULL
) {
605 pproc
->outp
[pproc
->outcnt
++] = c
;
611 proc_stderr_thread(sub_process
*pproc
)
613 DWORD bufsize
= 1024;
616 pproc
->errp
= malloc(bufsize
);
617 if (pproc
->errp
== NULL
)
622 if (ReadFile( (HANDLE
)pproc
->sv_stderr
[0], &c
, 1, &nread
, NULL
) == FALSE
) {
623 map_windows32_error_to_string(GetLastError());
628 if (pproc
->errcnt
+ nread
> bufsize
) {
629 bufsize
+= nread
+ 512;
630 pproc
->errp
= realloc(pproc
->errp
, bufsize
);
631 if (pproc
->errp
== NULL
) {
636 pproc
->errp
[pproc
->errcnt
++] = c
;
643 * Purpose: collects output from child process and returns results
649 * Notes/Dependencies:
657 sub_process
*pproc
= (sub_process
*)proc
;
658 bool_t stdin_eof
= FALSE
, stdout_eof
= FALSE
, stderr_eof
= FALSE
;
659 HANDLE childhand
= (HANDLE
) pproc
->pid
;
660 HANDLE tStdin
, tStdout
, tStderr
;
661 DWORD dwStdin
, dwStdout
, dwStderr
;
666 bool_t child_dead
= FALSE
;
670 * Create stdin thread, if needed
672 pproc
->inp
= stdin_data
;
673 pproc
->incnt
= stdin_data_len
;
676 CloseHandle((HANDLE
)pproc
->sv_stdin
[0]);
677 (HANDLE
)pproc
->sv_stdin
[0] = 0;
679 tStdin
= (HANDLE
) _beginthreadex( 0, 1024,
680 (unsigned (__stdcall
*) (void *))proc_stdin_thread
, pproc
, 0,
681 (unsigned int *) &dwStdin
);
683 pproc
->last_err
= GetLastError();
684 pproc
->lerrno
= E_SCALL
;
690 * Assume child will produce stdout and stderr
692 tStdout
= (HANDLE
) _beginthreadex( 0, 1024,
693 (unsigned (__stdcall
*) (void *))proc_stdout_thread
, pproc
, 0,
694 (unsigned int *) &dwStdout
);
695 tStderr
= (HANDLE
) _beginthreadex( 0, 1024,
696 (unsigned (__stdcall
*) (void *))proc_stderr_thread
, pproc
, 0,
697 (unsigned int *) &dwStderr
);
699 if (tStdout
== 0 || tStderr
== 0) {
701 pproc
->last_err
= GetLastError();
702 pproc
->lerrno
= E_SCALL
;
708 * Wait for all I/O to finish and for the child process to exit
711 while (!stdin_eof
|| !stdout_eof
|| !stderr_eof
|| !child_dead
) {
714 wait_list
[wait_count
++] = tStdin
;
717 wait_list
[wait_count
++] = tStdout
;
720 wait_list
[wait_count
++] = tStderr
;
723 wait_list
[wait_count
++] = childhand
;
726 wait_return
= WaitForMultipleObjects(wait_count
, wait_list
,
727 FALSE
, /* don't wait for all: one ready will do */
728 child_dead
? 1000 :INFINITE
); /* after the child dies, subthreads have
729 one second to collect all remaining output */
731 if (wait_return
== WAIT_FAILED
) {
732 /* map_windows32_error_to_string(GetLastError());*/
733 pproc
->last_err
= GetLastError();
734 pproc
->lerrno
= E_SCALL
;
738 ready_hand
= wait_list
[wait_return
- WAIT_OBJECT_0
];
740 if (ready_hand
== tStdin
) {
741 CloseHandle((HANDLE
)pproc
->sv_stdin
[0]);
742 (HANDLE
)pproc
->sv_stdin
[0] = 0;
747 } else if (ready_hand
== tStdout
) {
749 CloseHandle((HANDLE
)pproc
->sv_stdout
[0]);
750 (HANDLE
)pproc
->sv_stdout
[0] = 0;
751 CloseHandle(tStdout
);
755 } else if (ready_hand
== tStderr
) {
757 CloseHandle((HANDLE
)pproc
->sv_stderr
[0]);
758 (HANDLE
)pproc
->sv_stderr
[0] = 0;
759 CloseHandle(tStderr
);
763 } else if (ready_hand
== childhand
) {
765 if (GetExitCodeProcess(childhand
, &pproc
->exit_code
) == FALSE
) {
766 pproc
->last_err
= GetLastError();
767 pproc
->lerrno
= E_SCALL
;
774 /* ?? Got back a handle we didn't query ?? */
776 pproc
->lerrno
= E_FAIL
;
785 CloseHandle(tStdout
);
787 CloseHandle(tStderr
);
797 * Purpose: collects output from child process and returns results
803 * Notes/Dependencies:
814 pproc
= process_wait_for_any_private();
816 pproc
= (sub_process
*)proc
;
818 /* some sort of internal error */
822 childhand
= (HANDLE
) pproc
->pid
;
825 * This function is poorly named, and could also be used just to wait
826 * for child death if you're doing your own pipe I/O. If that is
827 * the case, close the pipe handles here.
829 if (pproc
->sv_stdin
[0]) {
830 CloseHandle((HANDLE
)pproc
->sv_stdin
[0]);
831 pproc
->sv_stdin
[0] = 0;
833 if (pproc
->sv_stdout
[0]) {
834 CloseHandle((HANDLE
)pproc
->sv_stdout
[0]);
835 pproc
->sv_stdout
[0] = 0;
837 if (pproc
->sv_stderr
[0]) {
838 CloseHandle((HANDLE
)pproc
->sv_stderr
[0]);
839 pproc
->sv_stderr
[0] = 0;
843 * Wait for the child process to exit
846 wait_return
= WaitForSingleObject(childhand
, INFINITE
);
848 if (wait_return
!= WAIT_OBJECT_0
) {
849 /* map_windows32_error_to_string(GetLastError());*/
850 pproc
->last_err
= GetLastError();
851 pproc
->lerrno
= E_SCALL
;
855 if (GetExitCodeProcess(childhand
, &pproc
->exit_code
) == FALSE
) {
856 pproc
->last_err
= GetLastError();
857 pproc
->lerrno
= E_SCALL
;
869 * Description: Clean up any leftover handles, etc. It is up to the
870 * caller to manage and free the input, ouput, and stderr buffers.
876 sub_process
*pproc
= (sub_process
*)proc
;
879 if (pproc
->using_pipes
) {
880 for (i
= 0; i
<= 1; i
++) {
881 if ((HANDLE
)pproc
->sv_stdin
[i
])
882 CloseHandle((HANDLE
)pproc
->sv_stdin
[i
]);
883 if ((HANDLE
)pproc
->sv_stdout
[i
])
884 CloseHandle((HANDLE
)pproc
->sv_stdout
[i
]);
885 if ((HANDLE
)pproc
->sv_stderr
[i
])
886 CloseHandle((HANDLE
)pproc
->sv_stderr
[i
]);
889 if ((HANDLE
)pproc
->pid
)
890 CloseHandle((HANDLE
)pproc
->pid
);
898 * Create a command line buffer to pass to CreateProcess
900 * Returns: the buffer or NULL for failure
901 * Shell case: sh_name a:/full/path/to/script argv[1] argv[2] ...
902 * Otherwise: argv[0] argv[1] argv[2] ...
904 * Notes/Dependencies:
905 * CreateProcess does not take an argv, so this command creates a
906 * command line for the executable.
910 make_command_line( char *shell_name
, char *full_exec_path
, char **argv
)
914 int* enclose_in_quotes
= NULL
;
915 int* enclose_in_quotes_i
;
916 unsigned int bytes_required
= 0;
918 char* command_line_i
;
919 int cygwin_mode
= 0; /* HAVE_CYGWIN_SHELL */
920 int have_sh
= 0; /* HAVE_CYGWIN_SHELL */
922 #ifdef HAVE_CYGWIN_SHELL
923 have_sh
= (shell_name
!= NULL
|| strstr(full_exec_path
, "sh.exe"));
927 if (shell_name
&& full_exec_path
) {
929 = strlen(shell_name
) + 1 + strlen(full_exec_path
);
931 * Skip argv[0] if any, when shell_name is given.
935 * Add one for the intervening space.
937 if (*argv
) bytes_required
++;
941 while (*(argvi
++)) argc
++;
944 enclose_in_quotes
= (int*) calloc(1, argc
* sizeof(int));
946 if (!enclose_in_quotes
) {
951 /* We have to make one pass through each argv[i] to see if we need
952 * to enclose it in ", so we might as well figure out how much
953 * memory we'll need on the same pass.
957 enclose_in_quotes_i
= enclose_in_quotes
;
960 unsigned int backslash_count
= 0;
963 * We have to enclose empty arguments in ".
965 if (!(*p
)) *enclose_in_quotes_i
= 1;
971 * We have to insert a backslash for each "
972 * and each \ that precedes the ".
974 bytes_required
+= (backslash_count
+ 1);
978 #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL)
984 * At one time we set *enclose_in_quotes_i for '*' or '?' to suppress
985 * wildcard expansion in programs linked with MSVC's SETARGV.OBJ so
986 * that argv in always equals argv out. This was removed. Say you have
987 * such a program named glob.exe. You enter
989 * at the sh command prompt. Obviously the intent is to make glob do the
990 * wildcarding instead of sh. If we set *enclose_in_quotes_i for '*' or '?',
991 * then the command line that glob would see would be
993 * and the _setargv in SETARGV.OBJ would _not_ expand the *.
997 *enclose_in_quotes_i
= 1;
1001 backslash_count
= 0;
1006 * Add one for each character in argv[i].
1013 if (*enclose_in_quotes_i
) {
1015 * Add one for each enclosing ",
1016 * and one for each \ that precedes the
1019 bytes_required
+= (backslash_count
+ 2);
1023 * Add one for the intervening space.
1025 if (*(++argvi
)) bytes_required
++;
1026 enclose_in_quotes_i
++;
1030 * Add one for the terminating NULL.
1034 command_line
= (char*) malloc(bytes_required
);
1036 if (!command_line
) {
1037 if (enclose_in_quotes
) free(enclose_in_quotes
);
1041 command_line_i
= command_line
;
1043 if (shell_name
&& full_exec_path
) {
1044 while(*shell_name
) {
1045 *(command_line_i
++) = *(shell_name
++);
1048 *(command_line_i
++) = ' ';
1050 while(*full_exec_path
) {
1051 *(command_line_i
++) = *(full_exec_path
++);
1055 *(command_line_i
++) = ' ';
1060 enclose_in_quotes_i
= enclose_in_quotes
;
1064 unsigned int backslash_count
= 0;
1066 if (*enclose_in_quotes_i
) {
1067 *(command_line_i
++) = '\"';
1072 if (cygwin_mode
&& have_sh
) { /* HAVE_CYGWIN_SHELL */
1073 /* instead of a \", cygwin likes "" */
1074 *(command_line_i
++) = '\"';
1078 * We have to insert a backslash for the "
1079 * and each \ that precedes the ".
1083 while(backslash_count
) {
1084 *(command_line_i
++) = '\\';
1088 #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL)
1089 } else if (*p
== '\\') {
1092 backslash_count
= 0;
1097 * Copy the character.
1099 *(command_line_i
++) = *(p
++);
1102 if (*enclose_in_quotes_i
) {
1103 #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL)
1105 * Add one \ for each \ that precedes the
1108 while(backslash_count
--) {
1109 *(command_line_i
++) = '\\';
1112 *(command_line_i
++) = '\"';
1116 * Append an intervening space.
1119 *(command_line_i
++) = ' ';
1122 enclose_in_quotes_i
++;
1126 * Append the terminating NULL.
1128 *command_line_i
= '\0';
1130 if (enclose_in_quotes
) free(enclose_in_quotes
);
1131 return command_line
;
1135 * Description: Given an argv and optional envp, launch the process
1136 * using the default stdin, stdout, and stderr handles.
1137 * Also, register process so that process_wait_for_any_private()
1138 * can be used via process_file_io(NULL) or
1139 * process_wait_for_any().
1143 * Notes/Dependencies:
1155 if (DuplicateHandle(GetCurrentProcess(),
1156 GetStdHandle(STD_INPUT_HANDLE
),
1157 GetCurrentProcess(),
1161 DUPLICATE_SAME_ACCESS
) == FALSE
) {
1163 "process_easy: DuplicateHandle(In) failed (e=%d)\n",
1165 return INVALID_HANDLE_VALUE
;
1167 if (DuplicateHandle(GetCurrentProcess(),
1168 GetStdHandle(STD_OUTPUT_HANDLE
),
1169 GetCurrentProcess(),
1173 DUPLICATE_SAME_ACCESS
) == FALSE
) {
1175 "process_easy: DuplicateHandle(Out) failed (e=%d)\n",
1177 return INVALID_HANDLE_VALUE
;
1179 if (DuplicateHandle(GetCurrentProcess(),
1180 GetStdHandle(STD_ERROR_HANDLE
),
1181 GetCurrentProcess(),
1185 DUPLICATE_SAME_ACCESS
) == FALSE
) {
1187 "process_easy: DuplicateHandle(Err) failed (e=%d)\n",
1189 return INVALID_HANDLE_VALUE
;
1192 hProcess
= process_init_fd(hIn
, hOut
, hErr
);
1194 if (process_begin(hProcess
, argv
, envp
, argv
[0], NULL
)) {
1195 fake_exits_pending
++;
1196 ((sub_process
*) hProcess
)->exit_code
= process_last_err(hProcess
);
1198 /* close up unused handles */
1204 process_register(hProcess
);