From 4201d1d42fe26695d283b5354b153d64c0a2c9e3 Mon Sep 17 00:00:00 2001 From: Werner Fink Date: Fri, 1 Apr 2011 12:45:26 +0000 Subject: [PATCH] Respect the device an the command line of sulogin as well as the standard input. --- src/consoles.c | 206 +++++++++++++++++++++++++++++++++---------------- src/consoles.h | 2 +- 2 files changed, 142 insertions(+), 66 deletions(-) diff --git a/src/consoles.c b/src/consoles.c index 6688889..8db7ad1 100644 --- a/src/consoles.c +++ b/src/consoles.c @@ -29,11 +29,9 @@ #include #include #ifdef __linux__ -# ifndef TIOCGDEV # include # include # include -# endif #endif #include #include @@ -206,19 +204,91 @@ void consalloc(char * name) consoles->next = tail; } -void detect_consoles(const char *console, int fallback) +void detect_consoles(const char *device, int fallback) { + int fd; #ifdef __linux__ char *attrib, *cmdline; FILE *fc; +#endif + if (!device || *device == '\0') + fd = dup(fallback); + else fd = open(device, O_RDWR|O_NONBLOCK|O_NOCTTY|O_CLOEXEC); + if (fd >= 0) { + DIR *dir; + char *name; + struct stat st; +#ifdef TIOCGDEV + unsigned int devnum; +#endif + + if (fstat(fd, &st) < 0) { + close(fd); + goto fallback; + } + comparedev = st.st_rdev; +#ifdef __linux__ + /* + * Check if the device detection for Linux system console should be used. + */ + if (comparedev == makedev(TTYAUX_MAJOR, 0)) { /* /dev/tty */ + close(fd); + device = "/dev/tty"; + goto fallback; + } + if (comparedev == makedev(TTYAUX_MAJOR, 1)) { /* /dev/console */ + close(fd); + goto console; + } + if (comparedev == makedev(TTYAUX_MAJOR, 2)) { /* /dev/ptmx */ + close(fd); + device = "/dev/tty"; + goto fallback; + } + if (comparedev == makedev(TTY_MAJOR, 0)) { /* /dev/tty0 */ + struct vt_stat vt; + if (ioctl(fd, VT_GETSTATE, &vt) < 0) { + close(fd); + goto fallback; + } + comparedev = makedev(TTY_MAJOR, (int)vt.v_active); + } +#endif +#ifdef TIOCGDEV + if (ioctl (fd, TIOCGDEV, &devnum) < 0) { + close(fd); + goto fallback; + } + comparedev = (dev_t)devnum; +#endif + close(fd); + dir = opendir("/dev"); + if (!dir) + goto fallback; + name = scandev(dir); + if (name) + consalloc(name); + closedir(dir); + if (!consoles) + goto fallback; + return; + } +#ifdef __linux__ +console: + /* + * Detection of devices used for Linux system consolei using + * the /proc/consoles API with kernel 2.6.38 and higher. + */ if ((fc = fopen("/proc/consoles", "re"))) { char fbuf[16]; int maj, min; DIR *dir; dir = opendir("/dev"); - if (!dir) - goto out1; + if (!dir) { + fclose(fc); + goto fallback; + } while ((fscanf(fc, "%*s %*s (%[^)]) %d:%d", &fbuf[0], &maj, &min) == 3)) { char * name; @@ -232,18 +302,22 @@ void detect_consoles(const char *console, int fallback) consalloc(name); } closedir(dir); -out1: fclose(fc); return; } - + /* + * Detection of devices used for Linux system console using + * the sysfs /sys/class/tty/ API with kernel 2.6.37 and higher. + */ if ((attrib = actattr("console"))) { char *words = attrib, *token; DIR *dir; dir = opendir("/dev"); - if (!dir) - goto out2; + if (!dir) { + free(attrib); + goto fallback; + } while ((token = strsep(&words, " \t\r\n"))) { char * name; @@ -264,19 +338,25 @@ out1: consalloc(name); } closedir(dir); -out2: free(attrib); + if (!consoles) + goto fallback; return; } - + /* + * Detection of devices used for Linux system console using + * kernel parameter on the kernels command line. + */ if ((cmdline = oneline("/proc/cmdline"))) { char *words= cmdline, *token; DIR *dir; dir = opendir("/dev"); - if (!dir) - goto out3; + if (!dir) { + free(cmdline); + goto fallback; + } while ((token = strsep(&words, " \t\r\n"))) { #ifdef TIOCGDEV unsigned int devnum; @@ -285,7 +365,6 @@ out2: struct stat st; #endif char *colon, *name; - int fd; if (*token != 'c') continue; @@ -335,63 +414,60 @@ out2: consalloc(name); } closedir(dir); -out3: free(cmdline); + /* + * Detection of the device used for Linux system console using + * the ioctl TIOCGDEV if available (e.g. official 2.6.38). + */ + if (!consoles) { +#ifdef TIOCGDEV + unsigned int devnum; + const char *name; + + if (!device || *device == '\0') + fd = dup(fallback); + else fd = open(device, O_RDWR|O_NONBLOCK|O_NOCTTY|O_CLOEXEC); + + if (fd < 0) + goto fallback; + + if (ioctl (fd, TIOCGDEV, &devnum) < 0) { + close(fd); + goto fallback; + } + comparedev = (dev_t)devnum; + close(fd); + + if (device && *device != '\0') + name = device; + else name = ttyname(fallback); + + if (!name) + name = "/dev/tty1"; + + consalloc(strdup(name)); + if (consoles) { + if (!device || *device == '\0') + consoles->fd = fallback; + return; + } +#endif + goto fallback; + } return; } #endif /* __linux __ */ - if (console && *console) { - int fd; - DIR *dir; - char *name; -#ifdef TIOCGDEV - unsigned int devnum; -#else -# ifdef __linux__ - struct vt_stat vt; -# endif - struct stat st; -#endif - - if ((fd = open(console, O_RDWR|O_NONBLOCK|O_NOCTTY|O_CLOEXEC)) < 0) - return; -#ifdef TIOCGDEV - if (ioctl (fd, TIOCGDEV, &devnum) < 0) { - close(fd); - return; - } - comparedev = (dev_t)devnum; -#else - if (fstat(fd, &st) < 0) { - close(fd); - return; - } -# ifdef __linux__ - comparedev = st.st_rdev; - if (comparedev == makedev(TTY_MAJOR, 0)) { - if (ioctl(fd, VT_GETSTATE, &vt) < 0) { - close(fd); - return; - } - comparedev = makedev(TTY_MAJOR, (int)vt.v_active); - } -# endif -#endif - close(fd); - dir = opendir("/dev"); - if (!dir) - return; - name = scandev(dir); - if (name) - consalloc(name); - closedir(dir); - return; - } - +fallback: if (fallback >= 0) { - const char *name = ttyname(fallback); + const char *name; + + if (device && *device != '\0') + name = device; + else name = ttyname(fallback); + if (!name) - name = "/dev/console"; + name = "/dev/tty"; + consalloc(strdup(name)); if (consoles) consoles->fd = fallback; diff --git a/src/consoles.h b/src/consoles.h index 07526aa..024a12a 100644 --- a/src/consoles.h +++ b/src/consoles.h @@ -45,4 +45,4 @@ struct console { struct console *next; }; extern struct console *consoles; -extern void detect_consoles(const char *console, int fallback); +extern void detect_consoles(const char *, int);