处理CTRL + C时,出现错误“致命的Flex扫描仪内部错误-缓冲区结尾”

时间:2019-04-28 10:26:43

标签: c shell signals flex-lexer

我正在编写一个小的Shell程序,同时尝试处理Ctrl + C信号,但我想尝试在按下该键时打印换行符。 这是我的代码。

static sigjmp_buf env;              

void sigint_handler(int signo){     
    siglongjmp(env, 42);            
}                                   


void myShellLoop(){                                                                  
    int parserStatus;                                                                

    signal(SIGINT, sigint_handler);                                                  

    while(1){                                                                        
        if(sigsetjmp(env,1)==42){                                                    
            printf("\n");                                                            
            continue;                                                                
        }                                                                            
        //Initialize a new command, to parse and execute.                            
        initializeGlobalCommand();                                                   

        parserStatus = yyparse();                                                    
        if(parserStatus == 0)                                                        
            executeShellCommand();                                                   
        else                                                                         
            printf("Not a valid shell command\n");                                   
    }                                                                                
}                                                                                    

但是在我按Ctrl + C之后,它确实转到换行符,但是flex却给了我这个错误:

fatal flex scanner internal error--end of buffer missed

以下是屏幕截图: enter image description here

如何正确处理ctrl + c?

编辑:fork()的代码段:

int execute(int cmdNumber){                                                                                                 
    pid_t pid;                                                                                                              
    int status;                                                                                                             

    pid = fork();                                                                                                           

    if(pid == 0){                                                                                                           
        signal(SIGINT, SIG_DFL);                                                                                            
        if(execvp(globalCommand.sCommands[cmdNumber].arguments[0], globalCommand.sCommands[cmdNumber].arguments) == -1){    
            perror("myShell: Command error");                                                                               
            exit(EXIT_FAILURE);                                                                                             
        }                                                                                                                   
    }                                                                                                                       
    else if(pid < 0){                                                                                                       
        //Error forking.                                                                                                    
        perror("myShell");                                                                                                  
    }                                                                                                                       
    else{                                                                                                                   
            do{                                                                                                                                                                                                                  
                waitpid(pid, &status, WUNTRACED);                                                                                                                                                                             
            }while(!WIFEXITED(status) && !WIFSIGNALED(status) && !globalCommand.background);
    }
    return 1;
}


1 个答案:

答案 0 :(得分:0)

您“残酷地”跳出(f)lex(/ yacc / bison)代码回到 myShellLoop 中,因此引入不一致并不奇怪

重新定义YY_INPUT并在按下 control-c 时返回一个特殊字符,以返回在解析器中管理的特殊值/令牌,以调用 yyerror 中止以正常方式

例如在您的词法分析器文件中:

%{
...
extern void my_yy_input(char*, int *, int);

#undef YY_INPUT
#define YY_INPUT(b,r,s) my_yy_input(b,&r,s)

%}
...

使用

static sigjmp_buf env;              

void sigint_handler(int signo){     
  siglongjmp(env, '@');            
}                                   

void my_yy_input( char * buff, int * nRead, int maxToRead )
{
  *nRead =  1;

  if(sigsetjmp(env,1 ) == '@') {                                                    
    *buff = '@';
    return;
  }

  *buff = getchar();
 }
相关问题