void analyseCommand(char *cmd) { char *program = NULL; int start, end; int canExecute = 0; if(setExpressionDelimiters(cmd, "^( *[^&<> ]+)+", &start, &end)) { /* command begins from the start */ program = getExpression(cmd, start, end, 0); canExecute = 1; } else if (setExpressionDelimiters(cmd, "[^<> ] ( *[^<> ]+)+", &start, &end)) { /* command begins from somewhere else */ program = getExpression(cmd, start, end, 1); canExecute = 1; } if(!canExecute) { exit(EXIT_FAILURE); } if(redirectInput(cmd)) { exit(EXIT_FAILURE); } redirectOutput(cmd); free(cmd); executeProgram(program); }
/****************************************************** Tries to redirect, fork, and execute the job passed to the method. This method is designed to work with two pipes, so it should not be used for the first and last jobs in the pipeline. PRE: The necessary pipes have already been created and file descriptor array pointers are stored in the vector pipe_fds. POST: Returns true in the parent if successful. Nothing is returned on success in the child. Returns false if an error was encountered. */ bool PipeManager::createMiddleChild(int command_index) { // linux system call int pid = fork(); // error checking if (pid == -1) { cout << "Execution error: " << endl; cout << " Could not create process." << endl; return false; } // child code if (pid == 0) { // figure out which pipes we're using int out_pipe = command_index; int in_pipe = command_index - 1; redirectInput(pipe_fds[in_pipe][0]); // read end of the pipe close(pipe_fds[in_pipe][1]); redirectOutput(pipe_fds[out_pipe][1]); // write end of pipe close(pipe_fds[out_pipe][0]); // close all other pipes for (int closePtr = 0; closePtr < pipe_fds.size(); closePtr++) { if ((closePtr != in_pipe) && (closePtr != out_pipe)) { //linux system calls close(pipe_fds[closePtr][0]); close(pipe_fds[closePtr][1]); } } // replace process code with the given job callExec(command_index); } // still here, must be in parent pids.push_back(pid); return true; }
/****************************************************** Tries to redirect, fork, and execute the last job in the piped command. PRE: The necessary pipes have already been created and file descriptor array pointers are stored in the vector pipe_fds. POST: Returns true in the parent if successful. Nothing is returned on success in the child. Returns false if an error was encountered. */ bool PipeManager::createLastChild() { // linux system call int pid = fork(); // error checking if (pid == -1) { cout << "Execution error: " << endl; cout << " Could not create process." << endl; return false; } // child code if (pid == 0) { // figure out which pipe we're using int my_pipe = pipe_fds.size() - 1; close(pipe_fds[my_pipe][1]); // we don't want to write to pipe redirectInput(pipe_fds[my_pipe][0]); // read end of the pipe // close all other pipes for (int closePtr = 0; closePtr < pipe_fds.size(); closePtr++) { if (closePtr != my_pipe) { //linux system calls close(pipe_fds[closePtr][0]); close(pipe_fds[closePtr][1]); } } // replace process code with last job callExec(my_command.getCommands().size() - 1); } // still here, must be in parent pids.push_back(pid); return true; }
int main(int argc, char *argv[]){ char *line; pipeline pl; int run; //flags int redo = 0; int skip = 0; int isResume = 0; char *promptstr; char* buffer; numExits = 0; jobIndex = 0; histIndex = 0; back = 0; script = 0; FILE* in; /* check for the right number of arguments */ //if ( argc > 2 ) { // printusage(argv[0]); // exit(-1); //} if (argc >= 2) { DIR* dirp; struct dirent *dp; int isFound = 0; if ((dirp = opendir(".")) == NULL) { perror("couldn't open path"); return 0; } //put files into array and sort their names while ((dp = readdir(dirp)) != NULL) { if (strcmp(dp->d_name, argv[1]) == 0) { isFound = 1; } } if (isFound == 0) { printf("%s: Command not found\n", argv[1]); } else { in = fopen(argv[1], "r"); buffer = (char*)malloc(sizeof(in)); script = 1; } } //struct termios saved_term_mode; struct sigaction action; action.sa_handler = killHandle; /* set tick to be the handler function */ sigemptyset(&action.sa_mask); /* clear out masked functions */ action.sa_flags = 0; /* no special handling */ struct sigaction action2; action2.sa_handler = susHandle; /* set tick to be the handler function */ sigemptyset(&action2.sa_mask); /* clear out masked functions */ action2.sa_flags = 0; /* no special handling */ /* * Use the sigaction function to associate the signal action with SIGALRM. */ if (sigaction(SIGINT, &action, NULL) < 0 ) { fprintf(stderr, "SIGINT\n"); exit(-1); } if(sigaction(SIGTSTP, &action2, NULL) < 0) { fprintf(stderr, "SIGTSTP\n"); exit(-1); } //saved_term_mode = set_raw_term_mode(); initHistory(); initJobs(); //strcpy(jobs[1], "hey"); /* set prompt */ promptstr = PROMPT; run = TRUE; if (script == 0) prompt(promptstr); while ( run ) { /// if reexecute was not called if (redo == 0) { if (script == 0) { if ( NULL == (line = readLongString(stdin)) ) { if ( feof(stdin) ) run = FALSE; } } else { fgets(line, sizeof(in), in); if (line[0] == '%') { line++; isResume = 1; } } } else { //printf("histInd: %d\n", histIndex); ///if reexecute was called, ///find the correct place in the history ///list to extract the reexecuted command int temp = histIndex; temp--; int ind = 0; while (ind != reNumber) { temp--; ind++; } line = history[temp]; printf("%s\n", line); } if (line == NULL) { if (feof(stdin)) run = FALSE; } else { if (line[0] == '%') { line++; isResume = 1; } /* We got a line, send it off to the pipeline cracker and * launch it */ //if (redo == 0) //{ pl = crack_pipeline(line); //} redo = 0; /* * Show that it worked. This is where you're going to do * something radically different: rather than printing the * pipeline, you're going to execute it. */ if ( pl != NULL && strlen(pl->cline) > 0) { /* if (pl->cline[0] == '%') { int i; isResume = 1; pl->stage[0].argv[0][0] = ' '; for (i = 0; i < strlen(pl->cline)-1; i++) { pl->stage[0].argv[0][i] = pl->stage[0].argv[0][i+1]; } pl->stage[0].argv[0][strlen(pl->cline)-1] = '\0'; } */ //print_pipeline(stdout,pl); /* print it. */ addHistory(pl->cline); ///add to the history what was typed into the command line if (strcmp(pl->stage[0].argv[0], "history") == 0) { ///print the history if possible if (pl->stage[0].argc > 1) { printf("Junk after built-in command\n"); skip = 1; } numExits = 0; if (skip == 0) printHistory(); skip = 0; } else if (strcmp(pl->stage[0].argv[0], "jobs") == 0) { ///print the suspended jobs if possible if (pl->stage[0].argc > 1) { printf("Junk after built-in command\n"); skip = 1; } numExits = 0; if (skip == 0) printJobs(); skip = 0; } else if (strcmp(pl->stage[0].argv[0], "exit") == 0) { ///exit vssh if possible if (pl->stage[0].argc > 1) { fprintf(stderr, "Junk after built-in command\n"); skip = 1; } numExits++; if (skip == 0) exitCmd(); skip = 0; } else if (strcmp(pl->stage[0].argv[0], "bg") == 0) { ///background the most recently suspended job if possible if (pl->stage[0].argc > 1) { fprintf(stderr, "Junk after built-in command\n"); skip = 1; } numExits = 0; if (skip == 0) bg(jobs[jobIndex-1]); skip = 0; } else if (strcmp(pl->stage[0].argv[0], "fg") == 0) { ///foreground the most recently backgrounded job if possible if (pl->stage[0].argc > 1) { fprintf(stderr, "Junk after built-in command\n"); skip = 1; } numExits = 0; if (skip == 0) fg(jobs[jobIndex-1]); skip = 0; } else if (strcmp(pl->stage[0].argv[0], "cd") == 0) { ///change the directory of vssh if possible if (pl->stage[0].argc > 2) { fprintf(stderr, "Junk after built-in command\n"); skip = 1; } numExits = 0; if (skip == 0) cd(pl->stage[0].argv[1]); skip = 0; } else if (isResume == 1) { ///foreground the specified job if possible if (pl->stage[0].argc > 1) { fprintf(stderr, "Junk after built-in command\n"); skip = 1; } numExits = 0; if (skip == 0) { //pl->stage[0].argv[0]++; int i; int killFlag = 0; for (i = 0; i < strlen(pl->stage[0].argv[0]); i++) { if (!isdigit(pl->stage[0].argv[0][i])) { ///if the supplied job number is not a number ///then print error killFlag = 1; fprintf(stderr, "%s: No such job.\n", pl->stage[0].argv[0]); } } if (killFlag == 0) { if (atoi(pl->stage[0].argv[0]) <= 0 || atoi(pl->stage[0].argv[0]) > jobIndex) ///if the supplied job number is not a valid job index ///then print error fprintf(stderr, "%s: No such job.\n", pl->stage[0].argv[0]); else resume(jobs[atoi(pl->stage[0].argv[0])-1]->id, atoi(pl->stage[0].argv[0])-1); } } skip = 0; } else if (strcmp(pl->stage[0].argv[0], "!") == 0) { ///reexecute the specified history command if possible if (pl->stage[0].argc > 2 || strlen(pl->stage[0].argv[1]) > 3) { fprintf(stderr, "Junk after built-in command\n"); skip = 1; } ///if the number supplied is not a valid history index ///then print error if (pl->stage[0].argv[1][0] == '0' && skip == 0) { fprintf(stderr, "%s: Event not found\n", pl->stage[0].argv[1]); skip = 1; } if (strlen(history[atoi(pl->stage[0].argv[1])]) <= 0 && skip == 0) { fprintf(stderr, "%s: Event not found\n", pl->stage[0].argv[1]); skip = 1; } int i; for (i = 0; i < strlen(pl->stage[0].argv[1]); i++) { if (!isdigit(pl->stage[0].argv[1][i]) && skip == 0) { ///if the number supplied is not a number ///then print error fprintf(stderr, "%s: Event not found\n", pl->stage[0].argv[1]); skip = 1; } } numExits = 0; if (skip == 0) { redo = 1; reNumber = atoi(pl->stage[0].argv[1]); //printf("renum: %d\n", reNumber); //pl = crack_pipeline(history[atoi(pl->stage[0].argv[1])]); //printf("%s\n", pl->cline); //lineno++; //continue; } skip = 0; } else if (strcmp(pl->stage[0].argv[0], "kill") == 0) { ///kill the specified job if possible if (pl->stage[0].argc > 2) { fprintf(stderr, "Junk after built-in command\n"); skip = 1; } numExits = 0; if (skip == 0) { int i; int killFlag = 0; for (i = 0; i < strlen(pl->stage[0].argv[1]); i++) { ///if the supplied job number is not a number ///then print error if (!isdigit(pl->stage[0].argv[1][i])) { killFlag = 1; fprintf(stderr, "%s: No such job.\n", pl->stage[0].argv[1]); } } if (killFlag == 0) { if (atoi(pl->stage[0].argv[1]) <= 0 || atoi(pl->stage[0].argv[1]) > jobIndex) ///if the supplied job number is not a valid job index ///then print error fprintf(stderr, "%s: No such job.\n", pl->stage[0].argv[1]); else killProcess(atoi(pl->stage[0].argv[1])-1, jobs[atoi(pl->stage[0].argv[1])-1]->id); } } skip = 0; } else { ///pipe/redirect as necessary numExits = 0; //int i; //for (i = 0; i < pl->length; i++) //{ //else //{ //handle backgrounding "&" //find the & int j; int andFound = 0; int pipeFound = 0; for (j = 1; j < strlen(pl->cline); j++) { if (pl->cline[j] == '|') { //fprintf(stderr, "Pipelines cannot be backgrounded\n"); pipeFound = 1; } else if (pl->cline[j] == '&') { //error if & is not the last arg, exec nothing if (pipeFound == 1) { fprintf(stderr, "Pipelines cannot be backgrounded\n"); } else if (j != strlen(pl->cline) - 1) { andFound = 1; fprintf(stderr, "Junk after '&'.\n"); } else if (pl->cline[j-1] == ' ') { andFound = 1; pl->cline[j] = '\0'; //backExec(pl->stage[0].argv[0], pl->stage[0].argv, pl->cline); back = 1; } } } if (pl->length >= 2) { ///pipe if the pipline has 2 or more stages pipeCmd(pl); } else if (pl->stage[0].outname != NULL && pl->stage[0].inname != NULL) { redirectBoth(pl->stage[0].argv, pl->stage[0].inname, pl->stage[0].outname); } else if (pl->stage[0].outname != NULL) { ///otherwise redirect output if there is an outfile redirectOutput(pl->stage[0].argv, pl->stage[0].outname, pl->cline); } else if (pl->stage[0].inname != NULL) { ///otherwise redirect input if there is an infile redirectInput(pl->stage[0].argv, pl->stage[0].inname, pl->cline); } else if (andFound == 0) { //execute if not a built-in command execute(pl->stage[0].argv[0], pl->stage[0].argv, pl->cline); } back = 0; //} //} } } free_pipeline(pl); fflush(stdout); /* also frees line */ lineno++; /* readLongString trims newlines, so increment it manually */ } if (run ) { if (script == 0) /* assuming we still want to run */ prompt(promptstr); } } return 0; }