Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

373 lines
9.4 KiB

/***
*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;
}