home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Professional
/
OS2PRO194.ISO
/
os2
/
sysutils
/
msshell
/
ms_sh200.zoo
/
src
/
stdargv.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-06-20
|
13KB
|
593 lines
/* 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