示例#1
0
// Executes a <pipeline> rooted with cmd and returns the status of the last
// command executed.
int processPipeline(CMD* cmd)
{
    assert(cmd);
    assert(ISPIPE(cmd->type) || cmd->type == SIMPLE || cmd->type == SUBCMD);
    
    if(ISPIPE(cmd->type))
    {
        int pipeStatus = execPipe(cmd);
        updateStatusVar(pipeStatus);
        return pipeStatus;
    }
    else
    {
        return processStage(cmd);
    }
}
示例#2
0
/*
use: process a <pipeline>
args: 
	cmd 	= root of command tree
	fdin 	= input file descriptor
return: status of process
*/
int processPipe(CMD *cmd, int fdin, bool suppress) {

	int status;			// status of process

	// <stage> | <pipeline> case
	if (cmd->type == PIPE) {

		int fd[2];		// file descriptors
		
		// build the pipe
		if (pipe(fd) == -1) {
			status = errno;
			errorExit(status);
		}

		// built-in command
		if (isSpecial(cmd->left)) {
			processSpecial(cmd->left, true);
			status = processPipe(cmd->right, fd[0], true);
			return setStat(status);
		}

		pid_t pID = fork();		// process ID of fork

		// error check
		if (pID < 0) {
			status = errno;
			errorExit(status);
		}
		// child process
		else if (pID == 0) {

			// update input
			if (fdin != 0) {
				dup2(fdin, 0);
				close(fdin);
			}
			
			// update output
			close(fd[0]);
			dup2(fd[1], 1);
			close(fd[1]);

			// left side of pipe
			status = processStage(cmd->left);
		}
		// parent process
		else {
			
			// close file descriptors
			if (fdin != 0) {
				close(fdin);
			}
			close(fd[1]);

			// right side of pipe
			int temp = processPipe(cmd->right, fd[0], true);

			// close last file descriptor
			close(fd[0]);

			// wait for child process to finish
			(void) signal(SIGINT, SIG_IGN);
			waitpid(pID, &status, 0);

			// update status
			if (status == 0) {
				status = temp;
			}
			else {
				status = (WIFEXITED(status) ? WEXITSTATUS(status) : 
					128+WTERMSIG(status));
			}
			(void) signal(SIGINT, SIG_DFL);
		}

	}
	// <stage> case
	else {

		// built-in command
		if (isSpecial(cmd)) {
			if (suppress) {
				status = processSpecial(cmd, true);
			}
			else {
				status = processSpecial(cmd, false);
			}
			return setStat(status);
		}

		pid_t pID = fork();		// process ID of fork

		// error check
		if (pID < 0) {
			status = errno;
			errorExit(status);
		}
		// child process
		else if (pID == 0) {
			
			// update input
			if (fdin != 0) {
				dup2(fdin, 0);
				close(fdin);
			}

			status = processStage(cmd);
		}
		// parent process
		else {

			//close input
			if (fdin != 0) {
				close(fdin);
			}

			// wait for child process to finish
			(void) signal(SIGINT, SIG_IGN);
			waitpid(pID, &status, 0);

			// update status
			status = (WIFEXITED(status) ? WEXITSTATUS(status) : 
				128+WTERMSIG(status));
			(void) signal(SIGINT, SIG_DFL);
		}
	}

	return setStat(status);
}
示例#3
0
char SWBasicFilter::processText(std::string &text, const SWKey *key, const SWModule *module) {
    char *from;
    char token[4096];
    int tokpos = 0;
    bool intoken = false;
    bool inEsc = false;
    int escStartPos = 0, escEndPos = 0;
    int tokenStartPos = 0, tokenEndPos = 0;
    std::string lastTextNode;
    BasicFilterUserData *userData = createUserData(module, key);

    std::string orig = text;
    from = &orig[0u];
    text = "";

    if (processStages & INITIALIZE) {
        if (processStage(INITIALIZE, text, from, userData)) {    // processStage handled it all
            delete userData;
            return 0;
        }
    }

    for (;*from; from++) {

        if (processStages & PRECHAR) {
            if (processStage(PRECHAR, text, from, userData))    // processStage handled this char
                continue;
        }

        if (*from == tokenStart[tokenStartPos]) {
            if (tokenStartPos == (tokenStartLen - 1)) {
                intoken = true;
                tokpos = 0;
                token[0] = 0;
                token[1] = 0;
                token[2] = 0;
                inEsc = false;
            }
            else tokenStartPos++;
            continue;
        }

        if (*from == escStart[escStartPos]) {
            if (escStartPos == (escStartLen - 1)) {
                intoken = true;
                tokpos = 0;
                token[0] = 0;
                token[1] = 0;
                token[2] = 0;
                inEsc = true;
            }
            else escStartPos++;
            continue;
        }

        if (inEsc) {
            if (*from == escEnd[escEndPos]) {
                if (escEndPos == (escEndLen - 1)) {
                    intoken = inEsc = false;
                    userData->lastTextNode = lastTextNode;

                    if (!userData->suspendTextPassThru)  { //if text through is disabled no tokens should pass, too
                        if ((!handleEscapeString(text, token, userData)) && (passThruUnknownEsc)) {
                            appendEscapeString(text, token);
                        }
                    }
                    escEndPos = escStartPos = tokenEndPos = tokenStartPos = 0;
                    lastTextNode = "";
                    continue;
                }
            }
        }

        if (!inEsc) {
            if (*from == tokenEnd[tokenEndPos]) {
                if (tokenEndPos == (tokenEndLen - 1)) {
                    intoken = false;
                    userData->lastTextNode = lastTextNode;
                    if ((!handleToken(text, token, userData)) && (passThruUnknownToken)) {
                        text += tokenStart;
                        text += token;
                        text += tokenEnd;
                    }
                    escEndPos = escStartPos = tokenEndPos = tokenStartPos = 0;
                    lastTextNode = "";
                    continue;
                }
            }
        }

        if (intoken) {
            if (tokpos < 4090) {
                token[tokpos++] = *from;
                token[tokpos+2] = 0;
            }
        }
        else {
             if ((!userData->supressAdjacentWhitespace) || (*from != ' ')) {
                if (!userData->suspendTextPassThru) {
                    text.push_back(*from);
                    userData->lastSuspendSegment.clear();
                }
                else    userData->lastSuspendSegment.push_back(*from);
                lastTextNode.push_back(*from);
             }
            userData->supressAdjacentWhitespace = false;
        }

        if (processStages & POSTCHAR)
            processStage(POSTCHAR, text, from, userData);

    }

    if (processStages & FINALIZE)
        processStage(FINALIZE, text, from, userData);

    delete userData;
    return 0;
}
示例#4
0
// Executes a pipeline and returns the exit status of the pipe. The arg
// pipeRoot is the PIPE or PIPE_ERR command at the root of the pipeline.
// This function draws upon code from Professor Stan Eisenstat at Yale
// University
int execPipe(CMD* pipeRoot)
{
    // count the number of stages in the pipeline
    int numStages = 1;
    for(CMD* cmd = pipeRoot; ISPIPE(cmd->type); cmd = cmd->right, numStages++);
    
    // create table to hold pid and exit status of all stages in the pipe
    struct {
        int pid, status;
    } processTable[numStages];
    
    int fd[2];             // holds file descriptors for the pipe
    int pid, status;       //   the pid and status of a single stage
    int fdIn = STDIN_FD;   //   the read end of the last pipe, or the original
                           //   stdin
    
    CMD* cmd = pipeRoot;
    for(int i = 0; ISPIPE(cmd->type); cmd = cmd->right, i++)
    {
        if(pipe(fd) < 0 || (pid = fork()) < 0)
        {
            perror(EXEC_NAME);
            return errno;
        }
        else if(pid == 0)
        {
            // child
            close(fd[0]);
            
            // redirect stdin to the last pipe read (if there was a last pipe)
            if(fdIn != STDIN_FD)
            {
                dup2(fdIn, STDIN_FD);
                close(fdIn);
            }
            
            bool shouldCloseFD1 = false;
            // redirect stdout to the new pipe write (if it's not stdout)
            if(fd[1] != STDOUT_FD)
            {
                dup2(fd[1], STDOUT_FD);
                shouldCloseFD1 = true;
            }
            
            // if this is a PIPE_ERR, redirect stderr to the new pipe write
            // (if it's not stderr)
            if(cmd->type == PIPE_ERR && fd[1] != STDERR_FD)
            {
                dup2(fd[1], STDERR_FD);
                shouldCloseFD1 = true;
            }
            
            if(shouldCloseFD1) close(fd[1]);
            
            exit(processStage(cmd->left));
        }
        else
        {
            // parent
            processTable[i].pid = pid;
            
            // close the read end of the last pipe if it's not the orig stdin
            if(i > 0)
            {
                close(fdIn);
            }
            
            fdIn = fd[0]; // remember the read end of the new pipe
            close(fd[1]);
        }
    }
    // cmd is now the right child of last PIPE or PIPE_ERR, the last stage of
    // the pipeline
    
    // if the last stage is a built-in command, it should affect the parent
    // shell, so execute it here instead of forking off a process
    if(cmd->type == SIMPLE && IS_BUILTIN(cmd->argv[0]))
    {
        processTable[numStages - 1].pid = -1; // unused pid
        processTable[numStages - 1].status = processSimple(cmd, false);
        close(fdIn);
    }
    else if((pid = fork()) < 0)
    {
        perror(EXEC_NAME);
        return errno;
    }
    else if(pid == 0)
    {
        // child
        if(fdIn != STDIN_FD)
        {
            dup2(fdIn, STDIN_FD);
            close(fdIn);
        }
        exit(processStage(cmd));
    }
    else
    {
        // parent
        processTable[numStages - 1].pid = pid;
        close(fdIn);
    }
    
    // wait for children to die
    signal(SIGINT, SIG_IGN);
    for(int i = 0; i < numStages; )
    {
        pid = wait(&status);
        int j;
        for(j = 0; j < numStages && processTable[j].pid != pid; j++);
        
        // only add to the processTable if the child's pid is in the table;
        // that is, ignore zombies
        if(j < numStages)
        {
            processTable[j].status = status;
            i++;
        }
    }
    signal(SIGINT, SIG_DFL);
    
    for(int i = 0; i < numStages; i++)
    {
        if(GET_STATUS(processTable[i].status) != 0)
        {
            return GET_STATUS(processTable[i].status);
        }
    }
    return 0;
}