1 /* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */
2 /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
3 /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
7 #include <msvcrt/stdio.h>
8 #include <msvcrt/stdlib.h>
9 #include <msvcrt/string.h>
10 #include <msvcrt/errno.h>
11 //#include <msvcrt/limits.h>
12 #include <msvcrt/process.h>
13 #include <msvcrt/ctype.h>
14 #include <msvcrt/io.h>
17 #include <msvcrt/msvcrtdbg.h>
36 // information about crtdll file handles is not passed to child
37 int _fileinfo_dll
= 0;
40 direct_exec_tail(const char *program
, const char *args
,
42 PROCESS_INFORMATION
*ProcessInformation
)
45 static STARTUPINFO StartupInfo
;
47 StartupInfo
.cb
= sizeof(STARTUPINFO
);
48 StartupInfo
.lpReserved
= NULL
;
49 StartupInfo
.dwFlags
= 0 /*STARTF_USESTDHANDLES*/;
50 StartupInfo
.wShowWindow
= SW_SHOWDEFAULT
;
51 StartupInfo
.lpReserved2
= NULL
;
52 StartupInfo
.cbReserved2
= 0;
53 StartupInfo
.hStdInput
= _get_osfhandle(0);
54 StartupInfo
.hStdOutput
= _get_osfhandle(1);
55 StartupInfo
.hStdError
= _get_osfhandle(2);
58 if (! CreateProcessA((char *)program
,(char *)args
,NULL
,NULL
,TRUE
,0,(LPVOID
)envp
,NULL
,&StartupInfo
,ProcessInformation
) )
60 __set_errno( GetLastError() );
64 return (int)ProcessInformation
->hProcess
;
67 static int vdm_exec(const char *program
, char **argv
, char **envp
,
68 PROCESS_INFORMATION
*ProcessInformation
)
70 static char args
[1024];
74 strcpy(args
,"vdm.exe ");
75 while(argv
[i
] != NULL
) {
81 return direct_exec_tail(program
,args
,envp
,ProcessInformation
);
84 static int go32_exec(const char *program
, char **argv
, char **envp
,
85 PROCESS_INFORMATION
*ProcessInformation
)
87 char * penvblock
, * ptr
;
91 for (i
= 0, len
= 0; envp
[i
]; i
++) {
92 len
+= strlen(envp
[i
]) + 1;
94 penvblock
= ptr
= (char*)malloc(len
+ 1);
95 if (penvblock
== NULL
)
98 for(i
= 0, *ptr
= 0; envp
[i
]; i
++) {
100 ptr
+= strlen(envp
[i
]) + 1;
104 for(i
= 0, len
= 0; argv
[i
]; i
++) {
105 len
+= strlen(argv
[i
]) + 1;
108 args
= (char*) malloc(len
+ 1);
115 for(i
= 0, *args
= 0; argv
[i
]; i
++) {
116 strcat(args
,argv
[i
]);
117 if (argv
[i
+1] != NULL
) {
122 result
= direct_exec_tail(program
,args
,(const char*)penvblock
,ProcessInformation
);
129 command_exec(const char *program
, char **argv
, char **envp
,
130 PROCESS_INFORMATION
*ProcessInformation
)
132 static char args
[1024];
139 strcpy(args
,"cmd.exe /c ");
140 while(argv
[i
] != NULL
) {
141 strcat(args
,argv
[i
]);
146 return direct_exec_tail(program
,args
,envp
,ProcessInformation
);
150 static int script_exec(const char *program
, char **argv
, char **envp
,
151 PROCESS_INFORMATION
*ProcessInformation
)
157 /* Note: the following list is not supposed to mention *every*
158 possible extension of an executable file. It only mentions
159 those extensions that can be *omitted* when you invoke the
160 executable from one of the shells used on MSDOS. */
162 const char *extension
;
163 int (*interp
)(const char *, char **, char **,
164 PROCESS_INFORMATION
*);
166 { ".com", vdm_exec
},
167 { ".exe", go32_exec
},
168 { ".dll", go32_exec
},
169 { ".cmd", command_exec
},
170 { ".bat", command_exec
},
171 { ".btm", command_exec
},
172 { ".sh", script_exec
}, /* for compatibility with ms_sh */
173 { ".ksh", script_exec
},
174 { ".pl", script_exec
}, /* Perl */
175 { ".sed", script_exec
},
177 { 0, script_exec
}, /* every extension not mentioned above calls it */
181 /* This is the index into the above array of the interpreter
182 which is called when the program filename has no extension. */
183 #define INTERP_NO_EXT (sizeof(interpreters)/sizeof(interpreters[0]) - 3)
185 /*-------------------------------------------------*/
190 int _spawnve(int mode
, const char *path
, char *const argv
[], char *const envp
[])
192 /* This is the one that does the work! */
193 PROCESS_INFORMATION ProcessInformation
;
194 union { char *const *x
; char **p
; } u
;
198 char rpath
[FILENAME_MAX
], *rp
, *rd
=0;
204 DPRINT("_spawnve('%s')\n", path
);
206 if (path
== 0 || argv
[0] == 0)
212 if (strlen(path
) > FILENAME_MAX
- 1)
214 errno
= ENAMETOOLONG
;
219 u
.x
= argv
; argvp
= u
.p
;
220 u
.x
= envp
; envpp
= u
.p
;
222 fflush(stdout
); /* just in case */
223 for (rp
=rpath
; *path
; *rp
++ = *path
++)
227 if (*path
== '\\' || *path
== '/')
232 /* If LFN is supported on the volume where rpath resides, we
233 might have something like foo.bar.exe or even foo.exe.com.
234 If so, look for RPATH.ext before even trying RPATH itself. */
237 for (i
=0; interpreters
[i
].extension
; i
++)
239 strcpy(rp
, interpreters
[i
].extension
);
240 if (_access(rpath
, F_OK
) == 0 && !(is_dir
= (_access(rpath
, D_OK
) == 0)))
250 const char *rpath_ext
;
262 for ( ; interpreters
[i
].extension
; i
++)
263 if (_stricmp(rpath_ext
, interpreters
[i
].extension
) == 0
264 && _access(rpath
, F_OK
) == 0
265 && !(is_dir
= (_access(rpath
, D_OK
) == 0)))
274 errno
= is_dir
? EISDIR
: ENOENT
;
278 i
= interpreters
[i
].interp(rpath
, argvp
, envpp
, &ProcessInformation
);
279 if (mode
== P_OVERLAY
)
283 WaitForSingleObject(ProcessInformation
.hProcess
,INFINITE
);
284 GetExitCodeProcess(ProcessInformation
.hProcess
,&ExitCode
);
286 CloseHandle(ProcessInformation
.hThread
);
287 CloseHandle(ProcessInformation
.hProcess
);
291 CloseHandle(ProcessInformation
.hThread
);
299 const char * find_exec(char * path
,char *rpath
)
307 if (strlen(path
) > FILENAME_MAX
- 1)
310 /* copy path in rpath */
311 for (rd
=path
,rp
=rpath
; *rd
; *rp
++ = *rd
++)
314 /* try first with the name as is */
315 for (i
=0; interpreters
[i
].extension
; i
++)
317 strcpy(rp
, interpreters
[i
].extension
);
318 if (_access(rpath
, F_OK
) == 0 && !(is_dir
= (_access(rpath
, D_OK
) == 0)))
327 /* search in the PATH */
328 char winpath
[MAX_PATH
];
329 if( GetEnvironmentVariableA("PATH",winpath
,MAX_PATH
))
336 for ( ; *ep
&& (*ep
!= ';') ; *rp
++ = *ep
++)
339 for (rd
=path
; *rd
; *rp
++ = *rd
++)
342 for (i
=0; interpreters
[i
].extension
; i
++)
344 strcpy(rp
, interpreters
[i
].extension
);
345 if (_access(rpath
, F_OK
) == 0 && !(is_dir
= (_access(rpath
, D_OK
) == 0)))
361 int _spawnvpe(int nMode
, const char* szPath
, char* const* szaArgv
, char* const* szaEnv
)
363 char rpath
[FILENAME_MAX
];
365 return _spawnve(nMode
, find_exec((char*)szPath
,rpath
), szaArgv
, szaEnv
);