/*** *stdenvp.c - standard _setenvp routine * * Copyright (c) 1989-2001, Microsoft Corporation. All rights reserved. * *Purpose: * This module is called by the C start-up routine to set up "_environ". * Its sets up an array of pointers to strings in the environment. * The global symbol "_environ" is set to point to this array. * *Revision History: * 11-07-84 GFW initial version * 01-08-86 SKS Modified for OS/2 * 05-21-86 SKS Call _stdalloc to get memory for strings * 09-04-86 SKS Added check to skip the "*C_FILE_INFO" string * 10-21-86 SKS Improved check for "*C_FILE_INFO"/"_C_FILE_INFO" * 02-19-88 SKS Handle case where environment starts with a single null * 05-10-88 JCR Modified code to accept far pointer from _stdalloc * 06-01-88 PHG Merged DLL and normal versions * 07-12-88 JCR Largely re-written: (1) split mem allocation into two * seperate malloc() calls to help simplify putenv(), * (2) stdalloc() no longer robs from stack, (3) cProc/cEnd * sequence, (4) misc cleanup * 09-20-88 WAJ Initial 386 version * 12-13-88 JCR Use rterr.inc parameters for runtime errors * 04-09-90 GJF Added #include . Made the calling type * _CALLTYPE1. Also, fixed the copyright and cleaned up * up the formatting a bit. * 06-05-90 GJF Changed error message interface. * 10-08-90 GJF New-style function declarator. * 10-31-90 GJF Fixed statement appending the final NULL (Stevewo * found the bug). * 12-11-90 SRW Changed to include and setup _environ * correctly for Win32 * 01-21-91 GJF ANSI naming. * 02-07-91 SRW Change _WIN32_ specific code to allocate static copy * 02-18-91 SRW Change _WIN32_ specific code to allocate copy of * variable strings as well [_WIN32_] * 07-25-91 GJF Changed strupr to _strupr. * 03-31-92 DJM POSIX support. * 04-20-92 GJF Removed conversion to upper-case code for Win32. * 04-06-93 SKS Replace _CRTAPI* with __cdecl * 11-24-93 CFW Rip out Cruiser and filter out "=c:\foo" type. * 11-29-93 CFW Remove unused POSIX stuff, wide char enable. * 12-07-93 CFW Change _TCHAR to _TSCHAR. * 01-10-95 CFW Debug CRT allocs. * 04-07-95 CFW Free environment block on demand. * 07-03-95 GJF Always free environment block. * 02-20-96 SKS Set _aenvptr/_wenvptr to NULL after freeing what it * points to (a copy of environment strings). * 06-30-97 GJF Added explicit, conditional init. of the mbctype table. * Set __env_initialized flag. Also detab-ed. * 01-04-99 GJF Changes for 64-bit size_t. * 03-05-01 PML Don't AV if _aenvptr is NULL (vs7#174755). * 03-27-01 PML Return error instead of calling amsg_exit (vs7#231220) * 11-06-01 GB Code Cleaning * *******************************************************************************/ #include #include #include #include #include #include #include #include #ifndef CRTDLL #ifdef _MBCS /* * Flag to ensure multibyte ctype table is only initialized once */ extern int __mbctype_initialized; #endif /* * Flag checked by getenv() and _putenv() to determine if the environment has * been initialized. */ extern int __env_initialized; #endif /*** *_setenvp - set up "envp" for C programs * *Purpose: * Reads the environment and build the envp array for C programs. * *Entry: * The environment strings occur at _aenvptr. * The list of environment strings is terminated by an extra null * byte. Thus two null bytes in a row indicate the end of the * last environment string and the end of the environment, resp. * *Exit: * "environ" points to a null-terminated list of pointers to ASCIZ * strings, each of which is of the form "VAR=VALUE". The strings * are copied from the environment area. This array of pointers will * be malloc'ed. The block pointed to by _aenvptr is deallocated. * *Uses: * Allocates space on the heap for the environment pointers. * *Exceptions: * If space cannot be allocated, program is terminated. * *******************************************************************************/ #ifdef WPRFLAG #define _tsetenvp _wsetenvp #define _tenvptr _wenvptr #else #define _tsetenvp _setenvp #define _tenvptr _aenvptr #endif int __cdecl _tsetenvp ( void ) { _TSCHAR *p; _TSCHAR **env; /* _environ ptr traversal pointer */ int numstrings; /* number of environment strings */ int cchars; #if !defined(CRTDLL) && defined(_MBCS) /* If necessary, initialize the multibyte ctype table. */ if ( __mbctype_initialized == 0 ) __initmbctable(); #endif numstrings = 0; p = _tenvptr; /* * We called __crtGetEnvironmentStrings[AW] just before this, * so if _[aw]envptr is NULL, we failed to get the environment. * Return an error. */ if (p == NULL) return -1; /* * NOTE: starting with single null indicates no environ. * Count the number of strings. Skip drive letter settings * ("=C:=C:\foo" type) by skipping all environment variables * that begin with '=' character. */ while (*p != _T('\0')) { /* don't count "=..." type */ if (*p != _T('=')) ++numstrings; p += _tcslen(p) + 1; } /* need pointer for each string, plus one null ptr at end */ if ( (_tenviron = env = (_TSCHAR **) _malloc_crt((numstrings+1) * sizeof(_TSCHAR *))) == NULL ) return -1; /* copy strings to malloc'd memory and save pointers in _environ */ for ( p = _tenvptr ; *p != L'\0' ; p += cchars ) { cchars = (int)_tcslen(p) + 1; /* don't copy "=..." type */ if (*p != _T('=')) { if ( (*env = (_TSCHAR *)_malloc_crt(cchars * sizeof(_TSCHAR))) == NULL ) { _free_crt(_tenviron); _tenviron = NULL; return -1; } _tcscpy(*env, p); env++; } } _free_crt(_tenvptr); _tenvptr = NULL; /* and a final NULL pointer */ *env = NULL; #ifndef CRTDLL /* * Set flag for getenv() and _putenv() to know the environment * has been set up. */ __env_initialized = 1; #endif return 0; }