1/*  *********************************************************************
2    *  Broadcom Common Firmware Environment (CFE)
3    *
4    *  UI Command Dispatch			File: ui_cmddisp.c
5    *
6    *  This module contains routines to maintain the command table,
7    *  parse and execute commands
8    *
9    *  Author:  Mitch Lichtenberg
10    *
11    *********************************************************************
12    *
13    *  Copyright 2000,2001,2002,2003
14    *  Broadcom Corporation. All rights reserved.
15    *
16    *  This software is furnished under license and may be used and
17    *  copied only in accordance with the following terms and
18    *  conditions.  Subject to these conditions, you may download,
19    *  copy, install, use, modify and distribute modified or unmodified
20    *  copies of this software in source and/or binary form.  No title
21    *  or ownership is transferred hereby.
22    *
23    *  1) Any source code used, modified or distributed must reproduce
24    *     and retain this copyright notice and list of conditions
25    *     as they appear in the source file.
26    *
27    *  2) No right is granted to use any trade name, trademark, or
28    *     logo of Broadcom Corporation.  The "Broadcom Corporation"
29    *     name may not be used to endorse or promote products derived
30    *     from this software without the prior written permission of
31    *     Broadcom Corporation.
32    *
33    *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
34    *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
35    *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
36    *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
37    *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
38    *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
39    *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
40    *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
41    *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
42    *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
43    *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
44    *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
45    *     THE POSSIBILITY OF SUCH DAMAGE.
46    ********************************************************************* */
47
48
49#include <stdarg.h>
50
51#include "cfe.h"
52#include "lib_try.h"
53#include "env_subr.h"
54#include "ui_command.h"
55
56/*  *********************************************************************
57    *  Types
58    ********************************************************************* */
59
60
61/*  *********************************************************************
62    *  Globals
63    ********************************************************************* */
64
65static jmp_buf ui_jmpbuf;		/* for getting control in exceptions */
66
67/*  *********************************************************************
68    *  ui_errstring(errcode)
69    *
70    *  Return a string that corresponds to a CFE error code
71    *
72    *  Input parameters:
73    *  	   errcode - code to translate
74    *
75    *  Return value:
76    *  	   string describing error code
77    ********************************************************************* */
78
79const char *ui_errstring(int errcode)
80{
81    return cfe_errortext(errcode);
82}
83
84
85/*  *********************************************************************
86    *  ui_showerror(errcode,tmplt,...)
87    *
88    *  printf-like function to display a CFE error code along with
89    *  other information.  Works sort of like 'perror'.  You can
90    *  return the value passed to this routine to a CFE UI handler
91    *  since it returns its input.
92    *
93    *  Input parameters:
94    *  	   errcode - CFE error code
95    *  	   tmplt,... - printf parameters
96    *
97    *  Return value:
98    *  	   errcode
99    ********************************************************************* */
100
101int ui_showerror(int errcode,char *tmplt,...)
102{
103    va_list marker;
104
105    va_start(marker,tmplt);
106    xvprintf(tmplt,marker);
107    va_end(marker);
108    xprintf(": %s\n",ui_errstring(errcode));
109
110    return errcode;
111}
112
113
114/*  *********************************************************************
115    *  ui_do_one_command(head)
116    *
117    *  Process one CLI command from a command queue
118    *
119    *  Input parameters:
120    *  	   head - queue of commands
121    *
122    *  Return value:
123    *  	   return value from CFE UI function
124    ********************************************************************* */
125
126
127static int ui_do_one_command(queue_t *head)
128{
129    int res;
130    ui_cmdline_t cmd;
131
132    res = cmd_lookup(head, &cmd);
133
134    if (res == 0) {
135
136	res = cmd_sw_validate(&cmd,cmd.switches);
137	if (res != -1) {
138	    xprintf("Invalid switch: %s\n",
139		    cmd_sw_name(&cmd,res));
140	    return CFE_ERR_INV_PARAM;
141	    }
142
143	if (lib_setjmp(ui_jmpbuf) != 0) return -1;
144	res = (*cmd.func)(&cmd,cmd.argc-cmd.argidx,
145		    &(cmd.argv[cmd.argidx]));
146	}
147    cmd_free(&cmd);
148    return res;
149}
150
151
152/*  *********************************************************************
153    *  ui_restart(arg)
154    *
155    *  Restart the command interpreter -- can be called if you get
156    *  deep inside a UI routine and want to bail out.
157    *
158    *  Input parameters:
159    *  	   arg - value to return from ui_do_one_command
160    *
161    *  Return value:
162    *  	   nothing
163    ********************************************************************* */
164
165void ui_restart(int arg)
166{
167    if (arg == 0) arg = -1;
168
169    lib_longjmp(ui_jmpbuf,arg);
170}
171
172/*  *********************************************************************
173    *  ui_init_cmddisp()
174    *
175    *  Initialize the command dispatcher.
176    *
177    *  Input parameters:
178    *  	   nothing
179    *
180    *  Return value:
181    *  	   0
182    ********************************************************************* */
183
184int ui_init_cmddisp(void)
185{
186    cmd_init();
187
188    return 0;
189}
190
191/*  *********************************************************************
192    *  ui_showusage(cmd)
193    *
194    *  Display the usage for a command, given a command line
195    *  structure
196    *
197    *  Input parameters:
198    *  	   cmd - command line structure (typically passed in from
199    *  	         the command interpreter)
200    *
201    *  Return value:
202    *  	   CFE_ERR_INV_COMMAND
203    ********************************************************************* */
204
205int ui_showusage(ui_cmdline_t *cmd)
206{
207    cmd_showusage(cmd);
208
209    return CFE_ERR_INV_COMMAND;
210}
211
212
213/*  *********************************************************************
214    *  ui_docommands_internal(head)
215    *
216    *  Process (possibly multiple) commands from a list of tokens
217    *
218    *  Input parameters:
219    *  	   buf - buffer
220    *
221    *  Return value:
222    *  	   exit status of first command that failed, or null
223    ********************************************************************* */
224static int ui_docommands_internal(queue_t *head)
225{
226    queue_t cmdqueue;
227    ui_command_t *cmd;
228    int status = CMD_ERR_BLANK;
229    int term;
230
231    q_init(&cmdqueue);
232
233    /*
234     * Find all the individual commands
235     */
236
237    while ((cmd = cmd_readcommand(head))) {
238
239	if (cmd == NULL) {
240	    return CMD_ERR_BLANK;
241	    }
242
243	q_enqueue(&cmdqueue,(queue_t *) cmd);
244	}
245
246    /*
247     * Do each command
248     */
249
250    while ((cmd = (ui_command_t *) q_deqnext(&(cmdqueue)))) {
251	status = ui_do_one_command(&(cmd->head));
252	term = cmd->term;
253	KFREE(cmd);
254	if (status == CMD_ERR_BLANK) continue;
255
256	/*
257	 * And causes us to stop at the first failure.
258	 */
259	if ((term == CMD_TERM_AND) && (status != 0)) break;
260
261	/*
262	 * OR causes us to stop at the first success.
263	 */
264
265	if ((term == CMD_TERM_OR) && (status == 0)) break;
266
267	/*
268	 * Neither AND nor OR causes us to keep chugging away.
269	 */
270	}
271
272    /*
273     * Free any remaining tokens and commands that we did not do
274     */
275
276    while ((cmd = (ui_command_t *) q_deqnext(&(cmdqueue)))) {
277	cmd_free_tokens(&(cmd->head));
278	KFREE(cmd);
279	}
280
281    return status;
282}
283
284
285/*  *********************************************************************
286    *  ui_docommands(str)
287    *
288    *  Do one or more commands.  This is the main UI function.
289    *
290    *  Input parameters:
291    *  	   str - command string
292    *
293    *  Return value:
294    *  	   return value of failing command, or 0 if all commands
295    *  	   succeeded
296    ********************************************************************* */
297
298int ui_docommands(char *str)
299{
300    queue_t cmd_list;
301    int res;
302
303    /* Convert the command into a token list */
304    cmd_build_list(&cmd_list,str);
305
306    /* Walk the list and expand environment variables */
307    cmd_walk_and_expand(&cmd_list);
308
309    /* Process each command.  This removes tokens from the list */
310    res = ui_docommands_internal(&cmd_list);
311
312    /* Free any leftover tokens.  There should not be any. */
313    cmd_free_tokens(&cmd_list);
314
315    return res;
316}
317