2013-11-20 3 views
0

사용자가 ctrl-C를 입력 할 때 종료해서는 안되지만 새로운 프롬프트 라인을 생성해야하는 더미 쉘을 작성하고 있습니다. 현재 Ctrl-C를 입력해도 쉘이 종료되지 않지만 새 프롬프트 행은 인쇄되지 않습니다. 이것이 왜 그런지, 그리고 어떻게 해결할 수 있는지 알고 있습니까?더미 쉘에서 CTRL-C 처리

내 코드는 다음과 같습니다 :

#include <stdlib.h> 
#include <stdio.h> 
#include <errno.h> 
#include <string.h> 
#include <unistd.h> 
#include <sys/wait.h> 
#include <signal.h> 
#define BUFFER_SIZE 1<<16 
#define ARRAY_SIZE 1<<16 

void INThandler(int); 
static void parseCmdArgs(char *buffer, char** cmdArgs, 
       size_t cmdArgsSize, size_t *nargs) 
{ 
    char *bufCmdArgs[cmdArgsSize]; 
    char **temp; 
    char *buf; 
    size_t n, p; 

    cmdArgs[0] = buf = bufCmdArgs[0] = buffer; 

    for(temp=bufCmdArgs; (*temp=strsep(&buf, " \n\t")) != NULL ;){ 
     if ((*temp != '\0') && (++temp >= &bufCmdArgs[cmdArgsSize])) 
      break; 
    } 

    for (p=n=0; bufCmdArgs[n]!=NULL; n++){ 
     if(strlen(bufCmdArgs[n])>0) 
      cmdArgs[p++]=bufCmdArgs[n]; 
    } 

    *nargs=p; 
    cmdArgs[p]=NULL; 
} 

void INThandler(int sig) 
{ 
    printf("\n> "); 
    signal(sig, SIG_IGN); 
    } 
int main(void) 
{ 
    char buffer[BUFFER_SIZE]; 
    char *args[ARRAY_SIZE]; 
    int retStatus; 
    size_t nargs; 
    pid_t pid; 


    printf("$dummyshell\n"); 
    signal(SIGINT, INThandler); 
    while(1){ 

     printf("> "); 
     fgets(buffer, BUFFER_SIZE, stdin); 
     parseCmdArgs(buffer, args, ARRAY_SIZE, &nargs); 


     if (nargs==0) 
      continue; 

     if (!strcmp(args[0], "help")) 
     { 
      printf("cat     cd (absolute path references only\n"); 
      printf("exit\n"); 
      printf("help     history\n"); 
      printf("jobs     kill\n"); 
      printf("ls      more\n"); 
      printf("ps      pwd\n"); 
      continue; 
     } 

     if (!strcmp(args[0], "exit")) 
      exit(0); 

    pid = fork(); 

     if (pid){  
      wait(&retStatus); 
     } 

     else { 
      if(execvp(args[0], args)) { 
      fprintf(stderr, "%s\n", strerror(errno)); 
       exit(127); 
      } 
     } 
    /* pid = fork(); 
    if (pid == 0) 
     setpgrp(); 
    else if (pid) 
     pid = wait(&retStatus); 
    else { 
     if (execvp(args[0], args)){ 
     fprintf(stderr, "%s\n", strerror(errno)); 
     exit(127); 
     } 
     }*/ 


    }  
    return 0; 
} 
+0

1) 시그널 핸들러 내에서'printf()'를 사용하지 마라. 그것은 시그널 세이프가 아닙니다. 2)'sigsetjmp'를보세요. – wildplasser

+0

'sigsetjmp'를 찾았지만 어떻게 도움이 될지 모르겠다. – user2264035

+0

신호가 감지되면 메인 루프 (여전히 fflush() BTW가 필요함)의'printf (">");'프롬프트로 돌아갈 수 있습니다. – wildplasser

답변

0

하지만 FFLUSH을 통해 무엇을 전달할 것()?

fflush(stdout); 

것 -하지만이 때문에 fgets(buffer, BUFFER_SIZE, stdin)의 필요하지 않습니다.

터미널 장치를 참조하는 출력 스트림은 항상 기본적으로 라인 버퍼 됨 입니다. 이러한 스트림에 대한 보류중인 출력은 터미널 장치를 참조하는 입력 스트림이 읽힐 때마다 자동으로 작성됩니다 ( ).

(man stdio를 참조하십시오.) 내가 대신 "\>" 인쇄, 당신은 인터럽트 핸들러가 main 함수에서 while 루프에 뛰어 싶어 있으리라 믿고있어

0

.

이 경우 sigsetjmpsiglongjmp을 사용할 수 있습니다. 예를 들어 [1]을보고 싶을 수도 있습니다.

#include <stdio.h> 
#include <signal.h> 
#include <setjmp.h> 

jmp_buf JumpBuffer; 
void  INThandler(int); 

void main(void) 
{ 
    signal(SIGINT, INThandler); 
    while (1) { 
      if (setjmp(JumpBuffer) == 0) { 
      printf(">"); 
      /*...*/ 
      } 
    } 
} 

void INThandler(int sig) 
{ 
    signal(sig, SIG_IGN); 
    signal(SIGINT, INThandler); 
    longjmp(JumpBuffer, 1); 
} 

이것은 [2]에서 수정되었습니다. sigaction(), sigprocmask() 또는 sigsuspend()을 사용하는 경우 siglongjmpsigsetjmp 기능을 각각 사용해야합니다. [3]

소스 :