2307 lines
67 KiB
C
2307 lines
67 KiB
C
/*
|
|
* COMPONENT_NAME: BLDPROCESS
|
|
*
|
|
* FUNCTIONS: arg_value
|
|
* built_ins
|
|
* entry_pattern
|
|
* get_dotsbx_options
|
|
* get_local_rcfile
|
|
* get_options
|
|
* hvalue
|
|
* in_arg_list
|
|
* init_htable
|
|
* init_one
|
|
* init_to_optlist
|
|
* load_entry
|
|
* load_htable
|
|
* load_max_args
|
|
* load_min_args
|
|
* load_options
|
|
* load_posix_entry1417
|
|
* load_using_posix1065
|
|
* match_arg_list
|
|
* match_entry
|
|
* match_pattern
|
|
* next_token
|
|
* print_htable
|
|
* print_internals
|
|
* rc_file_options
|
|
* set_duplicates
|
|
* set_ver
|
|
* skip_white_space
|
|
* special_case
|
|
* test_conflicts
|
|
* ui_arg_cnt
|
|
* ui_arg_value
|
|
* ui_args_to_argv
|
|
* ui_entries_to_argv2069
|
|
* ui_entry_cnt
|
|
* ui_entry_value
|
|
* ui_init
|
|
* ui_is_auto
|
|
* ui_is_info
|
|
* ui_is_set
|
|
* ui_load
|
|
* ui_print
|
|
* ui_print_revision2233
|
|
* ui_restore_progname
|
|
* ui_set_progname
|
|
* ui_unset
|
|
* ui_ver_level
|
|
* ui_ver_switch
|
|
* uiquit
|
|
*
|
|
* ORIGINS: 27,71
|
|
*
|
|
* This module contains IBM CONFIDENTIAL code. -- (IBM
|
|
* Confidential Restricted when combined with the aggregated
|
|
* modules for this product)
|
|
* SOURCE MATERIALS
|
|
*
|
|
* (C) COPYRIGHT International Business Machines Corp. 1994
|
|
* All Rights Reserved
|
|
* US Government Users Restricted Rights - Use, duplication or
|
|
* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
|
|
*/
|
|
/*
|
|
* @OSF_FREE_COPYRIGHT@
|
|
* COPYRIGHT NOTICE
|
|
* Copyright (c) 1992, 1991, 1990
|
|
* Open Software Foundation, Inc.
|
|
*
|
|
* Permission is hereby granted to use, copy, modify and freely distribute
|
|
* the software in this file and its documentation for any purpose without
|
|
* fee, provided that the above copyright notice appears in all copies and
|
|
* that both the copyright notice and this permission notice appear in
|
|
* supporting documentation. Further, provided that the name of Open
|
|
* Software Foundation, Inc. ("OSF") not be used in advertising or
|
|
* publicity pertaining to distribution of the software without prior
|
|
* written permission from OSF. OSF makes no representations about the
|
|
* suitability of this software for any purpose. It is provided "as is"
|
|
* without express or implied warranty.
|
|
*/
|
|
/*
|
|
* HISTORY
|
|
* $Log: interface.c,v $
|
|
* Revision 1.3.13.8 1993/11/10 18:44:34 root
|
|
* CR 463. Pedantic changes
|
|
* [1993/11/10 18:43:05 root]
|
|
*
|
|
* Revision 1.3.13.7 1993/11/10 16:56:49 root
|
|
* CR 463. Cast stdrup paramater to (char *)
|
|
* [1993/11/10 16:55:54 root]
|
|
*
|
|
* Revision 1.3.13.6 1993/11/08 22:23:23 damon
|
|
* CR 463. Pedantic changes
|
|
* [1993/11/08 22:22:32 damon]
|
|
*
|
|
* Revision 1.3.13.5 1993/11/08 20:18:08 damon
|
|
* CR 463. Pedantic changes
|
|
* [1993/11/08 20:17:25 damon]
|
|
*
|
|
* Revision 1.3.13.4 1993/11/05 20:34:20 damon
|
|
* CR 463. Pedantic changes
|
|
* [1993/11/05 20:33:35 damon]
|
|
*
|
|
* Revision 1.3.13.3 1993/11/04 00:03:24 damon
|
|
* CR 463. More pedantic
|
|
* [1993/11/04 00:02:52 damon]
|
|
*
|
|
* Revision 1.3.13.2 1993/11/03 20:40:25 damon
|
|
* CR 463. More pedantic
|
|
* [1993/11/03 20:38:04 damon]
|
|
*
|
|
* Revision 1.3.13.1 1993/10/22 19:21:40 damon
|
|
* CR 761. Removed SB_RC_OP
|
|
* [1993/10/22 19:12:44 damon]
|
|
*
|
|
* Revision 1.3.11.1 1993/08/19 18:35:18 damon
|
|
* CR 622. Changed if STDC to ifdef STDC
|
|
* [1993/08/19 18:33:07 damon]
|
|
*
|
|
* Revision 1.3.6.7 1993/04/29 14:59:06 damon
|
|
* CR 463. Pedantic changes
|
|
* [1993/04/29 14:58:50 damon]
|
|
*
|
|
* Revision 1.3.6.6 1993/04/09 17:22:39 damon
|
|
* CR 446. Remove warnings with added includes
|
|
* [1993/04/09 17:21:48 damon]
|
|
*
|
|
* Revision 1.3.6.5 1993/04/08 21:16:40 damon
|
|
* CR 446. Clean up include files
|
|
* [1993/04/08 21:16:09 damon]
|
|
*
|
|
* Revision 1.3.6.4 1993/01/21 18:47:54 damon
|
|
* CR 401. Fixed redundant decls.
|
|
* [1993/01/21 18:45:54 damon]
|
|
*
|
|
* Revision 1.3.6.3 1993/01/21 18:39:13 damon
|
|
* CR 401. Added stdarg
|
|
* [1993/01/21 18:34:08 damon]
|
|
*
|
|
* Taken from 2.1.1
|
|
* [1992/06/15 16:31:24 damon]
|
|
*
|
|
* Revision 1.3.2.10 1992/12/03 17:21:01 damon
|
|
* ODE 2.2 CR 183. Added CMU notice
|
|
* [1992/12/03 17:08:18 damon]
|
|
*
|
|
* Revision 1.3.2.9 1992/11/12 18:27:53 damon
|
|
* CR 329. Removed ANSI function decl.
|
|
* [1992/11/12 18:11:29 damon]
|
|
*
|
|
* Revision 1.3.2.8 1992/09/24 19:01:34 gm
|
|
* CR282: Made more portable to non-BSD systems.
|
|
* [1992/09/23 18:21:49 gm]
|
|
*
|
|
* Revision 1.3.2.7 1992/09/15 19:27:11 damon
|
|
* CR 265. Fixed initialization problem.
|
|
* [1992/09/15 19:26:54 damon]
|
|
*
|
|
* Revision 1.3.2.6 1992/09/15 19:20:57 damon
|
|
* CR 265. Not all systems have getopt stuff defined
|
|
* [1992/09/15 19:20:23 damon]
|
|
*
|
|
* Revision 1.3.2.5 1992/08/07 15:31:29 damon
|
|
* CR 266. Changed salloc to strdup
|
|
* [1992/08/07 15:29:12 damon]
|
|
*
|
|
* Revision 1.3.2.4 1992/08/06 21:10:20 damon
|
|
* CR 265. Fixed initialization problem.
|
|
* [1992/08/06 21:08:39 damon]
|
|
*
|
|
* Revision 1.3.2.3 1992/08/06 15:58:38 damon
|
|
* CR 265. Now optionally uses getopt
|
|
* [1992/08/06 15:58:12 damon]
|
|
*
|
|
* Revision 1.3.2.2 1992/06/15 18:10:36 damon
|
|
* Synched with 2.1.1
|
|
* [1992/06/15 18:04:34 damon]
|
|
*
|
|
* Revision 1.3.2.2 1992/03/25 22:48:12 damon
|
|
* Changes for ui_print_revision
|
|
* [1992/03/25 21:52:29 damon]
|
|
*
|
|
* Revision 1.3 1991/12/05 21:05:10 devrcs
|
|
* changed *rcargc = alloc_arg to *rcargc >= alloc_arg
|
|
* [91/06/25 15:00:10 mckeen]
|
|
*
|
|
* added VERSION_OP as an alias for REV_OP
|
|
* [91/06/03 13:41:56 ezf]
|
|
*
|
|
* Changed reading .sandboxrc file so it removes any trailing spaces
|
|
* and does not count them as arguments.
|
|
* Made a difference between loading arguments from the command line
|
|
* and from ui_load so that ui does not exit on failures from ui_load.
|
|
* It now returns ERROR. Added uiquit () to do this and the global
|
|
* boolean from_ui_load.
|
|
* [91/01/29 11:17:18 randyb]
|
|
*
|
|
* Second submission
|
|
* [91/01/22 12:48:12 randyb]
|
|
*
|
|
* Added return_prog_name () before uquits
|
|
* [91/01/22 12:31:21 randyb]
|
|
*
|
|
* Wrote these routines to handle user interface in a standard way.
|
|
* There are a series of public functions each starting with "ui_".
|
|
* The other functions are static and are not meant to be used outside
|
|
* the library.
|
|
* [91/01/08 12:13:16 randyb]
|
|
*
|
|
* Initial version.
|
|
* [90/12/10 16:23:51 damon]
|
|
*
|
|
* Wrote these routines to handle user interface in a standard way.
|
|
* There are a series of public functions each starting with "ui_".
|
|
* The other functions are static and are not meant to be used outside
|
|
* the library.
|
|
* [91/01/08 12:13:16 randyb]
|
|
*
|
|
* Initial version.
|
|
* [90/12/10 16:23:51 damon]
|
|
*
|
|
* $EndLog$
|
|
*/
|
|
/******************************************************************************
|
|
** Open Software Foundation **
|
|
** Cambridge, MA **
|
|
** Randy Barbano, Damon Poole, Martha Hester **
|
|
** December 1990 **
|
|
*******************************************************************************
|
|
**
|
|
** Description: These functions provide a common user interface for the
|
|
** ODE tools. They parse the command line, provide an interface to
|
|
** the information, and provide a common way of printing out messages.
|
|
**
|
|
** functions:
|
|
** ui_init (int, ** char, int, * struct) int
|
|
** ui_set_progname (* char) int
|
|
** init_htable ( int, ** char) int
|
|
** hvalue (* char) unsigned
|
|
** init_one (* struct, * char, int) void
|
|
** load_htable (int, * struct) void
|
|
** test_conflicts (* struct) void
|
|
** match_pattern (* char) * struct
|
|
** hvalue
|
|
** hvalue
|
|
** rc_file_options (int, ** char, * char, * int, *** char) BOOLEAN
|
|
** get_local_rcfile (* char, * char, * char) BOOLEAN
|
|
** ui_print (int, * char, va_list) void
|
|
** get_dotsbx_options (* char, * char, * int, *** char) BOOLEAN
|
|
** ui_print
|
|
** get_options (* struct, * char) * char
|
|
** next_token (** char, * char) BOOLEAN
|
|
** skip_white_space (** char) void
|
|
** ui_print
|
|
** load_options (int, ** char, int, * struct) int
|
|
** built_ins (* char) * char
|
|
** special_case (* char) BOOLEAN
|
|
** ui_unset (* char) int
|
|
** match_pattern
|
|
** ui_print
|
|
** entry_pattern (* char, * struct, int) * char
|
|
** match_pattern
|
|
** load_entry (* struct, * struct, ** char, * char, int, * int) void
|
|
** load_min_args (* struct, ** char, ** struct, int, * int, * int) void
|
|
** match_arg_list (* char, * char) BOOLEAN
|
|
** in_arg_list (* struct, * char) BOOLEAN
|
|
** load_max_args (* struct, ** char, ** struct, int, * int, * int) void
|
|
** match_arg_list
|
|
** in_arg_list
|
|
** ui_unset
|
|
** set_duplicates (* struct, ** struct, * char) void
|
|
** match_entry (* struct, * char, ** struct) void
|
|
** print_htable () void
|
|
** ui_print
|
|
** print_internals (* struct, * struct, * struct, int) void
|
|
** ui_print
|
|
** ui_restore_progname () int
|
|
** ui_load (* char, int, va_list) int
|
|
** built_ins
|
|
** special_case
|
|
** match_pattern
|
|
** ui_print
|
|
** load_entry
|
|
** ui_unset
|
|
** set_duplicates
|
|
** ui_is_set (* char) BOOLEAN
|
|
** match_pattern
|
|
** ui_print
|
|
** ui_entry_cnt (* char) int
|
|
** match_pattern
|
|
** ui_print
|
|
** ui_arg_cnt (* char, int) int
|
|
** ui_print
|
|
** match_pattern
|
|
** ui_entry_value (* char, int) * char
|
|
** ui_print
|
|
** match_pattern
|
|
** ui_arg_value (* char, int, int) * char
|
|
** ui_print
|
|
** match_pattern
|
|
** arg_value (* struct, int, int) * char
|
|
** ui_print
|
|
** ui_entries_to_argv (* char, *** char) int
|
|
** match_pattern
|
|
** ui_print
|
|
** ui_args_to_argv (* char, int, *** char) int
|
|
** ui_print
|
|
** match_pattern
|
|
** ui_ver_switch () * char
|
|
** ui_print
|
|
** ui_is_auto () BOOLEAN
|
|
** ui_is_info () BOOLEAN
|
|
** ui_ver_level () int
|
|
**
|
|
*/
|
|
|
|
#ifndef lint
|
|
static char sccsid[] = "@(#)87 1.1 src/bldenv/sbtools/libode/interface.c, bldprocess, bos412, GOLDA411a 1/19/94 17:41:16";
|
|
#endif /* not lint */
|
|
|
|
#include "ui.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ode/sandboxes.h>
|
|
#include <ode/util.h>
|
|
|
|
extern char *optarg;
|
|
extern int optind;
|
|
extern int opterr;
|
|
|
|
static void
|
|
load_using_posix (
|
|
int usrct, /* number of arguments to parse */
|
|
char ** usr_list, /* list of arguments */
|
|
int initct, /* count of lines to initialize */
|
|
UIINIT * init); /* initialization information */
|
|
static int
|
|
load_posix_entry (
|
|
HTABLE * hptr, /* points to one table pattern */
|
|
char * entry,
|
|
char * arg);
|
|
|
|
void
|
|
#ifdef __STDC__
|
|
uiquit ( int , ... );
|
|
#else
|
|
uiquit ( va_alist );
|
|
#endif
|
|
int ui_init ( argc, argv, initct, init, posix_ct, posix_ops )
|
|
|
|
/*
|
|
* Initialize ui with the argv passed in as well as any switches
|
|
* appearing in the rc file. This procedure must be called before
|
|
* any of the other library procedures are called. This replaces
|
|
* the old call to parse_cmd_line.
|
|
* Returns ERROR if not successful, OK otherwise.
|
|
*/
|
|
|
|
int argc; /* the number of command line arugments */
|
|
char ** argv; /* strings with each argument */
|
|
int initct; /* count of lines to initialize */
|
|
UIINIT * init; /* initialization information */
|
|
int posix_ct; /* count of lines to initialize */
|
|
UIINIT * posix_ops; /* initialization information */
|
|
|
|
{
|
|
const char ** arglist; /* list of rc file arguments */
|
|
int argct; /* rc file arg count */
|
|
|
|
from_ui_load = FALSE;
|
|
ui_set_progname ( "ui_init" );
|
|
init_htable ( argc, argv );
|
|
load_htable ( initct, init );
|
|
load_htable ( posix_ct, posix_ops );
|
|
|
|
if ( rc_file_options ( argc, argv, &argct, &arglist ))
|
|
load_options ( argct, arglist, initct, init );
|
|
|
|
if ( posix_ct > 0 ) {
|
|
ui_print ( VDEBUG, "Using getopt to parse switches\n" );
|
|
load_using_posix ( argc - 1 , argv + 1, initct, init );
|
|
load_options ( argc - 1 - optind, (const char **) (argv + 1 + optind),
|
|
posix_ct, posix_ops );
|
|
} else
|
|
load_options ( argc - 1, (const char **) (argv + 1), initct, init );
|
|
/* if */
|
|
print_htable ();
|
|
ui_restore_progname ();
|
|
return ( OK );
|
|
} /* ui init */
|
|
|
|
|
|
void
|
|
ui_set_progname ( const char * newname )
|
|
|
|
/*
|
|
* Put the newname into progname after having saved the
|
|
* initial value.
|
|
*/
|
|
|
|
{
|
|
save_progname = progname;
|
|
progname = newname;
|
|
} /* ui set_progname */
|
|
|
|
|
|
void
|
|
ui_restore_progname (void)
|
|
|
|
/*
|
|
* Puts previous progname back into progname.
|
|
*/
|
|
|
|
{
|
|
progname = save_progname;
|
|
} /* ui restore progname */
|
|
|
|
|
|
|
|
static void
|
|
init_htable ( int argc, char ** argv )
|
|
|
|
/*
|
|
* Initializes the entire hash table with default values.
|
|
* Also loads the know options.
|
|
*/
|
|
{
|
|
HTABLE * hptr; /* points to one entry */
|
|
int ct; /* misc counter */
|
|
|
|
auto_pos = hvalue ( AUTO_OP );
|
|
info_pos = hvalue ( INFO_OP );
|
|
|
|
if (( argc > 1 ) && streq ( argv[1], DEBUG_OP ))
|
|
verbosity = VDEBUG; /* a way to get inside interface info */
|
|
else if (( argc > 1 ) && streq ( argv[1], VERBOSE_OP ))
|
|
verbosity = VDETAIL;
|
|
else
|
|
verbosity = VNORMAL;
|
|
|
|
if (( htbl = (HTABLE *) malloc (sizeof ( HTABLE ) * HTABLESIZE)) == NULL )
|
|
uquit ( ERROR, FALSE, "sys: cannot create space for user interface.\n" );
|
|
|
|
for ( ct = 0; ct < HTABLESIZE; ct++ ) {
|
|
hptr = htbl + ct;
|
|
hptr->pattern = strdup ( EMPTY_STRING );
|
|
hptr->entry = NULL;
|
|
hptr->arg_list = NULL;
|
|
hptr->entry_list = NULL;
|
|
hptr->next_pattern = NULL;
|
|
hptr->num_entries = hptr->num_args = 0;
|
|
} /* for */
|
|
|
|
init_one ( htbl + auto_pos, AUTO_OP, 0 );
|
|
init_one ( htbl + info_pos, INFO_OP, 0 );
|
|
init_one ( htbl + hvalue ( RC_OP), RC_OP, 1 );
|
|
} /* init htable */
|
|
|
|
|
|
|
|
static unsigned
|
|
hvalue ( const char * string )
|
|
|
|
/*
|
|
* Calculates the hash value of the string.
|
|
*/
|
|
{
|
|
unsigned hashval; /* cumulative value */
|
|
|
|
for ( hashval = 0; *string != NUL; string++ )
|
|
hashval = *string + 31 * hashval;
|
|
|
|
return ( hashval % HTABLESIZE );
|
|
} /* hvalue */
|
|
|
|
|
|
|
|
static
|
|
void init_one (
|
|
HTABLE * hptr, /* points to one entry */
|
|
const char * pattern, /* pattern to match */
|
|
int argct) /* args allowed or needed */
|
|
|
|
/*
|
|
* Initializes a single hash table entry.
|
|
*/
|
|
|
|
|
|
{
|
|
hptr->pattern = strdup ( (char *)pattern );
|
|
hptr->duplicates = OVERWRITE;
|
|
hptr->max_entries = 1;
|
|
hptr->min_args = hptr->max_args = argct;
|
|
|
|
if ( argct == 0 )
|
|
hptr->legal_args = strdup ( EMPTY_STRING );
|
|
else
|
|
hptr->legal_args = strdup ( ARGS_OP );
|
|
} /* init one */
|
|
|
|
|
|
|
|
static void
|
|
load_htable (
|
|
int initct, /* count of lines to initialize */
|
|
UIINIT * init) /* initialization information */
|
|
|
|
/*
|
|
* loads the initial values into the hash table. The
|
|
* built-in values are already loaded.
|
|
*/
|
|
|
|
|
|
{
|
|
HTABLE * hptr; /* points to one entry */
|
|
UIINIT * iptr; /* points to initialization information */
|
|
int ct; /* misc counter */
|
|
|
|
for ( ct = 0; ct < initct; ct++ ) {
|
|
iptr = init + ct;
|
|
|
|
test_conflicts ( iptr );
|
|
|
|
if (( hptr = match_pattern ( iptr->pattern )) != NULL )
|
|
uquit ( ERROR, FALSE,
|
|
"internal error: program has duplicate patterns: %s.\n",
|
|
iptr->pattern );
|
|
|
|
hptr = htbl + hvalue ( iptr->pattern );
|
|
|
|
if ( ! streq ( hptr->pattern, EMPTY_STRING )) {
|
|
while ( hptr->next_pattern != NULL )
|
|
hptr = hptr->next_pattern;
|
|
|
|
hptr->next_pattern = ( HTABLE * ) malloc ( sizeof ( HTABLE ));
|
|
hptr = hptr->next_pattern;
|
|
hptr->entry = NULL;
|
|
hptr->entry_list = NULL;
|
|
hptr->arg_list = NULL;
|
|
hptr->next_pattern = NULL;
|
|
hptr->num_entries = hptr->num_args = 0;
|
|
} /* if */
|
|
|
|
hptr->pattern = iptr->pattern;
|
|
hptr->duplicates = iptr->duplicates;
|
|
hptr->max_entries = iptr->max_entries;
|
|
hptr->min_args = iptr->min_args;
|
|
hptr->max_args = iptr->max_args;
|
|
hptr->legal_args = iptr->legal_args;
|
|
} /* for */
|
|
} /* load htable */
|
|
|
|
|
|
|
|
static void
|
|
test_conflicts (
|
|
UIINIT * iptr) /* points to initialization information */
|
|
|
|
/*
|
|
* Tests user entered intialization array to make sure it is
|
|
* legal.
|
|
*/
|
|
|
|
|
|
{
|
|
if ( *(iptr->pattern) == NUL )
|
|
uquit ( ERROR, FALSE, "internal error: UIINIT pattern set to NULL.\n" );
|
|
|
|
if ( iptr->max_entries < 1 && iptr->max_entries != UNLIMITED )
|
|
uquit ( ERROR, FALSE,
|
|
"internal error: UIINIT %s max_enties < 1.\n", iptr->pattern );
|
|
|
|
if ( iptr->duplicates < TOGGLE || iptr->duplicates > ACCUM )
|
|
uquit ( ERROR, FALSE,
|
|
"internal error: UIINIT %s duplicates out of range.\n", iptr->pattern );
|
|
|
|
if ( iptr->min_args < 0 )
|
|
uquit ( ERROR, FALSE,
|
|
"internal error: UIINIT %s min_args < 0.\n", iptr->pattern );
|
|
|
|
if ( iptr->max_args < UNLIMITED )
|
|
uquit ( ERROR, FALSE,
|
|
"internal error: UIINIT %s max_args < 0.\n", iptr->pattern );
|
|
|
|
if ( iptr->min_args > iptr->max_args && iptr-> max_args != UNLIMITED )
|
|
uquit ( ERROR, FALSE,
|
|
"internal error: UIINIT %s max_args < min_args.\n", iptr->pattern );
|
|
|
|
if ( iptr->legal_args == NULL )
|
|
uquit ( ERROR, FALSE,
|
|
"internal error: UIINIT %s legal_args set to NULL.\n", iptr->pattern );
|
|
|
|
if ( iptr->max_args == 0 && iptr->duplicates == ACCUM )
|
|
uquit ( ERROR, FALSE,
|
|
"internal error: UIINIT %s max_args = 0 && duplicates = ACCUM.\n",
|
|
iptr->pattern );
|
|
|
|
if ( iptr->max_entries != 1 && iptr->duplicates == TOGGLE )
|
|
uquit ( ERROR, FALSE,
|
|
"internal error: UIINIT %s max_entires != 1 && duplicates = TOGGLE.\n",
|
|
iptr->pattern );
|
|
|
|
if ( iptr->max_entries > 1 && *(iptr->pattern) != '!' &&
|
|
( strpbrk ( iptr->pattern, "*?[" ) == NULL ))
|
|
uquit ( ERROR, FALSE,
|
|
"internal error: UIINIT unique pattern %s allows max_entires > 1.\n",
|
|
iptr->pattern );
|
|
} /* test conflicts */
|
|
|
|
|
|
|
|
static HTABLE *
|
|
match_pattern ( const char * pattern )
|
|
|
|
/*
|
|
* Finds the match to the pattern in the hash table.
|
|
* Returns a pointer to the table entry; NULL if none found.
|
|
*/
|
|
{
|
|
HTABLE * hptr; /* points to one entry */
|
|
|
|
hptr = htbl + hvalue ( pattern );
|
|
|
|
while ( hptr != NULL ) {
|
|
if ( streq ( hptr->pattern, pattern ))
|
|
break;
|
|
hptr = hptr->next_pattern;
|
|
} /* while */
|
|
|
|
return ( hptr );
|
|
} /* match pattern */
|
|
|
|
|
|
|
|
static BOOLEAN rc_file_options (
|
|
int argc, /* the number of command line arugments */
|
|
char ** argv, /* command line arguments */
|
|
int * rc_argc, /* the number of rc file options */
|
|
const char *** rc_argv) /* strings with each argument */
|
|
|
|
|
|
/*
|
|
* Determine the rc file to parse for default options.
|
|
*/
|
|
|
|
{
|
|
char ** argv_ptr, /* agrv traveler */
|
|
* rc_file_name, /* name of rc file */
|
|
* nameonly; /* in case more than name given */
|
|
int argn; /* misc counter */
|
|
BOOLEAN alt_rc = FALSE; /* misc boolean */
|
|
|
|
/* Check to see if a different .sandboxrc file should be used. */
|
|
argv_ptr = argv + 1;
|
|
|
|
if ( ( nameonly = strrchr ( *argv, SLASH )) != NULL )
|
|
nameonly++;
|
|
else
|
|
nameonly = *argv;
|
|
|
|
for ( argn = 1; argn < argc; argn++ ) {
|
|
if ( streq ( *argv_ptr, RC_OP )) {
|
|
alt_rc = TRUE;
|
|
break;
|
|
} /* if */
|
|
|
|
argv_ptr++;
|
|
} /* end for */
|
|
|
|
if ( alt_rc ) {
|
|
if ( access ( *(++argv_ptr), R_OK ) == OK )
|
|
rc_file_name = *argv_ptr;
|
|
|
|
else if ( ! get_local_rcfile ( *argv_ptr, &rc_file_name, EMPTY_STRING )) {
|
|
ui_print ( VDEBUG, "Could not find rc file : %s\n", *argv_ptr );
|
|
return ( FALSE );
|
|
} /* else if */
|
|
} /* if */
|
|
|
|
else if ( ! get_local_rcfile ( nameonly, &rc_file_name, RCEXT )) {
|
|
if ( ! get_default_usr_rcfile ( &rc_file_name, FALSE ))
|
|
return ( FALSE );
|
|
} /* else if */
|
|
|
|
ui_print ( VDETAIL, "Reading rc file : %s\n", rc_file_name );
|
|
return ( get_dotsbx_options ( rc_file_name, nameonly, rc_argc, rc_argv ));
|
|
} /* rc file options */
|
|
|
|
|
|
|
|
static BOOLEAN get_local_rcfile (
|
|
char * cname, /* command name */
|
|
char ** rcfile, /* string to hold name of file */
|
|
const char * ext) /* extension to end of file name */
|
|
|
|
/*
|
|
* Builds path and searches for existence of rc file with same
|
|
* name as program calling routine.
|
|
* Returns TRUE if local name is found; FALSE otherwise.
|
|
*/
|
|
|
|
{
|
|
char trcfile [ PATH_LEN ], /* temporary holder */
|
|
* env_input; /* holds values from getenv */
|
|
|
|
if (( env_input = getenv ( "HOME" )) == NULL )
|
|
return ( FALSE );
|
|
|
|
if ( streq ( ext, EMPTY_STRING ))
|
|
concat ( trcfile, PATH_LEN, env_input, "/", cname, ext, NULL );
|
|
else
|
|
concat ( trcfile, PATH_LEN, env_input, "/.", cname, ext, NULL );
|
|
|
|
if ( access ( trcfile, R_OK ) != OK ) {
|
|
*rcfile = NULL;
|
|
return ( FALSE );
|
|
} /* if */
|
|
|
|
*rcfile = strdup ( trcfile );
|
|
return ( TRUE );
|
|
} /* get local rcfile */
|
|
|
|
|
|
#ifdef __STDC__
|
|
void ui_print ( int msg_verbosity, ... )
|
|
#else
|
|
void ui_print ( va_alist )
|
|
vadcl
|
|
#endif
|
|
|
|
/*
|
|
* This procedure takes the in va_alist and parses out the
|
|
* pieces it needs then passes the rest to a regular print
|
|
* routine. It provides a standard printing routine for
|
|
* the ODE commands.
|
|
*/
|
|
|
|
{
|
|
#ifndef __STDC__
|
|
int msg_verbosity; /* print on verbosity level */
|
|
#endif
|
|
va_list arglist; /* variable length arg list */
|
|
char * msg_format; /* printf formatting */
|
|
|
|
static const char * outfmt[] = { /* leader for output */
|
|
"", /* VALWAYS */
|
|
">> FATAL ERROR", /* VFATAL */
|
|
"", /* VQUIET */
|
|
">> WARNING", /* VWARN */
|
|
"", /* VNORMAL */
|
|
">> DIAGNOSTIC", /* VDIAG */
|
|
"> ", /* VDETAIL */
|
|
">> DEBUG INFO" /* VDEBUG */
|
|
};
|
|
|
|
static FILE * outfile[] = { /* placement of output */
|
|
stdout, /* VALWAYS */
|
|
stderr, /* VFATAL */
|
|
stdout, /* VQUIET */
|
|
stderr, /* VWARN */
|
|
stdout, /* VNORMAL */
|
|
stderr, /* VDIAG */
|
|
stdout, /* VDETAIL */
|
|
stderr /* VDEBUG */
|
|
};
|
|
|
|
static int last_ver = VNORMAL; /* former verbosity level */
|
|
|
|
fflush ( stdout );
|
|
#ifdef __STDC__
|
|
va_start ( arglist, msg_verbosity );
|
|
#else
|
|
va_start ( arglist );
|
|
msg_verbosity = va_arg ( arglist, int );
|
|
#endif
|
|
|
|
if (( msg_verbosity <= verbosity ) ||
|
|
( msg_verbosity == VCONT && last_ver <= verbosity )) {
|
|
msg_format = va_arg ( arglist, char * );
|
|
|
|
if ( msg_verbosity == VFATAL || msg_verbosity == VWARN ||
|
|
msg_verbosity == VDIAG || msg_verbosity == VDEBUG )
|
|
fprintf ( outfile[msg_verbosity], "%s in %s:\n>> ",
|
|
outfmt[msg_verbosity], progname );
|
|
|
|
if ( msg_verbosity == VDETAIL )
|
|
fprintf ( outfile[msg_verbosity], "%s", outfmt[msg_verbosity] );
|
|
|
|
if ( msg_verbosity == VCONT ) {
|
|
if ( last_ver == VFATAL || last_ver == VWARN ||
|
|
last_ver == VDIAG || last_ver == VDEBUG )
|
|
fprintf ( outfile[last_ver], ">> " );
|
|
else if ( last_ver == VDETAIL )
|
|
fprintf ( outfile[last_ver], "> " );
|
|
|
|
vfprintf ( outfile[last_ver], msg_format, arglist );
|
|
} /* if */
|
|
|
|
else
|
|
vfprintf ( outfile[msg_verbosity], msg_format, arglist );
|
|
} /* if */
|
|
|
|
if ( msg_verbosity != VCONT )
|
|
last_ver = msg_verbosity;
|
|
|
|
va_end ( arglist );
|
|
}
|
|
|
|
typedef const char * CCS;
|
|
|
|
static BOOLEAN get_dotsbx_options (
|
|
const char * rc_file_name, /* name of rc file to parse */
|
|
const char * command, /* name of command to look for */
|
|
int * rcargc, /* option count */
|
|
const char *** rcargv) /* list of options */
|
|
|
|
/*
|
|
* Reads the options from the .sandboxrc file
|
|
* Returns TRUE if file was read.
|
|
*/
|
|
|
|
|
|
{
|
|
FILE * rcfile; /* ptr to rc file */
|
|
char * options, /* list of options found in sandbox */
|
|
token [ TOKEN_LENGTH ]; /* holds each option */
|
|
int alloc_arg = 10, /* available arguments */
|
|
ct; /* misc counter */
|
|
|
|
if (( rcfile = fopen ( rc_file_name, READ )) == NULL ) {
|
|
ui_print ( VWARN, "could not open %s.\n", rc_file_name );
|
|
return ( FALSE );
|
|
} /* if */
|
|
|
|
options = get_options ( rcfile, command );
|
|
|
|
if ( options == NULL || *options == NUL )
|
|
return ( FALSE ); /* return immediately if options is empty */
|
|
|
|
if (( *rcargv = (const char **) calloc ( 10, sizeof (char **))) == NULL ) {
|
|
ui_print ( VWARN, "could not calloc space for rc file options.\n" );
|
|
return ( FALSE );
|
|
} /* if */
|
|
|
|
*rcargc = 0; /* Allocate 10 args, realloc later if more needed. */
|
|
|
|
for (;;) {
|
|
if ( ! next_token ( &options, token ))
|
|
return ( FALSE );
|
|
|
|
if ( *token == NUL || *token == SPACE )
|
|
break;
|
|
|
|
rm_newline ( token );
|
|
|
|
if ( *rcargc >= alloc_arg ) {
|
|
alloc_arg += 10;
|
|
|
|
if (( *rcargv = (const char **) realloc
|
|
( *rcargv, sizeof (char **) * alloc_arg )) == NULL )
|
|
return ( FALSE );
|
|
} /* if */
|
|
|
|
if (( (*rcargv)[*rcargc] = strdup ( token )) == NULL )
|
|
return ( FALSE );
|
|
|
|
(*rcargc)++;
|
|
} /* for */
|
|
|
|
ui_print ( VDEBUG, "Tokens are:\n" );
|
|
|
|
for ( ct = 0; ct < *rcargc; ct++ )
|
|
ui_print ( VCONT, "%s\n", (*rcargv)[ct] );
|
|
|
|
fclose ( rcfile );
|
|
return ( TRUE );
|
|
} /* get dotsbx options */
|
|
|
|
|
|
|
|
static char * get_options (
|
|
FILE * rc_file, /* file to read from */
|
|
const char * command) /* command to search for */
|
|
|
|
/*
|
|
* Generic procedure to find the options associated with a
|
|
* command in a given file.
|
|
*/
|
|
|
|
|
|
{
|
|
char * ptr, /* misc pointer to each line */
|
|
* field,
|
|
buf [ PATH_LEN ], /* misc string */
|
|
options [ PATH_LEN ],
|
|
options2 [ PATH_LEN ];
|
|
|
|
*options = NUL;
|
|
|
|
while ( fgets ( buf, PATH_LEN, rc_file ) != NULL ) {
|
|
if (( ptr = strchr ( buf, '#' )) != NULL ) /* Check for comment. */
|
|
*ptr = NUL;
|
|
|
|
ptr = buf;
|
|
field = nxtarg ( &ptr, WHITESPACE );
|
|
|
|
if ( *field == NUL )
|
|
continue;
|
|
|
|
/* For every line which matches the desired command,
|
|
* add the list of options to the end of the options string. */
|
|
if ( gmatch ( command, field )) {
|
|
concat ( options2, PATH_LEN, options, " ", ptr, NULL );
|
|
strcpy ( options, options2 );
|
|
} /* if */
|
|
} /* while */
|
|
|
|
ptr = options + strlen ( options ) - 1;
|
|
return ( strdup ( options ));
|
|
} /* get options */
|
|
|
|
|
|
|
|
static BOOLEAN next_token (
|
|
char ** str, /* string to parse */
|
|
char token[]) /* token to fill */
|
|
|
|
/*
|
|
* This function extracts the next token from the string.
|
|
* Returns TRUE if there is not an illegal token.
|
|
*/
|
|
|
|
|
|
{
|
|
char * env;
|
|
int ct, /* misc counter */
|
|
expand,
|
|
braces;
|
|
|
|
if ( *str != NULL )
|
|
skip_white_space ( str );
|
|
|
|
if ( *str == NULL || **str == NUL || **str == NEWLINE ) {
|
|
*token = NUL;
|
|
return ( TRUE );
|
|
} /* if */
|
|
|
|
/* If a '$' is encountered, the remainder of the token is an
|
|
* environment variable and needs to be expanded. Strip off
|
|
* the '$' and record the fact that it needs to be expanded. */
|
|
expand = FALSE;
|
|
braces = FALSE;
|
|
|
|
if ( **str == '$' ) {
|
|
expand = TRUE;
|
|
(*str)++;
|
|
|
|
if ( **str == '{' ) {
|
|
braces = TRUE;
|
|
(*str)++;
|
|
} /* if */
|
|
} /* if */
|
|
|
|
/* A token is either all of the characters within quotes or all of
|
|
* the characters between two areas of whitespace. */
|
|
ct = 0;
|
|
|
|
if ( **str == '"' ) {
|
|
(*str)++;
|
|
|
|
while ( **str != NUL && **str != '"' ) {
|
|
if ( ct >= TOKEN_LENGTH ) {
|
|
ui_print ( VWARN, "token too long: %s.\n", *str );
|
|
return ( FALSE );
|
|
} /* if */
|
|
|
|
token[ct++] = *(*str)++;
|
|
} /* while */
|
|
|
|
if ( **str == '"' )
|
|
(*str)++;
|
|
} /* if */
|
|
|
|
else if ( braces ) {
|
|
(*str)++;
|
|
|
|
while ( **str != NUL && **str != '}' ) {
|
|
if( ct >= TOKEN_LENGTH ) {
|
|
ui_print ( VWARN, "token too long: %s.\n", *str );
|
|
return ( FALSE );
|
|
} /* if */
|
|
|
|
token[ct++] = *(*str)++;
|
|
} /* while */
|
|
|
|
if(**str == '}')
|
|
(*str)++;
|
|
} /* else if */
|
|
|
|
else {
|
|
while ( ! WHITESPACEFN ( *str ) && **str != NUL ) {
|
|
if( ct >= TOKEN_LENGTH ) {
|
|
ui_print ( VWARN, "token too long: %s.\n", *str );
|
|
return ( FALSE );
|
|
} /* if */
|
|
|
|
token[ct++] = *(*str)++;
|
|
} /* while */
|
|
} /* else */
|
|
|
|
if ( ct < TOKEN_LENGTH )
|
|
token[ct] = NUL;
|
|
|
|
/* If a '$' was encountered earlier, expand the token. */
|
|
if ( expand ) {
|
|
env = getenv ( token );
|
|
if ( strlen ( env ) > (unsigned) TOKEN_LENGTH ) {
|
|
ui_print ( VWARN, "Environment variable too long: %s\n", env );
|
|
return ( FALSE );
|
|
} /* if */
|
|
|
|
else
|
|
strcpy ( token, env );
|
|
|
|
if ( token == NULL )
|
|
token = strdup ( EMPTY_STRING );
|
|
} /* endif */
|
|
|
|
return ( TRUE );
|
|
} /* next token */
|
|
|
|
|
|
|
|
static void skip_white_space (
|
|
char ** str)
|
|
|
|
/* advance to none white space */
|
|
|
|
|
|
{
|
|
while ( WHITESPACEFN (*str) && **str != NUL )
|
|
(*str)++;
|
|
} /* skip white space */
|
|
|
|
|
|
|
|
static void
|
|
load_options (
|
|
int usrct, /* number of arguments to parse */
|
|
const char ** usr_list, /* list of arguments */
|
|
int initct, /* count of lines to initialize */
|
|
UIINIT * init) /* initialization information */
|
|
|
|
/*
|
|
* Enters the arg_list into the ui information table. First
|
|
* the built in's and special cases are checked, then the user
|
|
* entries. Then load them according to type: first time,
|
|
* toggles, repeats of overwrite and accums.
|
|
* Returns ERROR if there is a failure; OK otherwise.
|
|
*/
|
|
|
|
|
|
{
|
|
HTABLE * hptr; /* points to one table pattern */
|
|
ENTRY_SET * eptr = NULL; /* points to entry */
|
|
const char * opt; /* points to option */
|
|
const char * pattern; /* pattern to match option */
|
|
int ct = 0; /* count of arg list being parsed */
|
|
int usrct2; /* number of arguments to parse */
|
|
char ** usr_list2; /* list of arguments */
|
|
|
|
usrct2 = usrct - 1;
|
|
usr_list2 = usr_list2 + 1;
|
|
|
|
while ( ct < usrct ) {
|
|
opt = *(usr_list + ct);
|
|
|
|
if (( pattern = built_ins ( opt )) == NULL ) {
|
|
if ( special_case ( opt )) { /* try built in, special case before user */
|
|
ct++;
|
|
continue;
|
|
} /* if */
|
|
|
|
if (( pattern = entry_pattern ( opt, init, initct )) == NULL )
|
|
uiquit ( ERROR, TRUE, "No such option: %s.\n", opt );
|
|
} /* if */
|
|
|
|
if (( hptr = match_pattern ( pattern )) == NULL )
|
|
uquit ( ERROR, FALSE, "Program error in ui function load_options.\n" );
|
|
|
|
if ( hptr->num_entries == 0 )
|
|
load_entry ( hptr, NULL, usr_list, opt, usrct, &ct );
|
|
|
|
else if ( hptr->duplicates == TOGGLE )
|
|
ui_unset ( pattern );
|
|
|
|
else {
|
|
set_duplicates ( hptr, &eptr, opt );
|
|
load_entry ( hptr, eptr, usr_list, opt, usrct, &ct );
|
|
} /* else */
|
|
|
|
ct++;
|
|
} /* while */
|
|
} /* load options */
|
|
|
|
static void
|
|
init_to_optlist (
|
|
int initct,
|
|
UIINIT * init,
|
|
char * optbuf)
|
|
{
|
|
int ct;
|
|
int i=0;
|
|
UIINIT * initptr;
|
|
|
|
initptr = init;
|
|
for ( ct = 0; ct < initct; ct++, initptr++ ) {
|
|
if ( *(initptr -> pattern) == '-' ) {
|
|
optbuf [i++] = *(initptr -> pattern + 1);
|
|
if ( initptr -> min_args == 1 )
|
|
optbuf [i++] = ':';
|
|
/* if */
|
|
} /* if */
|
|
|
|
} /* for */
|
|
optbuf [ i ] = '\0';
|
|
ui_print ( VDEBUG, "getopt option list is '%s'\n", optbuf );
|
|
} /* end init_to_optlist */
|
|
|
|
static void
|
|
load_using_posix (
|
|
int usrct, /* number of arguments to parse */
|
|
char ** usr_list, /* list of arguments */
|
|
int initct, /* count of lines to initialize */
|
|
UIINIT * init) /* initialization information */
|
|
{
|
|
int errflg = 0;
|
|
int c;
|
|
char optbuf [100];
|
|
char entry [3];
|
|
HTABLE * hptr; /* points to one table pattern */
|
|
const char * pattern; /* pattern to match option */
|
|
|
|
entry [0] = '-';
|
|
entry [2] = '\0';
|
|
init_to_optlist ( initct, init, optbuf );
|
|
|
|
/*
|
|
* Tell getopt not to send diagnostic messages to stderr
|
|
*/
|
|
/*
|
|
opterr = 0;
|
|
*/
|
|
|
|
/*
|
|
* Start at the first argument instead of skipping it.
|
|
*/
|
|
optind = 0;
|
|
|
|
while ( !errflg && ( c = getopt ( usrct, usr_list, optbuf ) ) != -1 ) {
|
|
entry [1] = c;
|
|
ui_print ( VDEBUG, "entry '%s'\n", entry );
|
|
if (( pattern = entry_pattern ( entry, init, initct )) == NULL )
|
|
uiquit ( ERROR, TRUE, "No such option: %s.\n", entry );
|
|
if (( hptr = match_pattern ( pattern )) == NULL )
|
|
uquit ( ERROR, FALSE, "Program error in ui function load_options.\n" );
|
|
|
|
load_posix_entry ( hptr, entry, optarg );
|
|
} /* while */
|
|
} /* end load_using_posix */
|
|
|
|
static char * built_ins (
|
|
const char * opt) /* option to check */
|
|
|
|
/*
|
|
* Checks to see if the opt matches one of the built-in
|
|
* patterns.
|
|
* Returns pointer to pattern if found; else NULL.
|
|
*/
|
|
|
|
|
|
{
|
|
if ( streq ( opt, AUTO_OP ))
|
|
return ( strdup ( AUTO_OP ));
|
|
|
|
if ( streq ( opt, INFO_OP ))
|
|
return ( strdup ( INFO_OP ));
|
|
|
|
if ( streq ( opt, RC_OP ))
|
|
return ( strdup ( RC_OP ));
|
|
|
|
return ( NULL );
|
|
} /* built ins */
|
|
|
|
|
|
|
|
static char *
|
|
entry_pattern (
|
|
const char * entry, /* entry to match */
|
|
UIINIT * patlist, /* pattern list to search through */
|
|
int patct) /* number of patterns in list */
|
|
|
|
/*
|
|
* Finds pattern to match entry in pattern list. Purpose is to
|
|
* search pathlist in same order as program provided it.
|
|
* Returns pointer to pattern if found; else NULL.
|
|
*/
|
|
|
|
|
|
{
|
|
UIINIT * pptr; /* points to pattern list */
|
|
int ct; /* misc counter */
|
|
|
|
for ( ct = 0; ct < patct; ct++ ) {
|
|
pptr = patlist + ct;
|
|
if ( gmatch ( entry, pptr->pattern ))
|
|
return ( (char *)pptr->pattern );
|
|
} /* for */
|
|
|
|
return ( NULL );
|
|
} /* entry pattern */
|
|
|
|
|
|
|
|
static BOOLEAN special_case (
|
|
const char * opt) /* option to check */
|
|
|
|
/*
|
|
* Checks option against internal, special values. If there
|
|
* is a match, it carries out the appropriate action.
|
|
* Returns TRUE if opt matches a special case.
|
|
*/
|
|
|
|
|
|
{
|
|
if ( streq ( opt, QUIET_OP ))
|
|
verbosity = VQUIET;
|
|
else if ( streq ( opt, NORMAL_OP ))
|
|
verbosity = VNORMAL;
|
|
else if ( streq ( opt, VERBOSE_OP ))
|
|
verbosity = VDETAIL;
|
|
else if ( streq ( opt, DEBUG_OP ))
|
|
verbosity = VDEBUG;
|
|
|
|
else if ( streq ( opt, NOAUTO_OP )) {
|
|
if ( ui_unset ( AUTO_OP ) != OK )
|
|
ui_print ( VWARN, "Error in program; unable to unset %s.\n", AUTO_OP );
|
|
} /* else if */
|
|
|
|
else if ( streq ( opt, USAGE_OP )) {
|
|
ui_restore_progname ();
|
|
print_usage ();
|
|
exit ( OK );
|
|
} /* else if */
|
|
|
|
else if ( streq ( opt, REV_OP ) || streq ( opt, VERSION_OP ) ) {
|
|
ui_restore_progname ();
|
|
ui_print_revision ();
|
|
exit ( OK );
|
|
} /* else if */
|
|
|
|
else
|
|
return ( FALSE );
|
|
|
|
return ( TRUE );
|
|
} /* special case */
|
|
|
|
|
|
|
|
int set_ver (
|
|
char * opt) /* option to check */
|
|
|
|
/*
|
|
* Allows setting of verbosity. This is a temporary function.
|
|
* Returns OK if verbosity level is legal, else ERROR.
|
|
*/
|
|
|
|
|
|
{
|
|
if ( streq ( opt, QUIET_OP ))
|
|
verbosity = VQUIET;
|
|
else if ( streq ( opt, NORMAL_OP ))
|
|
verbosity = VNORMAL;
|
|
else if ( streq ( opt, VERBOSE_OP ))
|
|
verbosity = VDETAIL;
|
|
else if ( streq ( opt, DEBUG_OP ))
|
|
verbosity = VDEBUG;
|
|
else
|
|
return ( ERROR );
|
|
|
|
return ( OK );
|
|
} /* set ver */
|
|
|
|
|
|
|
|
int ui_unset ( const char * pattern )
|
|
|
|
/*
|
|
* Unsets the ui information for pattern. Sets the pattern
|
|
* back to its initialized state.
|
|
* Returns ERROR if there is no such pattern; OK otherwise.
|
|
*/
|
|
{
|
|
HTABLE * hptr; /* points to one table pattern */
|
|
|
|
if (( hptr = match_pattern ( pattern )) == NULL )
|
|
return ( ERROR );
|
|
|
|
hptr->entry = NULL;
|
|
hptr->arg_list = NULL;
|
|
hptr->entry_list = NULL;
|
|
hptr->next_pattern = NULL;
|
|
hptr->num_entries = hptr->num_args = 0;
|
|
return ( OK );
|
|
} /* ui unset */
|
|
|
|
|
|
|
|
static int load_entry (
|
|
HTABLE * hptr, /* points to table pattern to fill */
|
|
ENTRY_SET * eptr, /* points to entry to load */
|
|
const char ** usrlist, /* list of user supplied arguments */
|
|
const char * entry, /* points to user supplied entry */
|
|
int usrct, /* number of user supplied arguments */
|
|
int * pct) /* pointer to count of user list */
|
|
|
|
/*
|
|
* Puts entry into place indicated by hptr and eptr.
|
|
*/
|
|
|
|
|
|
{
|
|
(hptr->num_entries)++;
|
|
|
|
if ( hptr->num_entries > hptr->max_entries &&
|
|
hptr->max_entries != UNLIMITED ) {
|
|
uiquit ( ERROR, TRUE, "More than %d entr%s for option: %s.\n",
|
|
hptr->max_entries, hptr->max_entries > 1 ? "ies" : "y", hptr->pattern );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
if ( eptr == NULL ) {
|
|
hptr->entry = entry;
|
|
|
|
if ( load_min_args ( hptr, usrlist, &(hptr->arg_list), usrct,
|
|
&(hptr->num_args), pct ) == ERROR )
|
|
return ( ERROR );
|
|
|
|
load_max_args ( hptr, usrlist, &(hptr->arg_list), usrct,
|
|
&(hptr->num_args), pct );
|
|
} /* if */
|
|
|
|
else {
|
|
eptr->entry = entry;
|
|
|
|
if ( load_min_args ( hptr, usrlist, &(eptr->arg_list), usrct,
|
|
&(eptr->num_args), pct ) == ERROR )
|
|
return ( ERROR );
|
|
|
|
load_max_args ( hptr, usrlist, &(eptr->arg_list), usrct,
|
|
&(eptr->num_args), pct );
|
|
return ( ERROR );
|
|
} /* else */
|
|
|
|
return ( OK );
|
|
} /* load entry */
|
|
|
|
void
|
|
#ifdef __STDC__
|
|
uiquit ( int status, ... )
|
|
#else
|
|
uiquit ( va_alist )
|
|
va_dcl
|
|
#endif
|
|
|
|
/* This procedure takes a variable length argument list and
|
|
prints out the name of the function that failed, the error
|
|
message, usage if asked for, and then, if it is not a from
|
|
ui_load error, exits with the code entered. This program
|
|
is actually uquit with a check for ui_load added. */
|
|
|
|
{
|
|
#ifndef __STDC__
|
|
int status;
|
|
#endif
|
|
va_list args; /* see vprintf(3) and varargs(5) for details */
|
|
int usage; /* do you print usage */
|
|
char * fmt; /* format string */
|
|
|
|
fflush ( stdout );
|
|
#ifdef __STDC__
|
|
va_start ( args, status );
|
|
#else
|
|
va_start ( args );
|
|
status = va_arg ( args, int ); /* gets the first argument and type */
|
|
#endif
|
|
usage = va_arg ( args, int ); /* gets the second argument and type */
|
|
fmt = va_arg ( args, char * );
|
|
|
|
if ( from_ui_load )
|
|
fprintf ( stderr, "ERROR: " );
|
|
|
|
else {
|
|
ui_restore_progname ();
|
|
fprintf ( stderr, ">> FATAL ERROR in %s:\n ", progname );
|
|
} /* if */
|
|
|
|
vfprintf ( stderr, fmt, args ); /* print out error message */
|
|
|
|
if ( usage )
|
|
print_usage ();
|
|
|
|
va_end ( args );
|
|
|
|
if ( ! from_ui_load )
|
|
exit ( status );
|
|
} /* uiquit */
|
|
|
|
|
|
|
|
static int load_min_args (
|
|
HTABLE * hptr, /* points to one table pattern */
|
|
const char ** usrlist, /* list of user supplied arguments */
|
|
ARG_SET ** arglist, /* place to put argument list */
|
|
int usrct, /* the number of user arugments */
|
|
int * argct, /* running total of arguments for entry */
|
|
int * pcount) /* counts current usrlist */
|
|
|
|
/*
|
|
* This function attempts to load the minimum number of required
|
|
* arguments into the entry.
|
|
*/
|
|
|
|
|
|
{
|
|
ARG_SET * argptr=NULL; /* points to additonal args */
|
|
|
|
if ( *arglist != NULL ) {
|
|
argptr = *arglist;
|
|
|
|
while ( argptr->next_arg != NULL ) /* bring argptr to end of arglist */
|
|
argptr = argptr->next_arg;
|
|
} /* if */
|
|
|
|
while ( *argct < hptr->min_args ) { /* get min number fields */
|
|
if ( *pcount + 1 < usrct )
|
|
(*pcount)++;
|
|
|
|
else {
|
|
uiquit ( ERROR, TRUE, "option %s requires %d argument%s.\n",
|
|
hptr->pattern, hptr->min_args, hptr->min_args == 1 ? "" : "s" );
|
|
return ( ERROR );
|
|
} /* else */
|
|
|
|
if ( ! match_arg_list ( *(usrlist + *pcount), hptr->legal_args )) {
|
|
uiquit ( ERROR, TRUE,
|
|
"argument: %s, not in %s's list of legal arguments. List is:\n\t%s\n",
|
|
*(usrlist + *pcount), hptr->pattern, hptr->legal_args );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
if ( in_arg_list ( *arglist, *(usrlist + *pcount)))
|
|
continue;
|
|
|
|
if ( *arglist == NULL ) {
|
|
*arglist = ( ARG_SET * ) malloc ( sizeof ( ARG_SET ));
|
|
argptr = *arglist;
|
|
} /* if */
|
|
|
|
else {
|
|
argptr->next_arg = ( ARG_SET * ) malloc ( sizeof ( ARG_SET ));
|
|
argptr = argptr->next_arg;
|
|
} /* else */
|
|
|
|
argptr->arg = *(usrlist + *pcount);
|
|
argptr->next_arg = NULL;
|
|
(*argct)++;
|
|
} /* while */
|
|
|
|
return ( OK );
|
|
} /* load min args */
|
|
|
|
static int load_posix_entry (
|
|
HTABLE * hptr, /* points to one table pattern */
|
|
char * entry,
|
|
char * arg)
|
|
/*
|
|
* This function attempts to load the minimum number of required
|
|
* arguments into the entry.
|
|
*/
|
|
{
|
|
ARG_SET * argptr; /* points to additonal args */
|
|
|
|
ui_print ( VDEBUG, "Loading entry '%s'.\n", entry );
|
|
hptr -> num_entries = 1;
|
|
hptr -> entry = strdup ( entry );
|
|
|
|
if ( arg != NULL ) {
|
|
if ( ! match_arg_list ( arg, hptr->legal_args )) {
|
|
uiquit ( ERROR, TRUE,
|
|
"argument: %s, not in %s's list of legal arguments. List is:\n\t%s\n",
|
|
arg, hptr->pattern, hptr->legal_args );
|
|
return ( ERROR );
|
|
} /* if */
|
|
hptr -> arg_list = ( ARG_SET * ) malloc ( sizeof ( ARG_SET ));
|
|
argptr = hptr -> arg_list;
|
|
|
|
argptr->arg = strdup (arg);
|
|
argptr->next_arg = NULL;
|
|
hptr -> num_args = 1;
|
|
} /* if */
|
|
return ( OK );
|
|
} /* load min args */
|
|
|
|
|
|
|
|
static BOOLEAN match_arg_list (
|
|
const char * arg, /* argument to check */
|
|
const char * list) /* space separated list to check against */
|
|
|
|
/*
|
|
* Tests the argument to see if it is in the legal list.
|
|
* Returns TRUE if it is; FALSE otherwise.
|
|
*/
|
|
|
|
|
|
{
|
|
char copy [ PATH_LEN ], /* don't touch original list */
|
|
* listptr, /* points to copy of list */
|
|
* token; /* holds each match from list */
|
|
|
|
strcpy ( copy, list );
|
|
listptr = copy;
|
|
|
|
while ( (*(token = nxtarg ( &listptr, WHITESPACE ))) != NUL ) {
|
|
if ( gmatch ( arg, token ))
|
|
return ( TRUE );
|
|
} /* while */
|
|
|
|
return ( FALSE );
|
|
} /* match arg list */
|
|
|
|
|
|
|
|
static BOOLEAN in_arg_list (
|
|
ARG_SET * list, /* list of args to check */
|
|
const char * arg) /* argument to check for */
|
|
|
|
/*
|
|
* Checks to see if arg is already in list.
|
|
* Returns TRUE if arg is in list.
|
|
*/
|
|
|
|
|
|
{
|
|
while ( list != NULL ) {
|
|
if ( streq ( list->arg, arg ))
|
|
return ( TRUE );
|
|
list = list->next_arg;
|
|
} /* while */
|
|
|
|
return ( FALSE );
|
|
} /* in arg list */
|
|
|
|
|
|
|
|
static void load_max_args (
|
|
HTABLE * hptr, /* points to one table pattern */
|
|
const char ** usrlist, /* list of user supplied arguments */
|
|
ARG_SET ** arglist, /* place to put argument list */
|
|
int usrct, /* the number of user arugments */
|
|
int * argct, /* running total of arguments for entry */
|
|
int * pcount) /* counts current usrlist */
|
|
|
|
/*
|
|
* This function attempts to load up to the maximum number of
|
|
* required arguments into the entry.
|
|
*/
|
|
|
|
|
|
{
|
|
ARG_SET * argptr=NULL; /* points to additonal args */
|
|
BOOLEAN in = TRUE; /* misc boolean */
|
|
|
|
if ( *arglist != NULL ) {
|
|
argptr = *arglist;
|
|
|
|
while ( argptr->next_arg != NULL ) /* bring argptr to end of arglist */
|
|
argptr = argptr->next_arg;
|
|
} /* if */
|
|
|
|
while ((( hptr->max_args == UNLIMITED ) || ( *argct < hptr->max_args )) &&
|
|
in ) {
|
|
if ( *pcount + 1 < usrct ) {
|
|
(*pcount)++;
|
|
|
|
if (! (in = match_arg_list (*(usrlist + *pcount), hptr->legal_args )))
|
|
(*pcount)--;
|
|
|
|
else {
|
|
if ( in_arg_list ( *arglist, *(usrlist + *pcount)))
|
|
continue;
|
|
|
|
if ( *arglist == NULL ) {
|
|
*arglist = ( ARG_SET * ) malloc ( sizeof ( ARG_SET ));
|
|
argptr = *arglist;
|
|
} /* if */
|
|
|
|
else {
|
|
argptr->next_arg = ( ARG_SET * ) malloc ( sizeof ( ARG_SET ));
|
|
argptr = argptr->next_arg;
|
|
} /* else */
|
|
|
|
argptr->arg = *(usrlist + *pcount);
|
|
argptr->next_arg = NULL;
|
|
(*argct)++;
|
|
} /* else */
|
|
} /* if */
|
|
|
|
else
|
|
in = FALSE;
|
|
} /* while */
|
|
} /* load max args */
|
|
|
|
|
|
|
|
static int set_duplicates (
|
|
HTABLE * hptr, /* points to one table pattern */
|
|
ENTRY_SET ** eeptr, /* points to entry ptr */
|
|
const char * entry) /* points to entry */
|
|
|
|
/*
|
|
* Sets counts and pointers appropriately for handling OVERWRITE
|
|
* and ACCUM duplicates.
|
|
*/
|
|
|
|
|
|
{
|
|
if ( hptr->max_entries == 1 ) {
|
|
if ( ! streq ( hptr->entry, entry )) {
|
|
if ( streq ( ARGS_OP, hptr->pattern ))
|
|
uiquit ( ERROR, TRUE, "Only 1 argument allowed.\n" );
|
|
else
|
|
uiquit ( ERROR, TRUE, "More than 1 entry for option: %s.\n",
|
|
hptr->pattern );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
hptr->num_entries = 0;
|
|
|
|
if ( hptr->duplicates != ACCUM ) { /* overwrite existing entry */
|
|
hptr->num_args = 0;
|
|
hptr->arg_list = NULL;
|
|
} /* else */
|
|
|
|
else if ( ! streq ( hptr->entry, entry )) {
|
|
hptr->num_args = 0; /* can't accum different entry */
|
|
hptr->arg_list = NULL;
|
|
} /* else if */
|
|
} /* if */
|
|
|
|
else {
|
|
match_entry ( hptr, entry, eeptr );
|
|
|
|
if ( hptr->duplicates == OVERWRITE ) {
|
|
if ( *eeptr == NULL ) {
|
|
hptr->num_args = 0;
|
|
hptr->arg_list = NULL;
|
|
} /* if */
|
|
|
|
else {
|
|
(*eeptr)->num_args = 0;
|
|
(*eeptr)->arg_list = NULL;
|
|
} /* else */
|
|
} /* if */
|
|
} /* else */
|
|
|
|
return ( OK );
|
|
} /* set duplicates */
|
|
|
|
|
|
|
|
static void match_entry (
|
|
HTABLE * hptr, /* points to one table pattern */
|
|
const char * entry, /* option to actually match */
|
|
ENTRY_SET ** eeptr) /* points to entry */
|
|
|
|
/*
|
|
* Finds matching entry and set the eptr to it. If there is
|
|
* no entry yet or the new entry matches the first entry in
|
|
* the apattern, return eeptr as NULL. If the new entry matches
|
|
* an existing entry, return a pointer to that entry. Finally,
|
|
* if the entry does not exist, create space for it.
|
|
*/
|
|
|
|
|
|
{
|
|
*eeptr = NULL;
|
|
|
|
if ( hptr->entry == NULL )
|
|
return;
|
|
|
|
if ( streq ( hptr->entry, entry )) { /* entry already in place */
|
|
(hptr->num_entries)--; /* subtract entry as it will be added later */
|
|
return;
|
|
} /* if */
|
|
|
|
if ( hptr->entry_list == NULL ) {
|
|
hptr->entry_list = ( ENTRY_SET * ) malloc ( sizeof ( ENTRY_SET ));
|
|
*eeptr = hptr->entry_list;
|
|
} /* if */
|
|
|
|
else {
|
|
*eeptr = hptr->entry_list;
|
|
|
|
if ( streq ( (*eeptr)->entry, entry )) {
|
|
(hptr->num_entries)--;
|
|
return;
|
|
} /* if */
|
|
|
|
while ( (*eeptr)->next_entry != NULL ) {
|
|
*eeptr = (*eeptr)->next_entry;
|
|
|
|
if ( streq ( (*eeptr)->entry, entry )) {
|
|
(hptr->num_entries)--;
|
|
return;
|
|
} /* if */
|
|
} /* while */
|
|
|
|
(*eeptr)->next_entry = ( ENTRY_SET * ) malloc ( sizeof ( ENTRY_SET ));
|
|
*eeptr = (*eeptr)->next_entry;
|
|
} /* else */
|
|
|
|
(*eeptr)->num_args = 0;
|
|
(*eeptr)->arg_list = NULL;
|
|
(*eeptr)->next_entry = NULL;
|
|
} /* match entry */
|
|
|
|
|
|
|
|
static void print_htable (void)
|
|
|
|
/*
|
|
* Prints out the initialized portion of the hash table.
|
|
*/
|
|
|
|
{
|
|
HTABLE * hptr; /* points to each table entry */
|
|
ARG_SET * aptr; /* points to args */
|
|
ENTRY_SET * eptr; /* points to entries */
|
|
int ct; /* misc counter */
|
|
|
|
ui_print ( VDEBUG, "Contents of interface table:\n" );
|
|
|
|
for ( ct = 0; ct < HTABLESIZE; ct++ ) {
|
|
hptr = htbl + ct;
|
|
aptr = hptr->arg_list;
|
|
eptr = hptr->entry_list;
|
|
|
|
if ( *(hptr->pattern) != NUL ) {
|
|
print_internals ( hptr, aptr, eptr, ct );
|
|
hptr = hptr->next_pattern;
|
|
|
|
while ( hptr != NULL ) {
|
|
aptr = hptr->arg_list;
|
|
eptr = hptr->entry_list;
|
|
print_internals ( hptr, aptr, eptr, -1 );
|
|
hptr = hptr->next_pattern;
|
|
} /* while */
|
|
} /* if */
|
|
} /* for */
|
|
|
|
ui_print ( VCONT, "vl=%d; ap=%d; ip=%d.\n", verbosity, auto_pos, info_pos );
|
|
} /* print htable */
|
|
|
|
|
|
|
|
static void print_internals (
|
|
HTABLE * hptr, /* points to table entry */
|
|
ARG_SET * aptr, /* points to args */
|
|
ENTRY_SET * eptr, /* points to entries */
|
|
int ct) /* table entry */
|
|
|
|
/*
|
|
* Prints out internals of a single hash table entry.
|
|
*/
|
|
|
|
|
|
{
|
|
if ( ct == -1 )
|
|
ui_print ( VCONT, " %s: maxe=%d; dup=%d; mina=%d; maxa=%d; a=%s.\n",
|
|
hptr->pattern, hptr->max_entries, hptr->duplicates,
|
|
hptr->min_args, hptr->max_args, hptr->legal_args );
|
|
else
|
|
ui_print ( VCONT, "%-2d: %s: maxe=%d; dup=%d; mina=%d; maxa=%d; a=%s.\n",
|
|
ct, hptr->pattern, hptr->max_entries, hptr->duplicates,
|
|
hptr->min_args, hptr->max_args, hptr->legal_args );
|
|
|
|
if ( hptr->num_entries > 0 ) {
|
|
ui_print ( VCONT, " e=%s; numa=%d; nume=%d.\n",
|
|
hptr->entry, hptr->num_args, hptr->num_entries );
|
|
|
|
while ( aptr != NULL ) {
|
|
ui_print ( VCONT, " arg: %s.\n", aptr->arg );
|
|
aptr = aptr->next_arg;
|
|
} /* while */
|
|
|
|
while ( eptr != NULL ) {
|
|
aptr = eptr->arg_list;
|
|
ui_print ( VCONT, " e=%s: numa=%d.\n", eptr->entry, eptr->num_args );
|
|
|
|
while ( aptr != NULL ) {
|
|
ui_print ( VCONT, " arg: %s\n", aptr->arg );
|
|
aptr = aptr->next_arg;
|
|
} /* while */
|
|
|
|
eptr = eptr->next_entry;
|
|
} /* while */
|
|
} /* if */
|
|
} /* print internals */
|
|
|
|
|
|
#ifdef __STDC__
|
|
int ui_load ( const char * pattern, ... )
|
|
#else
|
|
int ui_load ( va_alist )
|
|
va_dcl
|
|
#endif
|
|
/*
|
|
* Looks for exact match to pattern and loads the table
|
|
* entry. It peals off the first two arguments to get the
|
|
* pattern to match and the arg count. It then creates a
|
|
* **char list of the rest of the arguments and passes this
|
|
* to the functions that load entries.
|
|
* Returns OK if it is successful, else ERROR.
|
|
*/
|
|
|
|
{
|
|
#ifndef __STDC__
|
|
char * pattern; /* pattern to match in table */
|
|
#endif
|
|
HTABLE * hptr; /* points to one pattern */
|
|
va_list arglist; /* variable length arg list */
|
|
const char * match; /* misc string ptr */
|
|
const char ** vlist=NULL; /* holds list of arguments from arglist */
|
|
int argct, /* number of arguments to parse */
|
|
ct, /* dummy counter */
|
|
rvalue = OK; /* return value */
|
|
|
|
from_ui_load = TRUE;
|
|
fflush ( stdout );
|
|
#ifdef __STDC__
|
|
va_start ( arglist, pattern ); /* load first two fields */
|
|
#else
|
|
va_start ( arglist );
|
|
pattern = va_arg ( arglist, char * ); /* load first two fields */
|
|
#endif
|
|
argct = va_arg ( arglist, int );
|
|
|
|
if (( match = built_ins ( pattern )) == NULL ) {
|
|
if ( special_case ( pattern )) { /* try built in, special case */
|
|
va_end ( arglist );
|
|
from_ui_load = FALSE;
|
|
return ( rvalue );
|
|
} /* if */
|
|
|
|
pattern = strdup ( (char *)pattern );
|
|
} /* if */
|
|
|
|
else
|
|
pattern = match;
|
|
|
|
if (( hptr = match_pattern ( pattern )) == NULL ) {
|
|
ui_print ( VDEBUG, "pattern: %s, not in entry table.\n", pattern );
|
|
rvalue = ERROR;
|
|
} /* if */
|
|
|
|
if ( rvalue != ERROR && hptr->max_entries != 1 ) {
|
|
ui_print ( VDEBUG, "cannot ui_load pattern: %s, with max_entries: %d.\n",
|
|
pattern, hptr->max_entries );
|
|
rvalue = ERROR;
|
|
} /* if */
|
|
|
|
if ( rvalue != ERROR ) {
|
|
if ( argct > 0 ) {
|
|
argct++; /* account for pattern */
|
|
|
|
if (( vlist = ( const char ** ) calloc ( argct, sizeof ( char * )))
|
|
== NULL )
|
|
uquit ( ERROR, FALSE, "sys: could not calloc space for vlist.\n" );
|
|
|
|
*vlist = pattern;
|
|
|
|
for ( ct = 1; ct < argct; ct++ )
|
|
*(vlist + ct) = strdup ( va_arg ( arglist, char * ));
|
|
} /* if */
|
|
|
|
ct = 0;
|
|
|
|
if ( hptr->num_entries == 0 ) {
|
|
if ( load_entry ( hptr, NULL, vlist, pattern, argct, &ct ) == ERROR )
|
|
rvalue = ERROR;
|
|
} /* if */
|
|
|
|
else if ( hptr->duplicates == TOGGLE ) {
|
|
if ( ui_unset ( pattern ) == ERROR )
|
|
rvalue = ERROR;
|
|
} /* else if */
|
|
|
|
else {
|
|
if ( set_duplicates ( hptr, NULL, pattern ) == ERROR )
|
|
rvalue = ERROR;
|
|
else if ( load_entry ( hptr, NULL, vlist, pattern, argct, &ct ) == ERROR )
|
|
rvalue = ERROR;
|
|
} /* else */
|
|
} /* if */
|
|
|
|
va_end ( arglist );
|
|
from_ui_load = FALSE;
|
|
return ( rvalue );
|
|
} /* ui load */
|
|
|
|
|
|
|
|
BOOLEAN ui_is_set ( const char * pattern )
|
|
|
|
/*
|
|
* Returns TRUE if pattern's entry is set; FALSE otherwise.
|
|
*/
|
|
|
|
{
|
|
HTABLE * hptr; /* points to one pattern */
|
|
|
|
if (( hptr = match_pattern ( pattern )) == NULL ) {
|
|
ui_print ( VDEBUG, "pattern: %s, not in entry table.\n", pattern );
|
|
return ( FALSE );
|
|
} /* if */
|
|
|
|
return ( hptr->num_entries != 0 );
|
|
} /* ui is set */
|
|
|
|
|
|
|
|
int ui_entry_cnt ( const char * pattern )
|
|
/*
|
|
* Returns number of entries which match pattern; 0 if no entries
|
|
* matched the pattern; ERROR if no such pattern.
|
|
*/
|
|
|
|
{
|
|
HTABLE * hptr; /* points to one pattern */
|
|
|
|
if (( hptr = match_pattern ( pattern )) == NULL ) {
|
|
ui_print ( VDEBUG, "pattern: %s, not in entry table.\n", pattern );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
return ( hptr->num_entries );
|
|
} /* ui entry cnt */
|
|
|
|
|
|
|
|
int ui_arg_cnt ( const char * pattern, int entry_num )
|
|
|
|
/*
|
|
* Returns number of arguments in entry; 0 if no entries matched
|
|
* the pattern; ERROR if no such pattern or entry_num.
|
|
*/
|
|
|
|
{
|
|
HTABLE * hptr; /* points to one pattern */
|
|
ENTRY_SET * eptr; /* points to one entry */
|
|
int ct; /* misc counter */
|
|
|
|
if ( entry_num < 1 ) {
|
|
ui_print ( VDEBUG, "entry number: %d, is less than 1.\n", entry_num );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
if (( hptr = match_pattern ( pattern )) == NULL ) {
|
|
ui_print ( VDEBUG, "pattern: %s, not in entry table.\n", pattern );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
if ( hptr->num_entries == 0 )
|
|
return ( 0 ); /* can use this to check for existence of match */
|
|
|
|
if ( entry_num == 1 )
|
|
return ( hptr->num_args );
|
|
|
|
if ( entry_num > hptr->num_entries ) {
|
|
ui_print ( VDEBUG,
|
|
"entry number: %d, greater than number of entries: %d.\n",
|
|
entry_num, hptr->num_entries );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
eptr = hptr->entry_list;
|
|
|
|
for ( ct = 2; ct < entry_num; ct++ )
|
|
eptr = eptr->next_entry;
|
|
|
|
return ( eptr->num_args );
|
|
} /* ui arg cnt */
|
|
|
|
|
|
|
|
char * ui_entry_value ( const char * pattern, int entry_num )
|
|
|
|
/*
|
|
* Value of a particular entry of a particular pattern.
|
|
* Returns pointer to string; NULL if no such pattern or entry_num
|
|
* or pattern not matched.
|
|
*/
|
|
|
|
{
|
|
HTABLE * hptr; /* points to one pattern */
|
|
ENTRY_SET * eptr; /* points to one entry */
|
|
int ct; /* misc counter */
|
|
|
|
if ( entry_num < 1 ) {
|
|
ui_print ( VDEBUG, "entry number: %d, is less than 1.\n", entry_num );
|
|
return ( NULL );
|
|
} /* if */
|
|
|
|
if (( hptr = match_pattern ( pattern )) == NULL ) {
|
|
ui_print ( VDEBUG, "pattern: %s, not in entry table.\n", pattern );
|
|
return ( NULL );
|
|
} /* if */
|
|
|
|
if ( hptr->num_entries == 0 )
|
|
return ( NULL ); /* can use this to check for existence of match */
|
|
|
|
if ( entry_num == 1 )
|
|
return ( (char *)hptr->entry );
|
|
|
|
if ( entry_num > hptr->num_entries ) {
|
|
ui_print ( VDEBUG,
|
|
"entry number: %d, greater than number of entries: %d.\n",
|
|
entry_num, hptr->num_entries );
|
|
return ( NULL );
|
|
} /* if */
|
|
|
|
eptr = hptr->entry_list;
|
|
|
|
for ( ct = 2; ct < entry_num; ct++ )
|
|
eptr = eptr->next_entry;
|
|
|
|
return ( (char *)eptr->entry );
|
|
} /* ui entry value */
|
|
|
|
|
|
|
|
char * ui_arg_value ( const char * pattern, int entry_num, int arg_num )
|
|
|
|
/*
|
|
* Value of a particular argument of a particular entry.
|
|
* Returns pointer to string; NULL if no such pattern, entry_num,
|
|
* or arg_num, also NULL if pattern not matched.
|
|
*/
|
|
|
|
{
|
|
HTABLE * hptr; /* points to one pattern */
|
|
ENTRY_SET * eptr; /* points to one entry */
|
|
int ct; /* misc counter */
|
|
|
|
if ( entry_num < 1 ) {
|
|
ui_print ( VDEBUG, "entry number: %d, is less than 1.\n", entry_num );
|
|
return ( NULL );
|
|
} /* if */
|
|
|
|
if ( arg_num < 1 ) {
|
|
ui_print ( VDEBUG, "argument number: %d, is less than 1.\n", arg_num );
|
|
return ( NULL );
|
|
} /* if */
|
|
|
|
if (( hptr = match_pattern ( pattern )) == NULL ) {
|
|
ui_print ( VDEBUG, "pattern: %s, not in entry table.\n", pattern );
|
|
return ( NULL );
|
|
} /* if */
|
|
|
|
if ( hptr->num_entries == 0 )
|
|
return ( NULL );
|
|
|
|
if ( entry_num == 1 )
|
|
return ( arg_value ( hptr->arg_list, arg_num, hptr->num_args ));
|
|
|
|
if ( entry_num > hptr->num_entries ) {
|
|
ui_print ( VDEBUG,
|
|
"entry number: %d, greater than number of entries: %d.\n",
|
|
entry_num, hptr->num_entries );
|
|
return ( NULL );
|
|
} /* if */
|
|
|
|
eptr = hptr->entry_list;
|
|
|
|
for ( ct = 2; ct < entry_num; ct++ )
|
|
eptr = eptr->next_entry;
|
|
|
|
return ( arg_value ( eptr->arg_list, arg_num, eptr->num_args ));
|
|
} /* ui arg value */
|
|
|
|
|
|
|
|
static char * arg_value (
|
|
ARG_SET * arglist, /* list of args to run down */
|
|
int argnum, /* argument number to reach */
|
|
int maxargs) /* maximum arguments available */
|
|
|
|
/*
|
|
* Finds the argument in the arglist specified by the argnum.
|
|
* Returns pointer to this string; NULL if if cannot find string
|
|
* for any reason.
|
|
*/
|
|
|
|
|
|
{
|
|
int ct; /* misc counter */
|
|
|
|
if ( argnum > maxargs ) {
|
|
ui_print ( VDEBUG,
|
|
"argument number: %d, greater than number of argument: %d.\n",
|
|
argnum, maxargs );
|
|
return ( NULL );
|
|
} /* if */
|
|
|
|
for ( ct = 1; ct < argnum; ct++ )
|
|
arglist = arglist->next_arg;
|
|
|
|
return ( (char *)arglist->arg );
|
|
} /* arg value */
|
|
|
|
|
|
|
|
int ui_entries_to_argv ( const char * pattern, char *** entries )
|
|
|
|
/*
|
|
* Place all entries for a pattern into a char ** list.
|
|
* Returns number of entries put in "entries"; 0 if no
|
|
* entries; ERROR if no such pattern or entry.
|
|
*/
|
|
{
|
|
HTABLE * hptr; /* points to one pattern */
|
|
ENTRY_SET * eptr; /* points to one entry */
|
|
int ct; /* misc counter */
|
|
|
|
if (( hptr = match_pattern ( pattern )) == NULL ) {
|
|
ui_print ( VDEBUG, "pattern: %s, not in entry table.\n", pattern );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
if ( hptr->num_entries == 0 )
|
|
return ( 0 );
|
|
|
|
if (( *entries = ( char ** ) calloc ( hptr->num_entries,
|
|
sizeof ( char * )))
|
|
== NULL )
|
|
uquit ( ERROR, FALSE, "sys: could not calloc space for entry argv list.\n");
|
|
|
|
**entries = (char *)hptr->entry;
|
|
eptr = hptr->entry_list;
|
|
|
|
for ( ct = 1; ct < hptr->num_entries; ct++ ) {
|
|
*(*entries + ct) = (char *)eptr->entry;
|
|
eptr = eptr->next_entry;
|
|
} /* for */
|
|
|
|
return ( hptr->num_entries );
|
|
} /* ui entries to argv */
|
|
|
|
|
|
|
|
int ui_args_to_argv (
|
|
const char * pattern, /* pattern to match in table */
|
|
int entry_num, /* entry number of matching pattern */
|
|
char *** arguments) /* list to hold argument */
|
|
|
|
/*
|
|
* Place all arguments for a particular entry of a pattern into
|
|
* a char ** list.
|
|
* Returns number of arguments put in "arguments"; 0 if no
|
|
* arguments; ERROR if no such pattern or entry_num.
|
|
*/
|
|
|
|
{
|
|
HTABLE * hptr; /* points to one pattern */
|
|
ENTRY_SET * eptr; /* points to one entry */
|
|
ARG_SET * aptr; /* points to one argument */
|
|
int total, /* misc integer */
|
|
ct; /* misc counter */
|
|
|
|
if ( entry_num < 1 ) {
|
|
ui_print ( VDEBUG, "entry number: %d, is less than 1.\n", entry_num );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
if (( hptr = match_pattern ( pattern )) == NULL ) {
|
|
ui_print ( VDEBUG, "pattern: %s, not in entry table.\n", pattern );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
if ( hptr->num_entries == 0 )
|
|
return ( 0 );
|
|
|
|
if ( entry_num == 1 ) {
|
|
aptr = hptr->arg_list;
|
|
total = hptr->num_args;
|
|
} /* if */
|
|
|
|
else {
|
|
if ( entry_num > hptr->num_entries ) {
|
|
ui_print ( VDEBUG,
|
|
"entry number: %d, greater than number of entries: %d.\n",
|
|
entry_num, hptr->num_entries );
|
|
return ( ERROR );
|
|
} /* if */
|
|
|
|
eptr = hptr->entry_list;
|
|
|
|
for ( ct = 2; ct < entry_num; ct++ )
|
|
eptr = eptr->next_entry;
|
|
|
|
aptr = eptr->arg_list;
|
|
total = eptr->num_args;
|
|
} /* else */
|
|
|
|
if ( total == 0 )
|
|
return ( 0 );
|
|
|
|
if (( *arguments = ( char ** ) calloc ( total, sizeof ( char * )))
|
|
== NULL )
|
|
uquit ( ERROR, FALSE, "could not calloc space for argument argv list.\n" );
|
|
|
|
for ( ct = 0; ct < total; ct++ ) {
|
|
*(*arguments + ct) = (char *)aptr->arg;
|
|
aptr = aptr->next_arg;
|
|
} /* for */
|
|
|
|
return ( total );
|
|
} /* ui args to argv */
|
|
|
|
|
|
|
|
char * ui_ver_switch (void)
|
|
|
|
/*
|
|
* Returns a command line switch, "string", corresponding to
|
|
* the current verbosity level.
|
|
*/
|
|
|
|
{
|
|
switch ( verbosity ) {
|
|
case VQUIET : return ( strdup ( QUIET_OP ));
|
|
case VNORMAL : return ( strdup ( NORMAL_OP ));
|
|
case VDETAIL : return ( strdup ( VERBOSE_OP ));
|
|
case VDEBUG : return ( strdup ( DEBUG_OP ));
|
|
default : ui_print ( VFATAL, "illegal level of verbosity: %d.\n",
|
|
verbosity );
|
|
return ( NULL );
|
|
} /* switch */
|
|
} /* ui verbose switch */
|
|
|
|
|
|
|
|
BOOLEAN ui_is_auto (void)
|
|
|
|
/*
|
|
* Shortcut function.
|
|
* Returns is -auto set?
|
|
*/
|
|
{
|
|
return ( (htbl+auto_pos)->num_entries != 0 );
|
|
} /* ui is auto */
|
|
|
|
|
|
|
|
BOOLEAN ui_is_info (void)
|
|
|
|
/*
|
|
* Shortcut function.
|
|
* Returns is -info set?
|
|
*/
|
|
{
|
|
return ( (htbl+info_pos)->num_entries != 0 );
|
|
} /* ui is info */
|
|
|
|
|
|
|
|
int ui_ver_level (void)
|
|
|
|
/*
|
|
* Returns the current verbosity level as an integer level.
|
|
*/
|
|
{
|
|
return ( verbosity );
|
|
} /* ui ver level */
|
|
|
|
void
|
|
ui_print_revision (void)
|
|
{
|
|
ui_print ( VALWAYS, "program : %s\nrelease : %s\nlibode : %s\n",
|
|
progname, BUILD_VERSION, BUILD_DATE );
|
|
}
|