# include # include # include # include # include void handler_sigint(int id) { (void)id; write(1, "\n", 1); rl_replace_line("", 1); rl_on_new_line(); rl_redisplay(); } void handler_sigint_execution(int id) { (void)id; write(1, "\n", 1); exit(0); } int main(int argc, char *argv[], char *envp[]) { (void)argc; (void)argv; char *line_input; char *prompt; pid_t pid; char **argvtmp; int wstatus; signal(SIGINT, handler_sigint); // signal handling for SINGINT while interactive mode line_input = NULL; prompt = strdup("\e[0;31m>\e[0m "); while (1) { if (line_input) free(line_input); line_input = readline(prompt); if (line_input && *line_input) { signal(SIGINT, SIG_IGN); // stop signal handling for SIGINT because end of interactive mode pid = fork(); if (pid == 0) { signal(SIGINT, handler_sigint_execution); // start signal handling for SIGINT in child process if (!strncmp("sleep", line_input, 5)) { argvtmp = malloc(sizeof(char*) * 3); argvtmp[0] = strdup("sleep"); argvtmp[1] = strdup("2"); argvtmp[2] = NULL; execve("/bin/sleep", argvtmp, envp); } else if (!strncmp("echo", line_input, 4)) { write(1, "3", 2); sleep(1); write(1, "\b2", 2); sleep(1); write(1, "\b1", 2); sleep(1); write(1, "\b0\n", 3); execve("/bin/echo", argv, envp); } else { write(1, line_input, strlen(line_input)); write(1, " 3", 2); sleep(1); write(1, "\b2", 2); sleep(1); write(1, "\b1", 2); sleep(1); write(1, "\b0\n", 3); exit(0); } } else { wait(&wstatus); if (WIFEXITED(wstatus)) write(1, "the child terminated normally\n", 30); if (WIFSIGNALED(wstatus)) write(1, "the child was terminated by a signal\n", 37); } signal(SIGINT, handler_sigint); // restart signal handling for SIGINT because re-entring in interactive mode } else if (!line_input) { write(1, "exit\n", 5); exit(0); } } return (0); }