1 /*
2  * Copyright 1987, 1988, 1989 by Massachusetts Institute of Technology
3  *
4  * Permission to use, copy, modify, and distribute this software and
5  * its documentation for any purpose is hereby granted, provided that
6  * the names of M.I.T. and the M.I.T. S.I.P.B. not be used in
7  * advertising or publicity pertaining to distribution of the software
8  * without specific, written prior permission.  M.I.T. and the
9  * M.I.T. S.I.P.B. make no representations about the suitability of
10  * this software for any purpose.  It is provided "as is" without
11  * express or implied warranty.
12  */
13 
14 #ifdef HAS_STDLIB_H
15 #include <stdlib.h>
16 #endif
17 #ifdef HAVE_ERRNO_H
18 #include <errno.h>
19 #else
20 extern int errno;
21 #endif
22 #include "ss_internal.h"
23 #include <stdio.h>
24 
25 static int check_request_table PROTOTYPE((ss_request_table *rqtbl, int argc,
26 					  char *argv[], int sci_idx));
27 static int really_execute_command PROTOTYPE((int sci_idx, int argc,
28 					     char **argv[]));
29 
30 /*
31  * get_request(tbl, idx)
32  *
33  * Function:
34  *      Gets the idx'th request from the request table pointed to
35  *      by tbl.
36  * Arguments:
37  *      tbl (ss_request_table *)
38  *              pointer to request table
39  *      idx (int)
40  *              index into table
41  * Returns:
42  *      (ss_request_entry *)
43  *              pointer to request table entry
44  * Notes:
45  *      Has been replaced by a macro.
46  */
47 
48 #ifdef __SABER__
49 /* sigh.  saber won't deal with pointer-to-const-struct */
get_request(tbl,idx)50 static struct _ss_request_entry * get_request (tbl, idx)
51     ss_request_table * tbl;
52     int idx;
53 {
54     struct _ss_request_table *tbl1 = (struct _ss_request_table *) tbl;
55     struct _ss_request_entry *e = (struct _ss_request_entry *) tbl1->requests;
56     return e + idx;
57 }
58 #else
59 #define get_request(tbl,idx)    ((tbl) -> requests + (idx))
60 #endif
61 
62 /*
63  * check_request_table(rqtbl, argc, argv, sci_idx)
64  *
65  * Function:
66  *      If the command string in argv[0] is in the request table, execute
67  *      the commands and return error code 0.  Otherwise, return error
68  *      code ss_et_command_not_found.
69  * Arguments:
70  *      rqtbl (ss_request_table *)
71  *              pointer to request table
72  *      argc (int)
73  *              number of elements in argv[]
74  *      argv (char *[])
75  *              argument string array
76  *      sci_idx (int)
77  *              ss-internal index for subsystem control info structure
78  * Returns:
79  *      (int)
80  *              zero if command found, ss_et_command_not_found otherwise
81  * Notes:
82  */
83 
check_request_table(register ss_request_table * rqtbl,int argc,char * argv[],int sci_idx)84 static int check_request_table(register ss_request_table *rqtbl, int argc,
85 			       char *argv[], int sci_idx)
86 {
87 #ifdef __SABER__
88     struct _ss_request_entry *request;
89 #else
90     register ss_request_entry *request;
91 #endif
92     register ss_data *info;
93     register char const * const * name;
94     char *string = argv[0];
95     int i;
96 
97     info = ss_info(sci_idx);
98     info->argc = argc;
99     info->argv = argv;
100     for (i = 0; (request = get_request(rqtbl, i))->command_names; i++) {
101 	for (name = request->command_names; *name; name++)
102 	    if (!strcmp(*name, string)) {
103 		info->current_request = request->command_names[0];
104 		(request->function)(argc, (const char *const *) argv,
105 				    sci_idx,info->info_ptr);
106 		info->current_request = (char *)NULL;
107 		return(0);
108 	    }
109     }
110     return(SS_ET_COMMAND_NOT_FOUND);
111 }
112 
113 /*
114  * really_execute_command(sci_idx, argc, argv)
115  *
116  * Function:
117  *      Fills in the argc, argv values in the subsystem entry and
118  *      call the appropriate routine.
119  * Arguments:
120  *      sci_idx (int)
121  *              ss-internal index for subsystem control info structure
122  *      argc (int)
123  *              number of arguments in argument list
124  *      argv (char **[])
125  *              pointer to parsed argument list (may be reallocated
126  *              on abbrev expansion)
127  *
128  * Returns:
129  *      (int)
130  *              Zero if successful, ss_et_command_not_found otherwise.
131  * Notes:
132  */
133 
really_execute_command(int sci_idx,int argc,char ** argv[])134 static int really_execute_command(int sci_idx, int argc, char **argv[])
135 {
136     register ss_request_table **rqtbl;
137     register ss_data *info;
138 
139     info = ss_info(sci_idx);
140 
141     for (rqtbl = info->rqt_tables; *rqtbl; rqtbl++) {
142         if (check_request_table (*rqtbl, argc, *argv, sci_idx) == 0)
143             return(0);
144     }
145     return(SS_ET_COMMAND_NOT_FOUND);
146 }
147 
148 /*
149  * ss_execute_command(sci_idx, argv)
150  *
151  * Function:
152  *	Executes a parsed command list within the subsystem.
153  * Arguments:
154  *	sci_idx (int)
155  *		ss-internal index for subsystem control info structure
156  *	argv (char *[])
157  *		parsed argument list
158  * Returns:
159  *	(int)
160  *		Zero if successful, ss_et_command_not_found otherwise.
161  * Notes:
162  */
163 
ss_execute_command(int sci_idx,register char * argv[])164 int ss_execute_command(int sci_idx, register char *argv[])
165 {
166 	register int i, argc;
167 	char **argp;
168 
169 	argc = 0;
170 	for (argp = argv; *argp; argp++)
171 		argc++;
172 	argp = (char **)malloc((argc+1)*sizeof(char *));
173 	for (i = 0; i <= argc; i++)
174 		argp[i] = argv[i];
175 	i = really_execute_command(sci_idx, argc, &argp);
176 	free(argp);
177 	return(i);
178 }
179 
180 /*
181  * ss_execute_line(sci_idx, line_ptr)
182  *
183  * Function:
184  *      Parses and executes a command line within a subsystem.
185  * Arguments:
186  *      sci_idx (int)
187  *              ss-internal index for subsystem control info structure
188  *      line_ptr (char *)
189  *              Pointer to command line to be parsed.
190  * Returns:
191  *      (int)
192  *      	Error code.
193  * Notes:
194  */
195 
ss_execute_line(int sci_idx,char * line_ptr)196 int ss_execute_line(int sci_idx, char *line_ptr)
197 {
198     char **argv;
199     int argc, ret;
200 
201     /* flush leading whitespace */
202     while (line_ptr[0] == ' ' || line_ptr[0] == '\t')
203         line_ptr++;
204 
205     /* check if it should be sent to operating system for execution */
206     if (*line_ptr == '!') {
207         if (ss_info(sci_idx)->flags.escape_disabled)
208             return SS_ET_ESCAPE_DISABLED;
209         else {
210             line_ptr++;
211             return (system(line_ptr) < 0) ? errno : 0;
212         }
213     }
214 
215     /* parse it */
216     argv = ss_parse(sci_idx, line_ptr, &argc);
217     if (argc == 0) {
218 	free(argv);
219         return 0;
220     }
221 
222     /* look it up in the request tables, execute if found */
223     ret = really_execute_command (sci_idx, argc, &argv);
224 
225     free(argv);
226 
227     return(ret);
228 }
229