home *** CD-ROM | disk | FTP | other *** search
- static char rcsid[] = "$Header: cset.c,v 1.1 89/03/03 12:53:22 np Exp $";
- /* $Log: cset.c,v $
- * Revision 1.1 89/03/03 12:53:22 np
- * Initial revision
- *
- */
-
- /*
- * Copyright (C) 1985-1989 Nigel Perry
- *
- * This program is distributed without any warranty.
- * The author and and distributors accept no resposibility
- * to anyone for the consequence of using this program or
- * whether it serves any particular purpose or works at all,
- * unless they say so in writing.
- *
- * Everyone is granted permission to copy, modify and
- * redistribute this program, but only provided that:
- *
- * 1) They do so without financial or material gain.
- *
- * 2) The copyright notice and this notice are preserved on
- * all copies.
- *
- * 3) The original source is preserved in any redistribution.
- *
- * I hope you find this program useful!
- *
- */
-
- #include <stdio.h>
- #include "cset.h"
- #include "cset.d"
-
- #define strequ(a, b) (!strcmp(a,b))
-
- extern char *malloc(), *realloc();
-
- /* args:
- * args - array of char *'s to args (i.e. argv from main())
- * helpexit - exit program iff help given
- * return:
- * array of _opt_desc describing options
- */
-
- _opt_desc *_cset(args, helpexit) char **args;
- { char *name, *value, *info, *offset, *left, *right;
- int i, type, maxopt, max, score, helpgiven, len;
- _opt_entry *help_entry, *cp, *p;
- int do_help_entry;
- int super;
- _opt_desc *result, *resvec;
- extern _opt_entry _optable[];
- extern char *index();
-
- helpgiven = do_help_entry = 0;
- super = getuid() == 0; /* we be a super user */
-
- /* find largest option number, last entry in _optable is help_entry */
- help_entry = _optable;
- maxopt = 1;
- while( help_entry->_opt_pat ) { help_entry++; maxopt++; }
-
- /* get a vector for the result */
- for(i = 0; args[i]; i++); /* required length */
- resvec = result = (_opt_desc *) malloc( sizeof(_opt_desc) * (i + 1) );
- result[i]._opt_num = -1; /* flag end */
-
- for(i = 0; info = args[i]; i++)
- { if(*info == '+') /* +option */
- { name = info + 1;
- type = PLUS_KWD;
- result->_opt_type = '+';
- }
- else if(*info == '-') /* -option */
- { name = info + 1;
- type = DASH_KWD;
- result->_opt_type = '-';
- }
- else if(value = index(info, '='))
- { if(value != info) /* option=value */
- { name = info;
- *value++ = '\0'; /* add eos over =, bump ptr to value */
- if( *value == '\0' && args[i+1] != 0 ) /* option= value */
- value = args[++i];
- type = (SVAL_KWD | NVAL_KWD);
- result->_opt_type = '=';
- }
- else /* =<something> */
- { value++; /* ptr to <something> */
- if( strequ(value, "=") ) /* display complete option table */
- { d_optable(0, (_opt_entry *)0, super);
- helpgiven = 1;
- continue; /* don't wan't to scan optable, go direct to next */
- }
- else if( strequ(value, "+") ) /* display long optable */
- { d_optable(1, (_opt_entry *)0, super);
- helpgiven = 1;
- continue; /* don't wan't to scan optable, go direct to next */
- }
- else if( strequ(value, "#") ) /* display help info */
- { if(help_entry->_opt_types == 0)
- fprintf(stderr, "Sorry, no help available, see manual\n");
- else
- do_help_entry = 1;
- helpgiven = 1;
- continue; /* don't wan't to scan optable, go direct to next */
- }
- else /* see if <something> is an option */
- { /* scan optable for match */
- max = 0; /* best match so far */
- cp = (_opt_entry *)0;
- p = _optable;
- while( p->_opt_pat )
- { if( super || !(p->_opt_types & PRIV_BIT) )
- { if( (score = abbrev(p->_opt_pat, value)) > max )
- { max = score;
- cp = p;
- }
- }
- p++;
- }
- if(cp) /* got a match - print help message */
- { _opt_adorn(cp->_opt_types, &left, &right);
- len = strlen(left) + strlen(cp->_opt_pat) + strlen(right);
- fprintf(stderr, "%*s%s%s%s%*s%s\n", TAB1, "",
- left, cp->_opt_pat, right,
- TAB3 - (len + TAB1), "",
- cp->_opt_help == (char *)0 ? "(see manual)" : cp->_opt_help);
- helpgiven = 1;
- continue; /* don't wan't to scan optable */
- }
- else /* treat as possible BLNK_KWD */
- { name = info;
- type = BLNK_KWD | (i == 0 ? COMM_KWD : 0);
- result->_opt_type = ' ';
- }
- }
- }
- }
- else
- { name = info;
- type = BLNK_KWD | (i == 0 ? COMM_KWD : 0 );
- result->_opt_type = ' ';
- }
-
- /* scan optable for match */
- max = 0; /* best match so far */
- cp = (_opt_entry *)0;
- p = _optable;
- while( p->_opt_pat )
- { if( super || !(p->_opt_types & PRIV_BIT) ) /* check for PRIV_KWD */
- { if( p->_opt_types & type ) /* compatible type? */
- { if( (score = abbrev(p->_opt_pat, name)) > max )
- { /* better match */
- max = score;
- cp = p;
- }
- }
- }
- p++;
- }
- if(cp)
- { result->_opt_num = (int)(cp - _optable) + 1;
- switch( cp->_opt_types & type )
- { case SVAL_KWD:
- result->_opt.sval = value;
- break;
- case NVAL_KWD:
- if( read_num(value, cp->_opt_types, result) == 0 )
- { result->_opt_num = maxopt + 1; /* read_num failed */
- result->_opt.sval = info; /* return 'looks like' */
- }
- break;
- }
- }
- else if( type == BLNK_KWD )
- { result->_opt_num = 0; /* flag as a simple string */
- result->_opt.sval = info;
- }
- else
- { result->_opt_num = maxopt + 1; /* flag as looks like an option */
- result->_opt.sval = info;
- }
- result++; /* bump ptr */
- }
- result->_opt_num = -1; /* flag end */
-
- /* should we do help_entry */
- if( do_help_entry ) switch( help_entry->_opt_types )
- { case OPT_LIST:
- list_file(help_entry->_opt_help);
- break;
- case OPT_EXEC:
- system(help_entry->_opt_help);
- break;
- }
-
- /* see if we should exit... */
- if( helpexit && helpgiven ) exit(0);
- return(resvec);
- }
-
- #define CHUNK (sizeof(int) * 10)
-
- static read_num(str, type, result) char *str; _opt_desc *result;
- { int base, flag, offset, *mvals, maxnums, i;
-
- flag = 0; /* dont skip leading junk */
- offset = 0;
- base = type & BASE_MASK;
- if( !(type & MVAL_BIT) ) /* single number */
- { result->_opt.nval = numarg(str, &offset, base, &flag);
- if( flag == 0 || str[offset] != '\0' ) /* bad num or terminator */
- return(0); /* fail */
- }
- else /* multivalued */
- { maxnums = CHUNK;
- mvals = (int *)malloc(CHUNK);
- i = 1; /* mvals[0] will be number of numbers */
- do
- { if(i == maxnums) /* run out of space */
- { maxnums += CHUNK;
- mvals = (int *)realloc(mvals, CHUNK); /* grow it */
- }
- flag = 0;
- mvals[i++] = numarg(str, &offset, base, &flag);
- if(flag == 0) /* bad input */
- { free(mvals); /* give back vector */
- return(0);
- }
- } while( str[offset++] != '\0' );
- mvals[0] = i - 1; /* number of numbers found */
- result->_opt.mval = mvals;
- }
- return(1); /* ok */
- }
-
- static list_file(f) char *f;
- { FILE *in;
- char c;
-
- if( (in = fopen(f, "r")) == NULL ) return;
- while( (c = getc(in)) != EOF ) putc(c, stderr);
- fclose(in);
- }
-