#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include volatile sig_atomic_t terminate = 0; void sig_handler(int sig) { terminate = 1; } void createDup() { int master_fd; pid_t pid; signal(SIGINT, sig_handler); signal(SIGCHLD, sig_handler); pid = forkpty(&master_fd, NULL, NULL, NULL); if (pid < 0) { perror("forkpty"); exit(EXIT_FAILURE); } if (pid == 0) { // 子进程设置:如果父进程退出,自动收到 SIGTERM prctl(PR_SET_PDEATHSIG, SIGTERM); return; } else { char buffer[1024]; ssize_t num_read; int output_fd = open("output.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644); if (output_fd < 0) { perror("open output.txt"); exit(EXIT_FAILURE); } fd_set read_fds; int max_fd = (STDIN_FILENO > master_fd ? STDIN_FILENO : master_fd) + 1; while (!terminate) { FD_ZERO(&read_fds); FD_SET(STDIN_FILENO, &read_fds); FD_SET(master_fd, &read_fds); int ret = select(max_fd, &read_fds, NULL, NULL, NULL); if (ret < 0 && errno != EINTR) { perror("select"); break; } if (terminate) break; // 用户输入 if (FD_ISSET(STDIN_FILENO, &read_fds)) { num_read = read(STDIN_FILENO, buffer, sizeof(buffer)); if (num_read <= 0) break; write(master_fd, buffer, num_read); } // 子进程输出 if (FD_ISSET(master_fd, &read_fds)) { num_read = read(master_fd, buffer, sizeof(buffer)); if (num_read <= 0) break; write(STDOUT_FILENO, buffer, num_read); write(output_fd, buffer, num_read); } } kill(pid, SIGTERM); // 通知子进程退出 waitpid(pid, NULL, 0); close(output_fd); close(master_fd); exit(EXIT_SUCCESS); } } int main() { createDup(); signal(SIGINT, sig_handler); pid_t pid = fork(); if (pid < 0) { perror("fork"); exit(EXIT_FAILURE); } else if (pid == 0) { // 子进程确保在父进程退出时自动结束 prctl(PR_SET_PDEATHSIG, SIGTERM); printf("This is the child process.\n"); fflush(stdout); } else { printf("This is the parent process.\n"); fflush(stdout); } // 测试输入 char input[100]; printf("Enter something: "); fflush(stdout); if (fgets(input, sizeof(input), stdin) == NULL) exit(0); printf("You entered: %s", input); fflush(stdout); // 测试输出 printf("This is a test output.\n"); fflush(stdout); // 测试错误输出 fprintf(stderr, "This is a test error output.\n"); fflush(stderr); char *const argv[] = {"bash", NULL, NULL}; extern char **environ; execve("/usr/bin/bash", argv, environ); return 0; }