I am writing a small shell program, while trying to handle the Ctrl+C signal, I want trying to print a newline, when it is pressed.
Here's my code to do so.
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");
}
}
But after I press Ctrl+C, it does go to a newline, but then flex gives me this error:
fatal flex scanner internal error--end of buffer missed
How do I handle Ctrl+C properly?
Edit: Code snippet for 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;
}
you 'brutaly' go out of the (f)lex(/yacc/bison) code to come back in myShellLoop, so it is not surprising that introduces inconsistency
Redefine YY_INPUT
and when control-c is hit return a special character to return a special value/token managed in your parser to call yyerror to abort in a normal way
For instance in your lexer file :
%{
...
extern void my_yy_input(char*, int *, int);
#undef YY_INPUT
#define YY_INPUT(b,r,s) my_yy_input(b,&r,s)
%}
...
with
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();
}