int execute_simple_command(simple_command *cmd) { pid_t pid; int status; int result = 0; if(cmd->builtin == BUILTIN_CD){ return execute_cd(cmd->tokens); } else if(cmd->builtin == BUILTIN_EXIT){ exit(0); } else if(cmd->builtin == 0){ if((pid = fork()) == -1){ perror("fork"); exit(EXIT_FAILURE); } else if(pid > 0){ waitpid(pid, &status, 0); return status; } else if(pid == 0){ execute_nonbuiltin(cmd); exit(0); } } else{ printf("execute_simple error"); exit(EXIT_FAILURE); } return result; }
/** * Executes a simple command (no pipes). */ int execute_simple_command(simple_command *cmd) { /** * Check if the command is builtin. * 1. If it is, then handle BUILTIN_CD (see execute_cd function provided) * and BUILTIN_EXIT (simply exit with an appropriate exit status). * 2. If it isn't, then you must execute the non-builtin command. * - Fork a process to execute the nonbuiltin command * (see execute_nonbuiltin function above). * - The parent should wait for the child. * (see wait man pages). */ int command_number; /* Handle builtin commands. */ if((command_number = is_builtin(*(cmd->tokens)))) { switch(command_number) { case(BUILTIN_CD): if(execute_cd(cmd->tokens) != EXIT_SUCCESS) { printf("No such file or directory.\n"); } return 0; break; case(BUILTIN_EXIT): return -1; break; } /* Handle nonbuiltin commands. * Fork a process and use execute_nonbuiltin to execute the command. */ } else { int pid; if((pid = fork()) < 0) { perror("fork"); return EXIT_FAILURE; } else if (pid == 0) { //child /* The exit status of the child process will be the return value * of execute_nonbuiltin (if there is an error), or the exit * status of the command exec'd. */ exit(execute_nonbuiltin(cmd)); } else { //parent int status; /* Wait for the command to return, then return its exit status*/ if(wait(&status) != -1) { if(WIFEXITED(status)) { return WEXITSTATUS(status); } else { return EXIT_FAILURE; } } else { perror("wait"); return EXIT_FAILURE; } } } return EXIT_FAILURE; }
int execute_complex_command(command *c) { if(c->scmd != NULL){ if(c->scmd->builtin == 0){ execute_nonbuiltin(c->scmd); } } if (!strcmp(c->oper, "|")) { int pfd[2]; if(pipe(pfd) == -1){ perror("pipe"); exit(EXIT_FAILURE); } pid_t pid1, pid2; int status; pid1 = fork(); if(pid1 < 0){ perror("fork"); exit(EXIT_FAILURE); } else if(pid1 == 0){ close(pfd[0]); close(fileno(stdout)); dup2(pfd[1], fileno(stdout)); execute_complex_command(c->cmd1); exit(0); } else{ pid2 = fork(); if(pid2 < 0){ perror("fork"); exit(EXIT_FAILURE); } else if(pid2 == 0) { close(pfd[1]); close(fileno(stdin)); dup2(pfd[0], fileno(stdin)); execute_complex_command(c->cmd2); exit(0); } else{ close(pfd[0]); close(pfd[1]); waitpid(pid1, &status, 0); waitpid(pid2, &status, 0); } } } return 0; }
/** * Executes a simple command (no pipes). */ int execute_simple_command(simple_command *cmd) { /** * TODO: * Check if the command is builtin. * 1. If it is, then handle BUILTIN_CD (see execute_cd function provided) * and BUILTIN_EXIT (simply exit with an appropriate exit status). * 2. If it isn't, then you must execute the non-builtin command. * - Fork a process to execute the nonbuiltin command * (see execute_nonbuiltin function above). * - The parent should wait for the child. * (see wait man pages). */ if(cmd->builtin != 0){ if(is_builtin(cmd->tokens[0]) == BUILTIN_CD){ execute_cd(cmd->tokens); }else if(is_builtin(cmd->tokens[0]) == BUILTIN_EXIT){ return -1; } }else{ int r,status; if ((r = fork()) == -1){ // fork failed perror("fork"); exit(-1); } else if (r > 1){ // parent process wait(&status); } else if (r == 0){ // child process execute_nonbuiltin(cmd); exit(1); } } return 0; }
/** * Executes a complex command. A complex command is two commands chained * together with a pipe operator. */ int execute_complex_command(command *c) { /** * Check if this is a simple command, using the scmd field. * Execute nonbuiltin commands only. If it's exit or cd, you should not * execute these in a piped context, so simply ignore builtin commands. */ if(c->scmd) { /* The exit status of the child process will be the return value * of execute_nonbuiltin (if there is an error), or the exit * status of the command exec'd. */ exit(execute_nonbuiltin(c->scmd)); // printf("%s\n", c->scmd->tokens[0]); return 0; } /** * Shell currently only supports | operator. */ if (!strcmp(c->oper, "|")) { /** * Create a pipe "pfd" that generates a pair of file * descriptors, to be used for communication between the * parent and the child. Make sure to check any errors in * creating the pipe. */ int pfd[2]; if(pipe(pfd) != 0) { perror("pipe"); return EXIT_FAILURE; } /** * Fork a new process. * In the child: * - close one end of the pipe pfd and close the stdout * file descriptor. * - connect the stdout to the other end of the pipe (the * one you didn't close). * - execute complex command cmd1 recursively. * In the parent: * - fork a new process to execute cmd2 recursively. * - In child 2: * - close one end of the pipe pfd (the other one than * the first child), and close the standard input file * descriptor. * - connect the stdin to the other end of the pipe (the * one you didn't close). * - execute complex command cmd2 recursively. * - In the parent: * - close both ends of the pipe. * - wait for both children to finish. */ int pid; if((pid = fork()) < 0) { perror("fork"); return EXIT_FAILURE; } else if (pid == 0) { //child close(pfd[0]); if(dup2(pfd[1], fileno(stdout)) < 0) { perror("dup2"); return -1; } /* The exit status of the child process will be the return value * of execute_nonbuiltin (if there is an error), or the exit * status of the command exec'd. */ exit(execute_complex_command(c->cmd1)); } else { //parent if((pid = fork()) < 0) { perror("fork"); return EXIT_FAILURE; } else if (pid == 0) { //child close(pfd[1]); if(dup2(pfd[0], fileno(stdin)) < 0) { perror("dup2"); return -1; } /* The exit status of the child process will be the return * value of execute_nonbuiltin (if there is an error), or * the exit status of the command exec'd. */ exit(execute_complex_command(c->cmd2)); } else { //parent close(pfd[0]); close(pfd[1]); int status; int exitcode = -1; int waitedPID; while ((waitedPID = wait(&status)) > 0) { if(WIFEXITED(status)) { /*exitcode should be the exit status of the *last command in the pipeline. */ if(waitedPID == pid) { exitcode = WEXITSTATUS(status); } } else { return EXIT_FAILURE; } } return exitcode; } } } return 0; }