/*===========================================================================* * select_request_pipe * *===========================================================================*/ static int select_request_pipe(struct filp *f, int *ops, int block) { int orig_ops, r = 0, err; orig_ops = *ops; if ((*ops & (SEL_RD|SEL_ERR))) { /* Check if we can read 1 byte */ err = pipe_check(f, READING, f->filp_flags & ~O_NONBLOCK, 1, 1 /* Check only */); if (err != SUSPEND) r |= SEL_RD; if (err < 0 && err != SUSPEND) r |= SEL_ERR; if (err == SUSPEND && !(f->filp_mode & R_BIT)) { /* A "meaningless" read select, therefore ready * for reading and no error set. */ r |= SEL_RD; r &= ~SEL_ERR; } } if ((*ops & (SEL_WR|SEL_ERR))) { /* Check if we can write 1 byte */ err = pipe_check(f, WRITING, f->filp_flags & ~O_NONBLOCK, 1, 1 /* Check only */); if (err != SUSPEND) r |= SEL_WR; if (err < 0 && err != SUSPEND) r |= SEL_ERR; if (err == SUSPEND && !(f->filp_mode & W_BIT)) { /* A "meaningless" write select, therefore ready for writing and no error set. */ r |= SEL_WR; r &= ~SEL_ERR; } } /* Some options we collected might not be requested. */ *ops = r & orig_ops; if (!*ops && block) f->filp_pipe_select_ops |= orig_ops; return(OK); }
int lex(char *str, t_token **token) { int i; i = 0; while (str[i]) { i = comma_check(str, i, token); i = pipe_check(str, i, token); i = red_r(str, i, token); i = red_l(str, i, token); i = check_and(str, i, token); i = word_check(str, i, token); i = check_unk(str, i, token); } return (0); }
/* * process_cmd * * 명령 라인을 인자 (argument) 배열로 변환한다. * 내장 명령 처리 함수를 수행한다. * 내장 명령이 아니면 자식 프로세스를 생성하여 지정된 프로그램을 실행한다. * 파이프(|)를 사용하는 경우에는 두 개의 자식 프로세스를 생성한다. */ void process_cmd(char *cmdline) { int argc; char* argv[MAXARGS]; char* temp[MAXARGS]; //파이프를 처리하기 위한 변수들 int pipe_checker = 0; int pipefd[2]; //리다이렉션을 처리하기 위한 변수들. int fd; int saved_stdout; int redi_checker;//redirection checker // 명령 라인을 해석하여 인자 (argument) 배열로 변환한다. argc = parse_line(cmdline, argv); // 인자 배열에 파이프가 존재하는지 검사한다. pipe_checker = pipe_check(argc, argv); if(pipe_checker > 0) { pid_t pipe_pid; //명령어 분리 int temp_i = 0; int pipe_i; for(pipe_i = pipe_checker+1 ; pipe_i < argc; ++pipe_i) { temp[temp_i] = argv[pipe_i]; argv[pipe_i] = NULL; ++temp_i; } argv[pipe_checker] = NULL; temp[temp_i] = NULL; //파이프 생성 if( pipe(pipefd) == -1) { fprintf(stderr, "pipe creat error\n"); return; } pipe_pid = fork(); if(pipe_pid < 0) { fprintf(stderr, "fork failed\n"); } if(pipe_pid == 0) { close(pipefd[0]); //파이프 출력을 stdout으로 복제 if( dup2(pipefd[1], STDOUT_FILENO) < 0) { fprintf(stderr, "pipefd dup error\n"); exit(1); } //명령 실행 if(execvp(argv[0], argv) < 0) { fprintf(stdout, "pipe exec err\n"); exit(1); } } pipe_pid = fork(); if(pipe_pid < 0) { fprintf(stderr, "fork failed\n"); } if(pipe_pid == 0) { close(pipefd[1]); //파이프 입력을 stdin으로 복제 if (dup2(pipefd[0], STDIN_FILENO) < 0) { fprintf(stderr, "pipefd2 dup error\n"); exit(1); } //명령 실행 if(execvp(temp[0], temp) < 0) { fprintf(stdout, "pipe exec2 err\n"); exit(1); } } //부모 프로세스는 파이프의 read / write 모두 닫는다 close(pipefd[0]); close(pipefd[1]); //부모 프로세스는 두개의 자식 프로세스가 죵료할때까지 기다린다. while(wait(NULL) >= 0); return; } // 인자 배열에 리다이렉션이 존재하는지 검사한다. redi_checker = redirection_check(argc, argv); // 리다이렉션이 존재 할 경우 파일디스크립터 복제 // 문자열 처리 // ">"과 다음 인자를 NULL로 변경 if(redi_checker > 0) { //파일디스크립터 복제 fd = creat(argv[redi_checker+1], DEFAULT_FILE_MODE); if(fd < 0) { fprintf(stderr, "file descriptor creat error\n"); return; } saved_stdout = dup(1); //stdout if( dup2(fd, 1) < 0 ) { fprintf(stderr, "dup error\n"); return; } //문자열 처리 argc = redi_checker; argv[redi_checker] = NULL; argv[redi_checker+1] = NULL; } else if(redi_checker < 0) { //redi_checker error fprintf(stderr, "redirection error\n"); return; } /* 내장 명령 처리 함수를 수행한다. */ int result = builtin_cmd(argc, argv); if( result == 0 ) { if( redi_checker > 0 ) { //리다이렉션을 수행한 경우 stdout복구 close(fd); dup2(saved_stdout, 1); } //내장명령 처리를 완료하고 리턴 return; } else if(result < 0) { fprintf(stderr, "command try error\n"); return; } else { //내장명령어가 아닌 경우 //리다이렉션을 사용하였지만 //">"가 없었을 경우는 파일디스크립터를 복제 안하였으므로 //걸러주자. if(redi_checker != 0) { fprintf(stderr, "redirection error\n"); close(fd); dup2(saved_stdout, 1); return; } } //내장 명령어의 처리가 끝남 ///////////////////////////////////////////////////////////// //이 밑으로는 내장 명령어 목록에 존재하지 않는 명령에 대하여 //외부 프로그램을 실행한다. // /* * 자식 프로세스를 생성하여 프로그램을 실행한다. */ fprintf(stderr, "try external program\n"); //백그라운드 명령이 있는지 검사한다. int bgchecker = 0; if( !strcmp( argv[argc -1], "&") ) { bgchecker = 1; argv[argc - 1] = NULL; argc--; } pid_t pid, pid1; // 프로세스 생성 pid = fork(); if(pid == 0) //자식 프로세스 { pid1 = getpid(); /* execv 함수를 사용할때 사용된 코드 //외부 명령어를 실행하기 위하여 argv를 셋팅해준다. //char temp[128] = "/bin/"; //strcat(temp, argv[0]); //문자열 결합 확인을 위한 출력 //puts(temp);1 //변경된 문자열을 argv의 첫 인자로 교체해준다. //argv[0] = temp; */ //외장명령어 실행 if (execvp(argv[0], argv) < 0) { //실행 오류시 자식 에러 메세지를 출력하고 //자식 프로세스를 종료시킨다. fprintf(stdout, "command does not exist\n"); exit(0); return; } else { fprintf(stderr, "PID %d is terminated\n", pid1); } return; } else if(pid > 0) //부모 프로세스 { //자식 프로세스를 백그라운드로 실행하지 않을 경우 //자식 프로세스의 종료를 기다린다. if(bgchecker == 0) { wait(NULL); } //wait(NULL); } else { fprintf(stderr, "fork error\n"); return; } // 자식 프로세스에서 프로그램 실행 // 파이프 실행이면 자식 프로세스를 하나 더 생성하여 파이프로 연결 // foreground 실행이면 자식 프로세스가 종료할 때까지 기다린다. return; }