home *** CD-ROM | disk | FTP | other *** search
- /* MS-DOS stdargv Function
- *
- * MS-DOS stdargv - Copyright (c) 1990,1,2 Data Logic Limited.
- *
- * This code is subject to the following copyright restrictions:
- *
- * 1. Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice is duplicated in the
- * source form.
- *
- * $Header: c:/usr/src/shell/rcs/stdargv.c 2.0 1992/04/13 17:39:09 Ian_Stewartson Exp $
- *
- * $Log: stdargv.c $
- * Revision 2.0 1992/04/13 17:39:09 Ian_Stewartson
- * MS-Shell 2.0 Baseline release
- *
- *
- *
- * MODULE DEFINITION:
- *
- * This function expandes the command line parameters in a UNIX like manner.
- * Wild character *?[] are allowed in file names. @filename causes command lines
- * to be read from filename. Strings between " or ' are not expanded. All
- * entries in the array are malloced.
- *
- * This function replaces the standard Microsoft C5.1 & C6.0 C Run-Time
- * start up line processing function (_setargv in stdargv.obj).
- *
- * To get the OS2 version, compile with -DOS2
- *
- * Author:
- * Ian Stewartson
- * Data Logic, Queens House, Greenhill Way
- * Harrow, Middlesex HA1 1YR, UK.
- * istewart@datlog.co.uk or ukc!datlog!istewart
- */
-
- #include <sys/types.h> /* MS-DOS type definitions */
- #include <sys/stat.h> /* File status definitions */
- #include <stdio.h> /* Standard I/O delarations */
- #include <stdlib.h> /* Standard library functions */
- #include <errno.h> /* Error number declarations */
- #ifdef OS2
- #define INCL_DOSSESMGR
- #define INCL_DOSMEMMGR
- #define INCL_DOSPROCESS
- #define INCL_WINSWITCHLIST
- #include <os2.h> /* OS2 functions declarations */
- #else
- #include <dos.h> /* DOS functions declarations */
- #include <bios.h> /* BIOS functions declarations */
- #endif
- #include <ctype.h> /* Character type declarations */
- #include <string.h> /* String library functions */
- #include <limits.h> /* String library functions */
- #include <fcntl.h> /* File Control Declarations */
- #include <dirent.h> /* Direction I/O functions */
- #include <unistd.h>
- #include <glob.h> /* Globbing functions */
-
- /*
- * DATA DEFINITIONS:
- */
-
- #define MAX_LINE 160 /* Max line length */
- #define S_ENTRY sizeof (char *)
-
- /*
- * DATA DECLARATIONS:
- */
- #ifdef MSDOS
-
- extern void _setargv (void);
- static void _Ex_CommandLine (char *); /* Expand file */
- static void _Ex_ExpandIndirectFile (char *);
- static char *_Ex_GetSpace (int, char *); /* Get space */
- static void _Ex_AddArgument (char *); /* Add argument */
- static char *_Ex_SkipWhiteSpace (char *); /* Skip spaces */
- static char *_Ex_ConvertToUnixFormat (char *);
- static void _Ex_ExpandField (char *); /* Split file name */
- static void _Ex_FatalError (int, char *, char *);
- static char *_Ex_ConvertEnvVariables (char *);
- static char *_EX_OutOfMemory = "%s: %s\n";
-
- extern char far *_pgmptr; /* Program name */
- extern char **__argv; /* Current argument address */
- extern int __argc; /* Current argument count */
-
- #ifdef OS2
- extern ushort _aenvseg; /* Environment seg */
- extern ushort _acmdln; /* Command line offset */
- #endif
-
- /*
- * MODULE ABSTRACT: _setargv
- *
- * UNIX like command line expansion
- */
-
- void _setargv ()
- {
- char far *s; /* Temporary string pointer */
-
- # ifndef M_I86LM
- char buf[MAX_LINE]; /* Temporary space */
- # endif
-
- #ifdef OS2
- char far *argvp = (char far *)((((long)_aenvseg) << 16));
- ushort off = _acmdln;
- HSWITCH hswitch;
- SWCNTRL swctl;
- PIDINFO PidInfo;
- char *cp;
-
- while (--off)
- {
- if (argvp[off - 1] == 0)
- break;
- }
-
- /* Add program name */
-
- _pgmptr = &argvp[off];
-
- if (argvp[_acmdln] == 0)
- {
- # ifndef M_I86LM
- cp = buf;
- s = _pgmptr;
- while (*(cp++) = *(s++))
- continue;
-
- _Ex_AddArgument (_Ex_ConvertToUnixFormat (buf));
- # else
- _Ex_AddArgument (_Ex_ConvertToUnixFormat (_pgmptr));
- # endif
- }
-
- else
- {
- argvp += _acmdln;
-
- # ifndef M_I86LM
- cp = buf;
- s = argvp;
- while (*(cp++) = *(s++))
- continue;
-
- off = strlen (buf);
- _Ex_AddArgument (_Ex_ConvertToUnixFormat (buf));
- argvp += off + 1;
-
- cp = buf;
- s = argvp;
- while (*(cp++) = *(s++))
- continue;
-
- _Ex_CommandLine (buf);
- # else
-
- _Ex_AddArgument (_Ex_ConvertToUnixFormat (argvp));
- argvp += strlen (argvp) + 1;
- _Ex_CommandLine (argvp);
-
- # endif
-
- /* Set up the Window name. Give up if it does not work. */
-
- if (!DosGetPID (&PidInfo) &&
- ((hswitch = WinQuerySwitchHandle (0, PidInfo.pid))) &&
- (!WinQuerySwitchEntry (hswitch, &swctl)))
- {
- if ((cp = strrchr (__argv[0], '/')) == (char *)NULL)
- cp = __argv[0];
-
- else
- ++cp;
-
-
- strncpy (swctl.szSwtitle, cp, MAXNAMEL);
- swctl.szSwtitle[MAXNAMEL] = 0;
-
- if ((cp = strrchr (swctl.szSwtitle, '.')) != (char *)NULL)
- *cp = 0;
-
- WinChangeSwitchEntry (hswitch, &swctl);
- }
- }
- #else
- /* Set up pointer to command line */
- char far *argvp = (char far *)((((long)_psp) << 16) + 0x081L);
- unsigned int envs = *(int far *)((((long)_psp) << 16) + 0x02cL);
-
- /* Command line can be null or 0x0d terminated - convert to null */
-
- s = argvp;
-
- while (*s && (*s != 0x0d))
- ++s;
-
- if (*s == 0x0d)
- *s = 0;
-
- /* Set up global parameters and expand */
-
- __argc = 0;
-
- /* Get the program name */
-
- if ((_osmajor <= 2) || (envs == 0))
- s = "unknown";
-
- /* In the case of DOS 3+, we look in the environment space */
-
- else
- {
- s = (char far *)(((long)envs) << 16);
-
- while (*s)
- {
- while (*(s++) != 0)
- continue;
- }
-
- s += 3;
- }
-
- /* Add the program name */
-
- _pgmptr = s;
-
- # ifndef M_I86LM
- cp = buf;
- while (*(cp++) = *(s++))
- continue;
-
- _Ex_AddArgument (_Ex_ConvertToUnixFormat (buf));
-
- s = argvp;
- cp = buf;
- while (*(cp++) = *(s++))
- continue;
-
- _Ex_CommandLine (buf);
- # else
- _Ex_AddArgument (_Ex_ConvertToUnixFormat (s));
- _Ex_CommandLine (argvp);
- # endif
- #endif
-
- _Ex_AddArgument ((char *)NULL);
- --__argc;
- }
-
- /*
- * Expand the DOS Command line
- */
-
- static void _Ex_CommandLine (argvp)
- char *argvp; /* Line to expand */
- {
- char *spos; /* End of string pointer */
- char *cpos; /* Start of string pointer */
- char *fn; /* Extracted file name string */
-
- /* Search for next separator */
-
- spos = argvp;
-
- while (*(cpos = _Ex_SkipWhiteSpace (spos)))
- {
-
- /* Extract string argument */
-
- if ((*cpos == '"') || (*cpos == '\''))
- {
- spos = cpos + 1;
-
- do
- {
- if ((spos = strchr (spos, *cpos)) != NULL)
- {
- spos++;
- if (spos[-2] != '\\')
- break;
- }
-
- else
- spos = &spos[strlen (cpos)];
-
- } while (*spos);
-
- fn = _Ex_GetSpace (spos - cpos - 2, cpos + 1);
- }
-
- /* Extract normal argument */
-
- else
- {
- spos = cpos;
- while (!isspace (*spos) && *spos)
- spos++;
-
- fn = _Ex_GetSpace (spos - cpos, cpos);
- }
-
- /* Process argument */
-
- if (*cpos != '\'')
- fn = _Ex_ConvertEnvVariables (fn);
-
- switch (*cpos)
- {
- case '@': /* Expand file */
- _Ex_ExpandIndirectFile (fn);
- break;
-
- case '"': /* Expand string */
- case '\'':
- _Ex_AddArgument (fn);
- break;
-
- default: /* Expand field */
- _Ex_ExpandField (fn);
- }
-
- free (fn);
- }
- }
-
- /* Expand an indirect file Argument */
-
- static void _Ex_ExpandIndirectFile (file)
- char *file; /* Expand file name */
- {
- FILE *fp; /* File descriptor */
- char *EoLFound; /* Pointer */
- int c_maxlen = MAX_LINE;
- char *line; /* Line buffer */
- char *eolp;
-
- /* If file open fails, expand as a field */
-
- if ((fp = fopen (file + 1, "rt")) == NULL)
- {
- _Ex_ExpandField (file);
- return;
- }
-
- /* Grab some memory for the line */
-
- if ((line = malloc (c_maxlen)) == (char *)NULL)
- _Ex_FatalError (ENOMEM, _EX_OutOfMemory, (char *)NULL);
-
- /* For each line in the file, remove EOF characters and add argument */
-
- while (fgets (line, c_maxlen, fp) != (char *)NULL)
- {
- EoLFound = strchr (line, '\n');
- eolp = line;
-
- /* Handle continuation characters */
-
- while (TRUE)
- {
-
- /* Check for a continuation character */
-
- if (((EoLFound = strchr (eolp, '\n')) != (char *)NULL) &&
- (*(EoLFound - 1) == '\\'))
- {
- *(EoLFound - 1) = '\n';
- *EoLFound = 0;
- EoLFound = (char *)NULL;
- }
-
- else if (EoLFound == (char *)NULL)
- EoLFound = strchr (line, 0x1a);
-
- if (EoLFound != (char *)NULL)
- break;
-
- /* Find the end of the line */
-
- c_maxlen = strlen (line);
-
- /* Get some more space */
-
- if ((line = realloc (line, c_maxlen + MAX_LINE)) == (char *)NULL)
- _Ex_FatalError (ENOMEM, _EX_OutOfMemory, (char *)NULL);
-
- eolp = &line[c_maxlen];
-
- if (fgets (eolp, MAX_LINE, fp) == (char *)NULL)
- break;
- }
-
- /* Terminate the line and add it to the argument list */
-
- if (EoLFound != (char *)NULL)
- *EoLFound = 0;
-
- _Ex_AddArgument (line);
- }
-
- if (ferror(fp))
- _Ex_FatalError (errno, "%s: %s (%s)\n", file + 1);
-
- free (line);
- fclose (fp);
-
- /* Delete tempoary files */
-
- if (((line = strrchr (file + 1, '.')) != (char *)NULL) &&
- (stricmp (line, ".tmp") == 0))
- unlink (file + 1); /* Delete it */
- }
-
- /* Get space for an argument name */
-
- static char *_Ex_GetSpace (length, in_s)
- int length; /* String length */
- char *in_s; /* String address */
- {
- char *out_s; /* Malloced space address */
-
- if ((out_s = malloc (length + 1)) == (char *)NULL)
- _Ex_FatalError (ENOMEM, _EX_OutOfMemory, (char *)NULL);
-
- /* Copy string for specified length */
-
- strncpy (out_s, in_s, length);
- out_s[length] = 0;
-
- return (out_s);
- }
-
- /* Append an argument to the array */
-
- static void _Ex_AddArgument (Argument)
- char *Argument; /* Argument to add */
- {
- if (__argc == 0)
- __argv = (char **)malloc (50 * S_ENTRY);
-
- else if ((__argc % 50) == 0)
- __argv = (char **)realloc (__argv, (__argc + 50) * S_ENTRY);
-
- if (__argv == (char **)NULL)
- _Ex_FatalError (ENOMEM, _EX_OutOfMemory, (char *)NULL);
-
- if (Argument == (char *)NULL)
- __argv[__argc++] = (char *)NULL;
-
- else
- __argv[__argc++] = _Ex_GetSpace (strlen (Argument), Argument);
- }
-
- /* Skip over spaces */
-
- static char *_Ex_SkipWhiteSpace (a)
- char *a; /* String start address */
- {
- while (isspace(*a))
- a++;
-
- return (a);
- }
-
- /* Convert name to Unix format */
-
- static char *_Ex_ConvertToUnixFormat (a)
- char *a;
- {
- char *sp = a;
-
- while ((a = strchr (a, '\\')) != (char *)NULL)
- *(a++) = '/';
-
- #ifndef OS2
- return strlwr (sp);
- #else
- if (!IsHPFSFileSystem (sp))
- strlwr (sp);
-
- return sp;
- #endif
-
- }
-
- /* Find the location of meta-characters. If no meta, add the argument and
- * return NULL. If meta characters, return position of end of directory
- * name. If not multiple directories, return -1
- */
-
- static void _Ex_ExpandField (file)
- char *file;
- {
- int i = 0;
- glob_t gp;
-
- if (strpbrk (file, "?*[]\\") == (char *)NULL)
- {
- _Ex_AddArgument (file);
- return;
- }
-
- if (glob (file, GLOB_NOCHECK, (int (*)())NULL , &gp))
- _Ex_FatalError (ENOMEM, _EX_OutOfMemory, (char *)NULL);
-
- i = 0;
-
- while (i < gp.gl_pathc)
- _Ex_AddArgument (gp.gl_pathv[i++]);
-
- globfree (&gp);
- }
-
- /* Fatal errors */
-
- static void _Ex_FatalError (ecode, format, para)
- int ecode;
- char *format;
- char *para;
- {
- fprintf (stderr, format, "stdargv", strerror (ecode), para);
- exit (1);
- }
-
- /* Process Environment - note that field is a malloc'ed field */
-
- static char *_Ex_ConvertEnvVariables (field)
- char *field;
- {
- char *sp, *cp, *np, *ep;
- char save;
- int b_flag;
-
- sp = field;
-
- /* Replace any $ strings */
-
- while ((sp = strchr (sp, '$')) != (char *)NULL)
- {
-
- /* If ${...}, find the terminating } */
-
- if (*(cp = ++sp) == '{')
- {
- b_flag = 1;
- ++cp;
-
- while (*cp && (*cp != '}'))
- cp++;
- }
-
- /* Else must be $..., find the terminating non-alphanumeric */
-
- else
- {
- b_flag = 0;
-
- while (isalnum (*cp))
- cp++;
- }
-
- /* Grab the environment variable */
-
- if (cp == sp)
- continue;
-
- /* Get its value */
-
- save = *cp;
- *cp = 0;
- ep = getenv (sp + b_flag);
- *cp = save;
-
- if (ep != (char *)NULL)
- {
- np = _Ex_GetSpace (strlen(field) - (cp - sp) + strlen (ep) - 1, field);
- strcpy (&np[sp - field - 1], ep);
- free (field);
- strcpy ((sp = &np[strlen(np)]), cp + b_flag);
- field = np;
- }
- }
-
- return field;
- }
- #endif
-