2013-11-20 51 views
0

我正在寫一個僞殼,當用戶鍵入Ctrl-C,但應該只是產生一個新的提示行不應該終止。目前,當我鍵入ctrl-C時,我的shell不會終止,但它仍不會打印新的提示行。你知道爲什麼會出現這種情況,我該如何解決這個問題?處理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

如果檢測到信號,它可能會幫助您回到主循環中的printf(「>」);'仍然需要fflush()BTW)的提示符。 – wildplasser

回答

0

,但我會怎麼穿過fflush()?

這將是

fflush(stdout); 

- 但那不是必須的,因爲fgets(buffer, BUFFER_SIZE, stdin)的。

默認情況下,涉及終端設備的輸出流總是行緩衝 ;每當引用終端設備的輸入流被讀取時,等待輸出到這樣的流被自動寫入 。

(見man stdio。)

0

我假設你想要的中斷處理程序跳進while循環在你main功能,而不是打印"\>"

您可以使用此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]。

源頭