home *** CD-ROM | disk | FTP | other *** search
- /* arg_func.c ************************************** updated: 960801.15:39 TT
- *
- * Import : #includes
- * Export : global functions
- * Description : functions for parsing the command line and getting
- * arguments from the environment
- * Author : Tormod Tjaberg
- *
- * Note:
- * Not all programs may want both GetOpt and GetEnvArgs. Therefore I have
- * included special ifdef's for easy inclusion/exclusion.
- *
- * define NO_GETOPT ; if you don't want GetOpt
- * define NO_GETENVARG ; if you don't want GetEnvArgs
- *
- * The default is both functions
- *
- * Copyright (C) 1992-96 Tormod Tjaberg
- * This is free software, distributed under the terms of the
- * GNU General Public License. For details see the file COPYING
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <string.h>
- #include "arg_func.h"
-
- /* gsar does not parse the environment
- */
- #define NO_GETENVARG
-
- #ifndef NO_GETOPT
-
- /* variables used by GetOpt
- */
- int OptInx = 1; /* index into argv, skip argv[0]; filename */
- int CurOpt; /* current option checked for validity */
- char *pOptArg; /* argument associated with option */
-
-
- /* GetOpt()
- *
- * Input : argc - number of arguments on the command line
- * argv - pointer to the argument vector
- * pOptStr - pointer to a string containing valid option characters
- * Returns: Current option being processed or an error
- *
- * Scan elements of argv (length is argc) for option characters given in
- * 'pOptStr'. Each time GetOpt is called it returns the next option character
- * from the option elements. When there are no more option charactes left
- * GetOpt returns EOF.
- *
- * 'pOptStr' is a string containing all valid option characters. If an option
- * character is encountered that is not in 'pOptStr', GetOpt returns:
- * BAD_CHAR. The offending character is stored in 'CurOpt'.
- *
- * If a character in the option string is followed by a colon, it means
- * that this option requires an argument. The argument can be the remainding
- * text in the current argv element, or the next argv element. The argument
- * is returned in 'pOptArg'. If no argument was found GetOpt returns:
- * MISSING_ARG and 'pOptArg' is set to NULL. 'CurOpt' contains the offending
- * option char.
- *
- * If a character is followed by two colons it means that this option
- * wants an optional argument. If there is any text left in the current argv
- * element it is returned in 'pOptarg'. If no argument was found 'pOptArg'
- * is set to NULL and the option character is returned.
- *
- * If the option string contains '|' EOF will not be returned when a
- * non option if found. Instead GetOpt returns '|'. If '|' is not specified
- * NON_OPT is returned. In both cases 'pGetOpt' will poin to the non option.
- * and 'OptInx' is the index of argv that contains the non option.
- *
- * Note, the following command line arguments have a special meaning:
- *
- * '-' : GetOpt returns: MISSING_OPT, 'pOptArg' is set to NULL
- * '--': Forces an end of option scanning. GetOpt returns: EOF
- * Can be detected by checking if `OptInx' != argc, argv[OptInx]
- * points to the argv element following the '--'
- *
- * Heavily inspired by the UN?X getopt, but a bit simpler
- */
- int GetOpt(int argc, char **argv, char *pOptStr)
- {
- static char *pCurOpt = ""; /* pointer to current option */
- char *pOptChar; /* pointer to char in option string */
-
- if (*pCurOpt == '\0') /* get a new pointer */
- {
- if (OptInx >= argc) /* no more of arguments on command line */
- return EOF;
-
- pCurOpt = argv[OptInx];
-
- if (*(pCurOpt++) != '-')
- {
- pCurOpt = ""; /* next time, get a new argv */
- pOptArg = argv[OptInx];
- OptInx++;
-
- if (strchr(pOptStr, '|') != NULL)
- return '|'; /* This might be a filename */
- else
- return NON_OPT;
- }
-
- if (*pCurOpt == '\0')
- return MISSING_OPT;
-
- if (*pCurOpt == '-') /* catch the '--' */
- {
- OptInx++; /* point to the argument behind '--' */
- return EOF;
- }
- }
-
- CurOpt = *pCurOpt++; /* CurOpt is the option character */
-
- if ((pOptChar = strchr(pOptStr, CurOpt)) == NULL)
- return BAD_CHAR; /* char not in option string, culprit in CurOpt */
-
- if (*(++pOptChar) != ':') /* option doesn't need argument */
- {
- pOptArg = NULL;
- if (*pCurOpt == '\0')
- ++OptInx;
- }
- else
- { /* option needs an argument, but how bad ? */
- if (*pCurOpt != '\0') /* remainder of argv is argument -d123 -> arg = 123 */
- pOptArg = pCurOpt;
- else
- if (*(++pOptChar) == ':') /* '::' optional arg, but no argument */
- pOptArg = NULL;
- else /* nothing behind option check next arg */
- {
- if (argc <= ++OptInx)
- {
- pOptArg = NULL; /* no arguments left but we needed one */
- return MISSING_ARG; /* return missing arg for option, culprit in CurOpt */
- }
- else /* white space separating arguments */
- pOptArg = argv[ OptInx ];
- }
-
- pCurOpt = ""; /* next time get a new argv */
- ++OptInx; /* next argv */
- }
- return CurOpt; /* return option letter */
- }
-
- #endif
-
- #ifndef NO_GETENVARG
- /* GetEnvArgs()
- *
- * Input : argc - number of arguments on the command line
- * argv - pointer to the argument vector
- * pEnvVar - environment variable we are to find
- * Returns: Number of arguments found in environment
- *
- * Create a new arvector with the enviroment arguments before the
- * program arguments. This way a command line option will override
- * the environment option. Any number of args can be given since we
- * malloc the new argument vector. The environment variable is not destroyed.
- *
- * This code originally used realloc, and did not make a copy of the
- * environment variable.
- */
- int GetEnvArgs(int *argc, char ***argv, char *pEnvVar)
- {
- char *pEnvStr; /* pointer to environment string */
- char **pArgV; /* pointer to our new argument vector */
- char **pStartArgV; /* pointer to our new argument vector */
- char *cp; /* character pointer */
- char *pBuf; /* pointer to copy of environment string */
- int count = 0;
- int envcount = 0;
- unsigned char ch;
-
- /* fetch contents of environment variable, if any */
- pEnvStr = getenv(pEnvVar);
-
- if (pEnvStr == NULL || *pEnvStr == 0)
- return 0 ;
-
- while (isspace(*pEnvStr)) /* avoid adding whitespace onto pArgV */
- pEnvStr++;
-
- if ((pBuf = (char *) malloc(1 + strlen(pEnvStr))) == NULL)
- Abort("error: unable to malloc memory for copy of environment string");
-
- strcpy(pBuf,pEnvStr); /* copy the original string into buffer */
-
- /* count how many arguments there are... so we can malloc */
- cp = pBuf;
- while(*cp != '\0') /* traverse environment string */
- {
- while (!isspace(*cp) && *cp != '\0')
- cp++;
- while (isspace(*cp))
- cp++;
- count++;
- }
-
- if (count == 0) /* if environment string is empty */
- return 0;
-
- envcount = count;
-
- /* malloc a vector that will hold all args + 1 to hold NULL */
- if ((pArgV = pStartArgV = (char **) malloc((count + *argc + 1) * sizeof(char *))) == NULL)
- Abort("error: unable to malloc for arguments");
-
- *(pArgV++) = *((*argv)++); /* copy argv[0] (filename) from argv */
-
- do
- {
- *(pArgV++) = pBuf; /* assign argument to new arg vector */
- while ((ch = *pBuf) != '\0' && !isspace(ch))
- pBuf++; /* step over the argument */
- if (ch != '\0')
- *(pBuf++) = '\0'; /* create a null terminated string */
- while ((ch = *pBuf) != '\0' && isspace(ch))
- pBuf++; /* step over the whitespace */
- } while (ch != '\0');
-
- /* now save old argc and copy in the old args */
- count += *argc;
-
- /* copy original arg vector */
- while (--(*argc))
- *(pArgV++) = *((*argv)++);
-
- *pArgV = NULL; /* The C-standard specifies that argv[argc] == NULL */
- *argc = count;
- *argv = pStartArgV; /* make argv point to our new vector */
-
- return envcount; /* number of args found in environment */
- }
- #endif
-
-