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(rqtbl,argc,argv,sci_idx)84 static int check_request_table (rqtbl, argc, argv, sci_idx)
85 register ss_request_table *rqtbl;
86 int argc;
87 char *argv[];
88 int sci_idx;
89 {
90 #ifdef __SABER__
91 struct _ss_request_entry *request;
92 #else
93 register ss_request_entry *request;
94 #endif
95 register ss_data *info;
96 register char const * const * name;
97 char *string = argv[0];
98 int i;
99
100 info = ss_info(sci_idx);
101 info->argc = argc;
102 info->argv = argv;
103 for (i = 0; (request = get_request(rqtbl, i))->command_names; i++) {
104 for (name = request->command_names; *name; name++)
105 if (!strcmp(*name, string)) {
106 info->current_request = request->command_names[0];
107 (request->function)(argc, (const char *const *) argv,
108 sci_idx,info->info_ptr);
109 info->current_request = (char *)NULL;
110 return(0);
111 }
112 }
113 return(SS_ET_COMMAND_NOT_FOUND);
114 }
115
116 /*
117 * really_execute_command(sci_idx, argc, argv)
118 *
119 * Function:
120 * Fills in the argc, argv values in the subsystem entry and
121 * call the appropriate routine.
122 * Arguments:
123 * sci_idx (int)
124 * ss-internal index for subsystem control info structure
125 * argc (int)
126 * number of arguments in argument list
127 * argv (char **[])
128 * pointer to parsed argument list (may be reallocated
129 * on abbrev expansion)
130 *
131 * Returns:
132 * (int)
133 * Zero if successful, ss_et_command_not_found otherwise.
134 * Notes:
135 */
136
really_execute_command(sci_idx,argc,argv)137 static int really_execute_command (sci_idx, argc, argv)
138 int sci_idx;
139 int argc;
140 char **argv[];
141 {
142 register ss_request_table **rqtbl;
143 register ss_data *info;
144
145 info = ss_info(sci_idx);
146
147 for (rqtbl = info->rqt_tables; *rqtbl; rqtbl++) {
148 if (check_request_table (*rqtbl, argc, *argv, sci_idx) == 0)
149 return(0);
150 }
151 return(SS_ET_COMMAND_NOT_FOUND);
152 }
153
154 /*
155 * ss_execute_command(sci_idx, argv)
156 *
157 * Function:
158 * Executes a parsed command list within the subsystem.
159 * Arguments:
160 * sci_idx (int)
161 * ss-internal index for subsystem control info structure
162 * argv (char *[])
163 * parsed argument list
164 * Returns:
165 * (int)
166 * Zero if successful, ss_et_command_not_found otherwise.
167 * Notes:
168 */
169
ss_execute_command(sci_idx,argv)170 int ss_execute_command(sci_idx, argv)
171 int sci_idx;
172 register char *argv[];
173 {
174 register int i, argc;
175 char **argp;
176
177 argc = 0;
178 for (argp = argv; *argp; argp++)
179 argc++;
180 argp = (char **)malloc((argc+1)*sizeof(char *));
181 for (i = 0; i <= argc; i++)
182 argp[i] = argv[i];
183 i = really_execute_command(sci_idx, argc, &argp);
184 free(argp);
185 return(i);
186 }
187
188 /*
189 * ss_execute_line(sci_idx, line_ptr)
190 *
191 * Function:
192 * Parses and executes a command line within a subsystem.
193 * Arguments:
194 * sci_idx (int)
195 * ss-internal index for subsystem control info structure
196 * line_ptr (char *)
197 * Pointer to command line to be parsed.
198 * Returns:
199 * (int)
200 * Error code.
201 * Notes:
202 */
203
ss_execute_line(sci_idx,line_ptr)204 int ss_execute_line (sci_idx, line_ptr)
205 int sci_idx;
206 char *line_ptr;
207 {
208 char **argv;
209 int argc, ret;
210
211 /* flush leading whitespace */
212 while (line_ptr[0] == ' ' || line_ptr[0] == '\t')
213 line_ptr++;
214
215 /* check if it should be sent to operating system for execution */
216 if (*line_ptr == '!') {
217 if (ss_info(sci_idx)->flags.escape_disabled)
218 return SS_ET_ESCAPE_DISABLED;
219 else {
220 line_ptr++;
221 return (system(line_ptr) < 0) ? errno : 0;
222 }
223 }
224
225 /* parse it */
226 argv = ss_parse(sci_idx, line_ptr, &argc);
227 if (argc == 0) {
228 free(argv);
229 return 0;
230 }
231
232 /* look it up in the request tables, execute if found */
233 ret = really_execute_command (sci_idx, argc, &argv);
234
235 free(argv);
236
237 return(ret);
238 }
239