struct termios ti;
/* reset echo */
- tcgetattr(0, &ti);
- ti.c_lflag |= ECHO;
- tcsetattr(0, TCSANOW, &ti);
+ if (tcgetattr(0, &ti) >= 0) {
+ ti.c_lflag |= ECHO;
+ tcsetattr(0, TCSANOW, &ti);
+ }
_exit(EXIT_SUCCESS); /* %% */
}
static void init_tty(struct login_context *cxt)
{
struct stat st;
- struct termios tt, ttt;
- struct winsize ws;
+ struct termios tt, ttt = { 0 };
+ struct winsize ws = { 0 };
+ int fd;
cxt->tty_mode = (mode_t) getlogindefs_num("TTYPERM", TTY_MODE);
get_terminal_name(&cxt->tty_path, &cxt->tty_name, &cxt->tty_number);
+ fd = get_terminal_stdfd();
/*
* In case login is suid it was possible to use a hardlink as stdin
if (!cxt->tty_path || !*cxt->tty_path ||
lstat(cxt->tty_path, &st) != 0 || !S_ISCHR(st.st_mode) ||
(st.st_nlink > 1 && strncmp(cxt->tty_path, "/dev/", 5) != 0) ||
- access(cxt->tty_path, R_OK | W_OK) != 0) {
+ access(cxt->tty_path, R_OK | W_OK) != 0 || fd == -EINVAL) {
syslog(LOG_ERR, _("FATAL: bad tty"));
sleepexit(EXIT_FAILURE);
/* The TTY size might be reset to 0x0 by the kernel when we close the stdin/stdout/stderr file
* descriptors so let's save the size now so we can reapply it later */
- memset(&ws, 0, sizeof(struct winsize));
- if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) < 0)
+ if (ioctl(fd, TIOCGWINSZ, &ws) < 0) {
syslog(LOG_WARNING, _("TIOCGWINSZ ioctl failed: %m"));
+ ws.ws_row = 0;
+ ws.ws_col = 0;
+ }
- tcgetattr(0, &tt);
- ttt = tt;
- ttt.c_cflag &= ~HUPCL;
+ if (tcgetattr(fd, &tt) >= 0) {
+ ttt = tt;
+ ttt.c_cflag &= ~HUPCL;
+ } else {
+ ttt.c_cflag = HUPCL;
+ }
- if ((fchown(0, 0, 0) || fchmod(0, cxt->tty_mode)) && errno != EROFS) {
+ if ((fchown(fd, 0, 0) || fchmod(fd, cxt->tty_mode)) && errno != EROFS) {
syslog(LOG_ERR, _("FATAL: %s: change permissions failed: %m"),
cxt->tty_path);
}
/* Kill processes left on this tty */
- tcsetattr(0, TCSANOW, &ttt);
+ if ((ttt.c_cflag & HUPCL) == 0)
+ tcsetattr(fd, TCSANOW, &ttt);
/*
* Let's close file descriptors before vhangup
open_tty(cxt->tty_path);
/* restore tty modes */
- tcsetattr(0, TCSAFLUSH, &tt);
+ if ((ttt.c_cflag & HUPCL) == 0)
+ tcsetattr(STDIN_FILENO, TCSAFLUSH, &tt);
/* Restore tty size */
if ((ws.ws_row > 0 || ws.ws_col > 0)