diff options
Diffstat (limited to 'shell/cttyhack.c')
-rw-r--r-- | shell/cttyhack.c | 71 |
1 files changed, 43 insertions, 28 deletions
diff --git a/shell/cttyhack.c b/shell/cttyhack.c index 4261289b4..6ff867413 100644 --- a/shell/cttyhack.c +++ b/shell/cttyhack.c | |||
@@ -50,9 +50,12 @@ | |||
50 | //config: | 50 | //config: |
51 | //config: # exec setsid sh -c 'exec sh </dev/tty1 >/dev/tty1 2>&1' | 51 | //config: # exec setsid sh -c 'exec sh </dev/tty1 >/dev/tty1 2>&1' |
52 | //config: | 52 | //config: |
53 | //config: Starting getty on a controlling tty from a shell script: | ||
54 | //config: | ||
55 | //config: # getty 115200 $(cttyhack) | ||
53 | 56 | ||
54 | //usage:#define cttyhack_trivial_usage | 57 | //usage:#define cttyhack_trivial_usage |
55 | //usage: "PROG ARGS" | 58 | //usage: "[PROG ARGS]" |
56 | //usage:#define cttyhack_full_usage "\n\n" | 59 | //usage:#define cttyhack_full_usage "\n\n" |
57 | //usage: "Give PROG a controlling tty if possible." | 60 | //usage: "Give PROG a controlling tty if possible." |
58 | //usage: "\nExample for /etc/inittab (for busybox init):" | 61 | //usage: "\nExample for /etc/inittab (for busybox init):" |
@@ -108,59 +111,71 @@ int cttyhack_main(int argc UNUSED_PARAM, char **argv) | |||
108 | char paranoia[sizeof(struct serial_struct) * 3]; | 111 | char paranoia[sizeof(struct serial_struct) * 3]; |
109 | } u; | 112 | } u; |
110 | 113 | ||
111 | if (!*++argv) { | ||
112 | bb_show_usage(); | ||
113 | } | ||
114 | |||
115 | strcpy(console, "/dev/tty"); | 114 | strcpy(console, "/dev/tty"); |
116 | fd = open(console, O_RDWR); | 115 | fd = open(console, O_RDWR); |
117 | if (fd >= 0) { | 116 | if (fd < 0) { |
118 | /* We already have ctty, nothing to do */ | ||
119 | close(fd); | ||
120 | } else { | ||
121 | /* We don't have ctty (or don't have "/dev/tty" node...) */ | 117 | /* We don't have ctty (or don't have "/dev/tty" node...) */ |
122 | do { | 118 | do { |
123 | #ifdef __linux__ | 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 methos first: | ||
127 | */ | ||
124 | int s = open_read_close("/sys/class/tty/console/active", | 128 | int s = open_read_close("/sys/class/tty/console/active", |
125 | console + 5, sizeof(console) - 5 - 1); | 129 | console + 5, sizeof(console) - 5); |
126 | if (s > 0) { | 130 | if (s > 0) { |
127 | /* found active console via sysfs (Linux 2.6.38+) */ | 131 | /* found active console via sysfs (Linux 2.6.38+) |
128 | console[5 + s] = '\0'; | 132 | * sysfs string looks like "ttyS0\n" so zap the newline: |
133 | */ | ||
134 | console[4 + s] = '\0'; | ||
129 | break; | 135 | break; |
130 | } | 136 | } |
131 | 137 | ||
132 | if (ioctl(0, VT_GETSTATE, &u.vt) == 0) { | 138 | if (ioctl(0, VT_GETSTATE, &u.vt) == 0) { |
133 | /* this is linux virtual tty */ | 139 | /* this is linux virtual tty */ |
134 | sprintf(console + 8, "S%d" + 1, u.vt.v_active); | 140 | sprintf(console + 8, "S%u" + 1, (int)u.vt.v_active); |
135 | break; | 141 | break; |
136 | } | 142 | } |
137 | #endif | 143 | #endif |
138 | #ifdef TIOCGSERIAL | 144 | #ifdef TIOCGSERIAL |
139 | if (ioctl(0, TIOCGSERIAL, &u.sr) == 0) { | 145 | if (ioctl(0, TIOCGSERIAL, &u.sr) == 0) { |
140 | /* this is a serial console, asuming it is named /dev/ttySn */ | 146 | /* this is a serial console; assuming it is named /dev/ttySn */ |
141 | sprintf(console + 8, "S%d", u.sr.line); | 147 | sprintf(console + 8, "S%u", (int)u.sr.line); |
142 | break; | 148 | break; |
143 | } | 149 | } |
144 | #endif | 150 | #endif |
145 | /* nope, could not find it */ | 151 | /* nope, could not find it */ |
146 | goto ret; | 152 | console[0] = '\0'; |
147 | } while (0); | 153 | } while (0); |
154 | } | ||
155 | |||
156 | argv++; | ||
157 | if (!argv[0]) { | ||
158 | if (!console[0]) | ||
159 | return EXIT_FAILURE; | ||
160 | puts(console); | ||
161 | return EXIT_SUCCESS; | ||
162 | } | ||
148 | 163 | ||
164 | if (fd < 0) { | ||
149 | fd = open_or_warn(console, O_RDWR); | 165 | fd = open_or_warn(console, O_RDWR); |
150 | if (fd < 0) | 166 | if (fd < 0) |
151 | goto ret; | 167 | goto ret; |
152 | //bb_error_msg("switching to '%s'", console); | ||
153 | dup2(fd, 0); | ||
154 | dup2(fd, 1); | ||
155 | dup2(fd, 2); | ||
156 | while (fd > 2) | ||
157 | close(fd--); | ||
158 | /* Some other session may have it as ctty, | ||
159 | * steal it from them: | ||
160 | */ | ||
161 | ioctl(0, TIOCSCTTY, 1); | ||
162 | } | 168 | } |
163 | 169 | //bb_error_msg("switching to '%s'", console); | |
164 | ret: | 170 | dup2(fd, 0); |
171 | dup2(fd, 1); | ||
172 | dup2(fd, 2); | ||
173 | while (fd > 2) | ||
174 | close(fd--); | ||
175 | /* Some other session may have it as ctty, | ||
176 | * try to steal it from them: | ||
177 | */ | ||
178 | ioctl(0, TIOCSCTTY, 1); | ||
179 | ret: | ||
165 | BB_EXECVP_or_die(argv); | 180 | BB_EXECVP_or_die(argv); |
166 | } | 181 | } |