]> git.ipfire.org Git - thirdparty/util-linux.git/blobdiff - login-utils/login.c
Merge branch 'login-terminal' of https://github.com/stoeckmann/util-linux
[thirdparty/util-linux.git] / login-utils / login.c
index 51c58898abf32cb95560b570a87a339e31b0ab0b..36956cce75e302151570836950de82ecf5779341 100644 (file)
@@ -173,9 +173,10 @@ static void __attribute__((__noreturn__))
        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);    /* %% */
 }
 
@@ -509,12 +510,14 @@ static void chown_tty(struct login_context *cxt)
 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
@@ -527,7 +530,7 @@ static void init_tty(struct login_context *cxt)
        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);
@@ -543,15 +546,20 @@ static void init_tty(struct login_context *cxt)
 
        /* 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);
@@ -559,7 +567,8 @@ static void init_tty(struct login_context *cxt)
        }
 
        /* 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
@@ -577,7 +586,8 @@ static void init_tty(struct login_context *cxt)
        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)