cttyhack: check sysfs for the name of the active console

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Kevin Cernekee 2011-07-13 09:26:58 +02:00 committed by Denys Vlasenko
parent 80856b37e8
commit 064e99646a

View File

@ -14,18 +14,22 @@
//config: bool "cttyhack"
//config: default y
//config: help
//config: One common problem reported on the mailing list is "can't access tty;
//config: job control turned off" error message which typically appears when
//config: one tries to use shell with stdin/stdout opened to /dev/console.
//config: One common problem reported on the mailing list is the "can't
//config: access tty; job control turned off" error message, which typically
//config: appears when one tries to use a shell with stdin/stdout on
//config: /dev/console.
//config: This device is special - it cannot be a controlling tty.
//config:
//config: Proper solution is to use correct device instead of /dev/console.
//config: The proper solution is to use the correct device instead of
//config: /dev/console.
//config:
//config: cttyhack provides "quick and dirty" solution to this problem.
//config: cttyhack provides a "quick and dirty" solution to this problem.
//config: It analyzes stdin with various ioctls, trying to determine whether
//config: it is a /dev/ttyN or /dev/ttySN (virtual terminal or serial line).
//config: If it detects one, it closes stdin/out/err and reopens that device.
//config: Then it executes given program. Opening the device will make
//config: On Linux it also checks sysfs for a pointer to the active console.
//config: If cttyhack is able to find the real console device, it closes
//config: stdin/out/err and reopens that device.
//config: Then it executes the given program. Opening the device will make
//config: that device a controlling tty. This may require cttyhack
//config: to be a session leader.
//config:
@ -115,33 +119,46 @@ int cttyhack_main(int argc UNUSED_PARAM, char **argv)
close(fd);
} else {
/* We don't have ctty (or don't have "/dev/tty" node...) */
if (0) {}
#ifdef TIOCGSERIAL
else if (ioctl(0, TIOCGSERIAL, &u.sr) == 0) {
/* this is a serial console */
sprintf(console + 8, "S%d", u.sr.line);
}
#endif
do {
#ifdef __linux__
else if (ioctl(0, VT_GETSTATE, &u.vt) == 0) {
/* this is linux virtual tty */
sprintf(console + 8, "S%d" + 1, u.vt.v_active);
}
int s = open_read_close("/sys/class/tty/console/active",
console + 5, sizeof(console) - 5 - 1);
if (s > 0) {
/* found active console via sysfs (Linux 2.6.38+) */
console[5 + s] = '\0';
break;
}
if (ioctl(0, VT_GETSTATE, &u.vt) == 0) {
/* this is linux virtual tty */
sprintf(console + 8, "S%d" + 1, u.vt.v_active);
break;
}
#endif
if (console[8]) {
fd = xopen(console, O_RDWR);
//bb_error_msg("switching to '%s'", console);
dup2(fd, 0);
dup2(fd, 1);
dup2(fd, 2);
while (fd > 2)
close(fd--);
/* Some other session may have it as ctty,
* steal it from them:
*/
ioctl(0, TIOCSCTTY, 1);
}
#ifdef TIOCGSERIAL
if (ioctl(0, TIOCGSERIAL, &u.sr) == 0) {
/* this is a serial console, asuming it is named /dev/ttySn */
sprintf(console + 8, "S%d", u.sr.line);
break;
}
#endif
/* nope, could not find it */
goto ret;
} while (0);
fd = xopen(console, O_RDWR);
//bb_error_msg("switching to '%s'", console);
dup2(fd, 0);
dup2(fd, 1);
dup2(fd, 2);
while (fd > 2)
close(fd--);
/* Some other session may have it as ctty,
* steal it from them:
*/
ioctl(0, TIOCSCTTY, 1);
}
ret:
BB_EXECVP_or_die(argv);
}