@@ -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
}
0 commit comments