// Executes an <and-or> rooted with cmd and returns the status of the last // command executed. int processAndOr(CMD* cmd) { assert(cmd); assert(cmd->type != SEP_BG && cmd->type != SEP_END); int lastStatus = 0; // status of last command executed if(cmd->type == SEP_AND) { if((lastStatus = processPipeline(cmd->left)) == 0) { lastStatus = processAndOr(cmd->right); } } else if(cmd->type == SEP_OR) { if((lastStatus = processPipeline(cmd->left)) != 0) { lastStatus = processAndOr(cmd->right); } } else { lastStatus = processPipeline(cmd); } return lastStatus; }
/* use: process an <and-or> args: cmd = root of command tree status = status of process skip = greedy flag return: status of process */ int processAndOr(CMD* cmd, int status, bool skip) { // <pipeline> && <and-or> case if (cmd->type == SEP_AND) { // left child if (!skip) { status = processPipe(cmd->left, 0, false); } // if left child is true, do right if (status == 0) { status = processAndOr(cmd->right, status, false); } else { status = processAndOr(cmd->right, status, true); } } // <pipeline> || <and-or> case else if (cmd->type == SEP_OR) { // left child if (!skip) { status = processPipe(cmd->left, 0, false); } // if left child is false, do right if (status != 0) { status = processAndOr(cmd->right, status, false); } else { status = processAndOr(cmd->right, status, true); } } // <pipeline> case else { if (!skip) { status = processPipe(cmd, 0, false); } } return status; }
int process(CMD* cmd) { if(!cmd) return 0; int zombieStatus; // never used after passing to waitpid while(waitpid(-1, &zombieStatus, WNOHANG) > 0); // reap zombie processes int exitStatus; if(cmd->type == SEP_BG) { if(cmd->left->type == SIMPLE) { processSimple(cmd->left, true); } else { processSubcommand(cmd->left, NULL, true); } exitStatus = process(cmd->right); // cmd->right may be NULL } else if(cmd->type == SEP_END) { if(!cmd->right) { exitStatus = processAndOr(cmd->left); } else { processAndOr(cmd->left); exitStatus = process(cmd->right); } } else { exitStatus = processAndOr(cmd); } return exitStatus; }
/* use: process a <command> or <list> args: cmd = root of command tree return: status of process */ int processCMD(CMD* cmd) { int status; // status of process // <and-or> ; <command> and <list> ; cases if (cmd->type == SEP_END) { // left child status = processCMD(cmd->left); // right child if (cmd->right) { status = processCMD(cmd->right); } } // <and-or> & <command> and <list> & cases else if (cmd->type == SEP_BG) { pid_t pID = fork(); // process ID of fork // error check if (pID < 0) { status = errno; errorExit(status); } // child process else if (pID == 0) { status = processCMD(cmd->left); exit(status); } // parent process else { status = 0; fprintf(stderr, "Backgrounded: %d\n", pID); if (cmd->right) { status = processCMD(cmd->right); } } } // <and-or> case else { status = processAndOr(cmd, 0, false); } return status; }