mirror of
https://github.com/troglobit/finit.git
synced 2026-10-07 00:00:23 +07:00
Refactor prepare_tty() & C:o, pass tty around
Most of the helper functions around TTYs assumed that STDIN_FILENO was already set up and unique for the give TTY they operated on. It turns out it wasn't. This patch refactors the open() of TTYs to ensure we do not clobber our TTY settings with multiple calls to tcsetattr() for the same TTY. Took a while to track this one down. Usually I don't run systems with more than one TTY, but the Alpine system on my home server did, and boy I've never been this close to giving up on computers, ever. Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
This commit is contained in:
+19
-33
@@ -241,6 +241,25 @@ static void prepare_tty(char *tty, speed_t speed, char *procname, struct rlimit
|
||||
struct sigaction sa;
|
||||
struct termios term;
|
||||
char name[80];
|
||||
int fd;
|
||||
|
||||
/* Detach from initial controlling TTY and become session leader */
|
||||
vhangup();
|
||||
setsid();
|
||||
|
||||
fd = open(tty, O_RDWR);
|
||||
if (fd < 0) {
|
||||
logit(LOG_ERR, "Failed opening %s: %m", tty);
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
dup2(fd, STDIN_FILENO);
|
||||
dup2(fd, STDOUT_FILENO);
|
||||
dup2(fd, STDERR_FILENO);
|
||||
close(fd);
|
||||
|
||||
if (ioctl(STDIN_FILENO, TIOCSCTTY, 1) < 0)
|
||||
logit(LOG_WARNING, "Failed TIOCSCTTY on %s: %m", tty);
|
||||
|
||||
/*
|
||||
* Reset to sane defaults in case of messup from prev. session
|
||||
@@ -251,7 +270,6 @@ static void prepare_tty(char *tty, speed_t speed, char *procname, struct rlimit
|
||||
* Disable ISIG (INTR, QUIT, SUSP) before handing over to getty.
|
||||
* It is up to the getty process to allow them again.
|
||||
*/
|
||||
tcdrain(STDIN_FILENO);
|
||||
if (!tcgetattr(STDIN_FILENO, &term)) {
|
||||
term.c_lflag &= ~ISIG;
|
||||
term.c_cc[VEOF] = _POSIX_VDISABLE;
|
||||
@@ -279,9 +297,6 @@ static void prepare_tty(char *tty, speed_t speed, char *procname, struct rlimit
|
||||
logit(LOG_WARNING, "%s: rlimit: Failed setting %s", tty, rlim2str(i));
|
||||
}
|
||||
|
||||
/* Create new session and process group */
|
||||
setsid();
|
||||
|
||||
/* Finit is responsible for the UTMP INIT_PROCESS record */
|
||||
utmp_set_init(tty, 0);
|
||||
if (!strncmp("/dev/", tty, 5))
|
||||
@@ -374,7 +389,6 @@ pid_t run_getty(char *tty, char *baud, char *term, int noclear, int nowait, stru
|
||||
speed = stty_parse_speed(baud);
|
||||
logit(LOG_INFO, "Starting built-in getty on %s, speed %u", tty, speed);
|
||||
prepare_tty(tty, speed, "tty", rlimit);
|
||||
|
||||
if (activate_console(noclear, nowait))
|
||||
_exit(getty(tty, speed, term, NULL));
|
||||
}
|
||||
@@ -388,40 +402,12 @@ pid_t run_getty2(char *tty, char *cmd, char *args[], int noclear, int nowait, st
|
||||
|
||||
pid = fork();
|
||||
if (!pid) {
|
||||
int i, fd;
|
||||
struct sigaction sa;
|
||||
|
||||
/* Reset signal handlers that were set by the parent process */
|
||||
for (i = 1; i < NSIG; i++)
|
||||
DFLSIG(sa, i, 0);
|
||||
|
||||
/* Detach from initial controlling TTY */
|
||||
vhangup();
|
||||
|
||||
close(STDERR_FILENO);
|
||||
close(STDOUT_FILENO);
|
||||
close(STDIN_FILENO);
|
||||
|
||||
/* Attach TTY to console */
|
||||
fd = open(tty, O_RDWR);
|
||||
if (fd != STDIN_FILENO)
|
||||
exit(1);
|
||||
|
||||
dup2(fd, STDIN_FILENO);
|
||||
dup2(fd, STDOUT_FILENO);
|
||||
dup2(fd, STDERR_FILENO);
|
||||
|
||||
/* Dunno speed, tell stty() to not mess with it */
|
||||
logit(LOG_INFO, "Starting external getty on %s, speed %u", tty, B0);
|
||||
prepare_tty(tty, B0, "getty", rlimit);
|
||||
|
||||
if (ioctl(STDIN_FILENO, TIOCSCTTY, 1) < 0)
|
||||
_pe("Failed TIOCSCTTY");
|
||||
|
||||
if (activate_console(noclear, nowait))
|
||||
_exit(execv(cmd, args));
|
||||
|
||||
close(fd);
|
||||
vhangup();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
+9
-41
@@ -147,12 +147,6 @@ static void do_getty(char *tty, char *name, size_t len)
|
||||
int ch;
|
||||
char *np;
|
||||
|
||||
/*
|
||||
* Clean up tty name.
|
||||
*/
|
||||
if (!strncmp(tty, _PATH_DEV, strlen(_PATH_DEV)))
|
||||
tty += 5;
|
||||
|
||||
/*
|
||||
* Display prompt.
|
||||
*/
|
||||
@@ -212,26 +206,16 @@ int getty(char *tty, speed_t speed, char *term, char *user)
|
||||
{
|
||||
const char cln[] = "\r\e[2K\n";
|
||||
char name[30];
|
||||
int fd;
|
||||
|
||||
/* Detach from initial controlling TTY */
|
||||
vhangup();
|
||||
|
||||
fd = open(tty, O_RDWR);
|
||||
if (fd < 0)
|
||||
err(1, "Failed opening %s", tty);
|
||||
|
||||
dup2(fd, STDIN_FILENO);
|
||||
dup2(fd, STDOUT_FILENO);
|
||||
dup2(fd, STDERR_FILENO);
|
||||
close(fd);
|
||||
|
||||
if (ioctl(STDIN_FILENO, TIOCSCTTY, 1) < 0)
|
||||
warn("Failed TIOCSCTTY");
|
||||
/*
|
||||
* Clean up tty name.
|
||||
*/
|
||||
if (!strncmp(tty, _PATH_DEV, strlen(_PATH_DEV)))
|
||||
tty += 5;
|
||||
|
||||
/* Set up TTY, re-enabling ISIG et al. */
|
||||
stty(STDIN_FILENO, speed);
|
||||
(void)write(STDOUT_FILENO, cln, strlen(cln));
|
||||
(void)write(STDERR_FILENO, cln, strlen(cln));
|
||||
|
||||
/* The getty process is responsible for the UTMP login record */
|
||||
utmp_set_login(tty, NULL);
|
||||
@@ -248,35 +232,19 @@ int getty(char *tty, speed_t speed, char *term, char *user)
|
||||
|
||||
int sh(char *tty)
|
||||
{
|
||||
int fd;
|
||||
char *arg0;
|
||||
struct termios term;
|
||||
char *args[2] = {
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
char *arg0;
|
||||
size_t len;
|
||||
struct termios term;
|
||||
|
||||
/* Detach from initial controlling TTY */
|
||||
vhangup();
|
||||
|
||||
fd = open(tty, O_RDWR);
|
||||
if (fd < 0)
|
||||
err(1, "Failed opening %s", tty);
|
||||
|
||||
dup2(fd, STDIN_FILENO);
|
||||
dup2(fd, STDOUT_FILENO);
|
||||
dup2(fd, STDERR_FILENO);
|
||||
|
||||
if (ioctl(STDIN_FILENO, TIOCSCTTY, 1) < 0)
|
||||
warn("Failed TIOCSCTTY");
|
||||
|
||||
/* The getty process is usually responsible for the UTMP login record */
|
||||
utmp_set_login(tty, NULL);
|
||||
|
||||
/* Set up TTY, re-enabling ISIG et al. */
|
||||
stty(fd, B0);
|
||||
close(fd);
|
||||
stty(STDIN_FILENO, B0);
|
||||
|
||||
/* Start /bin/sh as a login shell, i.e. with a prefix '-' */
|
||||
len = strlen(_PATH_BSHELL) + 2;
|
||||
|
||||
Reference in New Issue
Block a user