/*
* Copyright 1987, 1988, 1989 by Massachusetts Institute of Technology
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose is hereby granted, provided that
* the names of M.I.T. and the M.I.T. S.I.P.B. not be used in
* advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. M.I.T. and the
* M.I.T. S.I.P.B. make no representations about the suitability of
* this software for any purpose. It is provided "as is" without
* express or implied warranty.
*/
#ifdef HAS_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#else
extern int errno;
#endif
#include "ss_internal.h"
#include <stdio.h>
static int check_request_table PROTOTYPE((ss_request_table *rqtbl, int argc,
char *argv[], int sci_idx));
static int really_execute_command PROTOTYPE((int sci_idx, int argc,
char **argv[]));
/*
* get_request(tbl, idx)
*
* Function:
* Gets the idx'th request from the request table pointed to
* by tbl.
* Arguments:
* tbl (ss_request_table *)
* pointer to request table
* idx (int)
* index into table
* Returns:
* (ss_request_entry *)
* pointer to request table entry
* Notes:
* Has been replaced by a macro.
*/
#ifdef __SABER__
/* sigh. saber won't deal with pointer-to-const-struct */
static struct _ss_request_entry * get_request (tbl, idx)
ss_request_table * tbl;
int idx;
{
struct _ss_request_table *tbl1 = (struct _ss_request_table *) tbl;
struct _ss_request_entry *e = (struct _ss_request_entry *) tbl1->requests;
return e + idx;
}
#else
#define get_request(tbl,idx) ((tbl) -> requests + (idx))
#endif
/*
* check_request_table(rqtbl, argc, argv, sci_idx)
*
* Function:
* If the command string in argv[0] is in the request table, execute
* the commands and return error code 0. Otherwise, return error
* code ss_et_command_not_found.
* Arguments:
* rqtbl (ss_request_table *)
* pointer to request table
* argc (int)
* number of elements in argv[]
* argv (char *[])
* argument string array
* sci_idx (int)
* ss-internal index for subsystem control info structure
* Returns:
* (int)
* zero if command found, ss_et_command_not_found otherwise
* Notes:
*/
static int check_request_table(register ss_request_table *rqtbl, int argc,
char *argv[], int sci_idx)
{
#ifdef __SABER__
struct _ss_request_entry *request;
#else
register ss_request_entry *request;
#endif
register ss_data *info;
register char const * const * name;
char *string = argv[0];
int i;
info = ss_info(sci_idx);
info->argc = argc;
info->argv = argv;
for (i = 0; (request = get_request(rqtbl, i))->command_names; i++) {
for (name = request->command_names; *name; name++)
if (!strcmp(*name, string)) {
info->current_request = request->command_names[0];
(request->function)(argc, (const char *const *) argv,
sci_idx,info->info_ptr);
info->current_request = (char *)NULL;
return(0);
}
}
return(SS_ET_COMMAND_NOT_FOUND);
}
/*
* really_execute_command(sci_idx, argc, argv)
*
* Function:
* Fills in the argc, argv values in the subsystem entry and
* call the appropriate routine.
* Arguments:
* sci_idx (int)
* ss-internal index for subsystem control info structure
* argc (int)
* number of arguments in argument list
* argv (char **[])
* pointer to parsed argument list (may be reallocated
* on abbrev expansion)
*
* Returns:
* (int)
* Zero if successful, ss_et_command_not_found otherwise.
* Notes:
*/
static int really_execute_command(int sci_idx, int argc, char **argv[])
{
register ss_request_table **rqtbl;
register ss_data *info;
info = ss_info(sci_idx);
for (rqtbl = info->rqt_tables; *rqtbl; rqtbl++) {
if (check_request_table (*rqtbl, argc, *argv, sci_idx) == 0)
return(0);
}
return(SS_ET_COMMAND_NOT_FOUND);
}
/*
* ss_execute_command(sci_idx, argv)
*
* Function:
* Executes a parsed command list within the subsystem.
* Arguments:
* sci_idx (int)
* ss-internal index for subsystem control info structure
* argv (char *[])
* parsed argument list
* Returns:
* (int)
* Zero if successful, ss_et_command_not_found otherwise.
* Notes:
*/
int ss_execute_command(int sci_idx, register char *argv[])
{
register int i, argc;
char **argp;
argc = 0;
for (argp = argv; *argp; argp++)
argc++;
argp = (char **)malloc((argc+1)*sizeof(char *));
for (i = 0; i <= argc; i++)
argp[i] = argv[i];
i = really_execute_command(sci_idx, argc, &argp);
free(argp);
return(i);
}
/*
* ss_execute_line(sci_idx, line_ptr)
*
* Function:
* Parses and executes a command line within a subsystem.
* Arguments:
* sci_idx (int)
* ss-internal index for subsystem control info structure
* line_ptr (char *)
* Pointer to command line to be parsed.
* Returns:
* (int)
* Error code.
* Notes:
*/
int ss_execute_line(int sci_idx, char *line_ptr)
{
char **argv;
int argc, ret;
/* flush leading whitespace */
while (line_ptr[0] == ' ' || line_ptr[0] == '\t')
line_ptr++;
/* check if it should be sent to operating system for execution */
if (*line_ptr == '!') {
if (ss_info(sci_idx)->flags.escape_disabled)
return SS_ET_ESCAPE_DISABLED;
else {
line_ptr++;
return (system(line_ptr) < 0) ? errno : 0;
}
}
/* parse it */
argv = ss_parse(sci_idx, line_ptr, &argc);
if (argc == 0) {
free(argv);
return 0;
}
/* look it up in the request tables, execute if found */
ret = really_execute_command (sci_idx, argc, &argv);
free(argv);
return(ret);
}