execcmd.c source code

/*********************************************************************
* executeCmdLine parses a command line into its individual pipeline
* elements.  It creates a pipe to connect each intermediate member of
* the pipeline to its successor and forks children to exec the
* individual pipeline elements.   The executeCmdLine function should
* never return.  It handles all errors by calling exit(1).
*********************************************************************/

#include "ush.h"

void executeCmdLine(char *incmd)
{
    char **chargv;
    pid_t child_pid;
    char *cmd;
    char *nextcmd;
    int frontfd[2];
    int backfd[2];

    frontfd[0] = -1;
    frontfd[1] = -1;
    backfd[0] = -1;
    backfd[1] = -1;

    child_pid = 0;
    if ((nextcmd = incmd) == NULL)
	exit(1);

    for (;;) 
    {
	cmd = nextcmd;
	if (cmd == NULL) break;
        
	/* if last in pipeline, do not fork another */
	if ((nextcmd = strchr(nextcmd, PIPE_SYMBOL)) == NULL) 
	{
	    backfd[1] = -1;
	    child_pid = 0;
	}  
	else 
	{
    	    /* fork a child to execute next pipeline command */
	    *nextcmd = NULL_SYMBOL;
	    nextcmd++;
	    if (pipe(backfd)== -1) 
	    {
		perror("Could not create back pipe");
    		exit(1);
	    } 
	    else 
		if ((child_pid = fork()) == -1) 
		{
		    perror("Could not fork next child");
		    exit(1);
		}
	}
	if (child_pid == 0) 
	{
	    /* the child execs the command */
	    if (connectPipeLine(cmd, frontfd, backfd) == -1) 
	    {
		perror("Could not connect to pipeline");
    		exit(1);
	    } 
	    else 
		if (makeargv(cmd, BLANK_STRING, &chargv) > 0) 
		{
		    if (execvp(chargv[0], chargv) == -1)
    			perror("Invalid command");
		}
	    exit(1);
	}
	/* the parent closes front pipe and makes back pipe, front */
	close(frontfd[0]);
	close(frontfd[1]);
	frontfd[0] = backfd[0];
	frontfd[1] = backfd[1];
    }   
    close(backfd[0]);
    close(backfd[1]);
    exit(1);
}