// Takes a tokenized command string and prepares a command structures which are // then executed. exec_error prepare_command(int argc, char **cmdTokens) { int pipeIndex, argSplit1Len, argSplit2Len; char **argSplit1; char **argSplit2; Command *cmd1; Command *cmd2; exec_error error = NONE; pipeIndex = index_of(cmdTokens, argc, "|"); if (pipeIndex > 0) { // Split arguments into two for each side of the pipe. argSplit1Len = pipeIndex; argSplit1 = copy_token_array(cmdTokens, argSplit1Len); argSplit1[argSplit1Len] = '\0'; argSplit2Len = argc - pipeIndex - 1; argSplit2 = copy_token_array(cmdTokens + pipeIndex + 1, argSplit2Len); argSplit2[argSplit2Len] = '\0'; // Prepare input (left) side of pipe. First command will take // arguments from left of pipe. REDIRECT_TBA allows fd to be allocated // by command_redirect for possible input files. REDIRECT_NONE makes // sure redirection is not done to the output as this will be piped // later. cmd1 = new_command(argSplit1Len, argSplit1, REDIRECT_TBA, REDIRECT_NONE); error = command_redirect(&cmd1); if (error != NONE) { free(cmd1); return error; } // Prepare output (right) side of pipe taking the remaining arguments // on the RHS of the pipe. REDIRECT constants are switched as this // will be executed on the other half of the pipe. cmd2 = new_command(argSplit2Len, argSplit2, REDIRECT_NONE, REDIRECT_TBA); error = command_redirect(&cmd2); if (error != NONE) { free(cmd1); free(cmd2); return error; } // Execute piped command error = execute_piped(cmd1, cmd2); free_token_array(&argSplit1, argSplit1Len); free_token_array(&argSplit2, argSplit2Len); } else { // No pipe found. Prepare any redirects. cmd1 = new_command(argc, cmdTokens, REDIRECT_TBA, REDIRECT_TBA); error = command_redirect(&cmd1); if (error != NONE) { free(cmd1); return error; } error = execute_unpiped(cmd1); } return error; }
int main(int argc, char **argv, char **envp) { // the line they enter char line[BUFFER_LENGTH]; // the holder for search paths char search[MAX_PATHS][MAX_PATH_LEN]; int path_len = 0; register struct passwd *pw; register uid_t uid; char **env; env = envp; int dirchange; char* pipeptr; char* inptr; char* outptr; char* user; Command* basic; Command* firstC; Command* SecondC; char *buffer; uid = geteuid(); pw = getpwuid(uid); if (pw) { user = pw->pw_name; } // get the host name and put it in a buffer char hostname[64]; hostname[0] = '\0'; gethostname(hostname, sizeof(hostname)); // retrieve our path and put it into an array of search paths // not really needed if we're using execvp... oops /*char* path; path = getenv("PATH"); char* pch = strtok(path, ":"); while (pch != NULL) { strcpy(search[path_len], pch); pch = strtok(NULL, ":"); path_len++; }*/ dirchange = -1; while (TRUE) { printf("%s@%s$ ", pw->pw_name, hostname); fflush(stdout); //Make sure our line/buffer is indeed empty memset(line, '\0', sizeof(line)); //Set line to stuff from terminal //Also set buffer to alias line buffer = accept(line); //Check for various things in the line //to determine what combination of commands to run pipeptr = strpbrk(buffer, "|"); inptr = strpbrk(buffer, "<"); outptr = strpbrk(buffer, ">"); //Handle exit command if (strncmp(buffer, "exit", 4) == 0 || strncmp(buffer, "quit", 4) == 0) { return EXIT_SUCCESS; } //Handle CD command if (strncmp(buffer, "cd", 2) == 0) { change_dir(buffer); } else { //If we have an inbound redirect, nothing else can happen. if (inptr != NULL ) { char* pch = strtok(buffer, "<\n"); char first[256]; strcpy(first, pch); char second[256]; pch = strtok(NULL, "<\n"); strcpy(second, pch); basic = build_regular_command(first, env); execute_redirect_in(&(basic->argv), basic->is_background, basic->envv, second); memset(first, '\0', sizeof(char) * 256); memset(second, '\0', sizeof(char) * 256); memset(buffer, '\0', sizeof(buffer)); free(basic); basic = NULL; } else { //Otherwise, figure out what combo we have and run it. if (pipeptr != NULL && outptr != NULL ) { //Redirect out AND pipe //Tokenize once on pipe ( } ) char* pch = strtok(buffer, "|\n"); char first[256]; strcpy(first, pch); char second[256]; pch = strtok(NULL, "|\n"); strcpy(second, pch); char third[256]; //Tokenzie twice on > //Being sure to copy stuff to buffers //to avoid tampering with the pointer pch = strtok(second, ">\n"); strcpy(third, pch); char fourth[256]; pch = strtok(NULL, ">\n"); strcpy(fourth, pch); //Build our commands firstC = build_regular_command(first, env); SecondC = build_regular_command(third, env); //Execute everything execute_piped_out_redir(&(firstC->argv), firstC->is_background, firstC->envv, &(SecondC->argv), SecondC->is_background, SecondC->envv, fourth); //Free and clear stuff free(firstC); free(SecondC); firstC = NULL; SecondC = NULL; memset(first, '\0', sizeof(char) * 256); memset(second, '\0', sizeof(char) * 256); memset(third, '\0', sizeof(char) * 256); memset(fourth, '\0', sizeof(char) * 256); memset(buffer, '\0', sizeof(buffer)); } else if (pipeptr != NULL && outptr == NULL ) { //Just a pipe char* pch = strtok(buffer, "|\n"); char first[256]; strcpy(first, pch); char second[256]; pch = strtok(NULL, "|\n"); strcpy(second, pch); firstC = build_regular_command(first, env); SecondC = build_regular_command(second, env); execute_piped(&(firstC->argv), firstC->is_background, firstC->envv, &(SecondC->argv), SecondC->is_background, SecondC->envv); free(firstC); free(SecondC); firstC = NULL; SecondC = NULL; memset(first, '\0', sizeof(char) * 256); memset(second, '\0', sizeof(char) * 256); memset(buffer, '\0', sizeof(buffer)); } else if (pipeptr == NULL && outptr != NULL ) { char* pch = strtok(buffer, ">\n"); char first[256]; strcpy(first, pch); char second[256]; pch = strtok(NULL, ">\n"); strcpy(second, pch); basic = build_regular_command(first, env); execute_redirect_out(&(basic->argv), basic->is_background, basic->envv, second); memset(first, '\0', sizeof(char) * 256); memset(second, '\0', sizeof(char) * 256); memset(buffer, '\0', sizeof(buffer)); free(basic); basic = NULL; //Just an outbound redirect } else if (pipeptr == NULL && outptr == NULL ) { basic = build_regular_command(buffer, env); execute(&(basic->argv), basic->is_background, basic->envv); memset(basic, 0, sizeof(*basic)); memset(buffer, '\0', sizeof(buffer)); free(basic); basic = NULL; } } } //Clear buffer/line again. Just to be sure memset(buffer, '\0', sizeof(buffer)); memset(line, '\0', sizeof(line)); } return EXIT_SUCCESS; }