diff options
Diffstat (limited to 'shell/shell_common.c')
| -rw-r--r-- | shell/shell_common.c | 84 |
1 files changed, 83 insertions, 1 deletions
diff --git a/shell/shell_common.c b/shell/shell_common.c index 754fef34b..657f0df8f 100644 --- a/shell/shell_common.c +++ b/shell/shell_common.c | |||
| @@ -62,7 +62,9 @@ shell_builtin_read(struct builtin_read_params *params) | |||
| 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; |
| @@ -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(); |
| @@ -216,6 +221,13 @@ shell_builtin_read(struct builtin_read_params *params) | |||
| 216 | errno = 0; | 221 | errno = 0; |
| 217 | pfd->events = POLLIN; | 222 | pfd->events = POLLIN; |
| 218 | 223 | ||
| 224 | #if ENABLE_PLATFORM_MINGW32 | ||
| 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 | ||
| 219 | /* test bb_got_signal, then poll(), atomically wrt signals */ | 231 | /* test bb_got_signal, then poll(), atomically wrt signals */ |
| 220 | if (check_got_signal_and_poll(pfd, timeout) <= 0) { | 232 | if (check_got_signal_and_poll(pfd, timeout) <= 0) { |
| 221 | /* timed out, or some error */ | 233 | /* timed out, or some error */ |
| @@ -227,6 +239,41 @@ shell_builtin_read(struct builtin_read_params *params) | |||
| 227 | retval = (const char *)(uintptr_t)1; | 239 | retval = (const char *)(uintptr_t)1; |
| 228 | goto ret; | 240 | goto ret; |
| 229 | } | 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 | ||
| 230 | if (read(fd, &buffer[bufpos], 1) != 1) { | 277 | if (read(fd, &buffer[bufpos], 1) != 1) { |
| 231 | err = errno; | 278 | err = errno; |
| 232 | retval = (const char *)(uintptr_t)1; | 279 | retval = (const char *)(uintptr_t)1; |
| @@ -234,11 +281,37 @@ shell_builtin_read(struct builtin_read_params *params) | |||
| 234 | } | 281 | } |
| 235 | 282 | ||
| 236 | 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 | ||
| 237 | if (!(read_flags & BUILTIN_READ_RAW)) { | 300 | if (!(read_flags & BUILTIN_READ_RAW)) { |
| 238 | 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 | ||
| 239 | backslash = 0; | 309 | backslash = 0; |
| 240 | if (c != '\n') | 310 | if (c != '\n') |
| 241 | goto put; | 311 | goto put; |
| 312 | #if ENABLE_PLATFORM_MINGW32 | ||
| 313 | ++nchars; | ||
| 314 | #endif | ||
| 242 | continue; | 315 | continue; |
| 243 | } | 316 | } |
| 244 | if (c == '\\') { | 317 | if (c == '\\') { |
| @@ -279,7 +352,7 @@ shell_builtin_read(struct builtin_read_params *params) | |||
| 279 | } | 352 | } |
| 280 | put: | 353 | put: |
| 281 | bufpos++; | 354 | bufpos++; |
| 282 | } while (--nchars); | 355 | } while (IF_PLATFORM_MINGW32(backslash ||) --nchars); |
| 283 | 356 | ||
| 284 | if (argv[0]) { | 357 | if (argv[0]) { |
| 285 | /* Remove trailing space $IFS chars */ | 358 | /* Remove trailing space $IFS chars */ |
| @@ -334,8 +407,10 @@ shell_builtin_read(struct builtin_read_params *params) | |||
| 334 | 407 | ||
| 335 | ret: | 408 | ret: |
| 336 | free(buffer); | 409 | free(buffer); |
| 410 | #if !ENABLE_PLATFORM_MINGW32 | ||
| 337 | if (read_flags & BUILTIN_READ_SILENT) | 411 | if (read_flags & BUILTIN_READ_SILENT) |
| 338 | tcsetattr(fd, TCSANOW, &old_tty); | 412 | tcsetattr(fd, TCSANOW, &old_tty); |
| 413 | #endif | ||
| 339 | 414 | ||
| 340 | errno = err; | 415 | errno = err; |
| 341 | return retval; | 416 | return retval; |
| @@ -344,6 +419,7 @@ shell_builtin_read(struct builtin_read_params *params) | |||
| 344 | 419 | ||
| 345 | /* ulimit builtin */ | 420 | /* ulimit builtin */ |
| 346 | 421 | ||
| 422 | #if !ENABLE_PLATFORM_MINGW32 | ||
| 347 | struct limits { | 423 | struct limits { |
| 348 | uint8_t cmd; /* RLIMIT_xxx fit into it */ | 424 | uint8_t cmd; /* RLIMIT_xxx fit into it */ |
| 349 | 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 */ |
| @@ -712,3 +788,9 @@ shell_builtin_ulimit(char **argv) | |||
| 712 | 788 | ||
| 713 | return EXIT_SUCCESS; | 789 | return EXIT_SUCCESS; |
| 714 | } | 790 | } |
| 791 | #else | ||
| 792 | int FAST_FUNC shell_builtin_ulimit(char **argv UNUSED_PARAM) | ||
| 793 | { | ||
| 794 | return 1; | ||
| 795 | } | ||
| 796 | #endif | ||
