|
@@ -31,6 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
31
|
31
|
#include <ipxe/command.h>
|
32
|
32
|
#include <ipxe/parseopt.h>
|
33
|
33
|
#include <ipxe/settings.h>
|
|
34
|
+#include <ipxe/shell.h>
|
34
|
35
|
|
35
|
36
|
/** @file
|
36
|
37
|
*
|
|
@@ -38,15 +39,15 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
38
|
39
|
*
|
39
|
40
|
*/
|
40
|
41
|
|
41
|
|
-/** Shell exit flag */
|
42
|
|
-int shell_exit;
|
|
42
|
+/** Shell stop state */
|
|
43
|
+static int stop_state;
|
43
|
44
|
|
44
|
45
|
/**
|
45
|
46
|
* Execute command
|
46
|
47
|
*
|
47
|
48
|
* @v command Command name
|
48
|
49
|
* @v argv Argument list
|
49
|
|
- * @ret rc Command exit status
|
|
50
|
+ * @ret rc Return status code
|
50
|
51
|
*
|
51
|
52
|
* Execute the named command. Unlike a traditional POSIX execv(),
|
52
|
53
|
* this function returns the exit status of the command.
|
|
@@ -196,32 +197,22 @@ static int split_command ( char *command, char **tokens ) {
|
196
|
197
|
}
|
197
|
198
|
|
198
|
199
|
/**
|
199
|
|
- * Terminate command unconditionally
|
200
|
|
- *
|
201
|
|
- * @v rc Status of previous command
|
202
|
|
- * @ret terminate Terminate command
|
203
|
|
- */
|
204
|
|
-static int terminate_always ( int rc __unused ) {
|
205
|
|
- return 1;
|
206
|
|
-}
|
207
|
|
-
|
208
|
|
-/**
|
209
|
|
- * Terminate command only if previous command succeeded
|
|
200
|
+ * Process next command only if previous command succeeded
|
210
|
201
|
*
|
211
|
202
|
* @v rc Status of previous command
|
212
|
|
- * @ret terminate Terminate command
|
|
203
|
+ * @ret process Process next command
|
213
|
204
|
*/
|
214
|
|
-static int terminate_on_success ( int rc ) {
|
|
205
|
+static int process_on_success ( int rc ) {
|
215
|
206
|
return ( rc == 0 );
|
216
|
207
|
}
|
217
|
208
|
|
218
|
209
|
/**
|
219
|
|
- * Terminate command only if previous command failed
|
|
210
|
+ * Process next command only if previous command failed
|
220
|
211
|
*
|
221
|
212
|
* @v rc Status of previous command
|
222
|
|
- * @ret terminate Terminate command
|
|
213
|
+ * @ret process Process next command
|
223
|
214
|
*/
|
224
|
|
-static int terminate_on_failure ( int rc ) {
|
|
215
|
+static int process_on_failure ( int rc ) {
|
225
|
216
|
return ( rc != 0 );
|
226
|
217
|
}
|
227
|
218
|
|
|
@@ -229,54 +220,79 @@ static int terminate_on_failure ( int rc ) {
|
229
|
220
|
* Find command terminator
|
230
|
221
|
*
|
231
|
222
|
* @v tokens Token list
|
232
|
|
- * @ret terminator Terminator type
|
|
223
|
+ * @ret process_next "Should next command be processed?" function
|
233
|
224
|
* @ret argc Argument count
|
234
|
225
|
*/
|
235
|
226
|
static int command_terminator ( char **tokens,
|
236
|
|
- int ( **terminator ) ( int rc ) ) {
|
|
227
|
+ int ( **process_next ) ( int rc ) ) {
|
237
|
228
|
unsigned int i;
|
238
|
229
|
|
239
|
230
|
/* Find first terminating token */
|
240
|
231
|
for ( i = 0 ; tokens[i] ; i++ ) {
|
241
|
232
|
if ( tokens[i][0] == '#' ) {
|
242
|
233
|
/* Start of a comment */
|
243
|
|
- *terminator = terminate_always;
|
244
|
|
- return i;
|
|
234
|
+ break;
|
245
|
235
|
} else if ( strcmp ( tokens[i], "||" ) == 0 ) {
|
246
|
236
|
/* Short-circuit logical OR */
|
247
|
|
- *terminator = terminate_on_success;
|
|
237
|
+ *process_next = process_on_failure;
|
248
|
238
|
return i;
|
249
|
239
|
} else if ( strcmp ( tokens[i], "&&" ) == 0 ) {
|
250
|
240
|
/* Short-circuit logical AND */
|
251
|
|
- *terminator = terminate_on_failure;
|
|
241
|
+ *process_next = process_on_success;
|
252
|
242
|
return i;
|
253
|
243
|
}
|
254
|
244
|
}
|
255
|
245
|
|
256
|
246
|
/* End of token list */
|
257
|
|
- *terminator = terminate_always;
|
|
247
|
+ *process_next = NULL;
|
258
|
248
|
return i;
|
259
|
249
|
}
|
260
|
250
|
|
|
251
|
+/**
|
|
252
|
+ * Set shell stop state
|
|
253
|
+ *
|
|
254
|
+ * @v stop Shell stop state
|
|
255
|
+ */
|
|
256
|
+void shell_stop ( int stop ) {
|
|
257
|
+ stop_state = stop;
|
|
258
|
+}
|
|
259
|
+
|
|
260
|
+/**
|
|
261
|
+ * Test and consume shell stop state
|
|
262
|
+ *
|
|
263
|
+ * @v stop Shell stop state to consume
|
|
264
|
+ * @v stopped Shell had been stopped
|
|
265
|
+ */
|
|
266
|
+int shell_stopped ( int stop ) {
|
|
267
|
+ int stopped;
|
|
268
|
+
|
|
269
|
+ /* Test to see if we need to stop */
|
|
270
|
+ stopped = ( stop_state >= stop );
|
|
271
|
+
|
|
272
|
+ /* Consume stop state */
|
|
273
|
+ if ( stop_state <= stop )
|
|
274
|
+ stop_state = 0;
|
|
275
|
+
|
|
276
|
+ return stopped;
|
|
277
|
+}
|
|
278
|
+
|
261
|
279
|
/**
|
262
|
280
|
* Execute command line
|
263
|
281
|
*
|
264
|
282
|
* @v command Command line
|
265
|
|
- * @ret rc Command exit status
|
|
283
|
+ * @ret rc Return status code
|
266
|
284
|
*
|
267
|
285
|
* Execute the named command and arguments.
|
268
|
286
|
*/
|
269
|
287
|
int system ( const char *command ) {
|
270
|
|
- int ( * terminator ) ( int rc );
|
|
288
|
+ int ( * process_next ) ( int rc );
|
271
|
289
|
char *expcmd;
|
272
|
290
|
char **argv;
|
273
|
291
|
int argc;
|
274
|
292
|
int count;
|
|
293
|
+ int process;
|
275
|
294
|
int rc = 0;
|
276
|
295
|
|
277
|
|
- /* Reset exit flag */
|
278
|
|
- shell_exit = 0;
|
279
|
|
-
|
280
|
296
|
/* Perform variable expansion */
|
281
|
297
|
expcmd = expand_command ( command );
|
282
|
298
|
if ( ! expcmd )
|
|
@@ -291,23 +307,31 @@ int system ( const char *command ) {
|
291
|
307
|
|
292
|
308
|
split_command ( expcmd, tokens );
|
293
|
309
|
tokens[count] = NULL;
|
|
310
|
+ process = 1;
|
294
|
311
|
|
295
|
312
|
for ( argv = tokens ; ; argv += ( argc + 1 ) ) {
|
296
|
313
|
|
297
|
314
|
/* Find command terminator */
|
298
|
|
- argc = command_terminator ( argv, &terminator );
|
|
315
|
+ argc = command_terminator ( argv, &process_next );
|
299
|
316
|
|
300
|
317
|
/* Execute command */
|
301
|
|
- argv[argc] = NULL;
|
302
|
|
- rc = execv ( argv[0], argv );
|
|
318
|
+ if ( process ) {
|
|
319
|
+ argv[argc] = NULL;
|
|
320
|
+ rc = execv ( argv[0], argv );
|
|
321
|
+ }
|
303
|
322
|
|
304
|
|
- /* Check exit flag */
|
305
|
|
- if ( shell_exit )
|
|
323
|
+ /* Stop processing, if applicable */
|
|
324
|
+ if ( shell_stopped ( SHELL_STOP_COMMAND ) )
|
306
|
325
|
break;
|
307
|
326
|
|
308
|
|
- /* Handle terminator */
|
309
|
|
- if ( terminator ( rc ) )
|
|
327
|
+ /* Stop processing if we have reached the end
|
|
328
|
+ * of the command.
|
|
329
|
+ */
|
|
330
|
+ if ( ! process_next )
|
310
|
331
|
break;
|
|
332
|
+
|
|
333
|
+ /* Determine whether or not to process next command */
|
|
334
|
+ process = process_next ( rc );
|
311
|
335
|
}
|
312
|
336
|
}
|
313
|
337
|
|
|
@@ -322,7 +346,7 @@ int system ( const char *command ) {
|
322
|
346
|
*
|
323
|
347
|
* @v argc Argument count
|
324
|
348
|
* @v argv Argument list
|
325
|
|
- * @ret rc Exit code
|
|
349
|
+ * @ret rc Return status code
|
326
|
350
|
*/
|
327
|
351
|
static int echo_exec ( int argc, char **argv ) {
|
328
|
352
|
int i;
|
|
@@ -373,8 +397,8 @@ static int exit_exec ( int argc, char **argv ) {
|
373
|
397
|
return rc;
|
374
|
398
|
}
|
375
|
399
|
|
376
|
|
- /* Set exit flag */
|
377
|
|
- shell_exit = 1;
|
|
400
|
+ /* Stop shell processing */
|
|
401
|
+ shell_stop ( SHELL_STOP_COMMAND_SEQUENCE );
|
378
|
402
|
|
379
|
403
|
return exit_code;
|
380
|
404
|
}
|