APUE fig 1.10 샘플 코드 개선 – 프롬프트 및 입력 캐리지 리턴 최적화

6452 단어
APUE 버전 3 15페이지의 셸 2.c 예제 프로그램의 실행 효과는 다음과 같습니다.
 1 gcc ol.shell.c -o origin_shell
 2 
 3 ./origin_shell
 4 % date
 5 2015 12 13      22 04 48  CST
 6 % ^Cinterrupt
 7 ls
 8 Makefile    getcputc.c    mycat.c        myls_info.c    note.md        origin_shell    shell2.c    uidgid.c
 9 a.out        hello.c        myls.c        myls_sort.c    ol.shell.c    shell1.c    testerror.c
10 % %
11 couldn't execute: : No such file or directory
12 % ls
13 Makefile    getcputc.c    mycat.c        myls_info.c    note.md        origin_shell    shell2.c    uidgid.c
14 a.out        hello.c        myls.c        myls_sort.c    ol.shell.c    shell1.c    testerror.c
15 %

위의 예에서 볼 수 있듯이 두 가지 작은 문제가 존재한다.
1. ctrl+C를 통해 중단 신호를 입력할 때 포획 프로그램의 출력 문장을 중단한'%'가 바로 출력되지 않고 다음 차로 돌아갈 때 출력되어 10줄에 두 개의%%번호가 있다.
2.% 프롬프트가 나타나면 바로 리턴하여 11줄과 같은 오류를 알립니다.이때execlp 함수에 전달되는 buf 내용이 비어 있기 때문입니다.여기서 문제 1은 다음 절차에 나타납니다.
while (fgets(buf, MAXLINE, stdin) != NULL) { } //          fgets  ,           ,          :
 printf("interrupt
%%
"); // ,% 。 ,

printf("interrupt
%%
"); //
1 % ^Cinterrupt
2 %
3 ls
4 Makefile    mycat.c        note.md        shell2.c
5 a.out        myls.c        ol.shell.c    testerror.c
6 getcputc.c    myls_info.c    origin_shell    uidgid.c
7 hello.c        myls_sort.c    shell1.c

위에서 보듯이 위에서 보듯이''이(가) 추가되면 출력은% 이지만 세 번째 줄에서 보듯이 커서는% 다음 줄로 이동합니다.
하나의 해결 방법은 fflush () 함수를 사용하는 것이다.전체 코드, 21-24 줄 및 46 줄 추가:
 1 #include "../apue.h"
 2 #include <sys/wait.h>
 3 
 4 static void    sig_int(int);        /* our signal-catching function */
 5 
 6 int
 7 main(void)
 8 {
 9     char buf[MAXLINE];    /* from apue.h */
10     pid_t  pid;
11     int  status;
12 
13     if (signal(SIGINT, sig_int) == SIG_ERR)
14         err_sys("signal error");
15 
16     printf("%% ");    /* print prompt (printf requires %% to print %) */
17     while (fgets(buf, MAXLINE, stdin) != NULL) {
18         if (buf[strlen(buf) - 1] == '
') 19 buf[strlen(buf) - 1] = 0; /* replace newline with null */ 20 21 if (strlen(buf) == 0) { // if 22 printf("%% "); 23 continue; 24 } 25 26 if ((pid = fork()) < 0) { 27 err_sys("fork error"); 28 } else if (pid == 0) { /* child */ 29 execlp(buf, buf, (char *)0); 30 err_ret("couldn't execute: %s", buf); 31 exit(127); 32 } 33 34 /* parent */ 35 if ((pid = waitpid(pid, &status, 0)) < 0) 36 err_sys("waitpid error"); 37 printf("%% "); 38 } 39 exit(0); 40 } 41 42 void 43 sig_int(int signo) 44 { 45 printf(" interrupt!
%%
"); 46 fflush(stdout); // stdout 47 }

완성 후 효과는 다음과 같다.
1 % date
2 2015 12 13      22 31 53  CST
3 % ^C interrupt!
4 % date
5 2015 12 13      22 32 15  CST
6 %
7 %

좋은 웹페이지 즐겨찾기