diff options
Diffstat (limited to '')
-rw-r--r-- | shell/shell_common.c | 105 |
1 files changed, 96 insertions, 9 deletions
diff --git a/shell/shell_common.c b/shell/shell_common.c index e5c2cefb3..657f0df8f 100644 --- a/shell/shell_common.c +++ b/shell/shell_common.c | |||
@@ -55,14 +55,16 @@ const char* FAST_FUNC | |||
55 | shell_builtin_read(struct builtin_read_params *params) | 55 | shell_builtin_read(struct builtin_read_params *params) |
56 | { | 56 | { |
57 | struct pollfd pfd[1]; | 57 | struct pollfd pfd[1]; |
58 | #define fd (pfd[0].fd) /* -u FD */ | 58 | #define fd (pfd->fd) /* -u FD */ |
59 | unsigned err; | 59 | unsigned err; |
60 | unsigned end_ms; /* -t TIMEOUT */ | 60 | unsigned end_ms; /* -t TIMEOUT */ |
61 | int nchars; /* -n NUM */ | 61 | int nchars; /* -n NUM */ |
62 | char **pp; | 62 | char **pp; |
63 | char *buffer; | 63 | char *buffer; |
64 | char delim; | 64 | char delim; |
65 | #if !ENABLE_PLATFORM_MINGW32 | ||
65 | struct termios tty, old_tty; | 66 | struct termios tty, old_tty; |
67 | #endif | ||
66 | const char *retval; | 68 | const char *retval; |
67 | int bufpos; /* need to be able to hold -1 */ | 69 | int bufpos; /* need to be able to hold -1 */ |
68 | int startword; | 70 | int startword; |
@@ -142,7 +144,7 @@ shell_builtin_read(struct builtin_read_params *params) | |||
142 | * bash seems to ignore -p PROMPT for this use case. | 144 | * bash seems to ignore -p PROMPT for this use case. |
143 | */ | 145 | */ |
144 | int r; | 146 | int r; |
145 | pfd[0].events = POLLIN; | 147 | pfd->events = POLLIN; |
146 | r = poll(pfd, 1, /*timeout:*/ 0); | 148 | r = poll(pfd, 1, /*timeout:*/ 0); |
147 | /* Return 0 only if poll returns 1 ("one fd ready"), else return 1: */ | 149 | /* Return 0 only if poll returns 1 ("one fd ready"), else return 1: */ |
148 | return (const char *)(uintptr_t)(r <= 0); | 150 | return (const char *)(uintptr_t)(r <= 0); |
@@ -158,6 +160,7 @@ shell_builtin_read(struct builtin_read_params *params) | |||
158 | ifs = defifs; | 160 | ifs = defifs; |
159 | 161 | ||
160 | read_flags = params->read_flags; | 162 | read_flags = params->read_flags; |
163 | #if !ENABLE_PLATFORM_MINGW32 | ||
161 | if (nchars || (read_flags & BUILTIN_READ_SILENT)) { | 164 | if (nchars || (read_flags & BUILTIN_READ_SILENT)) { |
162 | tcgetattr(fd, &tty); | 165 | tcgetattr(fd, &tty); |
163 | old_tty = tty; | 166 | old_tty = tty; |
@@ -180,6 +183,7 @@ shell_builtin_read(struct builtin_read_params *params) | |||
180 | * Ignoring, it's harmless. */ | 183 | * Ignoring, it's harmless. */ |
181 | tcsetattr(fd, TCSANOW, &tty); | 184 | tcsetattr(fd, TCSANOW, &tty); |
182 | } | 185 | } |
186 | #endif | ||
183 | 187 | ||
184 | retval = (const char *)(uintptr_t)0; | 188 | retval = (const char *)(uintptr_t)0; |
185 | startword = 1; | 189 | startword = 1; |
@@ -196,6 +200,7 @@ shell_builtin_read(struct builtin_read_params *params) | |||
196 | if ((bufpos & 0xff) == 0) | 200 | if ((bufpos & 0xff) == 0) |
197 | buffer = xrealloc(buffer, bufpos + 0x101); | 201 | buffer = xrealloc(buffer, bufpos + 0x101); |
198 | 202 | ||
203 | IF_PLATFORM_MINGW32(loop:) | ||
199 | timeout = -1; | 204 | timeout = -1; |
200 | if (params->opt_t) { | 205 | if (params->opt_t) { |
201 | timeout = end_ms - (unsigned)monotonic_ms(); | 206 | timeout = end_ms - (unsigned)monotonic_ms(); |
@@ -204,8 +209,8 @@ shell_builtin_read(struct builtin_read_params *params) | |||
204 | * 32-bit unix time wrapped (year 2038+). | 209 | * 32-bit unix time wrapped (year 2038+). |
205 | */ | 210 | */ |
206 | if (timeout <= 0) { /* already late? */ | 211 | if (timeout <= 0) { /* already late? */ |
207 | retval = (const char *)(uintptr_t)1; | 212 | retval = (const char *)(uintptr_t)2; |
208 | goto ret; | 213 | break; |
209 | } | 214 | } |
210 | } | 215 | } |
211 | 216 | ||
@@ -214,14 +219,61 @@ shell_builtin_read(struct builtin_read_params *params) | |||
214 | * regardless of SA_RESTART-ness of that signal! | 219 | * regardless of SA_RESTART-ness of that signal! |
215 | */ | 220 | */ |
216 | errno = 0; | 221 | errno = 0; |
217 | pfd[0].events = POLLIN; | 222 | pfd->events = POLLIN; |
218 | //TODO race with a signal arriving just before the poll! | 223 | |
219 | if (poll(pfd, 1, timeout) <= 0) { | 224 | #if ENABLE_PLATFORM_MINGW32 |
220 | /* timed out, or EINTR */ | 225 | /* Don't poll if timeout is -1, it hurts performance. The |
226 | * caution above about interrupts isn't relevant on Windows | ||
227 | * where Ctrl-C causes an event, not a signal. | ||
228 | */ | ||
229 | if (timeout >= 0) | ||
230 | #endif | ||
231 | /* test bb_got_signal, then poll(), atomically wrt signals */ | ||
232 | if (check_got_signal_and_poll(pfd, timeout) <= 0) { | ||
233 | /* timed out, or some error */ | ||
221 | err = errno; | 234 | err = errno; |
235 | if (!err) { /* timed out */ | ||
236 | retval = (const char *)(uintptr_t)2; | ||
237 | break; | ||
238 | } | ||
222 | retval = (const char *)(uintptr_t)1; | 239 | retval = (const char *)(uintptr_t)1; |
223 | goto ret; | 240 | goto ret; |
224 | } | 241 | } |
242 | #if ENABLE_PLATFORM_MINGW32 | ||
243 | if (isatty(fd)) { | ||
244 | int64_t key; | ||
245 | |||
246 | key = windows_read_key(fd, NULL, timeout); | ||
247 | if (key == 0x03) { | ||
248 | /* ^C pressed */ | ||
249 | retval = (const char *)(uintptr_t)3; | ||
250 | goto ret; | ||
251 | } | ||
252 | else if (key == -1) { | ||
253 | /* timeout */ | ||
254 | retval = (const char *)(uintptr_t)2; | ||
255 | break; | ||
256 | } else if (key == 0x1a && bufpos == 0) { | ||
257 | /* ^Z at start of buffer */ | ||
258 | retval = (const char *)(uintptr_t)1; | ||
259 | break; | ||
260 | } else if (key == '\b') { | ||
261 | if (bufpos > 0) { | ||
262 | --bufpos; | ||
263 | ++nchars; | ||
264 | if (!(read_flags & BUILTIN_READ_SILENT)) { | ||
265 | console_write("\b \b", 3); | ||
266 | } | ||
267 | } | ||
268 | goto loop; | ||
269 | } | ||
270 | buffer[bufpos] = key == '\r' ? '\n' : key; | ||
271 | if (!(read_flags & BUILTIN_READ_SILENT)) { | ||
272 | /* echo input if not in silent mode */ | ||
273 | console_write(buffer + bufpos, 1); | ||
274 | } | ||
275 | } else | ||
276 | #endif | ||
225 | if (read(fd, &buffer[bufpos], 1) != 1) { | 277 | if (read(fd, &buffer[bufpos], 1) != 1) { |
226 | err = errno; | 278 | err = errno; |
227 | retval = (const char *)(uintptr_t)1; | 279 | retval = (const char *)(uintptr_t)1; |
@@ -229,11 +281,37 @@ shell_builtin_read(struct builtin_read_params *params) | |||
229 | } | 281 | } |
230 | 282 | ||
231 | c = buffer[bufpos]; | 283 | c = buffer[bufpos]; |
284 | #if ENABLE_PLATFORM_MINGW32 | ||
285 | if (c == '\n') { | ||
286 | if (backslash == 2 || (bufpos > 0 && buffer[bufpos - 1] == '\r')) { | ||
287 | /* We saw either: | ||
288 | * - BS CR LF: remove CR, fall through to ignore escaped LF | ||
289 | * and exit BS context. | ||
290 | * - CR LF not in BS context: replace CR with LF */ | ||
291 | buffer[--bufpos] = c; | ||
292 | nchars += 1 + (backslash == 2); | ||
293 | } | ||
294 | } else if (backslash == 2) { | ||
295 | /* We saw BS CR ??, keep escaped CR, exit BS context, | ||
296 | * process ?? */ | ||
297 | backslash = 0; | ||
298 | } | ||
299 | #endif | ||
232 | if (!(read_flags & BUILTIN_READ_RAW)) { | 300 | if (!(read_flags & BUILTIN_READ_RAW)) { |
233 | if (backslash) { | 301 | if (backslash) { |
302 | #if ENABLE_PLATFORM_MINGW32 | ||
303 | if (c == '\r') { | ||
304 | /* We have BS CR, keep CR for now, might see LF next */ | ||
305 | backslash = 2; | ||
306 | goto put; | ||
307 | } | ||
308 | #endif | ||
234 | backslash = 0; | 309 | backslash = 0; |
235 | if (c != '\n') | 310 | if (c != '\n') |
236 | goto put; | 311 | goto put; |
312 | #if ENABLE_PLATFORM_MINGW32 | ||
313 | ++nchars; | ||
314 | #endif | ||
237 | continue; | 315 | continue; |
238 | } | 316 | } |
239 | if (c == '\\') { | 317 | if (c == '\\') { |
@@ -274,7 +352,7 @@ shell_builtin_read(struct builtin_read_params *params) | |||
274 | } | 352 | } |
275 | put: | 353 | put: |
276 | bufpos++; | 354 | bufpos++; |
277 | } while (--nchars); | 355 | } while (IF_PLATFORM_MINGW32(backslash ||) --nchars); |
278 | 356 | ||
279 | if (argv[0]) { | 357 | if (argv[0]) { |
280 | /* Remove trailing space $IFS chars */ | 358 | /* Remove trailing space $IFS chars */ |
@@ -329,8 +407,10 @@ shell_builtin_read(struct builtin_read_params *params) | |||
329 | 407 | ||
330 | ret: | 408 | ret: |
331 | free(buffer); | 409 | free(buffer); |
410 | #if !ENABLE_PLATFORM_MINGW32 | ||
332 | if (read_flags & BUILTIN_READ_SILENT) | 411 | if (read_flags & BUILTIN_READ_SILENT) |
333 | tcsetattr(fd, TCSANOW, &old_tty); | 412 | tcsetattr(fd, TCSANOW, &old_tty); |
413 | #endif | ||
334 | 414 | ||
335 | errno = err; | 415 | errno = err; |
336 | return retval; | 416 | return retval; |
@@ -339,6 +419,7 @@ shell_builtin_read(struct builtin_read_params *params) | |||
339 | 419 | ||
340 | /* ulimit builtin */ | 420 | /* ulimit builtin */ |
341 | 421 | ||
422 | #if !ENABLE_PLATFORM_MINGW32 | ||
342 | struct limits { | 423 | struct limits { |
343 | uint8_t cmd; /* RLIMIT_xxx fit into it */ | 424 | uint8_t cmd; /* RLIMIT_xxx fit into it */ |
344 | uint8_t factor_shift; /* shift by to get rlim_{cur,max} values */ | 425 | uint8_t factor_shift; /* shift by to get rlim_{cur,max} values */ |
@@ -707,3 +788,9 @@ shell_builtin_ulimit(char **argv) | |||
707 | 788 | ||
708 | return EXIT_SUCCESS; | 789 | return EXIT_SUCCESS; |
709 | } | 790 | } |
791 | #else | ||
792 | int FAST_FUNC shell_builtin_ulimit(char **argv UNUSED_PARAM) | ||
793 | { | ||
794 | return 1; | ||
795 | } | ||
796 | #endif | ||