aboutsummaryrefslogtreecommitdiff
path: root/shell/shell_common.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--shell/shell_common.c105
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
55shell_builtin_read(struct builtin_read_params *params) 55shell_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
342struct limits { 423struct 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
792int FAST_FUNC shell_builtin_ulimit(char **argv UNUSED_PARAM)
793{
794 return 1;
795}
796#endif