|  | @@ -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 |  }
 |