diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/crt32/exec | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/crt32/exec')
26 files changed, 2813 insertions, 0 deletions
diff --git a/private/crt32/exec/cenvarg.c b/private/crt32/exec/cenvarg.c new file mode 100644 index 000000000..0a0755748 --- /dev/null +++ b/private/crt32/exec/cenvarg.c @@ -0,0 +1,373 @@ +/*** +*cenvarg.c - OS/2 set up environment, command line blocks +* +* Copyright (c) 1986-1991, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _cenvarg() - setup environment/command line blocks +* +*Revision History: +* 05-20-86 SKS Module created +* 10-03-86 SKS Wasn't clearing final null byte in environment block +* 10-13-86 SKS Check for environment segment > 32 KB (esp. > 64 KB) +* 10-23-86 SKS New format for C_FILE_INFO for Prot-Mode execution +* 12-17-86 SKS Support for new command line format +* 01-21-87 BCM Removed DCR475 switch, new command line format official +* 07-07-87 JCR Corrected bug in ENV_MAX check +* 05-24-88 SJM Removed support for ;C_FILE_INFO for Real-Mode execution +* 06-01-88 SJM Added support for .cmd files via comname/cmdname +* 12-27-88 JCR Added support for _fileinfo option +* 03-08-90 GJF Made calling type _CALLTYPE1, added #include +* <cruntime.h>, removed #include <register.h> and fixed +* the copyright. Also, cleaned up the formatting a bit. +* 04-02-90 GJF Added const to arg types. +* 08-10-90 SBM Compiles cleanly with -W3 +* 09-27-90 GJF New-style function declarator. +* 12-06-90 GJF Added Win32 support. That is, support for encoding +* _osfinfo[] data into _C_FILE_INFO environment variable. +* 01-18-91 GJF ANSI naming. +* 02-05-91 SRW Removed usage of _C_FILE_INFO to pass binary data +* to child process. [_WIN32_] +* 05-07-92 SKS Remove code which stripped the extension from a batch +* file while building arguments to CMD.EXE. This was +* done long ago (1988) for DOS 3.X, I think. +* 10-24-92 SKS Remove special code for batch files - not needed on NT +* 07-15-93 SRW Added _capture_argv function +* +*******************************************************************************/ + +#include <cruntime.h> +#include <stdio.h> +#include <errno.h> +#include <msdos.h> +#include <stdlib.h> +#include <stdarg.h> +#include <internal.h> +#include <string.h> + +#define ENV_MAX 32767 + +/*** +*int _cenvarg(argv, envp, argblk, envblk, name) - set up cmd line/environ +* +*Purpose: +* Set up the block forms of the environment and the command line. +* If "envp" is null, "_environ" is used instead. +* File handle info is passed in the environment if _fileinfo is !0. +* +*Entry: +* char **argv - argument vector +* char **envp - environment vector +* char **argblk - pointer to pointer set to malloc'ed space for args +* char **envblk - pointer to pointer set to malloc'ed space for env +* char *name - name of program being invoked +* +*Exit: +* returns 0 if ok, -1 if fails +* stores through argblk and envblk +* (calls malloc) +* +*Exceptions: +* +*******************************************************************************/ + +int _CALLTYPE1 _cenvarg ( + const char * const *argv, + const char * const *envp, + char **argblk, + char **envblk, + const char *name + ) +{ + REG1 const char * const *vp; + REG2 unsigned tmp; + REG3 char *cptr; + unsigned arg_len; + int cfi_len; /* counts the number of file handles in CFI */ + + /* + * Null environment pointer "envp" means use global variable "_environ" + */ + +#ifdef _CRUISER_ + int i; /* loop counter */ + + if (!envp) + envp = _environ; +#endif /* _CRUISER_ */ + + /* + * Allocate space for command line string + * tmp counts the number of bytes in the command line string + * including spaces between arguments + * An empty string is special -- 2 bytes + */ + + for (vp = argv, tmp = 2; *vp; tmp += strlen(*vp++) + 1) + if( tmp > ENV_MAX ) + break; + + /* + * Make sure there are not already > 32 KB in strings + */ + + if ((arg_len = tmp) >= ENV_MAX) { + *envblk = NULL; + errno = E2BIG; + _doserrno = E_badenv; + return(-1); + } + + /* + * Allocate space for the command line plus 2 null bytes + */ + + if ( (*argblk = malloc(tmp)) == NULL) { + *envblk = NULL; + errno = ENOMEM; + _doserrno = E_nomem; + return(-1); + } + + /* + * Allocate space for environment strings + * tmp counts the number of bytes in the environment strings + * including nulls between strings + * Also add "_C_FILE_INFO=" string + */ + +#ifdef _WIN32_ + if (envp) +#endif /* _WIN32_ */ + + for (vp = envp, tmp = 2; *vp; tmp += strlen(*vp++) + 1) + if( tmp > ENV_MAX ) + break; + +#ifdef _CRUISER_ + if (_fileinfo) + for (cfi_len = _nfile; cfi_len && !_osfile[cfi_len-1]; + cfi_len--) ; + else + cfi_len = 0; /* no _C_FILE_INFO */ + + /* + * mode-independent C-FILE-INFO calculation + */ + + if (cfi_len) /* Add 1 (each) for the "=" & null byte */ + /* Plus 2 bytes for each value in _osfile */ + tmp += /* strlen(_acfinfo) */ CFI_LENGTH + 2 + cfi_len + + cfi_len; + +#else /* ndef _CRUISER_ */ + +#ifdef _WIN32_ + + /* + ** The _osfile and _osfhnd arrays are passed as binary data in + ** dospawn.c + */ + + cfi_len = 0; /* no _C_FILE_INFO */ + +#else /* ndef _WIN32_ */ + +#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED! + +#endif /* _WIN32_ */ + +#endif /* _CRUISER_ */ + +#ifdef _WIN32_ + if (!envp) + *envblk = NULL; + else { +#endif /* _WIN32_ */ + + /* + * Check for too many strings to be placed in the environment + * Increment tmp for final null byte after environment strings + * "tmp + arg_len + strlen(name) + 1" must also be < ENV_MAX + * Do (long) comparison in case tmp > ENV_MAX from C_FILE_INFO + */ + + if( (long) tmp + arg_len + strlen(name) > ENV_MAX - 1 ) { + free(*argblk); + *argblk = NULL; + errno = E2BIG; + _doserrno = E_badenv; + return(-1); + } + + /* + * Allocate space for the environment strings plus extra null byte + */ + + if( !(*envblk = malloc(tmp)) ) { + free(*argblk); + *argblk = NULL; + errno = ENOMEM; + _doserrno = E_nomem; + return(-1); + } + +#ifdef _WIN32_ + } +#endif /* _WIN32_ */ + + /* + * Build the command line by concatenating the argument strings + * with spaces between, and two null bytes at the end + * NOTE: The argv[0] argument is followed by a null. + */ + + cptr = *argblk; + vp = argv; + + if (!*vp) /* Empty argument list ? */ + ++cptr; /* just two null bytes */ + else { /* argv[0] must be followed by a null */ + strcpy(cptr, *vp); + cptr += strlen(*vp++) + 1; + } + + while( *vp ) { + strcpy(cptr, *vp); + cptr += strlen(*vp++); + *cptr++ = ' '; + } + + * cptr = cptr[ -1 ] = '\0'; /* remove extra blank, add double null */ + +#ifdef _WIN32_ + if (envp) { +#endif /* _WIN32_ */ + + /* + * Build the environment block by concatenating the environment strings + * with nulls between and two null bytes at the end + * C_FILE_INFO is stored as if it were an environment string + */ + + cptr = *envblk; + vp = envp; + + if( !(*vp || cfi_len) ) /* No environment strings? */ + *cptr++ = '\0'; /* just two null bytes */ + + while( *vp ) { + strcpy(cptr, *vp); + cptr += 1 + strlen(*vp++); + } + +#ifdef _CRUISER_ + + if(cfi_len) { + strcpy(cptr,_acfinfo); + cptr += /* strlen(_acfinfo) */ CFI_LENGTH; + + i = cfi_len; + for(tmp = 0; i--; ++tmp) { + *cptr++ = (char)(((_osfile[tmp] >> 4) & 0xF) + 'A'); + *cptr++ = (char)((_osfile[tmp] & 0xF) + 'A'); + } + *cptr++ = '\0'; + } + +#else /* ndef _CRUISER_ */ + +#ifdef _WIN32_ + + /* + ** The _osfile and _osfhnd arrays are passed as binary data in + ** dospawn.c + */ + +#else /* ndef _WIN32_ */ + +#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED! + +#endif /* _WIN32_ */ + +#endif /* _CRUISER_ */ + +#ifdef _WIN32_ + } +#endif /* _WIN32_ */ + + /* + * Extra null terminates the segment + */ + *cptr = '\0'; + + return(0); +} + + +/*** +*int _capture_argv(arglist, static_argv, max_static_entries) - set up argv array +* for exec?? functions +* +*Purpose: +* Set up the argv array for the exec?? functions by captures the arguments +* from the passed va_list into the static_argv array. If the size of the +* static_argv array as specified by the max_static_entries parameter is +* not large enough, then allocates a dynamic array to hold the arguments. +* Return the address of the final argv array. If NULL then not enough +* memory to hold argument array. If different from static_argv parameter +* then call must free the return argv array when done with it. +* +* The scan of the arglist is terminated when a NULL argument is reached. +* The terminating NULL parameter is stored in the resulting argv array. +* +*Entry: +* va_list *arglist - pointer to variable length argument list. +* char *firstarg - first argument to store in array +* char **static_argv - pointer to static argv to use. +* size_t max_static_entries - maximum number of entries that can be placed +* in static_argv array. +* +*Exit: +* returns NULL if no memory. +* Otherwise returns pointer to argv array. +* (sometimes calls malloc) +* +*Exceptions: +* +*******************************************************************************/ + +char ** _CALLTYPE1 _capture_argv( + va_list *arglist, + const char *firstarg, + char **static_argv, + size_t max_static_entries + ) +{ + char ** argv; + char * nextarg; + size_t i; + size_t max_entries; + + nextarg = (char *)firstarg; + argv = static_argv; + max_entries = max_static_entries; + i = 0; + for (;;) { + if (i >= max_entries) { + if (argv == static_argv) + argv = malloc((max_entries * 2) * sizeof(char *)); + else + argv = realloc(argv, (max_entries * 2) * sizeof(char *)); + + if (argv == NULL) break; + max_entries += max_entries; + } + + argv[ i++ ] = nextarg; + if (nextarg == NULL) break; + nextarg = va_arg(*arglist, char *); + } + + return argv; +} diff --git a/private/crt32/exec/cfinfo.c b/private/crt32/exec/cfinfo.c new file mode 100644 index 000000000..e761a1f68 --- /dev/null +++ b/private/crt32/exec/cfinfo.c @@ -0,0 +1,22 @@ +/*** +*cfinfo.c - clears C file info flag +* +* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved. +* +*Purpose: +* Clears the C file info flag. By default, the openfile information +* is NOT passed along to children on spawn/exec calls. If the flag +* is set, openfile information WILL get passed on to children on +* spawn/exec calls. +* +*Revision History: +* 06-07-89 PHG Module created, based on asm version +* 04-03-90 GJF Added #include <cruntime.h>. Also, fixed the copyright. +* 01-23-92 GJF Added #include <stdlib.h> (contains decl of _fileinfo). +* +*******************************************************************************/ + +#include <cruntime.h> +#include <stdlib.h> + +int _fileinfo = 0; diff --git a/private/crt32/exec/dospawn.c b/private/crt32/exec/dospawn.c new file mode 100644 index 000000000..900c2996d --- /dev/null +++ b/private/crt32/exec/dospawn.c @@ -0,0 +1,303 @@ +/*** +*dospawn.c - OS/2 spawn a child process +* +* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _dospawn - spawn a child process +* +*Revision History: +* 06-07-89 PHG Module created, based on asm version +* 03-08-90 GJF Made calling type _CALLTYPE2 (for now), added #include +* <cruntime.h> and fixed the copyright. Also, cleaned +* up the formatting a bit. +* 04-02-90 GJF Now _CALLTYPE1. Added const to type of name arg. +* 07-24-90 SBM Removed '32' from API names +* 09-27-90 GJF New-style function declarator. +* 10-30-90 GJF Added _p_overlay (temporary hack). +* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h> +* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals. +* 01-16-91 SRW Fixed return value for dospawn [_WIN32_] +* 01-17-91 GJF ANSI naming. +* 01-25-91 SRW Changed CreateProcess parameters [_WIN32_] +* 01-29-91 SRW Changed CreateProcess parameters again [_WIN32_] +* 02-05-91 SRW Changed to pass _osfile and _osfhnd arrays as binary +* data to child process. [_WIN32_] +* 02-18-91 SRW Fixed code to return correct process handle and close +* handle for P_WAIT case. [_WIN32_] +* 04-05-91 SRW Fixed code to free StartupInfo.lpReserved2 after +* CreateProcess call. [_WIN32_] +* 04-26-91 SRW Removed level 3 warnings (_WIN32_) +* 12-02-91 SRW Fixed command line setup code to not append an extra +* space [_WIN32_] +* 12-16-91 GJF Return full 32-bit exit code from the child process +* [_WIN32_]. +* 02-14-92 GJF Replaced _nfile with _nhandle for Win32. +* 02-18-92 GJF Merged in 12-16-91 change from \\vangogh version +* 11-20-92 SKS errno/_doserrno must be 0 in case of success. This +* will distinguish a child process return code of -1L +* (errno == 0) from an actual error (where errno != 0). +* 01-08-93 CFW Added code to handle _P_DETACH case; add fdwCreate variable, +* nuke stdin, stdout, stderr entries of _osfile & _osfhnd tables, +* close process handle to completely detach process +* +*******************************************************************************/ + +#include <cruntime.h> +#include <oscalls.h> +#include <internal.h> +#include <process.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> + +int _VARTYPE1 _p_overlay = 2; + +/*** +*int _dospawn(mode, name, cmdblk, envblk) - spawn a child process +* +*Purpose: +* Spawns a child process +* +*Entry: +* int mode - _P_WAIT, _P_NOWAIT, _P_NOWAITO, _P_OVERLAY, or _P_DETACH +* char *name - name of program to execute +* char *cmdblk - parameter block +* char *envblk - environment block +* +*Exit: +* _P_OVERLAY: -1 = error, otherwise doesn't return +* _P_WAIT: termination code << 8 + result code +* _P_DETACH: -1 = error, 0 = success +* others: PID of process +* +*Exceptions: +* +*******************************************************************************/ + +int _CALLTYPE1 _dospawn ( + int mode, + const char *name, + char *cmdblk, + char *envblk + ) +{ + char syncexec, asyncresult, background; +#ifdef _CRUISER_ + + RESULTCODES result_codes; /* result code of DosExecPgm */ + ULONG exec_flags; /* flags for DosExecPgm */ + ULONG dosretval; /* OS/2 return value */ + +#else /* ndef _CRUISER_ */ + +#ifdef _WIN32_ + + LPSTR CommandLine; + STARTUPINFO StartupInfo; + PROCESS_INFORMATION ProcessInformation; + BOOL CreateProcessStatus; + ULONG dosretval; /* OS return value */ + DWORD retval; + DWORD fdwCreate = 0; /* Flags for CreateProcess */ + int cfi_len; /* counts the number of file handles in CFI */ + +#else /* ndef _WIN32_ */ + +#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED! + +#endif /* _WIN32_ */ + +#endif /* _CRUISER_ */ + + /* translate input mode value to individual flags */ + syncexec = asyncresult = background = 0; + switch (mode) { + case _P_WAIT: syncexec=1; break; /* synchronous execution */ + case 2: /* _P_OVERLAY */ + case _P_NOWAITO: break; /* asynchronous execution */ + case _P_NOWAIT: asyncresult=1; break; /* asynch + remember result */ + case _P_DETACH: background=1; break; /* detached in null scrn grp */ + default: + /* invalid mode */ + errno = EINVAL; + _doserrno = 0; /* not a Dos error */ + return -1; + } + +#ifdef _CRUISER_ + /* translate input mode value to system call value */ + if (syncexec) + exec_flags = EXEC_SYNC; + else + if (asyncresult) + exec_flags = EXEC_ASYNCRESULT; + else + if (background) + exec_flags = EXEC_BACKGROUND; + else + exec_flags = EXEC_ASYNC; + + /* issue system call to run process, want no DynaLink failure name */ + if (dosretval = DOSEXECPGM(NULL, 0, exec_flags, cmdblk, envblk, + &result_codes, (char *)name)) { + /* error -- map error code and return */ + _dosmaperr(dosretval); + return -1; + } + + if (mode == 2 /* _P_OVERLAY */) { + /* destroy ourselves */ + _exit(0); + } + else if (mode == _P_WAIT) { + /* return termination code and exit code -- note we only + return low byte of result code, although OS/2 allows a + word -- this is for XENIX compatability */ + return ((result_codes.codeTerminate & 0xFF) << 8) + + (result_codes.codeResult & 0xFF); + } + else { + /* asynchronous spawn -- return PID */ + return result_codes.codeTerminate; + } + +#else /* ndef _CRUISER_ */ + +#ifdef _WIN32_ + // + // Loop over null separate arguments, and replace null separators + // with spaces to turn it back into a single null terminated + // command line. + // + CommandLine = cmdblk; + while (*cmdblk) { + while (*cmdblk) { + cmdblk++; + } + + // + // If not last argument, turn null separator into a space. + // + if (cmdblk[1] != '\0') { + *cmdblk++ = ' '; + } + } + + memset(&StartupInfo,0,sizeof(StartupInfo)); + StartupInfo.cb = sizeof(StartupInfo); + + for (cfi_len = _nhandle; cfi_len && !_osfile[cfi_len-1];cfi_len--) { + } + + StartupInfo.cbReserved2 = (WORD)(sizeof( int ) + + (cfi_len * + (sizeof( char ) + sizeof( long ) ) + ) + ); + StartupInfo.lpReserved2 = calloc( StartupInfo.cbReserved2, 1 ); + memcpy( StartupInfo.lpReserved2, + &cfi_len, + sizeof( int ) + ); + memcpy( StartupInfo.lpReserved2 + sizeof( int ), + _osfile, + cfi_len * sizeof( char ) + ); + memcpy( StartupInfo.lpReserved2 + sizeof( int ) + + (cfi_len * sizeof( char )), + _osfhnd, + cfi_len * sizeof( long ) + ); + + if (background) + { + int fh; + + /* child process is detached, cannot access console, must nuke first + three entries (stdin, stdout, stderr) in _osfile & _osfhnd tables */ + + // set _osfile[] + for ( fh = 0 ; fh <= 2 ; ++fh ) + { + *(char *)(StartupInfo.lpReserved2 + + sizeof(int) + + fh * sizeof(char)) = 0; + } + + // set _osfhnd[] + for ( fh = 0 ; fh <= 2 ; ++fh ) + { + *(long *)(StartupInfo.lpReserved2 + + sizeof(int) + + cfi_len * sizeof(char) + + fh * sizeof(long)) = (long)INVALID_HANDLE_VALUE; + } + + fdwCreate |= DETACHED_PROCESS; + } + + /** + * Set errno to 0 to distinguish a child process + * which returns -1L from an error in the spawning + * (which will set errno to something non-zero + **/ + + _doserrno = errno = 0 ; + + CreateProcessStatus = CreateProcess( (LPSTR)name, + CommandLine, + NULL, + NULL, + TRUE, + fdwCreate, + envblk, + NULL, + &StartupInfo, + &ProcessInformation + ); + + dosretval = GetLastError(); + free( StartupInfo.lpReserved2 ); + + if (!CreateProcessStatus) + { + _dosmaperr(dosretval); + return -1; + } + + if (mode == 2 /* _P_OVERLAY */) { + /* destroy ourselves */ + _exit(0); + } + else if (mode == _P_WAIT) { + WaitForSingleObject(ProcessInformation.hProcess, (DWORD)(-1L)); + + /* return termination code and exit code -- note we return + the full exit code */ + GetExitCodeProcess(ProcessInformation.hProcess, &retval); + + CloseHandle(ProcessInformation.hProcess); + } + else if (mode == _P_DETACH) { + /* like totally detached asynchronous spawn, dude, + close process handle, return 0 for success */ + CloseHandle(ProcessInformation.hProcess); + retval = (DWORD)0; + } + else { + /* asynchronous spawn -- return PID */ + retval = (DWORD)ProcessInformation.hProcess; + } + + CloseHandle(ProcessInformation.hThread); + return retval; + +#else /* ndef _WIN32_ */ + +#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED! + +#endif /* _WIN32_ */ + +#endif /* _CRUISER_ */ +} diff --git a/private/crt32/exec/execl.c b/private/crt32/exec/execl.c new file mode 100644 index 000000000..3c2d5efd5 --- /dev/null +++ b/private/crt32/exec/execl.c @@ -0,0 +1,76 @@ +/*** +*execl.c - execute a file with a list of arguments +* +* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _execl() - execute a file with a list of arguments +* +*Revision History: +* 10-14-83 RN written +* 12-11-87 JCR Added "_LOAD_DS" to declaration +* 11-20-89 GJF Fixed copyright, indents. Added const attribute to +* types of filename and arglist. #include-d PROCESS.H +* and added ellipsis to match prototype. +* 03-08-90 GJF Replaced _LOAD_DS with _CALLTYPE2, added #include +* <cruntime.h> and removed #include <register.h>. +* 07-24-90 SBM Removed redundant includes, replaced <assertm.h> by +* <assert.h> +* 09-27-90 GJF New-style function declarator. +* 01-17-91 GJF ANSI naming. +* 02-14-90 SRW Use NULL instead of _environ to get default. +* 07-16-93 SRW ALPHA Merge +* +*******************************************************************************/ + +#include <cruntime.h> +#include <assert.h> +#include <stdlib.h> +#include <process.h> +#include <stdarg.h> +#include <internal.h> + +/*** +*int _execl(filename, arglist) - execute a file with arg list +* +*Purpose: +* Transform the argument list so it is a vector, then pass its address +* to execve. Use a pointer to the default environment vector. +* +*Entry: +* char *filename - file to execute +* char *arglist - list of arguments +* call as _execl(path, arg0, arg1, ..., argn, NULL); +* +*Exit: +* destroys the calling process, hopefully +* returns -1 if fails +* +*Exceptions: +* +*******************************************************************************/ + +int _CALLTYPE2 _execl ( + const char *filename, + const char *arglist, + ... + ) +{ + va_list vargs; + char * argbuf[64]; + char ** argv; + int result; + + assert(filename != NULL); + assert(*filename != '\0'); + assert(arglist != NULL); + assert(*arglist != '\0'); + + va_start(vargs, arglist); + argv = _capture_argv(&vargs, arglist, argbuf, 64); + va_end(vargs); + + result = _execve(filename,argv,NULL); + if (argv && argv != argbuf) free(argv); + return result; +} diff --git a/private/crt32/exec/execle.c b/private/crt32/exec/execle.c new file mode 100644 index 000000000..2b74e4d31 --- /dev/null +++ b/private/crt32/exec/execle.c @@ -0,0 +1,79 @@ +/*** +*execle.c - execute a file with arg list and environment +* +* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _execle() - execute a file +* +*Revision History: +* 10-14-83 RN written +* 12-11-87 JCR Added "_LOAD_DS" to declaration +* 11-20-89 GJF Fixed copyright, indents. Added const attribute to +* types of filename and arglist. #include-d PROCESS.H +* and added ellipsis to match prototype. +* 03-08-90 GJF Replaced _LOAD_DS with _CALLTYPE2, added #include +* <cruntime.h> and removed #include <register.h> +* 07-24-90 SBM Removed redundant includes, replaced <assertm.h> by +* <assert.h> +* 09-27-90 GJF New-style function declarator. +* 01-17-91 GJF ANSI naming. +* 07-16-93 SRW ALPHA Merge +* +*******************************************************************************/ + +#include <cruntime.h> +#include <assert.h> +#include <stddef.h> +#include <process.h> +#include <stdarg.h> +#include <internal.h> +#include <malloc.h> + +/*** +*int _execle(filename, arglist) - execute a file +* +*Purpose: +* Execute the given file (overlays the calling process). +* We must dig the environment vector out of the stack and pass it +* and address of argument vector to execve. +* +*Entry: +* char *filename - file to execute +* char *arglist - argument list followed by environment +* should be called like _execle(path, arg0, arg1, ..., argn, NULL, envp); +* +*Exit: +* destroys calling process (hopefully) +* if fails, returns -1. +* +*Exceptions: +* +*******************************************************************************/ + +int _CALLTYPE2 _execle ( + const char *filename, + const char *arglist, + ... + ) +{ + va_list vargs; + char * argbuf[64]; + char ** argv; + char ** envp; + int result; + + assert(filename != NULL); + assert(*filename != '\0'); + assert(arglist != NULL); + assert(*arglist != '\0'); + + va_start(vargs, arglist); + argv = _capture_argv(&vargs, arglist, argbuf, 64); + envp = va_arg(vargs, char **); + va_end(vargs); + + result = _execve(filename,argv,envp); + if (argv && argv != argbuf) free(argv); + return result; +} diff --git a/private/crt32/exec/execlp.c b/private/crt32/exec/execlp.c new file mode 100644 index 000000000..4e622be61 --- /dev/null +++ b/private/crt32/exec/execlp.c @@ -0,0 +1,77 @@ +/*** +*execlp.c - execute a file (search along PATH) +* +* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _execlp() - execute a file and search along PATH +* +*Revision History: +* 10-17-83 RN written +* 12-11-87 JCR Added "_LOAD_DS" to declaration +* 11-20-89 GJF Fixed copyright, indents. Added const attribute to +* types of filename and arglist. #include-d PROCESS.H +* and added ellipsis to match prototype. +* 03-08-90 GJF Replaced _LOAD_DS with _CALLTYPE2, added #include +* <cruntime.h> and removed #include <register.h>. +* 07-24-90 SBM Removed redundant includes, replaced <assertm.h> by +* <assert.h> +* 09-27-90 GJF New-style function declarator. +* 01-17-91 GJF ANSI naming. +* 07-16-93 SRW ALPHA Merge +* +*******************************************************************************/ + +#include <cruntime.h> +#include <assert.h> +#include <stddef.h> +#include <process.h> +#include <stdarg.h> +#include <internal.h> +#include <malloc.h> + +/*** +*int _execlp(filename, arglist) - execute a file, search along PATH +* +*Purpose: +* Execute the given file with the given arguments; search along PATH +* for the file. We pass the arguments to execvp where several paths +* will be tried until one works. +* +*Entry: +* char *filename - file to execute +* char *arglist - argument list +* call as _execlp(path, arg0, arg1, ..., argn, NULL); +* +*Exit: +* destroys calling process (hopefully) +* returns -1 if fails. +* +*Exceptions: +* +*******************************************************************************/ + +int _CALLTYPE2 _execlp ( + const char *filename, + const char *arglist, + ... + ) +{ + va_list vargs; + char * argbuf[64]; + char ** argv; + int result; + + assert(filename != NULL); + assert(*filename != '\0'); + assert(arglist != NULL); + assert(*arglist != '\0'); + + va_start(vargs, arglist); + argv = _capture_argv(&vargs, arglist, argbuf, 64); + va_end(vargs); + + result = _execvp(filename,argbuf); + if (argv && argv != argbuf) free(argv); + return result; +} diff --git a/private/crt32/exec/execlpe.c b/private/crt32/exec/execlpe.c new file mode 100644 index 000000000..991cf757a --- /dev/null +++ b/private/crt32/exec/execlpe.c @@ -0,0 +1,82 @@ +/*** +*execlpe.c - execute a file with environ, search along path +* +* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _execlpe() - execute a file with environ and search along PATH +* +*Revision History: +* 10-17-83 RN written +* ??-??-?? TC added execlpe +* 06-18-86 JMB added environment pointer which was erroneously missing +* 06-11-87 PHG removed unnecessary environment pointer (isn't this +* fun!) +* 12-11-87 JCR Added "_LOAD_DS" to declaration +* 11-20-89 GJF Fixed copyright, indents. Added const attribute to +* types of filename and arglist. #include-d PROCESS.H +* and added ellipsis to match prototype. +* 03-08-90 GJF Replaced _LOAD_DS with _CALLTYPE2, added #include +* <cruntime.h> and removed #include <register.h> +* 07-24-90 SBM Removed redundant includes, replaced <assertm.h> by +* <assert.h> +* 09-27-90 GJF New-style function declarator. +* 01-17-91 GJF ANSI naming. +* 07-16-93 SRW ALPHA Merge +* +*******************************************************************************/ + +#include <cruntime.h> +#include <assert.h> +#include <stdlib.h> +#include <process.h> +#include <stdarg.h> +#include <internal.h> + +/*** +*int _execlpe(filename, arglist) - execute a file with environ +* +*Purpose: +* Executes the given file with the parameters and the environment +* which is passed after the parameters. Searches along the PATH +* for the file (done by execvp). +* +*Entry: +* char *filename - file to execute +* char *arglist - argument list (environment is at the end) +* call as _execlpe(path, arg0, arg1, ..., argn, NULL, envp); +* +*Exit: +* destroys the calling process (hopefully) +* if fails, returns -1 +* +*Exceptions: +* +*******************************************************************************/ + +int _CALLTYPE2 _execlpe ( + const char *filename, + const char *arglist, + ... + ) +{ + va_list vargs; + char * argbuf[64]; + char ** argv; + char ** envp; + int result; + + assert(filename != NULL); + assert(*filename != '\0'); + assert(arglist != NULL); + assert(*arglist != '\0'); + + va_start(vargs, arglist); + argv = _capture_argv(&vargs, arglist, argbuf, 64); + envp = va_arg(vargs, char **); + va_end(vargs); + + result = _execvpe(filename,argv,envp); + if (argv && argv != argbuf) free(argv); + return result; +} diff --git a/private/crt32/exec/execv.c b/private/crt32/exec/execv.c new file mode 100644 index 000000000..a369e3738 --- /dev/null +++ b/private/crt32/exec/execv.c @@ -0,0 +1,60 @@ +/*** +*execv.c - execute a file +* +* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _execv() - execute a file +* +*Revision History: +* 10-14-83 RN written +* 12-11-87 JCR Added "_LOAD_DS" to declaration +* 11-20-89 GJF Fixed copyright, indents. Added const attribute to +* types of filename and argvector. +* 03-08-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include +* <cruntime.h> and removed #include <register.h> +* 07-24-90 SBM Removed redundant includes, replaced <assertm.h> by +* <assert.h> +* 09-27-90 GJF New-style function declarator. +* 01-17-91 GJF ANSI naming. +* 02-14-90 SRW Use NULL instead of _environ to get default. +* +*******************************************************************************/ + +#include <cruntime.h> +#include <assert.h> +#include <stdlib.h> +#include <process.h> + +/*** +*int _execv(filename, argvector) - execute a file +* +*Purpose: +* Executes a file with given arguments. Passes arguments to _execve and +* uses pointer to the default environment. +* +*Entry: +* char *filename - file to execute +* char **argvector - vector of arguments. +* +*Exit: +* destroys calling process (hopefully) +* if fails, returns -1 +* +*Exceptions: +* +*******************************************************************************/ + +int _CALLTYPE1 _execv ( + const char *filename, + const char * const *argvector + ) +{ + assert(filename != NULL); + assert(*filename != '\0'); + assert(argvector != NULL); + assert(*argvector != NULL); + assert(**argvector != '\0'); + + return(_execve(filename,argvector,NULL)); +} diff --git a/private/crt32/exec/execve.c b/private/crt32/exec/execve.c new file mode 100644 index 000000000..386ed4d0f --- /dev/null +++ b/private/crt32/exec/execve.c @@ -0,0 +1,2 @@ +#define EXECVE +#include "spawnve.c" diff --git a/private/crt32/exec/execvp.c b/private/crt32/exec/execvp.c new file mode 100644 index 000000000..f6b94de8b --- /dev/null +++ b/private/crt32/exec/execvp.c @@ -0,0 +1,62 @@ +/*** +*execvp.c - execute a file and search along PATH +* +* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _execvp() - execute a file and search along PATH +* +*Revision History: +* 10-17-83 RN written +* 10-29-85 TC added execvpe capability +* 12-11-87 JCR Added "_LOAD_DS" to declaration +* 11-20-89 GJF Fixed copyright, indents. Added const attribute to +* types of filename and argvector. +* 03-08-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include +* <cruntime.h> and removed #include <register.h> +* 05-21-90 GJF Fixed stack checking pragma syntax. +* 08-24-90 SBM Removed check_stack pragma since workhorse execve +* does stack checks +* 09-27-90 GJF New-style function declarator. +* 01-17-91 GJF ANSI naming. +* 02-14-90 SRW Use NULL instead of _environ to get default. +* +*******************************************************************************/ + +#include <cruntime.h> +#include <stdlib.h> +#include <process.h> + +/*** +*int _execvp(filename, argvector) - execute file; search along PATH +* +*Purpose: +* Execute the given file with given path and current environ. +* try to execute the file. start with the name itself (directory '.'), +* and if that doesn't work start prepending pathnames from the +* environment until one works or we run out. if the file is a pathname, +* don't go to the environment to get alternate paths. if errno comes +* back ENOEXEC, try it as a shell command file with up to MAXARGS-2 +* arguments from the original vector. if a needed text file is busy, +* wait a little while and try again before despairing completely +* Actually calls _execvpe() to do all the work. +* +*Entry: +* char *filename - file to execute +* char **argvector - vector of arguments +* +*Exit: +* destroys the calling process (hopefully) +* if fails, returns -1 +* +*Exceptions: +* +*******************************************************************************/ + +int _CALLTYPE1 _execvp ( + REG3 const char *filename, + const char * const *argvector + ) +{ + return _execvpe( filename, argvector, NULL ); +} diff --git a/private/crt32/exec/execvpe.c b/private/crt32/exec/execvpe.c new file mode 100644 index 000000000..650f34b2a --- /dev/null +++ b/private/crt32/exec/execvpe.c @@ -0,0 +1,171 @@ +/*** +*execvpe.c - execute a file with given environ; search along PATH +* +* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _execvpe() - execute a file with given environ +* +*Revision History: +* 10-17-83 RN written +* 10-29-85 TC added execvpe capability +* 11-19-86 SKS handle both kinds of slashes +* 12-01-86 JMB added Kanji file name support under conditional KANJI +* switches, corrected header info +* removed bogus check for env = b after call to strncpy(). +* 12-11-87 JCR Added "_LOAD_DS" to declaration +* 09-05-88 SKS Treat EACCES the same as ENOENT -- keep trying +* 10-18-88 GJF Removed copy of PATH string to local array, changed +* bbuf to be a malloc-ed buffer. Removed bogus limits +* on the size of that PATH string. +* 10-26-88 GJF Don't search PATH when relative pathname is given (per +* Stevesa). Also, if the name built from PATH component +* and filename is a UNC name, allow any error. +* 11-20-89 GJF Fixed copyright. Added const attribute to types of +* filename, argvector and envptr. Also, added "#include +* <jstring.h>" under KANJI switch (same as 5-17-89 change +* to CRT version). +* 03-08-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include +* <cruntime.h> and removed #include <register.h>. Also, +* cleaned up the formatting a bit. +* 07-24-90 SBM Removed redundant includes, replaced <assertm.h> by +* <assert.h> +* 09-27-90 GJF New-style function declarator. +* 01-17-91 GJF ANSI naming. +* 11-30-92 KRS Port _MBCS code from 16-bit tree. +* +*******************************************************************************/ + +#include <cruntime.h> +#include <errno.h> +#include <assert.h> +#include <stdlib.h> +#include <string.h> +#include <process.h> +#include <mbstring.h> + +#define SLASH "\\" +#define SLASHCHAR '\\' +#define XSLASHCHAR '/' +#define DELIMITER ";" + +#ifdef _MBCS +/* note, the macro below assumes p is to pointer to a single-byte character + * or the 1st byte of a double-byte character, in a string. + */ +#define ISPSLASH(p) ( ((p) == _mbschr((p), SLASHCHAR)) || ((p) == \ +_mbschr((p), XSLASHCHAR)) ) +#else +#define ISSLASH(c) ( ((c) == SLASHCHAR) || ((c) == XSLASHCHAR) ) +#endif + + +/*** +*int _execvpe(filename, argvector, envvector) - execute a file +* +*Purpose: +* Executes a file with given arguments and environment. +* try to execute the file. start with the name itself (directory '.'), +* and if that doesn't work start prepending pathnames from the +* environment until one works or we run out. if the file is a pathname, +* don't go to the environment to get alternate paths. If a needed text +* file is busy, wait a little while and try again before despairing +* completely +* +*Entry: +* char *filename - file to execute +* char **argvector - vector of arguments +* char **envvector - vector of environment variables +* +*Exit: +* destroys the calling process (hopefully) +* if fails, returns -1 +* +*Exceptions: +* +*******************************************************************************/ + +int _CALLTYPE1 _execvpe ( + REG3 const char *filename, + const char * const *argvector, + const char * const *envptr + ) +{ + REG1 char *env; + char *bbuf = NULL; + REG2 char *buf; + char *pfin; + + assert(filename != NULL); + assert(*filename != '\0'); + assert(argvector != NULL); + assert(*argvector != NULL); + assert(**argvector != '\0'); + + _execve(filename,argvector,envptr); + + /* In a SBCS build, _mbschr will map to strchr. */ + + if ( (errno != ENOENT) + || (_mbschr(filename, SLASHCHAR) != NULL) + || (_mbschr(filename, XSLASHCHAR) != NULL) + || *filename && *(filename+1) == ':' + || !(env=getenv("PATH")) ) + goto reterror; + + /* allocate a buffer to hold alternate pathnames for the executable + */ + if ( (buf = bbuf = (char *)malloc(_MAX_PATH)) == NULL ) goto reterror; + + do { + /* copy a component into bbuf[], taking care not to overflow it + */ + /* UNDONE: make sure ';' isn't 2nd byte of DBCS char */ + while ( (*env) && (*env != ';') && (buf < bbuf+_MAX_PATH-2) ) + *buf++ = *env++; + + *buf = '\0'; + pfin = --buf; + buf = bbuf; + +#ifdef _MBCS + if (*pfin == SLASHCHAR) { + if (pfin != _mbsrchr(buf,SLASHCHAR)) + /* *pfin is the second byte of a double-byte + * character + */ + strcat( buf, SLASH ); + } + else if (*pfin != XSLASHCHAR) + strcat(buf, SLASH); +#else + if (*pfin != SLASHCHAR && *pfin != XSLASHCHAR) + strcat(buf, SLASH); +#endif + + /* check that the final path will be of legal size. if so, + * build it. otherwise, return to the caller (return value + * and errno rename set from initial call to _execve()). + */ + if ( (strlen(buf) + strlen(filename)) < _MAX_PATH ) + strcat(buf, filename); + else + break; + + _execve(buf, argvector, envptr); + + if ( (errno != ENOENT) +#ifdef _MBCS + && (!ISPSLASH(buf) || !ISPSLASH(buf+1)) ) +#else + && (!ISSLASH(*buf) || !ISSLASH(*(buf+1))) ) +#endif + break; + } while ( *env && env++ ); + +reterror: + if (bbuf != NULL) + free(bbuf); + + return(-1); +} diff --git a/private/crt32/exec/fileinfo.c b/private/crt32/exec/fileinfo.c new file mode 100644 index 000000000..c617cf8c4 --- /dev/null +++ b/private/crt32/exec/fileinfo.c @@ -0,0 +1,22 @@ +/*** +*fileinfo.c - sets C file info flag +* +* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved. +* +*Purpose: +* Sets the C file info flag. By default, the openfile information +* is NOT passed along to children on spawn/exec calls. If the flag +* is set, openfile information WILL get passed on to children on +* spawn/exec calls. +* +*Revision History: +* 06-07-89 PHG Module created, based on asm version +* 04-03-90 GJF Added #include <cruntime.h>. Also, fixed the copyright. +* 01-23-92 GJF Added #include <stdlib.h> (contains decl of _fileinfo). +* +*******************************************************************************/ + +#include <cruntime.h> +#include <stdlib.h> + +int _fileinfo = -1; diff --git a/private/crt32/exec/getproc.c b/private/crt32/exec/getproc.c new file mode 100644 index 000000000..2cb78323e --- /dev/null +++ b/private/crt32/exec/getproc.c @@ -0,0 +1,62 @@ +/*** +*getproc.c - Get the address of a procedure in a DLL. +* +* Copyright (c) 1991, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _getdllprocadd() - gets a procedure address by name or +* ordinal +* +*Revision History: +* 08-21-91 BWM Wrote module. +* +*******************************************************************************/ + +#include <cruntime.h> +#include <oscalls.h> +#include <process.h> + +#if !defined(_WIN32_) +#error ERROR - ONLY WIN32 TARGET SUPPORTED! +#endif + +/*** +*int (*)() _getdllprocaddr(handle, name, ordinal) - Get the address of a +* DLL procedure specified by name or ordinal +* +*Purpose: +* +*Entry: +* int handle - a DLL handle from _loaddll +* char * name - Name of the procedure, or NULL to get by ordinal +* int ordinal - Ordinal of the procedure, or -1 to get by name +* +* +*Exit: +* returns a pointer to the procedure if found +* returns NULL if not found +* +*Exceptions: +* +*******************************************************************************/ + +int (_CALLTYPE1 * _CALLTYPE1 _getdllprocaddr(int hMod, + char * szProcName, + int iOrdinal))() +{ + typedef int (_CALLTYPE1 * PFN)(); + + if (szProcName == NULL) { + if (iOrdinal <= 65535) { + return ((PFN)GetProcAddress((HANDLE)hMod, (LPSTR)iOrdinal)); + } + } + else { + if (iOrdinal == -1) { + return ((PFN)GetProcAddress((HANDLE)hMod, szProcName)); + } + } + + return (NULL); + +} diff --git a/private/crt32/exec/loaddll.c b/private/crt32/exec/loaddll.c new file mode 100644 index 000000000..a6f41b7e2 --- /dev/null +++ b/private/crt32/exec/loaddll.c @@ -0,0 +1,70 @@ +/*** +*loaddll.c - load or free a Dynamic Link Library +* +* Copyright (c) 1991, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _loaddll() and _unloaddll() - load and unload DLL +* +*Revision History: +* 08-21-91 BWM Wrote module. +* +*******************************************************************************/ + +#include <cruntime.h> +#include <oscalls.h> +#include <assert.h> +#include <stdlib.h> +#include <process.h> + +#if !defined(_WIN32_) +#error ERROR - ONLY WIN32 TARGET SUPPORTED! +#endif + +/*** +*int _loaddll(filename) - Load a dll +* +*Purpose: +* Load a DLL into memory +* +*Entry: +* char *filename - file to load +* +*Exit: +* returns a unique DLL (module) handle if succeeds +* returns 0 if fails +* +*Exceptions: +* +*******************************************************************************/ + +int _CALLTYPE1 _loaddll(char * szName) +{ + return ((int)LoadLibrary(szName)); +} + +/*** +*int _unloaddll(handle) - Unload a dll +* +*Purpose: +* Unloads a DLL. The resources of the DLL will be freed if no other +* processes are using it. +* +*Entry: +* int handle - handle from _loaddll +* +*Exit: +* returns 0 if succeeds +* returns DOS error if fails +* +*Exceptions: +* +*******************************************************************************/ + +int _CALLTYPE1 _unloaddll(int hMod) +{ + if (!FreeLibrary((HANDLE)hMod)) { + return ((int)GetLastError()); + } + return (0); +} diff --git a/private/crt32/exec/makefile b/private/crt32/exec/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/crt32/exec/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/crt32/exec/sources b/private/crt32/exec/sources new file mode 100644 index 000000000..ed4f1c187 --- /dev/null +++ b/private/crt32/exec/sources @@ -0,0 +1,58 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + Steve Wood (stevewo) 12-Apr-1990 + jeffrob 29-sep-1990, use crt32.def + +NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl + +!ENDIF + +MAJORCOMP=crt +MINORCOMP=exec + +TARGETNAME=exec +TARGETPATH=..\obj +TARGETTYPE=LIBRARY +386_STDCALL=0 + +!INCLUDE ..\crt32.def + +SOURCES=cenvarg.c \ + fileinfo.c \ + dospawn.c \ + execl.c \ + execle.c \ + execlp.c \ + execlpe.c \ + execv.c \ + execve.c \ + execvp.c \ + execvpe.c \ + getproc.c \ + loaddll.c \ + spawnl.c \ + spawnle.c \ + spawnlp.c \ + spawnlpe.c \ + spawnv.c \ + spawnve.c \ + spawnvp.c \ + spawnvpe.c \ + system.c \ + wait.c diff --git a/private/crt32/exec/spawnl.c b/private/crt32/exec/spawnl.c new file mode 100644 index 000000000..826e5be46 --- /dev/null +++ b/private/crt32/exec/spawnl.c @@ -0,0 +1,83 @@ +/*** +*spawnl.c - spawn a child process +* +* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _spawnl() - spawn a child process +* +*Revision History: +* 04-15-84 DFW Re-do to correspond to similar exec call format +* 12-11-87 JCR Added "_LOAD_DS" to declaration +* 11-20-89 GJF Fixed copyright, alignment. Added const to arg types +* for pathname and arglist. #include-d PROCESS.H and +* added ellipsis to match prototype. +* 03-08-90 GJF Replaced _LOAD_DS with _CALLTYPE2 and added #include +* <cruntime.h>. +* 07-24-90 SBM Removed redundant includes, replaced <assertm.h> by +* <assert.h> +* 09-27-90 GJF New-style function declarator. +* 01-17-91 GJF ANSI naming. +* 02-14-90 SRW Use NULL instead of _environ to get default. +* 07-16-93 SRW ALPHA Merge +* +*******************************************************************************/ + +#include <cruntime.h> +#include <assert.h> +#include <stdlib.h> +#include <process.h> +#include <stdarg.h> +#include <internal.h> +#include <malloc.h> + +/*** +*int _spawnl(modeflag, pathname, arglist) - spawn a child process +* +*Purpose: +* Spawns a child process. +* formats the parameters and calls spawnve to do the actual work. The +* new process will inherit the parent's environment. NOTE - at least +* one argument must be present. This argument is always, by convention, +* the name of the file being spawned. +* +*Entry: +* int modeflag - defines which mode of spawn (WAIT, NOWAIT, or OVERLAY) +* only WAIT and OVERLAY are currently implemented +* char *pathname - file to be spawned +* char *arglist - list of argument +* call as _spawnl(modeflag, path, arg0, arg1, ..., argn, NULL); +* +*Exit: +* returns exit code of child process +* returns -1 if fails +* +*Exceptions: +* +*******************************************************************************/ + +int _CALLTYPE2 _spawnl ( + int modeflag, + const char *pathname, + const char *arglist, + ... + ) +{ + va_list vargs; + char * argbuf[64]; + char ** argv; + int result; + + assert(pathname != NULL); + assert(*pathname != '\0'); + assert(arglist != NULL); + assert(*arglist != '\0'); + + va_start(vargs, arglist); + argv = _capture_argv(&vargs, arglist, argbuf, 64); + va_end(vargs); + + result = _spawnve(modeflag,pathname,argv,NULL); + if (argv && argv != argbuf) free(argv); + return result; +} diff --git a/private/crt32/exec/spawnle.c b/private/crt32/exec/spawnle.c new file mode 100644 index 000000000..5b09417f2 --- /dev/null +++ b/private/crt32/exec/spawnle.c @@ -0,0 +1,83 @@ +/*** +*spawnle.c - spawn a child process with given environment +* +* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _spawnle() - spawn a child process with given environ +* +*Revision History: +* 04-15-84 DFW written +* 12-11-87 JCR Added "_LOAD_DS" to declaration +* 11-20-89 GJF Fixed copyright, alignment. Added const to arg types +* for pathname and arglist. #include-d PROCESS.H and +* added ellipsis to match prototype +* 03-08-90 GJF Replaced _LOAD_DS with _CALLTYPE2, added #include +* <cruntime.h> and removed #include <register.h> +* 07-24-90 SBM Removed redundant includes, replaced <assertm.h> by +* <assert.h> +* 09-27-90 GJF New-style function declarator. +* 01-17-91 GJF ANSI naming. +* 07-16-93 SRW ALPHA Merge +* +*******************************************************************************/ + +#include <cruntime.h> +#include <assert.h> +#include <stddef.h> +#include <process.h> +#include <stdarg.h> +#include <internal.h> +#include <malloc.h> + +/*** +*int _spawnle(modeflag, pathname, arglist) - spawn a child process with env. +* +*Purpose: +* Spawns a child process with given parameters and environment. +* formats the parameters and calls _spawnve to do the actual work. +* NOTE - at least one argument must be present. This argument is always, +* by convention, the name of the file being spawned. +* +*Entry: +* int modeflag - mode of spawn (WAIT, NOWAIT, OVERLAY) +* only WAIT, and OVERLAY currently implemented +* char *pathname - name of file to spawn +* char *arglist - argument list, environment is at the end +* call as _spawnle(modeflag, path, arg0, arg1, ..., argn, NULL, envp); +* +*Exit: +* returns exit code of spawned process +* if fails, return -1 +* +*Exceptions: +* +*******************************************************************************/ + +int _CALLTYPE2 _spawnle ( + int modeflag, + const char *pathname, + const char *arglist, + ... + ) +{ + va_list vargs; + char * argbuf[64]; + char ** argv; + char ** envp; + int result; + + assert(pathname != NULL); + assert(*pathname != '\0'); + assert(arglist != NULL); + assert(*arglist != '\0'); + + va_start(vargs, arglist); + argv = _capture_argv(&vargs, arglist, argbuf, 64); + envp = va_arg(vargs, char **); + va_end(vargs); + + result = _spawnve(modeflag,pathname,argv,envp); + if (argv && argv != argbuf) free(argv); + return result; +} diff --git a/private/crt32/exec/spawnlp.c b/private/crt32/exec/spawnlp.c new file mode 100644 index 000000000..22516c929 --- /dev/null +++ b/private/crt32/exec/spawnlp.c @@ -0,0 +1,85 @@ +/*** +*spawnlp.c - spawn a file; search along PATH +* +* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _spawnlp() - spawn a file with search along PATH +* +*Revision History: +* 04-15-84 DFW written +* 10-29-85 TC added spawnlpe +* 12-11-87 JCR Added "_LOAD_DS" to declaration +* 11-20-89 GJF Fixed copyright, alignment. Added const to arg types +* for filename and arglist. #include-d PROCESS.H and +* added ellipsis to match prototype. +* 03-08-90 GJF Replaced _LOAD_DS with _CALLTYPE2 and added #include +* <cruntime.h>. +* 07-24-90 SBM Removed redundant includes, replaced <assertm.h> by +* <assert.h> +* 09-27-90 GJF New-style function declarator. +* 01-17-91 GJF ANSI naming. +* 07-16-93 SRW ALPHA Merge +* +*******************************************************************************/ + +#include <cruntime.h> +#include <assert.h> +#include <stddef.h> +#include <process.h> +#include <stdarg.h> +#include <internal.h> +#include <malloc.h> + +/*** +*_spawnlp(modeflag, filename, arglist) - spawn file and search along PATH +* +*Purpose: +* Spawns a child process. +* formats the parameters and calls _spawnvp to do the work of searching +* the PATH environment variable and calling _spawnve. The NULL +* environment pointer indicates that the new process will inherit the +* parents process's environment. NOTE - at least one argument must be +* present. This argument is always, by convention, the name of the file +* being spawned. +* +*Entry: +* int modeflag - mode of spawn (WAIT, NOWAIT, OVERLAY) +* only WAIT, OVERLAY currently implemented +* char *pathname - file to spawn +* char *arglist - argument list +* call as _spawnlp(modeflag, path, arg0, arg1, ..., argn, NULL); +* +*Exit: +* returns exit code of child process +* returns -1 if fails +* +*Exceptions: +* +*******************************************************************************/ + +int _CALLTYPE2 _spawnlp ( + int modeflag, + const char *filename, + const char *arglist, + ... + ) +{ + va_list vargs; + char * argbuf[64]; + char ** argv; + int result; + + assert(filename != NULL); + assert(*filename != '\0'); + assert(arglist != NULL); + assert(*arglist != '\0'); + + va_start(vargs, arglist); + argv = _capture_argv(&vargs, arglist, argbuf, 64); + va_end(vargs); + + result = _spawnvp(modeflag,filename,argv); + if (argv && argv != argbuf) free(argv); + return result; +} diff --git a/private/crt32/exec/spawnlpe.c b/private/crt32/exec/spawnlpe.c new file mode 100644 index 000000000..10520aecb --- /dev/null +++ b/private/crt32/exec/spawnlpe.c @@ -0,0 +1,87 @@ +/*** +*spawnlpe.c - spawn a child process with environ and search along PATH +* +* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _spawnlpe() - spawn a child process with environ/PATH search +* +*Revision History: +* 04-15-84 DFW written +* 10-29-85 TC added spawnlpe +* 12-11-87 JCR Added "_LOAD_DS" to declaration +* 11-20-89 GJF Fixed copyright, alignment. Added const to arg types +* for filename and arglist. #include-d PROCESS.H and +* added ellipsis to match prototype. +* 03-08-90 GJF Replaced _LOAD_DS with _CALLTYPE2, added #include +* <cruntime.h> and removed #include <register.h>. +* 07-24-90 SBM Removed redundant includes, replaced <assertm.h> by +* <assert.h> +* 09-27-90 GJF New-style function declarator. +* 01-17-91 GJF ANSI naming. +* 07-16-93 SRW ALPHA Merge +* +*******************************************************************************/ + +#include <cruntime.h> +#include <assert.h> +#include <stddef.h> +#include <process.h> +#include <stdarg.h> +#include <internal.h> +#include <malloc.h> + +/*** +*int _spawnlpe(modeflag, filename, arglist) - spawn a child process +* +*Purpose: +* Spawns a child process. +* formats the parameters and calls _spawnvpe to do the work of searching +* the PATH environment variable and calling _spawnve. The NULL +* environment pointer indicates that the new process will inherit the +* parents process's environment. NOTE - at least one argument must be +* present. This argument is always, by convention, the name of the file +* being spawned. +* +*Entry: +* int modeflag - defines what mode of spawn (WAIT, NOWAIT, OVERLAY) +* only WAIT and OVERLAY currently supported +* char *pathname - file to spawn +* char *arglist - list of arguments (environ at end) +* call as _spawnlpe(modeflag, path, arg0, arg1, ..., argn, NULL, envp); +* +*Exit: +* returns exit code of spawned process +* returns -1 if fails +* +*Exceptions: +* +*******************************************************************************/ + +int _CALLTYPE2 _spawnlpe ( + int modeflag, + const char *filename, + const char *arglist, + ... + ) +{ + va_list vargs; + char * argbuf[64]; + char ** argv; + char ** envp; + int result; + + assert(filename != NULL); + assert(*filename != '\0'); + assert(arglist != NULL); + assert(*arglist != '\0'); + + va_start(vargs, arglist); + argv = _capture_argv(&vargs, arglist, argbuf, 64); + envp = va_arg(vargs, char **); + va_end(vargs); + + result = _spawnvpe(modeflag,filename,argv,envp); + if (argv && argv != argbuf) free(argv); + return result; +} diff --git a/private/crt32/exec/spawnv.c b/private/crt32/exec/spawnv.c new file mode 100644 index 000000000..fe90c213f --- /dev/null +++ b/private/crt32/exec/spawnv.c @@ -0,0 +1,67 @@ +/*** +*spawnv.c - spawn a child process +* +* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _spawnv() - spawn a child process +* +*Revision History: +* 04-15-84 DFW written +* 12-11-87 JCR Added "_LOAD_DS" to declaration +* 11-20-89 GJF Fixed copyright, alignment. Added const to arg types +* for pathname and argv. +* 03-08-90 GJF Replace _LOAD_DS with _CALLTYPE1 and added #include +* <cruntime.h>. +* 07-24-90 SBM Removed redundant includes, replaced <assertm.h> by +* <assert.h> +* 09-27-90 GJF New-style function declarator. +* 01-17-91 GJF ANSI naming. +* 02-14-90 SRW Use NULL instead of _environ to get default. +* +*******************************************************************************/ + +#include <cruntime.h> +#include <assert.h> +#include <stdlib.h> +#include <process.h> + +/*** +*int _spawnv(modeflag, pathname, argv) - spawn a child process +* +*Purpose: +* Spawns a child process. +* formats the parameters and calls _spawnve to do the actual work. The +* NULL environment pointer indicates that the new process will inherit +* the parents process's environment. NOTE - at least one argument must +* be present. This argument is always, by convention, the name of the +* file being spawned. +* +*Entry: +* int modeflag - mode to spawn (WAIT, NOWAIT, or OVERLAY) +* only WAIT and OVERLAY currently implemented +* char *pathname - file to spawn +* char **argv - vector of arguments +* +*Exit: +* returns exit code of child process +* if fails, returns -1 +* +*Exceptions: +* +*******************************************************************************/ + +int _CALLTYPE1 _spawnv ( + int modeflag, + const char *pathname, + const char * const *argv + ) +{ + assert(pathname != NULL); + assert(*pathname != '\0'); + assert(argv != NULL); + assert(*argv != NULL); + assert(**argv != '\0'); + + return(_spawnve(modeflag,pathname,argv,NULL)); +} diff --git a/private/crt32/exec/spawnve.c b/private/crt32/exec/spawnve.c new file mode 100644 index 000000000..00e321dd2 --- /dev/null +++ b/private/crt32/exec/spawnve.c @@ -0,0 +1,318 @@ +/*** +*spawnve.c - OS/2 low level routine eventually called by all _spawnXX routines +* also contains all code for _execve, called by _execXX routines +* +* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved. +* +*Purpose: +* +* This is the low level routine which is eventually invoked by all the +* _spawnXX routines. +* +* This is also the low-level routine which is eventually invoked by +* all of the _execXX routines. +* +*Revision History: +* 03-??-84 RLB created +* 05-??-84 DCW modified to fix bug in initialization of envblock +* pointer (used int 0 which would fail in long model) and +* changed (char *)0 to NULL. +* 03-31-86 SKS modified for OS/2; no OVERLAY mode, +* new format for DOS Exec function +* also check for Xenix or DOS style slash characters +* 10-13-86 SKS pass program name to _cenvarg() +* 11-19-86 SKS handle both kinds of slashes, with support for Kanji +* 01-29-87 BCM don't try ".com" extension in protected mode (OS/2) +* 12-11-87 JCR Added "_LOAD_DS" to declaration +* 05/31/88 SJM Re-written to allow spawn of .CMD files, increase +* speed. Added comexecmd routine. +* 06/01/88 SJM added #ifdef statements for execve.obj compilation +* 10-30-88 GJF Call _dospawn() for EXECVE, not _doexec(). +* 07-21-89 GJF Progagated fixes of 11-23-88 and 05-27-89 from CRT tree. +* 11-16-89 GJF Added code to execve/spawnve to ensure a relative or +* or absolute pathname is always used for the executable, +* not just a filename (otherwise DOSEXECPGM will search +* the PATH!). Also, cleaned up some of the erratic +* formatting. Same as 9-15-89 change to CRT version +* 11-20-89 GJF Added const attribute to types of appropriate args. +* 02-08-90 GJF Fixed bug in comexecmd (must free(comname) if and only +* if comname points to a malloc-ed block). Propagated +* from 02-07-90 change in crt6 version. +* 03-08-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include +* <cruntime.h> and removed #include <register.h>. +* 04-02-90 GJF Made comexecmd() _CALLTYPE4. Added #include <io.h> +* and a prototype for comexecmd() to fix compiler +* warnings (-W3). +* 05-21-90 GJF Fixed stack checking pragma syntax. +* 07-24-90 SBM Removed redundant include, minor optimization +* 09-27-90 GJF New-style function declarators. +* 12-28-90 SRW Added _CRUISER_ conditional around check_stack pragma +* 01-17-91 GJF ANSI naming. +* 08-21-91 JCR Call access() in before comexecmd (bug fix) +* 01-24-92 JCR upgraded for Win32 +* 10-24-92 SKS Remove special treatment for batch files - +* Windows NT will spawn %COMSPEC% automatically +* 11-30-92 KRS Ported _MBCS support from 16-bit tree. +* +*******************************************************************************/ + +#include <cruntime.h> +#include <io.h> +#include <process.h> +#include <errno.h> +#include <msdos.h> +#include <string.h> +#include <stdlib.h> +#include <internal.h> +#include <mbstring.h> + +#ifdef _CRUISER_ +#pragma check_stack(on) /* turn on stack checking */ +#endif /* ndef _CRUISER_ */ + +#define SLASHCHAR '\\' +#define XSLASHCHAR '/' + +#ifndef EXECVE +static int _CALLTYPE4 comexecmd(int mode, const char * name, + const char * const * argv, const char * const * envp); +#else +static int _CALLTYPE4 comexecmd(const char * name, + const char * const * argv, const char * const * envp); +#endif /* EXECVE */ + +/*** +*static int comexecmd(mode, name, argv, envp) - do the exec +* or spawn after name fixup +* +*Purpose: +* Spawns a child process with given parameters and environment. Either +* overlays current process or loads in free memory while parent process +* waits. If the named file is a .cmd file, modifies the calling sequence +* and prepends the /c and filename arguments into the command string +* +* Exec doesn't take a mode; instead, the parent process goes away as +* the child process is brought in. +* +*Entry: +* int mode - mode to spawn (WAIT, NOWAIT, or OVERLAY) +* only WAIT and OVERLAY currently supported +* +* **** mode is only used in the spawnve() version **** +* +* char *name - pathname of file to spawn. Includes the extension +* char **argv - vector of parameter strings +* char **envp - vector of environment variables +* +*Exit: +* returns exit code of child process +* if fails, returns -1 +* +*Exceptions: +* Returns a value of (-1) to indicate an error in exec'ing the child +* process. errno may be set to: +* +* E2BIG = failed in argument/environment processing (_cenvarg) +* argument list or environment too big; +* EACCESS = locking or sharing violation on file; +* EMFILE = too many files open; +* ENOENT = failed to find program name - no such file or directory; +* ENOEXEC = failed in exec - bad executable format; +* ENOMEM = failed in memory allocation (during malloc, or in +* setting up memory for executing child process). +* +*******************************************************************************/ + +static int _CALLTYPE4 comexecmd ( + +#ifndef EXECVE + REG3 int mode, +#endif /* EXECVE */ + + REG2 const char *name, + const char * const *argv, + const char * const *envp + ) +{ + char *argblk; + char *envblk; + REG4 int rc; + + if (_cenvarg(argv, envp, &argblk, &envblk, name) == -1) + return -1; + +#ifndef EXECVE + rc = _dospawn(mode, name, argblk, envblk); +#else + rc = _dospawn(_P_OVERLAY, name, argblk, envblk); +#endif + /* free memory */ + + free(argblk); + free(envblk); + + return rc; +} + +/*** +*int _spawnve(mode, name, argv, envp) - low level _spawnXX library function +*int _execve(name, argv, envp) - low level _execXX library function +* +*Purpose: +* spawns or execs a child process; takes a single pointer to an argument +* list as well as a pointer to the environment; unlike _spawnvpe, +* _spawnve does not search the PATH= list in processing the name +* parameter; mode specifies the parent's execution mode. +* +*Entry: +* int mode - parent process's execution mode: +* must be one of _P_OVERLAY, _P_WAIT, _P_NOWAIT; +* not used for _execve +* char *name - path name of program to spawn; +* char **argv - pointer to array of pointers to child's arguments; +* char **envp - pointer to array of pointers to child's environment +* settings. +* +*Exit: +* Returns : (int) a status value whose meaning is as follows: +* 0 = normal termination of child process; +* positive = exit code of child upon error termination +* (abort or exit(nonzero)); +* -1 = child process was not spawned; +* errno indicates what kind of error: +* (E2BIG, EINVAL, ENOENT, ENOEXEC, ENOMEM). +* +*Exceptions: +* Returns a value of (-1) to indicate an error in spawning the child +* process. errno may be set to: +* +* E2BIG = failed in argument/environment processing (_cenvarg) - +* argument list or environment too big; +* EINVAL = invalid mode argument; +* ENOENT = failed to find program name - no such file or directory; +* ENOEXEC = failed in spawn - bad executable format; +* ENOMEM = failed in memory allocation (during malloc, or in +* setting up memory for spawning child process). +* +*******************************************************************************/ + +/* Extension array - ordered in search order from right to left. + + ext_strings = array of extensions +*/ + +#ifdef _CRUISER_ +static char *ext_strings[] = { NULL, ".exe", ".com" }; +enum {CMD, EXE, COM, EXTFIRST=CMD, EXTLAST=COM}; +#else +static char *ext_strings[] = { ".cmd", ".bat", ".exe" , ".com" }; +enum {CMD, BAT, EXE, COM, EXTFIRST=CMD, EXTLAST=COM}; +#endif + +int _CALLTYPE1 + +#ifndef EXECVE + +_spawnve ( + REG3 int mode, + +#else + +_execve ( + +#endif /* EXECVE */ + + const char *name, + const char * const *argv, + const char * const *envp + ) +{ + char *ext; /* where the extension goes if we have to add one */ + REG1 char *p; + char *q; + REG2 char *pathname = (char *)name; + REG4 int rc; + REG5 int i; + +#ifdef _CRUISER_ + exstrings[CMD] = _osmode ? ".cmd" : ".bat"; +#endif + + p = _mbsrchr(pathname, SLASHCHAR); + q = strrchr(pathname, XSLASHCHAR); /* No need for _mbsrchr with "/" */ + + /* ensure that pathname is an absolute or relative pathname. also, + * position p to point at the filename portion of pathname (i.e., just + * after the last occurence of a colon, slash or backslash character */ + + if (!q) { + if (!p) + if (!(p = strchr(pathname, ':'))) { + + /* pathname is a filename only, force it to be + * a relative pathname. note that an extra byte + * is malloc-ed just in case pathname is NULL, + * to keep the heap from being trashed by + * strcpy */ + if (!(pathname = malloc(strlen(pathname) + 3))) + return(-1); + + strcpy(pathname, ".\\"); + strcat(pathname, name); + + /* set p to point to the start of the filename + * (i.e., past the ".\\" prefix) */ + p = pathname + 2; + } + /* else pathname has drive specifier prefix and p is + * is pointing to the ':' */ + } + else if (!p || q > p) /* p == NULL or q > p */ + p = q; + + + rc = -1; /* init to error value */ + + if (ext = strrchr(p, '.')) { + + /* extension given; only do filename */ + + if (_access(pathname, 0) != -1) { +#ifndef EXECVE + rc = comexecmd(mode, pathname, argv, envp); +#else + rc = comexecmd(pathname, argv, envp); +#endif + } + + } + else { + + /* no extension; try .cmd/.bat, then .com and .exe */ + + if (!(p = malloc(strlen(pathname) + 5))) + return(-1); + + strcpy(p, pathname); + ext = p + strlen(pathname); + + for (i = EXTLAST; i >= EXTFIRST; --i) { + strcpy(ext, ext_strings[i]); + + if (_access(p, 0) != -1) { +#ifndef EXECVE + rc = comexecmd(mode, p, argv, envp); +#else + rc = comexecmd(p, argv, envp); +#endif /* EXECVE */ + break; + } + } + free(p); + } + + if (pathname != name) + free(pathname); + + return rc; +} diff --git a/private/crt32/exec/spawnvp.c b/private/crt32/exec/spawnvp.c new file mode 100644 index 000000000..f31dc2c60 --- /dev/null +++ b/private/crt32/exec/spawnvp.c @@ -0,0 +1,62 @@ +/*** +*spawnvp.c - spawn a child process; search along PATH +* +* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _spawnvp() - spawn a child process; search along PATH +* +*Revision History: +* 04-15-84 DFW written +* 10-29-85 TC added spawnvpe capability +* 12-11-87 JCR Added "_LOAD_DS" to declaration +* 11-20-89 GJF Fixed copyright, alignment. Added const to arg types +* for filename and argv. +* 03-08-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include +* <cruntime.h> and removed #include <register.h> +* 05-21-90 GJF Fixed stack checking pragma syntax. +* 08-24-90 SBM Removed check_stack pragma since workhorse _spawnve +* does stack checks +* 09-27-90 GJF New-style function declarator. +* 01-17-91 GJF ANSI naming. +* 02-14-90 SRW Use NULL instead of _environ to get default. +* +*******************************************************************************/ + +#include <cruntime.h> +#include <stdlib.h> +#include <process.h> + +/*** +*int _spawnvp(modeflag, filename, argv) - spawn a child process (search PATH) +* +*Purpose: +* Spawns a child process, with search along PATH variable. +* formats the parameters and calls _spawnve to do the actual work. The +* NULL environment pointer indicates the new process will inherit the +* parents process's environment. NOTE - at least one argument must be +* present. This argument is always, by convention, the name of the file +* being spawned. +* +*Entry: +* int modeflag - mode to spawn (WAIT, NOWAIT, or OVERLAY) +* only WAIT and OVERLAY currently supported +* char *pathname - name of file to spawn +* char **argv - vector of arguments +* +*Exit: +* returns exit code of child process +* returns -1 if fails +* +*Exceptions: +* +*******************************************************************************/ + +int _CALLTYPE1 _spawnvp ( + int modeflag, + REG3 const char *filename, + const char * const *argv + ) +{ + return _spawnvpe(modeflag, filename, argv, NULL); +} diff --git a/private/crt32/exec/spawnvpe.c b/private/crt32/exec/spawnvpe.c new file mode 100644 index 000000000..ffbdbb55a --- /dev/null +++ b/private/crt32/exec/spawnvpe.c @@ -0,0 +1,209 @@ +/*** +*spawnvpe.c - spawn a child process with given environ (search PATH) +* +* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _spawnvpe() - spawn a child process with given environ (search +* PATH) +* +*Revision History: +* 04-15-84 DFW written +* 10-29-85 TC added spawnvpe capability +* 11-19-86 SKS handle both kinds of slashes +* 12-01-86 JMB added Kanji file name support under conditional KANJI +* switches. Corrected header info. Removed bogus check +* for env = b after call to strncpy +* 12-11-87 JCR Added "_LOAD_DS" to declaration +* 09-05-88 SKS Treat EACCES the same as ENOENT -- keep trying +* 10-17-88 GJF Removed copy of PATH string to local array, changed +* bbuf to be a malloc-ed buffer. Removed bogus limits +* on the size of that PATH string. +* 10-25-88 GJF Don't search PATH when relative pathname is given (per +* Stevesa). Also, if the name built from PATH component +* and filename is a UNC name, allow any error. +* 05-17-89 MT Added "include <jstring.h>" under KANJI switch +* 05-24-89 PHG Reduce _amblksiz to use minimal memory (DOS only) +* 08-29-89 GJF Use _getpath() to retrieve PATH components, fixing +* several problems in handling unusual or bizarre +* PATH's. +* 11-20-89 GJF Added const attribute to types of filename, argv and +* envptr. +* 03-08-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include +* <cruntime.h> and removed #include <register.h> +* 07-24-90 SBM Removed redundant includes, replaced <assertm.h> by +* <assert.h> +* 09-27-90 GJF New-style function declarator. +* 01-17-91 GJF ANSI naming. +* 09-25-91 JCR Changed ifdef "OS2" to "_DOS_" (unused in 32-bit tree) +* 11-30-92 KRS Port _MBCS code from 16-bit tree. +* +*******************************************************************************/ + +#include <cruntime.h> +#include <errno.h> +#include <assert.h> +#include <stdlib.h> +#include <string.h> +#include <malloc.h> +#include <internal.h> +#include <process.h> +#include <mbstring.h> + +#define SLASH "\\" +#define SLASHCHAR '\\' +#define XSLASHCHAR '/' +#define DELIMITER ";" + +#ifdef _MBCS +/* note, the macro below assumes p is to pointer to a single-byte character + * or the 1st byte of a double-byte character, in a string. + */ +#define ISPSLASH(p) ( ((p) == _mbschr((p), SLASHCHAR)) || ((p) == \ +_mbschr((p), XSLASHCHAR)) ) +#else +#define ISSLASH(c) ( ((c) == SLASHCHAR) || ((c) == XSLASHCHAR) ) +#endif + +/*** +*_spawnvpe(modeflag, filename, argv, envptr) - spawn a child process +* +*Purpose: +* Spawns a child process with the given arguments and environ, +* searches along PATH for given file until found. +* Formats the parameters and calls _spawnve to do the actual work. The +* NULL environment pointer indicates that the new process will inherit +* the parents process's environment. NOTE - at least one argument must +* be present. This argument is always, by convention, the name of the +* file being spawned. +* +*Entry: +* int modeflag - defines mode of spawn (WAIT, NOWAIT, or OVERLAY) +* only WAIT and OVERLAY supported +* char *filename - name of file to execute +* char **argv - vector of parameters +* char **envptr - vector of environment variables +* +*Exit: +* returns exit code of spawned process +* if fails, returns -1 +* +*Exceptions: +* +*******************************************************************************/ + +int _CALLTYPE1 _spawnvpe ( + int modeflag, + REG3 const char *filename, + const char * const *argv, + const char * const *envptr + ) +{ + int i; + REG1 char *env; + REG2 char *buf = NULL; + char *pfin; +#ifdef _DOS_ + int tempamblksiz; /* old _amblksiz */ +#endif + assert(filename != NULL); + assert(*filename != '\0'); + assert(argv != NULL); + assert(*argv != NULL); + assert(**argv != '\0'); + +#ifdef _DOS_ + tempamblksiz = _amblksiz; + _amblksiz = 0x10; /* reduce _amblksiz for efficient mallocs */ +#endif + + if ( + (i = _spawnve(modeflag, filename, argv, envptr)) != -1 + /* everything worked just fine; return i */ + + || (errno != ENOENT) + /* couldn't spawn the process, return failure */ + + /* In a SBCS build, _mbschr will map to strchr. */ + + || (_mbschr(filename, XSLASHCHAR) != NULL) + /* filename contains a '/', return failure */ + +#ifdef _DOS_ + || (_mbschr(filename,SLASHCHAR) != NULL) + /* filename contains a '\', return failure */ + + || *filename && *(filename+1) == ':' + /* drive specification, return failure */ +#endif + + || !(env = getenv("PATH")) + /* no PATH environment string name, return failure */ + + || ( (buf = (char *)malloc(_MAX_PATH)) == NULL ) + /* cannot allocate buffer to build alternate pathnames, return + * failure */ + ) { +#ifdef _DOS_ + _amblksiz = tempamblksiz; /* restore old _amblksiz */ +#endif + goto done; + } + +#ifdef _DOS_ + _amblksiz = tempamblksiz; /* restore old _amblksiz */ +#endif + + + /* could not find the file as specified, search PATH. try each + * component of the PATH until we get either no error return, or the + * error is not ENOENT and the component is not a UNC name, or we run + * out of components to try. + */ + + while ( (env = _getpath(env, buf, _MAX_PATH - 1)) && (*buf) ) { + + pfin = buf + strlen(buf) - 1; + + /* if necessary, append a '/' + */ +#ifdef _MBCS + if (*pfin == SLASHCHAR) { + if (pfin != _mbsrchr(buf,SLASHCHAR)) + /* fin is the second byte of a double-byte char */ + strcat(buf, SLASH ); + } + else if (*pfin !=XSLASHCHAR) + strcat(buf, SLASH); +#else + if (*pfin != SLASHCHAR && *pfin != XSLASHCHAR) + strcat(buf, SLASH); +#endif + /* check that the final path will be of legal size. if so, + * build it. otherwise, return to the caller (return value + * and errno rename set from initial call to _spawnve()). + */ + if ( (strlen(buf) + strlen(filename)) < _MAX_PATH ) + strcat(buf, filename); + else + break; + + /* try spawning it. if successful, or if errno comes back with a + * value other than ENOENT and the pathname is not a UNC name, + * return to the caller. + */ + if ( (i = _spawnve(modeflag, buf, argv, envptr)) != -1 + || ((errno != ENOENT) +#ifdef _MBCS + && (!ISPSLASH(buf) || !ISPSLASH(buf+1))) ) +#else + && (!ISSLASH(*buf) || !ISSLASH(*(buf+1)))) ) +#endif + break; + + } + +done: + if (buf != NULL) free(buf); + return(i); +} diff --git a/private/crt32/exec/system.c b/private/crt32/exec/system.c new file mode 100644 index 000000000..44536cf38 --- /dev/null +++ b/private/crt32/exec/system.c @@ -0,0 +1,95 @@ +/*** +*system.c - pass a command line to the shell +* +* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines system() - passes a command to the shell +* +*Revision History: +* 12-01-83 RN written +* 10-23-86 SKS Fixed use of strtok(), added check for NULL rtn from getenv +* 12-18-86 SKS PROTMODE symbol used for dual-modal version +* 02-23-86 JCR Put in support for NULL command pointer (MSDOS only) +* 04-13-86 JCR Added const to declaration +* 06-30-87 JCR Re-wrote system to use spawnvpe, removed XENIX conditional +* code, lots of general cleaning up. +* 07-01-87 PHG removed P->PROTMODE compile switch hack +* 09-22-87 SKS remove extern variable declarations, add ";" to assert()'s +* 11-10-87 SKS Removed IBMC20 switch, change PROTMODE to OS2 +* 12-11-87 JCR Added "_LOAD_DS" to declaration +* 02-22-88 JCR Added cast to get rid of cl const warning +* 09-05-88 SKS Treat EACCES the same as ENOENT -- keep trying +* 03-08-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include +* <cruntime.h>, removed some leftover DOS support and +* fixed the copyright. Also, cleaned up the formatting +* formatting a bit. +* 07-23-90 SBM Compiles cleanly with -W3 (removed unreferenced +* variable), removed redundant includes, replaced +* <assertm.h> by <assert.h>, minor optimizations +* 09-27-90 GJF New-style function declarator. +* 01-17-91 GJF ANSI naming. +* 02-14-90 SRW Use NULL instead of _environ to get default. +* 02-23-93 SKS Remove reference to _osmode and use of "command.com" +* +*******************************************************************************/ + +#include <cruntime.h> +#include <assert.h> +#include <process.h> +#include <io.h> +#include <stdlib.h> +#include <errno.h> + +/*** +*int system(command) - send the command line to a shell +* +*Purpose: +* Executes a shell and passes the command line to it. +* If command is NULL, determine if a command processor exists. +* +*Entry: +* char *command - command to pass to the shell (if NULL, just determine +* if command processor exists) +* +*Exit: +* if command != NULL returns status of the shell +* if command == NULL returns non-zero if CP exists, zero if CP doesn't exist +* +*Exceptions: +* +*******************************************************************************/ + +int _CALLTYPE1 system ( + const char *command + ) +{ + int catch; + char *argv[4]; + + argv[0] = getenv("COMSPEC"); + + if (command == NULL) { + return (!_access(argv[0],0)); + } + + assert(*command != '\0'); + + argv[1] = "/c"; + argv[2] = (char *) command; + argv[3] = NULL; + + /* If there is a COMSPEC defined, try spawning the shell */ + + if (argv[0]) /* Do not try to spawn the null string */ + if ((catch = _spawnve(_P_WAIT,argv[0],argv,NULL)) != -1 + || (errno != ENOENT && errno != EACCES)) + return(catch); + + /* No COMSPEC so set argv[0] to what COMSPEC should be. */ + argv[0] = "cmd.exe"; + + /* Let the _spawnvpe routine do the path search and spawn. */ + + return(_spawnvpe(_P_WAIT,argv[0],argv,NULL)); +} diff --git a/private/crt32/exec/wait.c b/private/crt32/exec/wait.c new file mode 100644 index 000000000..c6ba4cae4 --- /dev/null +++ b/private/crt32/exec/wait.c @@ -0,0 +1,199 @@ +/*** +*wait.c - OS/2 wait for child process to terminate +* +* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _wait() - wait for child process to terminate +* +*Revision History: +* 06-08-89 PHG Module created, based on asm version +* 03-08-90 GJF Made calling type _CALLTYPE2 (for now), added #include +* <cruntime.h> and fixed the copyright. Also, cleaned up +* the formatting a bit. +* 04-02-90 GJF Now _CALLTYPE1. +* 07-24-90 SBM Removed '32' from API names +* 09-27-90 GJF New-style function declarators. +* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h> +* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals. +* 01-17-91 GJF ANSI naming +* 02-18-91 SRW Fixed code to close process handle. [_WIN32_] +* 04-26-91 SRW Removed level 3 warnings [_WIN32_] +* 12-17-91 GJF Fixed _cwait for Win32. However, _wait is still +* broken [_WIN32_]. +* 07-21-92 GJF Removed _wait for Win32, not implemented and no good +* way to implement. +* 12-14-92 GJF For Win32, map ERROR_INVALID_HANDLE to ECHILD. +* +*******************************************************************************/ + +#include <cruntime.h> +#include <oscalls.h> +#include <process.h> +#include <errno.h> +#include <internal.h> +#include <stdlib.h> + +/*** +*int _cwait(stat_loc, process_id, action_code) - wait for specific child +* process +* +*Purpose: +* The function _cwait() suspends the calling-process until the specified +* child-process terminates. If the specifed child-process terminated +* prior to the call to _cwait(), return is immediate. +* +*Entry: +* int *stat_loc - pointer to where status is stored or NULL +* process_id - specific process id to be interrogated (0 means any) +* action_code - specific action to perform on process ID +* either _WAIT_CHILD or _WAIT_GRANDCHILD +* +*Exit: +* process ID of terminated child or -1 on error +* +* *stat_loc is updated to contain the following: +* Normal termination: lo-byte = 0, hi-byte = child exit code +* Abnormal termination: lo-byte = term status, hi-byte = 0 +* +*Exceptions: +* +*******************************************************************************/ + +int _CRTAPI1 _cwait ( + int *stat_loc, + int process_id, + int action_code + ) +{ +#ifdef _CRUISER_ + ULONG retstatus; /* return status from child */ + ULONG retval; /* return value from wait */ + char abnormend; /* child terminated abnormally */ + ULONG dosretval; /* return value from OS/2 call */ + RESULTCODES retcodes; /* return codes from child process */ + PID pid_finished; /* process id of child that finished */ + + /* call OS/2 wait for child routine */ + if (dosretval = DOSWAITCHILD(action_code, DCWW_WAIT, &retcodes, + &pid_finished, process_id)) { + /* error occured -- map error code and return */ + _dosmaperr(dosretval); + return -1; + } + + /* set status code values -- note that return value is + truncated to a byte for XENIX compatibility */ + + if (retcodes.codeTerminate != 0) { + abnormend = 1; + retstatus = retcodes.codeTerminate & 0xFF; + } + else { + abnormend = 0; + retstatus = (retcodes.codeResult & 0xFF) << 8 + + (retcodes.codeTerminate & 0xFF); + } + + if (stat_loc != NULL) + *stat_loc = retstatus; + + if (abnormend) { + /* abnormal termination, set errno and return -1 */ + errno = EINTR; + _doserrno = 0; /* no OS/2 error */ + return -1; + } + + return retval; + +#else /* ndef _CRUISER_ */ + +#ifdef _WIN32_ + + int retval; + int retstatus; + unsigned long oserror; + + DBG_UNREFERENCED_PARAMETER(action_code); + + /* Explicitly check for process_id being -1 or -2. In Windows NT, + * -1 is a handle on the current process, -2 is a handle on the + * current thread, and it is perfectly legal to to wait (forever) + * on either */ + if ( (process_id == -1) || (process_id == -2) ) { + errno = ECHILD; + return -1; + } + + /* wait for child process, then fetch its exit code */ + if ( (WaitForSingleObject((HANDLE)process_id, (DWORD)(-1L)) == 0) && + GetExitCodeProcess((HANDLE)process_id, (LPDWORD)&retstatus) ) { + retval = process_id; + } + else { + /* one of the API calls failed. map the error and set up to + return failure. note the invalid handle error is mapped in- + line to ECHILD */ + if ( (oserror = GetLastError()) == ERROR_INVALID_HANDLE ) { + errno = ECHILD; + _doserrno = oserror; + } + else + _dosmaperr(GetLastError()); + + retval = -1; + retstatus = -1; + } + + CloseHandle((HANDLE)process_id); + + if (stat_loc != NULL) + *stat_loc = retstatus; + + return retval; + +#else /* ndef _WIN32_ */ + +#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED! + +#endif /* _WIN32_ */ + +#endif /* _CRUISER_ */ +} + + +#ifndef _WIN32_ + +/*** +*int _wait(stat_loc) - wait for a child to terminate +* +*Purpose: +* The function _wait() suspends the calling-process until one of the +* immediate children terminates. If a child-process terminated prior to +* the call on the function _wait(), return is immediate. +* +*Entry: +* int *stat_loc - pointer to where status is stored or NULL +* +*Exit: +* returns process id or -1 on errors. +* +* *stat_loc is updated to contain the following: +* Normal termination: lo-byte = 0, hi-byte = child exit code +* Abnormal termination: lo-byte = term status, hi-byte = 0 +* +*Exceptions: +* +*******************************************************************************/ + +/* _wait calls _cwait to do all the real work */ +int _CRTAPI1 _wait ( + int *stat_loc + ) +{ + return _cwait(stat_loc, 0, _WAIT_CHILD); +} + + +#endif |