3 #include <process.h> /* for msvc _beginthreadex, _endthreadex */
13 static char *make_command_line(char *shell_name
, char *exec_path
, char **argv
);
15 typedef struct sub_process_t
{
23 volatile DWORD outcnt
;
25 volatile DWORD errcnt
;
33 /* keep track of children so we can implement a waitpid-like routine */
34 static sub_process
*proc_array
[MAXIMUM_WAIT_OBJECTS
];
35 static int proc_index
= 0;
36 static int fake_exits_pending
= 0;
39 * When a process has been waited for, adjust the wait state
40 * array so that we don't wait for it again
43 process_adjust_wait_state(sub_process
* pproc
)
50 for (i
= 0; i
< proc_index
; i
++)
51 if (proc_array
[i
]->pid
== pproc
->pid
)
57 memmove(&proc_array
[i
], &proc_array
[i
+1],
58 (proc_index
-i
) * sizeof(sub_process
*));
59 proc_array
[proc_index
] = NULL
;
64 * Waits for any of the registered child processes to finish.
67 process_wait_for_any_private(void)
69 HANDLE handles
[MAXIMUM_WAIT_OBJECTS
];
76 /* build array of handles to wait for */
77 for (i
= 0; i
< proc_index
; i
++) {
78 handles
[i
] = (HANDLE
) proc_array
[i
]->pid
;
80 if (fake_exits_pending
&& proc_array
[i
]->exit_code
)
84 /* wait for someone to exit */
85 if (!fake_exits_pending
) {
86 retval
= WaitForMultipleObjects(proc_index
, handles
, FALSE
, INFINITE
);
87 which
= retval
- WAIT_OBJECT_0
;
90 retval
= !WAIT_FAILED
;
94 /* return pointer to process */
95 if (retval
!= WAIT_FAILED
) {
96 sub_process
* pproc
= proc_array
[which
];
97 process_adjust_wait_state(pproc
);
104 * Terminate a process.
107 process_kill(HANDLE proc
, int signal
)
109 sub_process
* pproc
= (sub_process
*) proc
;
110 pproc
->signal
= signal
;
111 return (TerminateProcess((HANDLE
) pproc
->pid
, signal
));
115 * Use this function to register processes you wish to wait for by
116 * calling process_file_io(NULL) or process_wait_any(). This must be done
117 * because it is possible for callers of this library to reuse the same
118 * handle for multiple processes launches :-(
121 process_register(HANDLE proc
)
123 if (proc_index
< MAXIMUM_WAIT_OBJECTS
)
124 proc_array
[proc_index
++] = (sub_process
*) proc
;
128 * Return the number of processes that we are still waiting for.
131 process_used_slots(void)
137 * Public function which works kind of like waitpid(). Wait for any
138 * of the children to die and return results. To call this function,
139 * you must do 1 of things:
141 * x = process_easy(...);
145 * x = process_init_fd();
146 * process_register(x);
150 * x = process_init();
151 * process_register(x);
153 * You must NOT then call process_pipe_io() because this function is
154 * not capable of handling automatic notification of any child
159 process_wait_for_any(void)
161 sub_process
* pproc
= process_wait_for_any_private();
167 * Ouch! can't tell caller if this fails directly. Caller
168 * will have to use process_last_err()
170 (void) process_file_io(pproc
);
171 return ((HANDLE
) pproc
);
176 process_errno(HANDLE proc
)
178 return (((sub_process
*)proc
)->lerrno
);
182 process_signal(HANDLE proc
)
184 return (((sub_process
*)proc
)->signal
);
188 process_last_err(HANDLE proc
)
190 return (((sub_process
*)proc
)->last_err
);
194 process_exit_code(HANDLE proc
)
196 return (((sub_process
*)proc
)->exit_code
);
200 process_outbuf(HANDLE proc
)
202 return (((sub_process
*)proc
)->outp
);
206 process_errbuf(HANDLE proc
)
208 return (((sub_process
*)proc
)->errp
);
212 process_outcnt(HANDLE proc
)
214 return (((sub_process
*)proc
)->outcnt
);
218 process_errcnt(HANDLE proc
)
220 return (((sub_process
*)proc
)->errcnt
);
224 process_pipes(HANDLE proc
, int pipes
[3])
226 pipes
[0] = ((sub_process
*)proc
)->sv_stdin
[0];
227 pipes
[1] = ((sub_process
*)proc
)->sv_stdout
[0];
228 pipes
[2] = ((sub_process
*)proc
)->sv_stderr
[0];
238 * open file descriptors for attaching stdin/stdout/sterr
240 HANDLE stdin_pipes
[2];
241 HANDLE stdout_pipes
[2];
242 HANDLE stderr_pipes
[2];
243 SECURITY_ATTRIBUTES inherit
;
244 BYTE sd
[SECURITY_DESCRIPTOR_MIN_LENGTH
];
246 pproc
= malloc(sizeof(*pproc
));
247 memset(pproc
, 0, sizeof(*pproc
));
249 /* We can't use NULL for lpSecurityDescriptor because that
250 uses the default security descriptor of the calling process.
251 Instead we use a security descriptor with no DACL. This
252 allows nonrestricted access to the associated objects. */
254 if (!InitializeSecurityDescriptor((PSECURITY_DESCRIPTOR
)(&sd
),
255 SECURITY_DESCRIPTOR_REVISION
)) {
256 pproc
->last_err
= GetLastError();
257 pproc
->lerrno
= E_SCALL
;
258 return((HANDLE
)pproc
);
261 inherit
.nLength
= sizeof(inherit
);
262 inherit
.lpSecurityDescriptor
= (PSECURITY_DESCRIPTOR
)(&sd
);
263 inherit
.bInheritHandle
= TRUE
;
265 // By convention, parent gets pipe[0], and child gets pipe[1]
266 // This means the READ side of stdin pipe goes into pipe[1]
267 // and the WRITE side of the stdout and stderr pipes go into pipe[1]
268 if (CreatePipe( &stdin_pipes
[1], &stdin_pipes
[0], &inherit
, 0) == FALSE
||
269 CreatePipe( &stdout_pipes
[0], &stdout_pipes
[1], &inherit
, 0) == FALSE
||
270 CreatePipe( &stderr_pipes
[0], &stderr_pipes
[1], &inherit
, 0) == FALSE
) {
272 pproc
->last_err
= GetLastError();
273 pproc
->lerrno
= E_SCALL
;
274 return((HANDLE
)pproc
);
278 // Mark the parent sides of the pipes as non-inheritable
280 if (SetHandleInformation(stdin_pipes
[0],
281 HANDLE_FLAG_INHERIT
, 0) == FALSE
||
282 SetHandleInformation(stdout_pipes
[0],
283 HANDLE_FLAG_INHERIT
, 0) == FALSE
||
284 SetHandleInformation(stderr_pipes
[0],
285 HANDLE_FLAG_INHERIT
, 0) == FALSE
) {
287 pproc
->last_err
= GetLastError();
288 pproc
->lerrno
= E_SCALL
;
289 return((HANDLE
)pproc
);
291 pproc
->sv_stdin
[0] = (int) stdin_pipes
[0];
292 pproc
->sv_stdin
[1] = (int) stdin_pipes
[1];
293 pproc
->sv_stdout
[0] = (int) stdout_pipes
[0];
294 pproc
->sv_stdout
[1] = (int) stdout_pipes
[1];
295 pproc
->sv_stderr
[0] = (int) stderr_pipes
[0];
296 pproc
->sv_stderr
[1] = (int) stderr_pipes
[1];
298 pproc
->using_pipes
= 1;
302 return((HANDLE
)pproc
);
307 process_init_fd(HANDLE stdinh
, HANDLE stdouth
, HANDLE stderrh
)
311 pproc
= malloc(sizeof(*pproc
));
312 memset(pproc
, 0, sizeof(*pproc
));
315 * Just pass the provided file handles to the 'child side' of the
316 * pipe, bypassing pipes altogether.
318 pproc
->sv_stdin
[1] = (int) stdinh
;
319 pproc
->sv_stdout
[1] = (int) stdouth
;
320 pproc
->sv_stderr
[1] = (int) stderrh
;
322 pproc
->last_err
= pproc
->lerrno
= 0;
324 return((HANDLE
)pproc
);
329 find_file(char *exec_path
, LPOFSTRUCT file_info
)
335 fname
= malloc(strlen(exec_path
) + 5);
336 strcpy(fname
, exec_path
);
337 ext
= fname
+ strlen(fname
);
340 if ((exec_handle
= (HANDLE
)OpenFile(fname
, file_info
,
341 OF_READ
| OF_SHARE_COMPAT
)) != (HANDLE
)HFILE_ERROR
) {
347 if ((exec_handle
= (HANDLE
)OpenFile(fname
, file_info
,
348 OF_READ
| OF_SHARE_COMPAT
)) != (HANDLE
)HFILE_ERROR
) {
354 if ((exec_handle
= (HANDLE
)OpenFile(fname
, file_info
,
355 OF_READ
| OF_SHARE_COMPAT
)) != (HANDLE
)HFILE_ERROR
) {
360 /* should .com come before this case? */
361 if ((exec_handle
= (HANDLE
)OpenFile(exec_path
, file_info
,
362 OF_READ
| OF_SHARE_COMPAT
)) != (HANDLE
)HFILE_ERROR
) {
368 if ((exec_handle
= (HANDLE
)OpenFile(fname
, file_info
,
369 OF_READ
| OF_SHARE_COMPAT
)) != (HANDLE
)HFILE_ERROR
) {
380 * Description: Create the child process to be helped
384 * Notes/Dependencies:
394 sub_process
*pproc
= (sub_process
*)proc
;
395 char *shell_name
= 0;
396 int file_not_found
=0;
399 DWORD bytes_returned
;
402 STARTUPINFO startInfo
;
403 PROCESS_INFORMATION procInfo
;
409 * Shell script detection... if the exec_path starts with #! then
410 * we want to exec shell-script-name exec-path, not just exec-path
411 * NT doesn't recognize #!/bin/sh or #!/etc/Tivoli/bin/perl. We do not
412 * hard-code the path to the shell or perl or whatever: Instead, we
413 * assume it's in the path somewhere (generally, the NT tools
415 * We use OpenFile here because it is capable of searching the Path.
418 exec_handle
= find_file(exec_path
, &file_info
);
421 * If we couldn't open the file, just assume that Windows32 will be able
422 * to find and execute it.
424 if (exec_handle
== (HANDLE
)HFILE_ERROR
) {
428 /* Attempt to read the first line of the file */
429 if (ReadFile( exec_handle
,
430 buf
, sizeof(buf
) - 1, /* leave room for trailing NULL */
431 &bytes_returned
, 0) == FALSE
|| bytes_returned
< 2) {
433 pproc
->last_err
= GetLastError();
434 pproc
->lerrno
= E_IO
;
435 CloseHandle(exec_handle
);
438 if (buf
[0] == '#' && buf
[1] == '!') {
440 * This is a shell script... Change the command line from
441 * exec_path args to shell_name exec_path args
445 /* Make sure buf is NULL terminated */
446 buf
[bytes_returned
] = 0;
448 * Depending on the file system type, etc. the first line
449 * of the shell script may end with newline or newline-carriage-return
450 * Whatever it ends with, cut it off.
452 p
= strchr(buf
, '\n');
455 p
= strchr(buf
, '\r');
460 * Find base name of shell
462 shell_name
= strrchr( buf
, '/');
466 shell_name
= &buf
[2];/* skipping "#!" */
470 CloseHandle(exec_handle
);
476 command_line
= make_command_line( shell_name
, exec_path
, argv
);
478 command_line
= make_command_line( shell_name
, file_info
.szPathName
,
481 if ( command_line
== NULL
) {
483 pproc
->lerrno
= E_NO_MEM
;
488 if (arr2envblk(envp
, &envblk
) ==FALSE
) {
490 pproc
->lerrno
= E_NO_MEM
;
491 free( command_line
);
496 if ((shell_name
) || (file_not_found
)) {
497 exec_path
= 0; /* Search for the program in %Path% */
499 exec_path
= file_info
.szPathName
;
503 * Set up inherited stdin, stdout, stderr for child
505 GetStartupInfo(&startInfo
);
506 startInfo
.dwFlags
= STARTF_USESTDHANDLES
;
507 startInfo
.lpReserved
= 0;
508 startInfo
.cbReserved2
= 0;
509 startInfo
.lpReserved2
= 0;
510 startInfo
.lpTitle
= shell_name
? shell_name
: exec_path
;
511 startInfo
.hStdInput
= (HANDLE
)pproc
->sv_stdin
[1];
512 startInfo
.hStdOutput
= (HANDLE
)pproc
->sv_stdout
[1];
513 startInfo
.hStdError
= (HANDLE
)pproc
->sv_stderr
[1];
516 if (envblk
) free(envblk
);
519 DB (DB_JOBS
, ("CreateProcess(%s,%s,...)\n",
520 exec_path
? exec_path
: "NULL",
521 command_line
? command_line
: "NULL"));
526 0, /* default security attributes for thread */
527 TRUE
, /* inherit handles (e.g. helper pipes, oserv socket) */
530 0, /* default starting directory */
532 &procInfo
) == FALSE
) {
534 pproc
->last_err
= GetLastError();
535 pproc
->lerrno
= E_FORK
;
536 fprintf(stderr
, "process_begin: CreateProcess(%s, %s, ...) failed.\n",
537 exec_path
? exec_path
: "NULL", command_line
);
538 if (envblk
) free(envblk
);
539 free( command_line
);
544 pproc
->pid
= (int)procInfo
.hProcess
;
545 /* Close the thread handle -- we'll just watch the process */
546 CloseHandle(procInfo
.hThread
);
548 /* Close the halves of the pipes we don't need */
549 if (pproc
->sv_stdin
) {
550 CloseHandle((HANDLE
)pproc
->sv_stdin
[1]);
551 pproc
->sv_stdin
[1] = 0;
553 if (pproc
->sv_stdout
) {
554 CloseHandle((HANDLE
)pproc
->sv_stdout
[1]);
555 pproc
->sv_stdout
[1] = 0;
557 if (pproc
->sv_stderr
) {
558 CloseHandle((HANDLE
)pproc
->sv_stderr
[1]);
559 pproc
->sv_stderr
[1] = 0;
562 free( command_line
);
563 if (envblk
) free(envblk
);
571 proc_stdin_thread(sub_process
*pproc
)
575 if (WriteFile( (HANDLE
) pproc
->sv_stdin
[0], pproc
->inp
, pproc
->incnt
,
576 &in_done
, NULL
) == FALSE
)
578 // This if should never be true for anonymous pipes, but gives
579 // us a chance to change I/O mechanisms later
580 if (in_done
< pproc
->incnt
) {
581 pproc
->incnt
-= in_done
;
582 pproc
->inp
+= in_done
;
587 return 0; // for compiler warnings only.. not reached
591 proc_stdout_thread(sub_process
*pproc
)
593 DWORD bufsize
= 1024;
596 pproc
->outp
= malloc(bufsize
);
597 if (pproc
->outp
== NULL
)
602 if (ReadFile( (HANDLE
)pproc
->sv_stdout
[0], &c
, 1, &nread
, NULL
)
604 /* map_windows32_error_to_string(GetLastError());*/
609 if (pproc
->outcnt
+ nread
> bufsize
) {
610 bufsize
+= nread
+ 512;
611 pproc
->outp
= realloc(pproc
->outp
, bufsize
);
612 if (pproc
->outp
== NULL
) {
617 pproc
->outp
[pproc
->outcnt
++] = c
;
623 proc_stderr_thread(sub_process
*pproc
)
625 DWORD bufsize
= 1024;
628 pproc
->errp
= malloc(bufsize
);
629 if (pproc
->errp
== NULL
)
634 if (ReadFile( (HANDLE
)pproc
->sv_stderr
[0], &c
, 1, &nread
, NULL
) == FALSE
) {
635 map_windows32_error_to_string(GetLastError());
640 if (pproc
->errcnt
+ nread
> bufsize
) {
641 bufsize
+= nread
+ 512;
642 pproc
->errp
= realloc(pproc
->errp
, bufsize
);
643 if (pproc
->errp
== NULL
) {
648 pproc
->errp
[pproc
->errcnt
++] = c
;
655 * Purpose: collects output from child process and returns results
661 * Notes/Dependencies:
669 sub_process
*pproc
= (sub_process
*)proc
;
670 bool_t stdin_eof
= FALSE
, stdout_eof
= FALSE
, stderr_eof
= FALSE
;
671 HANDLE childhand
= (HANDLE
) pproc
->pid
;
672 HANDLE tStdin
= NULL
, tStdout
= NULL
, tStderr
= NULL
;
673 DWORD dwStdin
, dwStdout
, dwStderr
;
678 bool_t child_dead
= FALSE
;
679 BOOL GetExitCodeResult
;
682 * Create stdin thread, if needed
684 pproc
->inp
= stdin_data
;
685 pproc
->incnt
= stdin_data_len
;
688 CloseHandle((HANDLE
)pproc
->sv_stdin
[0]);
689 pproc
->sv_stdin
[0] = 0;
691 tStdin
= (HANDLE
) _beginthreadex( 0, 1024,
692 (unsigned (__stdcall
*) (void *))proc_stdin_thread
, pproc
, 0,
693 (unsigned int *) &dwStdin
);
695 pproc
->last_err
= GetLastError();
696 pproc
->lerrno
= E_SCALL
;
702 * Assume child will produce stdout and stderr
704 tStdout
= (HANDLE
) _beginthreadex( 0, 1024,
705 (unsigned (__stdcall
*) (void *))proc_stdout_thread
, pproc
, 0,
706 (unsigned int *) &dwStdout
);
707 tStderr
= (HANDLE
) _beginthreadex( 0, 1024,
708 (unsigned (__stdcall
*) (void *))proc_stderr_thread
, pproc
, 0,
709 (unsigned int *) &dwStderr
);
711 if (tStdout
== 0 || tStderr
== 0) {
713 pproc
->last_err
= GetLastError();
714 pproc
->lerrno
= E_SCALL
;
720 * Wait for all I/O to finish and for the child process to exit
723 while (!stdin_eof
|| !stdout_eof
|| !stderr_eof
|| !child_dead
) {
726 wait_list
[wait_count
++] = tStdin
;
729 wait_list
[wait_count
++] = tStdout
;
732 wait_list
[wait_count
++] = tStderr
;
735 wait_list
[wait_count
++] = childhand
;
738 wait_return
= WaitForMultipleObjects(wait_count
, wait_list
,
739 FALSE
, /* don't wait for all: one ready will do */
740 child_dead
? 1000 :INFINITE
); /* after the child dies, subthreads have
741 one second to collect all remaining output */
743 if (wait_return
== WAIT_FAILED
) {
744 /* map_windows32_error_to_string(GetLastError());*/
745 pproc
->last_err
= GetLastError();
746 pproc
->lerrno
= E_SCALL
;
750 ready_hand
= wait_list
[wait_return
- WAIT_OBJECT_0
];
752 if (ready_hand
== tStdin
) {
753 CloseHandle((HANDLE
)pproc
->sv_stdin
[0]);
754 pproc
->sv_stdin
[0] = 0;
759 } else if (ready_hand
== tStdout
) {
761 CloseHandle((HANDLE
)pproc
->sv_stdout
[0]);
762 pproc
->sv_stdout
[0] = 0;
763 CloseHandle(tStdout
);
767 } else if (ready_hand
== tStderr
) {
769 CloseHandle((HANDLE
)pproc
->sv_stderr
[0]);
770 pproc
->sv_stderr
[0] = 0;
771 CloseHandle(tStderr
);
775 } else if (ready_hand
== childhand
) {
778 GetExitCodeResult
= GetExitCodeProcess(childhand
, &ierr
);
779 if (ierr
== CONTROL_C_EXIT
) {
780 pproc
->signal
= SIGINT
;
782 pproc
->exit_code
= ierr
;
784 if (GetExitCodeResult
== FALSE
) {
785 pproc
->last_err
= GetLastError();
786 pproc
->lerrno
= E_SCALL
;
793 /* ?? Got back a handle we didn't query ?? */
795 pproc
->lerrno
= E_FAIL
;
804 CloseHandle(tStdout
);
806 CloseHandle(tStderr
);
816 * Purpose: collects output from child process and returns results
822 * Notes/Dependencies:
831 BOOL GetExitCodeResult
;
835 pproc
= process_wait_for_any_private();
837 pproc
= (sub_process
*)proc
;
839 /* some sort of internal error */
843 childhand
= (HANDLE
) pproc
->pid
;
846 * This function is poorly named, and could also be used just to wait
847 * for child death if you're doing your own pipe I/O. If that is
848 * the case, close the pipe handles here.
850 if (pproc
->sv_stdin
[0]) {
851 CloseHandle((HANDLE
)pproc
->sv_stdin
[0]);
852 pproc
->sv_stdin
[0] = 0;
854 if (pproc
->sv_stdout
[0]) {
855 CloseHandle((HANDLE
)pproc
->sv_stdout
[0]);
856 pproc
->sv_stdout
[0] = 0;
858 if (pproc
->sv_stderr
[0]) {
859 CloseHandle((HANDLE
)pproc
->sv_stderr
[0]);
860 pproc
->sv_stderr
[0] = 0;
864 * Wait for the child process to exit
867 wait_return
= WaitForSingleObject(childhand
, INFINITE
);
869 if (wait_return
!= WAIT_OBJECT_0
) {
870 /* map_windows32_error_to_string(GetLastError());*/
871 pproc
->last_err
= GetLastError();
872 pproc
->lerrno
= E_SCALL
;
876 GetExitCodeResult
= GetExitCodeProcess(childhand
, &ierr
);
877 if (ierr
== CONTROL_C_EXIT
) {
878 pproc
->signal
= SIGINT
;
880 pproc
->exit_code
= ierr
;
882 if (GetExitCodeResult
== FALSE
) {
883 pproc
->last_err
= GetLastError();
884 pproc
->lerrno
= E_SCALL
;
896 * Description: Clean up any leftover handles, etc. It is up to the
897 * caller to manage and free the input, ouput, and stderr buffers.
903 sub_process
*pproc
= (sub_process
*)proc
;
906 if (pproc
->using_pipes
) {
907 for (i
= 0; i
<= 1; i
++) {
908 if ((HANDLE
)pproc
->sv_stdin
[i
])
909 CloseHandle((HANDLE
)pproc
->sv_stdin
[i
]);
910 if ((HANDLE
)pproc
->sv_stdout
[i
])
911 CloseHandle((HANDLE
)pproc
->sv_stdout
[i
]);
912 if ((HANDLE
)pproc
->sv_stderr
[i
])
913 CloseHandle((HANDLE
)pproc
->sv_stderr
[i
]);
916 if ((HANDLE
)pproc
->pid
)
917 CloseHandle((HANDLE
)pproc
->pid
);
925 * Create a command line buffer to pass to CreateProcess
927 * Returns: the buffer or NULL for failure
928 * Shell case: sh_name a:/full/path/to/script argv[1] argv[2] ...
929 * Otherwise: argv[0] argv[1] argv[2] ...
931 * Notes/Dependencies:
932 * CreateProcess does not take an argv, so this command creates a
933 * command line for the executable.
937 make_command_line( char *shell_name
, char *full_exec_path
, char **argv
)
941 int* enclose_in_quotes
= NULL
;
942 int* enclose_in_quotes_i
;
943 unsigned int bytes_required
= 0;
945 char* command_line_i
;
946 int cygwin_mode
= 0; /* HAVE_CYGWIN_SHELL */
947 int have_sh
= 0; /* HAVE_CYGWIN_SHELL */
949 #ifdef HAVE_CYGWIN_SHELL
950 have_sh
= (shell_name
!= NULL
|| strstr(full_exec_path
, "sh.exe"));
954 if (shell_name
&& full_exec_path
) {
956 = strlen(shell_name
) + 1 + strlen(full_exec_path
);
958 * Skip argv[0] if any, when shell_name is given.
962 * Add one for the intervening space.
964 if (*argv
) bytes_required
++;
968 while (*(argvi
++)) argc
++;
971 enclose_in_quotes
= (int*) calloc(1, argc
* sizeof(int));
973 if (!enclose_in_quotes
) {
978 /* We have to make one pass through each argv[i] to see if we need
979 * to enclose it in ", so we might as well figure out how much
980 * memory we'll need on the same pass.
984 enclose_in_quotes_i
= enclose_in_quotes
;
987 unsigned int backslash_count
= 0;
990 * We have to enclose empty arguments in ".
992 if (!(*p
)) *enclose_in_quotes_i
= 1;
998 * We have to insert a backslash for each "
999 * and each \ that precedes the ".
1001 bytes_required
+= (backslash_count
+ 1);
1002 backslash_count
= 0;
1005 #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL)
1011 * At one time we set *enclose_in_quotes_i for '*' or '?' to suppress
1012 * wildcard expansion in programs linked with MSVC's SETARGV.OBJ so
1013 * that argv in always equals argv out. This was removed. Say you have
1014 * such a program named glob.exe. You enter
1016 * at the sh command prompt. Obviously the intent is to make glob do the
1017 * wildcarding instead of sh. If we set *enclose_in_quotes_i for '*' or '?',
1018 * then the command line that glob would see would be
1020 * and the _setargv in SETARGV.OBJ would _not_ expand the *.
1024 *enclose_in_quotes_i
= 1;
1028 backslash_count
= 0;
1033 * Add one for each character in argv[i].
1040 if (*enclose_in_quotes_i
) {
1042 * Add one for each enclosing ",
1043 * and one for each \ that precedes the
1046 bytes_required
+= (backslash_count
+ 2);
1050 * Add one for the intervening space.
1052 if (*(++argvi
)) bytes_required
++;
1053 enclose_in_quotes_i
++;
1057 * Add one for the terminating NULL.
1061 command_line
= (char*) malloc(bytes_required
);
1063 if (!command_line
) {
1064 if (enclose_in_quotes
) free(enclose_in_quotes
);
1068 command_line_i
= command_line
;
1070 if (shell_name
&& full_exec_path
) {
1071 while(*shell_name
) {
1072 *(command_line_i
++) = *(shell_name
++);
1075 *(command_line_i
++) = ' ';
1077 while(*full_exec_path
) {
1078 *(command_line_i
++) = *(full_exec_path
++);
1082 *(command_line_i
++) = ' ';
1087 enclose_in_quotes_i
= enclose_in_quotes
;
1091 unsigned int backslash_count
= 0;
1093 if (*enclose_in_quotes_i
) {
1094 *(command_line_i
++) = '\"';
1099 if (cygwin_mode
&& have_sh
) { /* HAVE_CYGWIN_SHELL */
1100 /* instead of a \", cygwin likes "" */
1101 *(command_line_i
++) = '\"';
1105 * We have to insert a backslash for the "
1106 * and each \ that precedes the ".
1110 while(backslash_count
) {
1111 *(command_line_i
++) = '\\';
1115 #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL)
1116 } else if (*p
== '\\') {
1119 backslash_count
= 0;
1124 * Copy the character.
1126 *(command_line_i
++) = *(p
++);
1129 if (*enclose_in_quotes_i
) {
1130 #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL)
1132 * Add one \ for each \ that precedes the
1135 while(backslash_count
--) {
1136 *(command_line_i
++) = '\\';
1139 *(command_line_i
++) = '\"';
1143 * Append an intervening space.
1146 *(command_line_i
++) = ' ';
1149 enclose_in_quotes_i
++;
1153 * Append the terminating NULL.
1155 *command_line_i
= '\0';
1157 if (enclose_in_quotes
) free(enclose_in_quotes
);
1158 return command_line
;
1162 * Description: Given an argv and optional envp, launch the process
1163 * using the default stdin, stdout, and stderr handles.
1164 * Also, register process so that process_wait_for_any_private()
1165 * can be used via process_file_io(NULL) or
1166 * process_wait_for_any().
1170 * Notes/Dependencies:
1182 if (proc_index
>= MAXIMUM_WAIT_OBJECTS
) {
1183 DB (DB_JOBS
, ("process_easy: All process slots used up\n"));
1184 return INVALID_HANDLE_VALUE
;
1186 if (DuplicateHandle(GetCurrentProcess(),
1187 GetStdHandle(STD_INPUT_HANDLE
),
1188 GetCurrentProcess(),
1192 DUPLICATE_SAME_ACCESS
) == FALSE
) {
1194 "process_easy: DuplicateHandle(In) failed (e=%ld)\n",
1196 return INVALID_HANDLE_VALUE
;
1198 if (DuplicateHandle(GetCurrentProcess(),
1199 GetStdHandle(STD_OUTPUT_HANDLE
),
1200 GetCurrentProcess(),
1204 DUPLICATE_SAME_ACCESS
) == FALSE
) {
1206 "process_easy: DuplicateHandle(Out) failed (e=%ld)\n",
1208 return INVALID_HANDLE_VALUE
;
1210 if (DuplicateHandle(GetCurrentProcess(),
1211 GetStdHandle(STD_ERROR_HANDLE
),
1212 GetCurrentProcess(),
1216 DUPLICATE_SAME_ACCESS
) == FALSE
) {
1218 "process_easy: DuplicateHandle(Err) failed (e=%ld)\n",
1220 return INVALID_HANDLE_VALUE
;
1223 hProcess
= process_init_fd(hIn
, hOut
, hErr
);
1225 if (process_begin(hProcess
, argv
, envp
, argv
[0], NULL
)) {
1226 fake_exits_pending
++;
1227 /* process_begin() failed: make a note of that. */
1228 if (!((sub_process
*) hProcess
)->last_err
)
1229 ((sub_process
*) hProcess
)->last_err
= -1;
1230 ((sub_process
*) hProcess
)->exit_code
= process_last_err(hProcess
);
1232 /* close up unused handles */
1238 process_register(hProcess
);