Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/shell/cttyhack.c
- Timestamp:
- Feb 25, 2011, 9:26:54 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2.2.9/mindi-busybox/shell/cttyhack.c
r1765 r2725 1 /* This code is adapted from busybox project 1 /* vi: set sw=4 ts=4: */ 2 /* 3 * Copyright (c) 2007 Denys Vlasenko <vda.linux@googlemail.com> 2 4 * 3 * Licensed under GPLv2 5 * Licensed under GPLv2, see file LICENSE in this source tree. 4 6 */ 5 7 #include "libbb.h" 6 8 9 //applet:IF_CTTYHACK(APPLET(cttyhack, _BB_DIR_BIN, _BB_SUID_DROP)) 10 11 //kbuild:lib-$(CONFIG_CTTYHACK) += cttyhack.o 12 13 //config:config CTTYHACK 14 //config: bool "cttyhack" 15 //config: default y 16 //config: help 17 //config: One common problem reported on the mailing list is "can't access tty; 18 //config: job control turned off" error message which typically appears when 19 //config: one tries to use shell with stdin/stdout opened to /dev/console. 20 //config: This device is special - it cannot be a controlling tty. 21 //config: 22 //config: Proper solution is to use correct device instead of /dev/console. 23 //config: 24 //config: cttyhack provides "quick and dirty" solution to this problem. 25 //config: It analyzes stdin with various ioctls, trying to determine whether 26 //config: it is a /dev/ttyN or /dev/ttySN (virtual terminal or serial line). 27 //config: If it detects one, it closes stdin/out/err and reopens that device. 28 //config: Then it executes given program. Opening the device will make 29 //config: that device a controlling tty. This may require cttyhack 30 //config: to be a session leader. 31 //config: 32 //config: Example for /etc/inittab (for busybox init): 33 //config: 34 //config: ::respawn:/bin/cttyhack /bin/sh 35 //config: 36 //config: Starting an interactive shell from boot shell script: 37 //config: 38 //config: setsid cttyhack sh 39 //config: 40 //config: Giving controlling tty to shell running with PID 1: 41 //config: 42 //config: # exec cttyhack sh 43 //config: 44 //config: Without cttyhack, you need to know exact tty name, 45 //config: and do something like this: 46 //config: 47 //config: # exec setsid sh -c 'exec sh </dev/tty1 >/dev/tty1 2>&1' 48 //config: 49 50 //usage:#define cttyhack_trivial_usage 51 //usage: "PROG ARGS" 52 //usage:#define cttyhack_full_usage "\n\n" 53 //usage: "Give PROG a controlling tty if possible." 54 //usage: "\nExample for /etc/inittab (for busybox init):" 55 //usage: "\n ::respawn:/bin/cttyhack /bin/sh" 56 //usage: "\nGiving controlling tty to shell running with PID 1:" 57 //usage: "\n $ exec cttyhack sh" 58 //usage: "\nStarting interactive shell from boot shell script:" 59 //usage: "\n setsid cttyhack sh" 60 61 #if !defined(__linux__) && !defined(TIOCGSERIAL) && !ENABLE_WERROR 62 # warning cttyhack will not be able to detect a controlling tty on this system 63 #endif 64 7 65 /* From <linux/vt.h> */ 8 66 struct vt_stat { 9 unsigned short v_active; 10 unsigned short v_signal; 11 unsigned short v_state; 67 unsigned short v_active; /* active vt */ 68 unsigned short v_signal; /* signal to send */ 69 unsigned short v_state; /* vt bitmask */ 12 70 }; 13 enum { VT_GETSTATE = 0x5603 }; 71 enum { VT_GETSTATE = 0x5603 }; /* get global vt state info */ 14 72 15 73 /* From <linux/serial.h> */ … … 27 85 char reserved_char[1]; 28 86 int hub6; 29 unsigned short closing_wait; /* time to wait before closing */30 unsigned short closing_wait2; /* no longer used... */87 unsigned short closing_wait; /* time to wait before closing */ 88 unsigned short closing_wait2; /* no longer used... */ 31 89 unsigned char *iomem_base; 32 90 unsigned short iomem_reg_shift; … … 36 94 }; 37 95 38 int cttyhack_main(int argc, char **argv) ATTRIBUTE_NORETURN;39 int cttyhack_main(int argc , char **argv)96 int cttyhack_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 97 int cttyhack_main(int argc UNUSED_PARAM, char **argv) 40 98 { 41 99 int fd; … … 52 110 53 111 strcpy(console, "/dev/tty"); 54 if (ioctl(0, TIOCGSERIAL, &u.sr) == 0) { 55 /* this is a serial console */ 56 sprintf(console + 8, "S%d", u.sr.line); 57 } else if (ioctl(0, VT_GETSTATE, &u.vt) == 0) { 58 /* this is linux virtual tty */ 59 sprintf(console + 8, "S%d" + 1, u.vt.v_active); 112 fd = open(console, O_RDWR); 113 if (fd >= 0) { 114 /* We already have ctty, nothing to do */ 115 close(fd); 116 } else { 117 /* We don't have ctty (or don't have "/dev/tty" node...) */ 118 if (0) {} 119 #ifdef TIOCGSERIAL 120 else if (ioctl(0, TIOCGSERIAL, &u.sr) == 0) { 121 /* this is a serial console */ 122 sprintf(console + 8, "S%d", u.sr.line); 123 } 124 #endif 125 #ifdef __linux__ 126 else if (ioctl(0, VT_GETSTATE, &u.vt) == 0) { 127 /* this is linux virtual tty */ 128 sprintf(console + 8, "S%d" + 1, u.vt.v_active); 129 } 130 #endif 131 if (console[8]) { 132 fd = xopen(console, O_RDWR); 133 //bb_error_msg("switching to '%s'", console); 134 dup2(fd, 0); 135 dup2(fd, 1); 136 dup2(fd, 2); 137 while (fd > 2) 138 close(fd--); 139 /* Some other session may have it as ctty, 140 * steal it from them: 141 */ 142 ioctl(0, TIOCSCTTY, 1); 143 } 60 144 } 61 145 62 if (console[8]) { 63 fd = xopen(console, O_RDWR); 64 //bb_error_msg("switching to '%s'", console); 65 dup2(fd, 0); 66 dup2(fd, 1); 67 dup2(fd, 2); 68 while (fd > 2) close(fd--); 69 } 70 71 execvp(argv[0], argv); 72 bb_perror_msg_and_die("cannot exec '%s'", argv[0]); 146 BB_EXECVP_or_die(argv); 73 147 }
Note:
See TracChangeset
for help on using the changeset viewer.