diff --git a/init/init.c b/init/init.c index 5e8990bc..d155ff99 100644 --- a/init/init.c +++ b/init/init.c @@ -313,6 +313,7 @@ struct communication static pid_t main_pid; static pid_t forward_signal_pid = -1; +static int tty_fd; static volatile sig_atomic_t caught_exit_signal = -1; static sigset_t handled_signals; @@ -2545,31 +2546,24 @@ static void daemon_start(struct daemon* daemon) fatal("fork: %m"); if ( daemon->need_tty ) { - if ( tcgetattr(0, &daemon->oldtio) ) + if ( tcgetattr(tty_fd, &daemon->oldtio) ) fatal("tcgetattr: %m"); } if ( daemon->pid == 0 ) { uninstall_signal_handler(); close(errfds[0]); + if ( setsid() < 0 ) + exit_errfd(errfds[1], "setsid"); if ( chdir(cd) < 0 ) exit_errfd(errfds[1], "chdir"); if ( daemon->need_tty ) { - pid_t pid = getpid(); - // TODO: Support for setsid(2). - if ( setpgid(0, 0) < 0 ) - exit_errfd(errfds[1], "setpgid"); - sigset_t oldset, sigttou; - sigemptyset(&sigttou); - sigaddset(&sigttou, SIGTTOU); - sigprocmask(SIG_BLOCK, &sigttou, &oldset); - if ( tcsetpgrp(0, pid) < 0 ) - exit_errfd(errfds[1], "tcsetpgrp"); + if ( ioctl(tty_fd, TIOCSCTTY, 1) < 0 ) + exit_errfd(errfds[1], "TIOCSCTTY"); daemon->oldtio.c_cflag |= CREAD; - if ( tcsetattr(0, TCSANOW, &daemon->oldtio) < 0 ) + if ( tcsetattr(tty_fd, TCSANOW, &daemon->oldtio) < 0 ) exit_errfd(errfds[1], "tcsetattr"); - sigprocmask(SIG_SETMASK, &oldset, NULL); dup3(errfds[1], 3, O_CLOEXEC); closefrom(4); } @@ -2723,10 +2717,10 @@ static void daemon_on_exit(struct daemon* daemon, int exit_code) sigemptyset(&sigttou); sigaddset(&sigttou, SIGTTOU); sigprocmask(SIG_BLOCK, &sigttou, &oldset); - if ( tcsetattr(0, TCSAFLUSH, &daemon->oldtio) ) + if ( tcsetattr(tty_fd, TCSAFLUSH, &daemon->oldtio) ) fatal("tcsetattr: %m"); - if ( tcsetpgrp(0, getpgid(0)) < 0 ) - fatal("tcsetpgrp: %m"); + if ( ioctl(tty_fd, TIOCSCTTY, 1) < 0 ) + fatal("TIOCSCTTY: %m"); sigprocmask(SIG_SETMASK, &oldset, NULL); } daemon_on_finished(daemon); @@ -3728,12 +3722,8 @@ static void set_hostname(void) static void set_kblayout(void) { - int tty_fd = open("/dev/tty", O_RDWR); - if ( !tty_fd ) - return warning("unable to set keyboard layout: /dev/tty: %m"); bool unsupported = tcgetblob(tty_fd, "kblayout", NULL, 0) < 0 && (errno == ENOTTY || errno == ENOENT); - close(tty_fd); if ( unsupported ) return; FILE* fp = fopen("/etc/kblayout", "r"); @@ -3766,9 +3756,6 @@ static void set_kblayout(void) static void set_videomode(void) { - int tty_fd = open("/dev/tty", O_RDWR); - if ( !tty_fd ) - return warning("unable to set video mode: /dev/tty: %m"); struct tiocgdisplay display; struct tiocgdisplays gdisplays; memset(&gdisplays, 0, sizeof(gdisplays)); @@ -3776,7 +3763,6 @@ static void set_videomode(void) gdisplays.displays = &display; bool unsupported = ioctl(tty_fd, TIOCGDISPLAYS, &gdisplays) < 0 || gdisplays.count == 0; - close(tty_fd); if ( unsupported ) return; FILE* fp = fopen("/etc/videomode", "r"); @@ -4303,13 +4289,14 @@ int main(int argc, char* argv[]) if ( getinit(0) != getpid() ) fatal("System is already managed by an init process"); - if ( !isatty(0) || !isatty(1) || !isatty(2) ) - fatal("stdin, stdout, and stderr must be the terminal"); - // Register handler that shuts down the system when init exits. if ( atexit(niht) != 0 ) fatal("atexit: %m"); + // Remember the controlling terminal to give it away and reclaim it. + if ( (tty_fd = open("/dev/tty", O_RDWR | O_CLOEXEC)) < 0 ) + fatal("/dev/tty: %m"); + // Handle signals but block them until the safe points where we handle them. // All child processes have to uninstall the signal handler and unblock the // signals or they keep blocking the signals. @@ -4461,9 +4448,6 @@ int main(int argc, char* argv[]) chain_location_dev_made = true; close(new_dev_fd); close(old_dev_fd); - int tty_fd = open("/dev/tty", O_RDWR | O_CLOEXEC); - if ( tty_fd < 0 ) - fatal("/dev/tty: %m"); // TODO: Forward the early init log to the chain init. // Run the chain booted operating system. pid_t child_pid = fork(); @@ -4512,7 +4496,6 @@ int main(int argc, char* argv[]) forward_signal_pid = -1; // Racy with waitpid. if ( ioctl(tty_fd, TIOCSCTTY, 1) < 0 ) fatal("ioctl: TIOCSCTTY: %m"); - close(tty_fd); if ( WIFEXITED(status) ) return WEXITSTATUS(status); else if ( WIFSIGNALED(status) )