Changeset 3232 in MondoRescue for branches/3.2/mindi-busybox/shell/cttyhack.c
- Timestamp:
- Jan 1, 2014, 12:47:38 AM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/3.2/mindi-busybox/shell/cttyhack.c
r2725 r3232 7 7 #include "libbb.h" 8 8 9 //applet:IF_CTTYHACK(APPLET(cttyhack, _BB_DIR_BIN, _BB_SUID_DROP))9 //applet:IF_CTTYHACK(APPLET(cttyhack, BB_DIR_BIN, BB_SUID_DROP)) 10 10 11 11 //kbuild:lib-$(CONFIG_CTTYHACK) += cttyhack.o … … 15 15 //config: default y 16 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. 17 //config: One common problem reported on the mailing list is the "can't 18 //config: access tty; job control turned off" error message, which typically 19 //config: appears when one tries to use a shell with stdin/stdout on 20 //config: /dev/console. 20 21 //config: This device is special - it cannot be a controlling tty. 21 22 //config: 22 //config: Proper solution is to use correct device instead of /dev/console. 23 //config: The proper solution is to use the correct device instead of 24 //config: /dev/console. 23 25 //config: 24 //config: cttyhack provides "quick and dirty" solution to this problem.26 //config: cttyhack provides a "quick and dirty" solution to this problem. 25 27 //config: It analyzes stdin with various ioctls, trying to determine whether 26 28 //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: On Linux it also checks sysfs for a pointer to the active console. 30 //config: If cttyhack is able to find the real console device, it closes 31 //config: stdin/out/err and reopens that device. 32 //config: Then it executes the given program. Opening the device will make 29 33 //config: that device a controlling tty. This may require cttyhack 30 34 //config: to be a session leader. … … 47 51 //config: # exec setsid sh -c 'exec sh </dev/tty1 >/dev/tty1 2>&1' 48 52 //config: 53 //config: Starting getty on a controlling tty from a shell script: 54 //config: 55 //config: # getty 115200 $(cttyhack) 49 56 50 57 //usage:#define cttyhack_trivial_usage 51 //usage: " PROG ARGS"58 //usage: "[PROG ARGS]" 52 59 //usage:#define cttyhack_full_usage "\n\n" 53 60 //usage: "Give PROG a controlling tty if possible." … … 105 112 } u; 106 113 107 if (!*++argv) { 108 bb_show_usage(); 114 strcpy(console, "/dev/tty"); 115 fd = open(console, O_RDWR); 116 if (fd < 0) { 117 /* We don't have ctty (or don't have "/dev/tty" node...) */ 118 do { 119 #ifdef __linux__ 120 /* Note that this method does not use _stdin_. 121 * Thus, "cttyhack </dev/something" can't be used. 122 * However, this method is more reliable than 123 * TIOCGSERIAL check, which assumes that all 124 * serial lines follow /dev/ttySn convention - 125 * which is not always the case. 126 * Therefore, we use this method first: 127 */ 128 int s = open_read_close("/sys/class/tty/console/active", 129 console + 5, sizeof(console) - 5); 130 if (s > 0) { 131 char *last; 132 /* Found active console via sysfs (Linux 2.6.38+). 133 * It looks like "[tty0 ]ttyS0\n" so zap the newline: 134 */ 135 console[4 + s] = '\0'; 136 /* If there are multiple consoles, 137 * take the last one: 138 */ 139 last = strrchr(console + 5, ' '); 140 if (last) 141 overlapping_strcpy(console + 5, last + 1); 142 break; 143 } 144 145 if (ioctl(0, VT_GETSTATE, &u.vt) == 0) { 146 /* this is linux virtual tty */ 147 sprintf(console + 8, "S%u" + 1, (int)u.vt.v_active); 148 break; 149 } 150 #endif 151 #ifdef TIOCGSERIAL 152 if (ioctl(0, TIOCGSERIAL, &u.sr) == 0) { 153 /* this is a serial console; assuming it is named /dev/ttySn */ 154 sprintf(console + 8, "S%u", (int)u.sr.line); 155 break; 156 } 157 #endif 158 /* nope, could not find it */ 159 console[0] = '\0'; 160 } while (0); 109 161 } 110 162 111 strcpy(console, "/dev/tty"); 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 } 163 argv++; 164 if (!argv[0]) { 165 if (!console[0]) 166 return EXIT_FAILURE; 167 puts(console); 168 return EXIT_SUCCESS; 144 169 } 145 170 171 if (fd < 0) { 172 fd = open_or_warn(console, O_RDWR); 173 if (fd < 0) 174 goto ret; 175 } 176 //bb_error_msg("switching to '%s'", console); 177 dup2(fd, 0); 178 dup2(fd, 1); 179 dup2(fd, 2); 180 while (fd > 2) 181 close(fd--); 182 /* Some other session may have it as ctty, 183 * try to steal it from them: 184 */ 185 ioctl(0, TIOCSCTTY, 1); 186 ret: 146 187 BB_EXECVP_or_die(argv); 147 188 }
Note:
See TracChangeset
for help on using the changeset viewer.