int buildin(char * s){ int rt = 0; //exit if(strcmp("exit",s) == 0){ rt = 1; exit(0); } //hisotry if(strcmp("history",s) == 0){ rt = 1; history(); } //exclamation if (*s == '!') { rt = 1; int id = 0; IDcounter--; if (IDcounter < 0) { IDcounter = 0; } if (*(s+1) == '\0') { id = IDcounter; char* redo = exclamation(id); buildin(redo); } else{ id = atoi(s+1); char* redo = exclamation(id); buildin(redo); } } return rt; }
/* * eval - Evaluate the command line that the user has just typed in * * If the user has requested a built-in command (quit, jobs, bg or fg) * then execute it immediately. Otherwise, fork a child process and * run the job in the context of the child. If the job is running in * the foreground, wait for it to terminate and then return. Note: * each child process must have a unique process group ID so that our * background children don't receive SIGINT (SIGTSTP) from the kernel * when we type ctrl-c (ctrl-z) at the keyboard. */ void eval(char *cmdline) { int bg; /* should the job run in bg or fg? */ struct cmdline_tokens tok; int pid; sigset_t mask; /* Parse command line */ bg = parseline(cmdline, &tok); if (bg == -1) return; /* parsing error */ if (tok.argv[0] == NULL) return; /* ignore empty lines */ if(buildin(&tok) == 0) { /* empty mask and add SIGCHLD, SIGINT and SIGTSTP to mask */ if(sigemptyset(&mask) == -1) return; if(sigaddset(&mask, SIGCHLD) == -1) return; if(sigaddset(&mask, SIGINT) == -1) return; if(sigaddset(&mask, SIGTSTP) == -1) return; /* to avoid race condition, we first block the signals in father process */ if(sigprocmask(SIG_BLOCK, &mask, NULL) == -1) return; if((pid = fork()) == 0){ if(sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1) return; redirect_io(tok.infile, tok.outfile); if(setpgid(0, 0) == -1) return; if(execve(tok.argv[0], tok.argv, environ) < 0){ fprintf(stderr, "%s: Command not found. \n", tok.argv[0]); exit(0); } } if(bg){ if(addjob(job_list, pid, BG, cmdline) == 0) return; } else { if(addjob(job_list, pid, FG, cmdline) == 0) return; } /* since we have already added the child processes into job_list, we unblock the signals here */ if(sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1) return; if(bg) { printf("[%d] (%d) %s\n", getjobpid(job_list, pid)->jid, pid, cmdline); } else { sigset_t temp_mask; sigemptyset(&temp_mask); while(fgpid(job_list) != 0 && getjobpid(job_list, pid)->state != ST){ sigsuspend(&temp_mask); } } } return; }
int main (int argc, char* argv[]) { lis = (process *)malloc(20*sizeof(process)); int batch = 0; input = stdin; output = STDOUT_FILENO; if(argc == 2){ batch = 1; input = fopen(argv[1], "r"); if (input == NULL) { char error_message[30] = "An error has occurred\n"; write(STDERR_FILENO, error_message, strlen(error_message)); exit(1); } } if (argc > 2) { char error_message[30] = "An error has occurred\n"; write(STDERR_FILENO, error_message, strlen(error_message)); } while(1){ char userInput[512]; process* temp; temp = (process* ) malloc(sizeof(process)); //printf("%s", "mysh # "); if (batch < 1) { write(1, "mysh # ", strlen("mysh # ")); } //scanf("%[^\n]",userInput); if(fgets(userInput, sizeof(userInput), input) == NULL){ if(feof(input)){ break; }else{ char error_message[30] = "An error has occurred\n"; write(STDERR_FILENO, error_message, strlen(error_message)); } } if(batch == 1){ write(1, userInput, strlen(userInput)); } //fgets(userInput, sizeof(userInput), stdin); //truncate the newline character size_t ln = strlen(userInput) - 1; if (userInput[ln] == '\n') userInput[ln] = '\0'; //store in process history temp->id = IDcounter+1; strcpy(temp->command,userInput); lis[IDcounter%20] = *temp; IDcounter++; //truncate space in front and after char* trim_input = truncate_space(userInput); //printf("%d",strcmp("history\n",userInput)); if(buildin(trim_input)==0){ int flag = 1; char * filename; char * ptr; char * star; star = trim_input; ptr = trim_input; int redirect = 0; int j; for (j = 0; j < strlen(trim_input); j++) { if (*ptr == ' ' && *(ptr-1) != ' ') { flag++; } if (*ptr == '>') { filename = ptr+1; filename = truncate_space(filename); redirect = 1; *ptr = '\0'; ptr = strlen(trim_input); } ptr++; } if (redirect == 1) { FILE* new = open(filename, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU); fflush(stdout); int b = dup(1); dup2(new, 1); //close(new); } trim_input = truncate_space(userInput); star = trim_input; ptr = trim_input+1; int q; for (q = 0; q < strlen(trim_input); q++) { if (*ptr == ' ' && *(ptr-1) != ' ') { flag++; } ptr++; } ptr = trim_input+1; pid_t child_pid; char* child_argv[flag+1]; int k = 0; int strlength = strlen(trim_input); for (ptr; ptr < strlength+trim_input+1; ptr++) { //printf("%d", strlen(trim_input)); if(*ptr != '>'){ if (*ptr == ' ' && (*(ptr-1) != ' ') && (*(ptr-1) != '\0')) { *ptr = '\0'; child_argv[k] = star; //printf("%s", star); star = ptr+1; k++; } else if (*ptr == '\0') { //printf("/%s", star); child_argv[k] = star; } } } child_argv[flag] = NULL; int status; if((child_pid = fork())< 0){ char error_message[30] = "An error has occurred\n"; write(STDERR_FILENO, error_message, strlen(error_message)); exit(1); } else if(child_pid == 0){ if(execvp(child_argv[0], child_argv) < 0 ){ char error_message[30] = "An error has occurred\n"; write(STDERR_FILENO, error_message, strlen(error_message)); exit(1); } } else{ wait(&status); } }
/** * parse command * return the number of command on success * return -1 on failed */ int parse_command(void) { /*char *cp = cmdline; char *avp = avline; int i = 0; while (*cp != '\0') { while (*cp==' ' || *cp=='\t') { // left trim cp++; } if (*cp=='\0' || *cp=='\n') { break; } cmd.args[i] = avp; // parse args while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n') { *avp++ = *cp++; } *avp++ = '\0'; printf("[%s]\n", cmd.args[i]); i++; } return 0;*/ /* a example command: cat < test.txt | grep -n public > test2.txt & */ if (check("\n")) { return 0; } if (buildin()) { return 0; } // 1. parse a simple command get_command(0); // 2. judge the input redirect if (check("<")) { getname(infile); } // 3. judge the pipe int i; for (i=1; i<PIPELINE; i++) { if (check("|")) { get_command(i); } else { break; } } // 4. judghe the output redirect if (check(">")) { if (check(">")) { append = 1; } getname(outfile); } // 5. judge the background job if (check("&")) { backgnd = 1; } // 6. judge the end of a command if (check("\n")) { cmd_count = i; return cmd_count; } else { fprintf(stderr, "command line syntax err"); return -1; } }