fis-gtm/sr_unix/cli_parse.c

1098 lines
30 KiB
C

/****************************************************************
* *
* Copyright 2001, 2012 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
* under a license. If you do not know the terms of *
* the license, please stop and do not read further. *
* *
****************************************************************/
#if defined(__MVS__) && !defined(_ISOC99_SOURCE)
#define _ISOC99_SOURCE
#endif
#include "mdef.h"
#include "gtm_stdio.h"
#include "gtm_string.h"
#include "cli.h"
#include "cli_parse.h"
#include "error.h"
#include "cli_disallow.h"
#define NO_STRING "NO"
/* Dynamically allocates (that is, grows) enough space for the current array
* of parameter strings during the lifetime of the process. Since the number
* of array elements is limited, it is better to allocate memory as needed
* rather than constantly free and reallocate. */
#define GROW_HEAP_IF_NEEDED(PARM_ARY_INDEX) \
{ \
if (TAREF1(parm_str_len, PARM_ARY_INDEX) > TAREF1(parm_ary_len, PARM_ARY_INDEX)) \
{ \
if (TAREF1(parm_ary, PARM_ARY_INDEX)) \
free(TAREF1(parm_ary, PARM_ARY_INDEX)); \
\
TAREF1(parm_ary, PARM_ARY_INDEX) = (char *)malloc(TAREF1(parm_str_len, PARM_ARY_INDEX)); \
\
TAREF1(parm_ary_len, PARM_ARY_INDEX) = TAREF1(parm_str_len, PARM_ARY_INDEX); \
} \
}
#if MAX_OPT_LEN > MAX_LINE
# error MAX_OPT_LEN is greater than MAX_LINE. Fix STRNCMP_STR and STRNCPY_STR usages below.
#endif
GBLDEF void (*func)(void); /* Function to be dispatched
to for this command */
GBLREF char cli_err_str[]; /* Parse Error message buffer */
static CLI_ENTRY *gpqual_root; /* pointer to root of
subordinate qualifier table */
static CLI_ENTRY *gpcmd_qual; /* pointer command qualifier table */
static CLI_ENTRY *gpcmd_verb; /* pointer to verb table */
static CLI_PARM *gpcmd_parm_vals; /* pointer to parameters for command */
GBLREF char cli_token_buf[];
GBLREF CLI_ENTRY *cmd_ary;
GBLREF IN_PARMS *cli_lex_in_ptr;
error_def(ERR_CLIERR);
error_def(ERR_MUNOACTION);
error_def(ERR_MUPCLIERR);
/*
* -----------------------------------------------
* Clear all parameter values and flags of command
* parameter table for a given command.
*
* Arguments:
* cmd_parms - address of parameter array
* follow - whether to clear extra value tables or not
* TRUE - follow down
* FALSE - do not follow down
*
* Return:
* none
* -----------------------------------------------
*/
void clear_parm_vals(CLI_ENTRY *cmd_parms, boolean_t follow) /* pointer to option's parameter table */
{
CLI_ENTRY *root_param;
int need_copy;
need_copy = (gpcmd_qual != cmd_parms);
while (strlen(cmd_parms->name) > 0)
{
if (cmd_parms->pval_str)
free(cmd_parms->pval_str);
/* if root table exists, copy over any qualifier values to the new parameter table */
if ((FALSE != follow) && need_copy &&
(root_param = find_cmd_param(cmd_parms->name, gpcmd_qual, FALSE)))
{
cmd_parms->pval_str = root_param->pval_str;
cmd_parms->negated = root_param->negated;
cmd_parms->present = root_param->present;
root_param->pval_str = 0;
} else
{
cmd_parms->negated = 0;
cmd_parms->present = 0;
cmd_parms->pval_str = 0;
/* dfault_str also implements default values.
0: it is not present by default,
DEFA_PRESENT: it is present by default, no value,
str pointer: it is present by default, with the value pointed to
*/
if (cmd_parms->dfault_str)
{
cmd_parms->present = CLI_DEFAULT;
if (CLI_PRESENT != (INTPTR_T)cmd_parms->dfault_str)
cmd_parms->pval_str = cmd_parms->dfault_str;
}
if ((FALSE != follow) && cmd_parms->qual_vals)
clear_parm_vals(cmd_parms->qual_vals, FALSE);
}
cmd_parms++;
}
}
/*
* ---------------------------------------------------------
* Find entry in the qualifier table
*
* Arguments:
* str - parameter string
* pparm - pointer to parameter table for this command
*
* Return:
* if found, index into command table array,
* else -1
* ---------------------------------------------------------
*/
int find_entry(char *str, CLI_ENTRY *pparm)
{
int match_ind, res, str_len;
boolean_t len_match;
int ind;
char *sp;
ind = 0;
match_ind = -1;
len_match = FALSE;
cli_strupper(str);
str_len = strlen(str);
while (0 < strlen(sp = (pparm + ind)->name))
{
/* As the table is parsed as long as the string in question is lexically smaller
than the entry in the table, we go on checking the next entry.
If a match is found, the lengths of the two strings (the table entry and the
string in question) are compared.
When the next entry is checked,
if it is not a match, the previous entry is the correct match;
if it is a match again (a longer entry), if the first match was a length-match
as well, the first entry is the match returned. otherwise an error is returned
since we cannot make a decision (does SE match SET or SEP). */
if (0 == (res = STRNCMP_STR(sp, str, str_len)))
{
if (-1 != match_ind)
{
if (FALSE == len_match)
return (-1);
break;
} else
{
if (str_len == strlen(sp))
len_match = TRUE;
match_ind = ind;
}
} else
{
if (0 < res)
break;
}
ind++;
}
if (-1 != match_ind && gpqual_root && 0 == STRNCMP_STR(gpqual_root->name, str, MAX_OPT_LEN))
return (-1);
return (match_ind);
}
/*
* -----------------------------------------------
* Find command in command table
*
* Arguments:
* str - command string
*
* Return:
* if found, index into command table array,
* else -1
* -----------------------------------------------
*/
int find_verb(char *str)
{
return (find_entry(str, cmd_ary));
}
/*
* ---------------------------------------------------------
* Find command parameter in command parameter table
*
* Arguments:
* str - parameter string
* pparm - pointer to parameter table for this command
*
* Return:
* if found, pointer to parameter structure
* else 0
* ---------------------------------------------------------
*/
CLI_ENTRY *find_cmd_param(char *str, CLI_ENTRY *pparm, int follow)
{
CLI_ENTRY *pparm_tmp;
int ind, ind_match;
char *sp;
ind_match = -1;
if (NULL == pparm)
return NULL;
if (0 <= (ind = find_entry(str, pparm)))
return pparm + ind;
if (FALSE == follow)
return NULL;
/* if to follow, go through the qual_vals, and check those tables */
for(ind =0; 0 < strlen((pparm + ind)->name); ind++)
{
pparm_tmp = (pparm + ind)->qual_vals;
if (pparm_tmp)
ind_match = find_entry(str, pparm_tmp);
if (-1 != ind_match)
return pparm_tmp + ind_match;
}
return NULL;
}
/*
* ---------------------------------------------------------
* Parse one option.
* Read tokens from the input.
* Check if it is a valid qualifier or parameter.
* If it is a parameter, get it, and save it in the
* global parameter array.
* If it is a qualifier, get its value and save it in a value table,
* corresponding to this option.
*
* Arguments:
* pcmd_parms - pointer to command parameter table
* eof - pointer to end of file flag
*
* Return:
* 1 - option parsed OK
* -1 - failure to parse option
* 0 - no more tokens, in which case
* the eof flag is set on end of file.
* ---------------------------------------------------------
*/
int parse_arg(CLI_ENTRY *pcmd_parms, int *eof)
{
CLI_ENTRY *pparm;
char *opt_str, *val_str;
int neg_flg;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
/* -----------------------------------------
* get qualifier marker, or parameter token
* -----------------------------------------
*/
if (VAL_LIST == gpcmd_verb->val_type && TREF(parms_cnt) == gpcmd_verb->max_parms)
return (0);
if (!cli_look_next_token(eof))
return (0);
/* -------------------------------------------------------------------
* here cli_token_buf is set by the previous cli_look_next_token(eof)
* call itself since it in turn calls cli_gettoken()
* -------------------------------------------------------------------
*/
if (!cli_is_qualif(cli_token_buf) && !cli_is_assign(cli_token_buf))
{ /* ----------------------------------------------------
* If token is not a qualifier, it must be a parameter
*
* No need to check for eof on cli_get_string_token(eof) since
* already checked that on the previous cli_look_next_token.
* now you have to skip initial white spaces before reading
* the string since cli_get_string_token considers a space
* as a blank token. hence the need for the skip_white_space()
* call.
* ------------------------------------------------------------
*/
skip_white_space();
cli_get_string_token(eof);
if (TREF(parms_cnt) >= gpcmd_verb->max_parms)
{
SNPRINTF(cli_err_str, MAX_CLI_ERR_STR, "Too many parameters ");
return (-1);
}
TAREF1(parm_str_len, TREF(parms_cnt)) = strlen(cli_token_buf) + 1;
GROW_HEAP_IF_NEEDED(TREF(parms_cnt));
memcpy(TAREF1(parm_ary, TREF(parms_cnt)), cli_token_buf, TAREF1(parm_str_len, TREF(parms_cnt)));
(TREF(parms_cnt))++;
return (1);
}
/* ---------------------------------------------------------------------
* cli_gettoken(eof) need not be checked for return value since earlier
* itself we have checked for return value in cli_look_next_token(eof)
* ---------------------------------------------------------------------
*/
cli_gettoken(eof);
opt_str = cli_token_buf;
if (!pcmd_parms)
{
SNPRINTF(cli_err_str, MAX_CLI_ERR_STR, "No qualifiers allowed for this command");
return (-1);
}
/* ------------------------------------------
* Qualifiers must start with qualifier token
* ------------------------------------------
*/
if (!cli_is_qualif(cli_token_buf))
{
SNPRINTF(cli_err_str, MAX_CLI_ERR_STR, "Qualifier expected instead of : %s ", opt_str);
return (-1);
}
/* -------------------------
* Get the qualifier string
* -------------------------
*/
if (!cli_look_next_token(eof) || 0 == cli_gettoken(eof))
{
SNPRINTF(cli_err_str, MAX_CLI_ERR_STR, "Qualifier string missing %s ", opt_str);
return (-1);
}
/* ---------------------------------------
* Fold the qualifier string to upper case
* ---------------------------------------
*/
cli_strupper(opt_str);
/* -------------------------
* See if option is negated and update
* -------------------------
*/
if (-1 == (neg_flg = cli_check_negated(&opt_str, pcmd_parms, &pparm)))
return (-1);
/* -------------------------------------------------------------
* If value is disallowed for this qualifier, and an assignment
* token is encounter, report error, values not allowed for
* negated qualifiers
* -------------------------------------------------------------
*/
if (neg_flg || VAL_DISALLOWED == pparm->required)
{
if (cli_look_next_token(eof) && cli_is_assign(cli_token_buf))
{
SNPRINTF(cli_err_str, MAX_CLI_ERR_STR,
"Assignment is not allowed for this option : %s",
pparm->name);
return (-1);
}
} else
{ /* --------------------------------------------------
* Get Value either optional, or required.
* In either case, there must be an assignment token
* --------------------------------------------------
*/
if (!cli_look_next_token(eof) || !cli_is_assign(cli_token_buf))
{
if (VAL_REQ == pparm->required)
{
SNPRINTF(cli_err_str, MAX_CLI_ERR_STR, "Option : %s needs value", pparm->name);
return (-1);
} else
{
if (pparm->present)
{
/* The option was specified before, so clean up that one,
* the last one overrides
*/
if (pparm->pval_str)
free(pparm->pval_str);
if (pparm->qual_vals)
clear_parm_vals(pparm->qual_vals, FALSE);
}
/* -------------------------------
* Allocate memory and save value
* -------------------------------
*/
if (pparm->parm_values)
{
MALLOC_CPY_STR(pparm->pval_str, pparm->parm_values->prompt);
if (!cli_get_sub_quals(pparm))
return (-1);
}
}
} else
{
cli_gettoken(eof);
/* ---------------------------------
* Get the assignment token + value
* ---------------------------------
*/
if (!cli_is_assign(cli_token_buf))
{
SNPRINTF(cli_err_str, MAX_CLI_ERR_STR, "Assignment missing after option : %s", pparm->name);
return (-1);
}
/* --------------------------------------------------------
* get the value token, "=" is NOT a token terminator here
* --------------------------------------------------------
*/
if (!cli_look_next_string_token(eof) || 0 == cli_get_string_token(eof))
{
SNPRINTF(cli_err_str, MAX_CLI_ERR_STR, "Unrecognized option : %s, value expected but not found",
pparm->name);
cli_lex_in_ptr->tp = 0;
return (-1);
}
val_str = cli_token_buf;
if (!cli_numeric_check(pparm, val_str))
{
cli_lex_in_ptr->tp = 0;
return (-1);
}
if (pparm->present)
{ /* The option was specified before, so clean up that one,
* the last one overrides
*/
if (pparm->pval_str)
free(pparm->pval_str);
if (pparm->qual_vals)
clear_parm_vals(pparm->qual_vals, FALSE);
}
/* -------------------------------
* Allocate memory and save value
* -------------------------------
*/
MALLOC_CPY_STR(pparm->pval_str, cli_token_buf);
if (!cli_get_sub_quals(pparm))
return (-1);
}
}
if (pparm->present)
pparm->negated = 0;
pparm->negated = neg_flg;
pparm->present = 1;
if (NULL != pparm->func)
func = pparm->func;
/* ----------------------------------------------------------------------------------------------------------------------
* If there is another level, update global pointers
* Notice that this global pointer updation should be done only at the end of this routine in order to ensure that the
* check_disallow() function invoked below sees the currently parsed argument as present (i.e. pparm->present = 1)
* ----------------------------------------------------------------------------------------------------------------------
*/
if (pparm->parms)
{ /*-------------------------------------------------------------------------------------------
* Check that the disallow conditions for this level are met before switching to next level
*-------------------------------------------------------------------------------------------
*/
if (FALSE == check_disallow(gpcmd_verb))
return (-1);
gpqual_root = pparm;
clear_parm_vals(pparm->parms, TRUE);
gpcmd_qual = pparm->parms;
gpcmd_verb = pparm; /* this needs to be done in order for check_disallow() to do the proper disallow check.
* an example that will not work otherwise is cli_disallow_mupip_replic_receive() */
}
return (1);
}
/* -----------------------------------------------------
* Check if the value is numeric if it is supposed to be
*
* Return:
* TRUE - It is numeric or val_type is not
* numeric anyway
* FALSE - Is not numeric
* -----------------------------------------------------
*/
boolean_t cli_numeric_check(CLI_ENTRY *pparm, char *val_str)
{
boolean_t retval = TRUE;
if (VAL_NUM == pparm->val_type)
{
if (pparm->hex_num)
{
if (!cli_is_hex(val_str))
{
SNPRINTF(cli_err_str, MAX_CLI_ERR_STR,
"Unrecognized value: %s, HEX number expected",
val_str);
retval = FALSE;
}
} else if (!cli_is_dcm(val_str))
{
SNPRINTF(cli_err_str, MAX_CLI_ERR_STR,
"Unrecognized value: %s, Decimal number expected",
val_str);
retval = FALSE;
}
}
return (retval);
}
/*---------------------------
* Check if option is negated
*---------------------------
*/
int cli_check_negated(char **opt_str_ptr, CLI_ENTRY *pcmd_parm_ptr, CLI_ENTRY **pparm_ptr)
{
int neg_flg;
CLI_ENTRY *pcmd_parms;
char *opt_str_tmp;
pcmd_parms = pcmd_parm_ptr;
opt_str_tmp = *opt_str_ptr;
if (0 == MEMCMP_LIT(*opt_str_ptr, NO_STRING))
{
*opt_str_ptr += SIZEOF(NO_STRING) - 1;
neg_flg = 1;
} else
neg_flg = 0;
/* --------------------------------------------
* search qualifier table for qualifier string
* --------------------------------------------
*/
if (0 == (*pparm_ptr = find_cmd_param(*opt_str_ptr, pcmd_parms, FALSE)))
{
/* Check that the qualifier does not have the NO prefix */
if (0 == (*pparm_ptr = find_cmd_param(opt_str_tmp, pcmd_parms, FALSE)))
{
SNPRINTF(cli_err_str, MAX_CLI_ERR_STR, "Unrecognized option : %s", *opt_str_ptr);
cli_lex_in_ptr->tp = 0;
return (-1);
} else
{
/* It was a valid qualifier with the prefix NO */
*opt_str_ptr = opt_str_tmp;
neg_flg = 0;
}
}
/* ----------------------------------------------------
* if option is negated and it is not negatable, error
* ----------------------------------------------------
*/
if (!(*pparm_ptr)->negatable && neg_flg)
{
SNPRINTF(cli_err_str, MAX_CLI_ERR_STR, "Option %s may not be negated", *opt_str_ptr);
return (-1);
}
return neg_flg;
}
/*
* --------------------------------------------------
*
* Process the qualifier to see if any extra parameters
* are possible in the <...>
* Return:
* TRUE - OK
* FALSE - Error
* --------------------------------------------------
*/
boolean_t cli_get_sub_quals(CLI_ENTRY *pparm)
{
CLI_ENTRY *pparm_qual, *pparm1;
char local_str[MAX_LINE], tmp_str[MAX_LINE], *tmp_str_ptr;
char *ptr_next_val, *ptr_next_comma, *ptr_equal;
int len_str, neg_flg, ptr_equal_len;
boolean_t val_flg, has_a_qual;
has_a_qual = FALSE;
pparm_qual = pparm->qual_vals;
if (!pparm_qual)
return TRUE;
if ((VAL_STR == pparm->val_type) || (VAL_LIST == pparm->val_type))
{
strncpy(local_str, pparm->pval_str, SIZEOF(local_str) - 1);
ptr_next_val = local_str;
while (NULL != ptr_next_val)
{
len_str= STRLEN(ptr_next_val);
strncpy(tmp_str, ptr_next_val, len_str);
tmp_str[len_str] = 0;
tmp_str_ptr = tmp_str;
ptr_next_comma = strchr(tmp_str_ptr, ',');
if (NULL == ptr_next_comma)
ptr_next_comma = tmp_str_ptr + len_str;
else
*ptr_next_comma = 0;
ptr_equal = strchr(tmp_str_ptr, '=');
if (ptr_equal && (ptr_equal < ptr_next_comma) )
*ptr_equal = 0;
else
ptr_equal = NULL;
/* Convert just the qualifier to upper case (e.g. in "enable,on,file=x.mjl" --> "ENABLE,ON,FILE=x.mjl")
* Do not convert the values of parameters to upper case as that might result in incorrect translation
* if UTF8 characters are present in the command line. The logic below anyways needs only the qualifiers
* to be translated.
*/
cli_strupper(tmp_str);
/* -------------------------
* See if option is negated
* -------------------------
*/
if (-1 == (neg_flg = cli_check_negated( &tmp_str_ptr, pparm_qual, &pparm1)))
return FALSE;
if (1 == neg_flg)
len_str -= STRLEN(NO_STRING);
if ((ptr_equal) && (ptr_equal + 1 < ptr_next_comma))
val_flg = TRUE;
else
val_flg = FALSE;
/* -------------------------------------------------------------
* If value is disallowed for this qualifier, and an assignment
* is encountered, report error, values not allowed for
* negated qualifiers
* -------------------------------------------------------------
*/
if (neg_flg || VAL_DISALLOWED == pparm1->required)
{
if (val_flg)
{
SNPRINTF(cli_err_str, MAX_CLI_ERR_STR,
"Assignment is not allowed for this option : %s",
pparm1->name);
cli_lex_in_ptr->tp = 0;
return FALSE;
}
} else
{
if ((!val_flg) && VAL_REQ == pparm1->required)
{
if (ptr_equal)
SNPRINTF(cli_err_str, MAX_CLI_ERR_STR,
"Unrecognized option : %s, value expected but not found",
pparm1->name);
else
SNPRINTF(cli_err_str, MAX_CLI_ERR_STR, "Option : %s needs value", tmp_str_ptr);
cli_lex_in_ptr->tp = 0;
return FALSE;
}
if (!cli_numeric_check(pparm1, ptr_equal + 1))
{
cli_lex_in_ptr->tp = 0;
return FALSE;
}
if (pparm1->present)
{
/* The option was specified before, so clean up that one,
* the last one overrides
*/
if (pparm1->pval_str)
free(pparm1->pval_str);
}
if ((!val_flg) && (VAL_NOT_REQ == pparm1->required) && pparm1->parm_values)
MALLOC_CPY_STR(pparm1->pval_str, pparm1->parm_values->prompt);
if (val_flg)
{
ptr_equal_len = STRLEN(ptr_equal + 1);
pparm1->pval_str = malloc(ptr_equal_len + 1);
strncpy(pparm1->pval_str, ptr_next_val + (ptr_equal - tmp_str_ptr) + 1, ptr_equal_len);
pparm1->pval_str[ptr_equal_len] = 0;
}
}
if (pparm1->present)
pparm->negated = 0;
pparm1->negated = neg_flg;
pparm1->present = CLI_PRESENT;
has_a_qual = TRUE;
if ((tmp_str_ptr + len_str) != ptr_next_comma)
{
ptr_next_val = strchr(ptr_next_val, ',')+ 1;
if (!*ptr_next_val)
{
SNPRINTF(cli_err_str, MAX_CLI_ERR_STR, "Option expected");
cli_lex_in_ptr->tp = 0;
return FALSE;
}
} else
ptr_next_val = NULL;
}
}
/* do one last parse on the qualifier table, if there is any other qualifier present,
* the DEFA_PRESENT one is not necessary, otherwise leave it as it is.
*/
if (has_a_qual)
{
pparm1 = pparm_qual;
while (0 != *pparm1->name)
{
if (CLI_DEFAULT == pparm1->present)
pparm1->present = CLI_ABSENT;
pparm1++;
}
}
return TRUE;
}
/*
* -----------------------------------------------------------
* Parse one command.
* Get tokens from the input stream.
* See if the first token is a command name, as it should be,
* and if it is, check if optional arguments that follow,
* are legal, and if they are, get their values and
* save them in a value table, corresponding to this
* option.
* If any of these conditions are not met, parse error occures.
*
* Return:
* 0 - command parsed OK
* EOF - end of file
* <> - failure to parse command
* -----------------------------------------------------------
*/
int parse_cmd(void)
{
int res, cmd_ind;
char *cmd_str;
int opt_cnt;
int eof, cmd_err;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
opt_cnt = 0;
gpqual_root = NULL;
func = 0;
cmd_err = 0;
TREF(parms_cnt) = 0; /* Parameters count */
*cli_err_str = 0;
cmd_str = cli_token_buf;
/* ------------------------
* If no more tokens exist
* ------------------------
*/
if (0 == cli_gettoken(&eof))
{
if (eof)
return (EOF);
return (0);
}
/* ------------------------------
* Find command in command table
* ------------------------------
*/
if (-1 != (cmd_ind = find_verb(cmd_str)))
{
gpcmd_qual = cmd_ary[cmd_ind].parms;
gpcmd_parm_vals = cmd_ary[cmd_ind].parm_values;
gpcmd_verb = &cmd_ary[cmd_ind];
if (gpcmd_qual)
clear_parm_vals(gpcmd_qual, TRUE);
func = cmd_ary[cmd_ind].func;
/* ----------------------
* Parse command options
* ----------------------
*/
do
{
res = parse_arg(gpcmd_qual, &eof);
if (1 == res)
{
opt_cnt++;
}
} while (1 == res);
} else
{
SNPRINTF(cli_err_str, MAX_CLI_ERR_STR, "Unrecognized command: %s", cmd_str);
cli_lex_in_ptr->tp = 0;
res = -1;
}
if ((1 > opt_cnt) && (-1 != res) && (VAL_REQ == cmd_ary[cmd_ind].required))
{
SNPRINTF(cli_err_str, MAX_CLI_ERR_STR, "Command argument expected, but not found");
res = -1;
}
/*------------------------------------------------------
* Check that the disallow conditions are met (to allow)
*------------------------------------------------------
*/
if ((-1 != res) && (FALSE == check_disallow(gpcmd_verb)))
res = -1;
/* -------------------------------------
* If parse error, display error string
* -------------------------------------
*/
if (-1 == res)
{
func = 0;
eof = 0;
}
else
return (0);
/* -------------------------
* If gettoken returned EOF
* -------------------------
*/
if (eof)
return (EOF);
else
return (ERR_CLIERR);
}
/* ------------------------------------------------------------
* See if command parameter is present on the command line,
* and if it is, return the pointer to its table entry.
*
* Arguments:
* parm_str - parameter string to search for
*
* Return:
* 0 - not present
* pointer to parameter entry
* ------------------------------------------------------------
*/
CLI_ENTRY *get_parm_entry(char *parm_str)
{
CLI_ENTRY *pparm;
bool root_match;
char local_str[MAX_LINE], *tmp_ptr;
STRNCPY_STR(local_str, parm_str, SIZEOF(local_str) - 1);
root_match = (gpqual_root && !STRNCMP_STR(gpqual_root->name, local_str, MAX_OPT_LEN));
/* ---------------------------------------
* search qualifier table for this option
* ---------------------------------------
*/
if (!gpcmd_qual)
return (NULL);
if (NULL == strchr(local_str,'.'))
pparm = find_cmd_param(local_str, gpcmd_qual, TRUE);
else
{
tmp_ptr= strchr(local_str,'.');
/* there should be at least 1 character after the . */
assert (tmp_ptr + 1 < local_str + strlen(local_str));
*tmp_ptr = 0;
pparm = find_cmd_param(local_str, gpcmd_qual, FALSE);
if (pparm)
pparm = find_cmd_param(tmp_ptr+1, pparm->qual_vals, FALSE);
}
if (root_match && !pparm)
return (gpqual_root);
else if (pparm)
return (pparm);
else
return (NULL);
}
/*
* ------------------------------------------------------------
* See if command parameter is present on the command line
*
* Arguments:
* entry - parameter string to search for
*
* Return:
* 0 - not present (i.e. CLI_ABSENT)
* <> 0 - present (either CLI_PRESENT or CLI_NEGATED)
* ------------------------------------------------------------
*/
int cli_present(char *entry)
{
CLI_ENTRY *pparm;
char local_str[MAX_LINE];
strncpy(local_str, entry, SIZEOF(local_str) - 1);
cli_strupper(local_str);
if (pparm = get_parm_entry(local_str))
{
if (pparm->negated)
return (CLI_NEGATED);
if ((CLI_PRESENT == pparm->present) || (CLI_DEFAULT == pparm->present))
return (CLI_PRESENT);
}
return (CLI_ABSENT);
}
/*
* ------------------------------------------------------------
* Get the command parameter value
*
* Arguments:
* entry - parameter string to search for
* val_buf - if parameter is present, it is copied to
* this buffer.
*
* Return:
* 0 - not present
* <> 0 - ok
* ------------------------------------------------------------
*/
bool cli_get_value(char *entry, char val_buf[])
{
CLI_ENTRY *pparm;
char local_str[MAX_LINE];
strncpy(local_str, entry, SIZEOF(local_str) - 1);
cli_strupper(local_str);
if (NULL == (pparm = get_parm_entry(local_str)))
return (FALSE);
if (!pparm->present || NULL == pparm->pval_str)
return (FALSE);
else
strcpy(val_buf, pparm->pval_str);
return (TRUE);
}
/*
* --------------------------------------------------
* See if the qualifier given by 'entry' is negated
* on the command line
*
* Return:
* TRUE - Negated
* FALSE - otherwise
* --------------------------------------------------
*/
boolean_t cli_negated(char *entry) /* entity */
{
CLI_ENTRY *pparm;
char local_str[MAX_LINE];
strncpy(local_str, entry, SIZEOF(local_str) - 1);
cli_strupper(local_str);
if (pparm = get_parm_entry(local_str))
return (pparm->negated);
return (FALSE);
}
bool cli_get_parm(char *entry, char val_buf[])
{
char *sp;
int ind;
int match_ind, res;
char local_str[MAX_LINE];
int eof;
char *gets_res;
int parm_len;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
ind = 0;
assert(0 != gpcmd_parm_vals);
STRNCPY_STR(local_str, entry, SIZEOF(local_str) - 1);
cli_strupper(local_str);
match_ind = -1;
while (0 < strlen(sp = (gpcmd_parm_vals + ind)->name)) /* implicit assignment intended */
{
if (0 == (res = STRNCMP_STR(sp, local_str, MAX_OPT_LEN))) /* implicit assignment intended */
{
if (-1 != match_ind)
return (FALSE);
else
match_ind = ind;
} else
{
if (0 < res)
break;
}
ind++;
}
if (-1 != match_ind)
{
if (NULL == TAREF1(parm_ary, match_ind))
{
if (!((gpcmd_parm_vals + match_ind)->parm_required)) /* Value not required */
return FALSE;
/* If no value and required, prompt for it */
PRINTF("%s", (gpcmd_parm_vals + match_ind)->prompt);
fflush(stdout);
gets_res = cli_fgets(local_str, MAX_LINE, stdin, FALSE);
if (gets_res)
{
parm_len = STRLEN(gets_res);
/* chop off newline */
if (parm_len && (local_str[parm_len - 1] == '\n'))
{
local_str[parm_len - 1] = '\0';
--parm_len;
}
TAREF1(parm_str_len, match_ind) = parm_len + 1;
GROW_HEAP_IF_NEEDED(match_ind);
if (parm_len)
memcpy(TAREF1(parm_ary, match_ind), &local_str[0], parm_len);
*(TAREF1(parm_ary, match_ind) + parm_len) = '\0';
} else
{ /* No string was returned so create a real ghost to point to.
Note that this should be revisited since this is NOT what should
be happening. We should be returning FALSE here but need to instead
return a null parm since current behaviors have a dependency on it
SE 10/2003
*/
TAREF1(parm_str_len, match_ind) = 1;
GROW_HEAP_IF_NEEDED(match_ind);
*TAREF1(parm_ary, match_ind) = '\0';
}
} else if (-1 == *TAREF1(parm_ary, match_ind) && 1 == TAREF1(parm_str_len, match_ind))
return (FALSE);
strcpy(val_buf, TAREF1(parm_ary, match_ind));
if (!cli_look_next_token(&eof) || (0 == cli_gettoken(&eof)))
{
TAREF1(parm_str_len, match_ind) = 1;
GROW_HEAP_IF_NEEDED(match_ind);
*TAREF1(parm_ary, match_ind) = -1;
} else
{
parm_len = STRLEN(cli_token_buf) + 1;
if (MAX_LINE < parm_len)
{
PRINTF("Parameter string too long\n");
fflush(stdout);
return (FALSE);
}
TAREF1(parm_str_len, match_ind) = parm_len;
GROW_HEAP_IF_NEEDED(match_ind);
memcpy(TAREF1(parm_ary, match_ind), cli_token_buf, parm_len);
}
} else
{
/* -----------------
* check qualifiers
* -----------------
*/
if (!cli_get_value(local_str, val_buf))
return (FALSE);
}
return (TRUE);
}
#ifdef GTM_TRIGGER
int parse_triggerfile_cmd(void)
{
int res, cmd_ind;
int opt_cnt;
int eof;
char cmd[] = "TRIGGER";
char *ptr;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
opt_cnt = 0;
gpqual_root = 0;
func = 0;
TREF(parms_cnt) = 0; /* Parameters count */
*cli_err_str = 0;
cmd_ind = find_verb(cmd);
assert(-1 != cmd_ind);
gpcmd_qual = cmd_ary[cmd_ind].qual_vals;
gpcmd_parm_vals = NULL;
gpcmd_verb = cmd_ary[cmd_ind].qual_vals;
if (gpcmd_qual)
clear_parm_vals(gpcmd_qual, TRUE);
func = cmd_ary[cmd_ind].func;
/* ----------------------
* Parse command options
* ----------------------
*/
do
{
res = parse_arg(gpcmd_qual, &eof);
} while (1 == res);
/* -------------------------------------
* If parse error, display error string
* -------------------------------------
*/
if (-1 == res)
func = 0;
else
return (0);
/* -------------------------
* If gettoken returned EOF
* -------------------------
*/
if (eof)
return (EOF);
else
return (ERR_MUNOACTION);
}
#endif