summaryrefslogtreecommitdiffstats
path: root/private/crt32/exec/cenvarg.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/crt32/exec/cenvarg.c')
-rw-r--r--private/crt32/exec/cenvarg.c373
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;
+}