|
@@ -216,6 +216,45 @@ int shell_stopped ( int stop ) {
|
216
|
216
|
return stopped;
|
217
|
217
|
}
|
218
|
218
|
|
|
219
|
+/**
|
|
220
|
+ * Expand settings within a token list
|
|
221
|
+ *
|
|
222
|
+ * @v argc Argument count
|
|
223
|
+ * @v tokens Token list
|
|
224
|
+ * @v argv Argument list to fill in
|
|
225
|
+ * @ret rc Return status code
|
|
226
|
+ */
|
|
227
|
+static int expand_tokens ( int argc, char **tokens, char **argv ) {
|
|
228
|
+ int i;
|
|
229
|
+
|
|
230
|
+ /* Expand each token in turn */
|
|
231
|
+ for ( i = 0 ; i < argc ; i++ ) {
|
|
232
|
+ argv[i] = expand_settings ( tokens[i] );
|
|
233
|
+ if ( ! argv[i] )
|
|
234
|
+ goto err_expand_settings;
|
|
235
|
+ }
|
|
236
|
+
|
|
237
|
+ return 0;
|
|
238
|
+
|
|
239
|
+ err_expand_settings:
|
|
240
|
+ assert ( argv[i] == NULL );
|
|
241
|
+ for ( ; i >= 0 ; i-- )
|
|
242
|
+ free ( argv[i] );
|
|
243
|
+ return -ENOMEM;
|
|
244
|
+}
|
|
245
|
+
|
|
246
|
+/**
|
|
247
|
+ * Free an expanded token list
|
|
248
|
+ *
|
|
249
|
+ * @v argv Argument list
|
|
250
|
+ */
|
|
251
|
+static void free_tokens ( char **argv ) {
|
|
252
|
+
|
|
253
|
+ /* Free each expanded argument */
|
|
254
|
+ while ( *argv )
|
|
255
|
+ free ( *(argv++) );
|
|
256
|
+}
|
|
257
|
+
|
219
|
258
|
/**
|
220
|
259
|
* Execute command line
|
221
|
260
|
*
|
|
@@ -225,58 +264,63 @@ int shell_stopped ( int stop ) {
|
225
|
264
|
* Execute the named command and arguments.
|
226
|
265
|
*/
|
227
|
266
|
int system ( const char *command ) {
|
|
267
|
+ int count = split_command ( ( char * ) command, NULL );
|
|
268
|
+ char *all_tokens[ count + 1 ];
|
228
|
269
|
int ( * process_next ) ( int rc );
|
229
|
|
- char *expcmd;
|
230
|
|
- char **argv;
|
|
270
|
+ char *command_copy;
|
|
271
|
+ char **tokens;
|
231
|
272
|
int argc;
|
232
|
|
- int count;
|
233
|
273
|
int process;
|
234
|
274
|
int rc = 0;
|
235
|
275
|
|
236
|
|
- /* Perform variable expansion */
|
237
|
|
- expcmd = expand_settings ( command );
|
238
|
|
- if ( ! expcmd )
|
|
276
|
+ /* Create modifiable copy of command */
|
|
277
|
+ command_copy = strdup ( command );
|
|
278
|
+ if ( ! command_copy )
|
239
|
279
|
return -ENOMEM;
|
240
|
280
|
|
241
|
|
- /* Count tokens */
|
242
|
|
- count = split_command ( expcmd, NULL );
|
243
|
|
-
|
244
|
|
- /* Create token array */
|
245
|
|
- if ( count ) {
|
246
|
|
- char * tokens[count + 1];
|
247
|
|
-
|
248
|
|
- split_command ( expcmd, tokens );
|
249
|
|
- tokens[count] = NULL;
|
250
|
|
- process = 1;
|
|
281
|
+ /* Split command into tokens */
|
|
282
|
+ split_command ( command_copy, all_tokens );
|
|
283
|
+ all_tokens[count] = NULL;
|
251
|
284
|
|
252
|
|
- for ( argv = tokens ; ; argv += ( argc + 1 ) ) {
|
|
285
|
+ /* Process individual commands */
|
|
286
|
+ process = 1;
|
|
287
|
+ for ( tokens = all_tokens ; ; tokens += ( argc + 1 ) ) {
|
253
|
288
|
|
254
|
|
- /* Find command terminator */
|
255
|
|
- argc = command_terminator ( argv, &process_next );
|
|
289
|
+ /* Find command terminator */
|
|
290
|
+ argc = command_terminator ( tokens, &process_next );
|
256
|
291
|
|
257
|
|
- /* Execute command */
|
258
|
|
- if ( process ) {
|
259
|
|
- argv[argc] = NULL;
|
260
|
|
- rc = execv ( argv[0], argv );
|
261
|
|
- }
|
|
292
|
+ /* Expand tokens and execute command */
|
|
293
|
+ if ( process ) {
|
|
294
|
+ char *argv[ argc + 1 ];
|
262
|
295
|
|
263
|
|
- /* Stop processing, if applicable */
|
264
|
|
- if ( shell_stopped ( SHELL_STOP_COMMAND ) )
|
|
296
|
+ /* Expand tokens */
|
|
297
|
+ if ( ( rc = expand_tokens ( argc, tokens, argv ) ) != 0)
|
265
|
298
|
break;
|
|
299
|
+ argv[argc] = NULL;
|
266
|
300
|
|
267
|
|
- /* Stop processing if we have reached the end
|
268
|
|
- * of the command.
|
269
|
|
- */
|
270
|
|
- if ( ! process_next )
|
271
|
|
- break;
|
|
301
|
+ /* Execute command */
|
|
302
|
+ rc = execv ( argv[0], argv );
|
272
|
303
|
|
273
|
|
- /* Determine whether or not to process next command */
|
274
|
|
- process = process_next ( rc );
|
|
304
|
+ /* Free tokens */
|
|
305
|
+ free_tokens ( argv );
|
275
|
306
|
}
|
|
307
|
+
|
|
308
|
+ /* Stop processing, if applicable */
|
|
309
|
+ if ( shell_stopped ( SHELL_STOP_COMMAND ) )
|
|
310
|
+ break;
|
|
311
|
+
|
|
312
|
+ /* Stop processing if we have reached the end of the
|
|
313
|
+ * command.
|
|
314
|
+ */
|
|
315
|
+ if ( ! process_next )
|
|
316
|
+ break;
|
|
317
|
+
|
|
318
|
+ /* Determine whether or not to process next command */
|
|
319
|
+ process = process_next ( rc );
|
276
|
320
|
}
|
277
|
321
|
|
278
|
|
- /* Free expanded command */
|
279
|
|
- free ( expcmd );
|
|
322
|
+ /* Free modified copy of command */
|
|
323
|
+ free ( command_copy );
|
280
|
324
|
|
281
|
325
|
return rc;
|
282
|
326
|
}
|