@@ -216,6 +216,45 @@ int shell_stopped ( int stop ) {
216216 return stopped ;
217217}
218218
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+
219258/**
220259 * Execute command line
221260 *
@@ -225,58 +264,63 @@ int shell_stopped ( int stop ) {
225264 * Execute the named command and arguments.
226265 */
227266int system ( const char * command ) {
267+ int count = split_command ( ( char * ) command , NULL );
268+ char * all_tokens [ count + 1 ];
228269 int ( * process_next ) ( int rc );
229- char * expcmd ;
230- char * * argv ;
270+ char * command_copy ;
271+ char * * tokens ;
231272 int argc ;
232- int count ;
233273 int process ;
234274 int rc = 0 ;
235275
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 )
239279 return - ENOMEM ;
240280
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 ;
251284
252- for ( argv = tokens ; ; argv += ( argc + 1 ) ) {
285+ /* Process individual commands */
286+ process = 1 ;
287+ for ( tokens = all_tokens ; ; tokens += ( argc + 1 ) ) {
253288
254- /* Find command terminator */
255- argc = command_terminator ( argv , & process_next );
289+ /* Find command terminator */
290+ argc = command_terminator ( tokens , & process_next );
256291
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 ];
262295
263- /* Stop processing, if applicable */
264- if ( shell_stopped ( SHELL_STOP_COMMAND ) )
296+ /* Expand tokens */
297+ if ( ( rc = expand_tokens ( argc , tokens , argv ) ) != 0 )
265298 break ;
299+ argv [argc ] = NULL ;
266300
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 );
272303
273- /* Determine whether or not to process next command */
274- process = process_next ( rc );
304+ /* Free tokens */
305+ free_tokens ( argv );
275306 }
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 );
276320 }
277321
278- /* Free expanded command */
279- free ( expcmd );
322+ /* Free modified copy of command */
323+ free ( command_copy );
280324
281325 return rc ;
282326}
0 commit comments