#define LOGFILE "signal_log.txt" // Signal handlers void sigusr1_handler(int signo); void sigusr2_handler(int signo); void sighup_handler(int signo); // SIGUSR1 handler void sigusr1_handler(int signo) { dprintf(STDOUT_FILENO, "Signal %d (%s) received in function %s() at line %d\n", signo, strsignal(signo), __FUNCTION__, __LINE__); fflush(stdout); } // SIGUSR2 handler void sigusr2_handler(int signo) { dprintf(STDOUT_FILENO, "Signal %d (%s) received in function %s() at line %d\n", signo, strsignal(signo),__FUNCTION__, __LINE__); fflush(stdout); } // SIGHUP handler void sighup_handler(int signo) { dprintf(STDOUT_FILENO, "Signal %d (%s) received in function %s() at line %d\n", signo, strsignal(signo), __FUNCTION__, __LINE__); fflush(stdout); } char *interpret(char *cmdline) { char **tokens; char *cmd; int i; char *result; char sysCommand; tokens=history_tokenize(cmdline); //Split cmdline into individual words. if(!tokens) return "no response needed"; cmd=tokens[0]; //Detecting commands: table lookup: 2 techniques //Using the parallel arrays to look up function calls for(i=0;commands[i];i++) { if(strcasecmp(cmd,commands[i])==0) return (methods[i])(cmd,&tokens[1]); } //Using struct CMDSTRUCT as an alternative lookup method. Pick either technique, not both //Note that its possible to create multiple aliases for the same command using either method. for(i=0;cmdStruct[i].cmd;i++) if(strcasecmp(cmd,cmdStruct[i].cmd)==0) return (cmdStruct[i].method)(cmd,&tokens[1]); sysCommand=system(cmdline); if (sysCommand==-1){ return"command status: fail"; }else if (sysCommand==0){ return"command status: sucsess";} } int main(int argc, char * argv[],char * envp[]) { char cmd[100]; char *cmdLine; char *expansion; time_t now=time(NULL); int nBytes; //size of msg rec'd char cwd[PATH_MAX]; signal(SIGINT,ctrlCHandler); read_history("shell.log"); add_history(ctime(&now)); fprintf(stdout,"Starting the shell at: %s\n",ctime(&now)); while(true) { if (getcwd(cwd, sizeof(cwd)) != NULL) { printf("Current working dir: %s\n", cwd); } else { perror("getcwd() error"); return 1; } signal(SIGIO, SIG_IGN); signal(SIGUSR1, sigusr1_handler); signal(SIGUSR2, sigusr2_handler); signal(SIGHUP, sighup_handler); cmdLine=readline("Enter a command: "); if(!cmdLine) break; history_expand(cmdLine,&expansion); add_history(expansion); if(strcasecmp(cmdLine,"bye")==0) break; char *response=interpret(cmdLine); fprintf(stdout,"%s\n",response); } write_history("shell.log"); system("echo Your session history is; cat -n shell.log"); fprintf(stdout,"Server is now terminated \n"); retur SIGHUP, Set up SIGIO as a signal to be ignored. (6 marks) a. The initial handler you should write for each of them should be stub routines that output a message: "Signal \# (SIGxxxx) received in function _FUNCTION_. Use strsignal to output the name of the signal using dprintf to send the output to a file. (The tail -f \& command will be demonstrated to allow you to follow text output to a file while a program is running. Ta.