#include #include #include #include #include #include #include #include #include static sigjmp_buf restart_jmp_buf; static const int restart_value = 69; static volatile sig_atomic_t jump_active = 0; void sigint_handler(int signo) { if(!jump_active) { return; } siglongjmp(restart_jmp_buf, restart_value); } char** split_input(char* input) { const size_t alloc_size = ((strlen(input) + 1) / 2) + 1; char** command = malloc(alloc_size * sizeof(char*)); if (command == NULL) { perror("malloc failed"); exit(1); } const char* separator = " "; char* parsed; uint32_t index = 0; parsed = strtok(input, separator); while (parsed != NULL) { command[index] = parsed; index++; parsed = strtok(NULL, separator); } command[index] = NULL; return command; } int cd(char* path) { return chdir(path); } int main() { struct sigaction s; s.sa_handler = sigint_handler; sigemptyset(&s.sa_mask); s.sa_flags = SA_RESTART; struct sigaction s_old; sigaction(SIGINT, &s, &s_old); int stat_loc; if(sigsetjmp(restart_jmp_buf, 1) == restart_value) { printf("\n"); } jump_active = 1; while(true) { char* input = readline("arsh> "); if(input == NULL) //CTRL + D { continue; } char** command = split_input(input); if(strcmp(command[0], "cd") == 0) { if (cd(command[1]) < 0) { perror(command[1]); } continue; //skip fork() } if(strcmp(command[0], "exit") == 0) { int32_t status_code = command[1] != NULL ? atoi(command[1]) : 0; exit(status_code); } pid_t child_pid = fork(); if (child_pid < 0) { perror("Fork failed"); exit(1); } if (child_pid == 0) { sigaction(SIGINT, &s_old, NULL); //never returns if call is successful if(execvp(command[0], command) < 0) { perror(command[0]); exit(1); } } else { waitpid(child_pid, &stat_loc, WUNTRACED); } free(input); free(command); } }