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/cenvarg.c | |
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/cenvarg.c')
-rw-r--r-- | private/crt32/exec/cenvarg.c | 373 |
1 files changed, 373 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; +} |