aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Fox <pgf@brightstareng.com>2005-09-07 16:56:02 +0000
committerPaul Fox <pgf@brightstareng.com>2005-09-07 16:56:02 +0000
commit02eb934b0f7120cfb783536d6b27f7e092fb991b (patch)
tree1e877e7458d4d84d4e26ebcf92435021c23872d1
parenta70aa86e25bd7969e846aff64206458b56b66c2c (diff)
downloadbusybox-w32-02eb934b0f7120cfb783536d6b27f7e092fb991b.tar.gz
busybox-w32-02eb934b0f7120cfb783536d6b27f7e092fb991b.tar.bz2
busybox-w32-02eb934b0f7120cfb783536d6b27f7e092fb991b.zip
committing:
Summary 0000242: ash: read -t broken this also implements -n and -s options to read. (they're configured together because most of their code is in common, and separating them seemed silly.
-rw-r--r--shell/Config.in20
-rw-r--r--shell/ash.c146
2 files changed, 108 insertions, 58 deletions
diff --git a/shell/Config.in b/shell/Config.in
index f9fb8488f..eb4616672 100644
--- a/shell/Config.in
+++ b/shell/Config.in
@@ -53,16 +53,22 @@ config CONFIG_ASH_JOB_CONTROL
53 help 53 help
54 Enable job control in the ash shell. 54 Enable job control in the ash shell.
55 55
56config CONFIG_ASH_TIMEOUT 56config CONFIG_ASH_READ_NCHARS
57 bool " Enable read timeout support." 57 bool " Enable 'read -n N' and 'read -s' support"
58 default n 58 default n
59 depends on CONFIG_ASH_JOB_CONTROL 59 depends on CONFIG_ASH
60 help 60 help
61 This option provides read -t <seconds> support. 61 'read -n N' will return a value after N characters have been read.
62 'read -s' will read without echoing the user's input.
62 63
63 read builtin which allows the function to pass control back 64config CONFIG_ASH_READ_TIMEOUT
64 if no character input is read from the terminal within a set 65 bool " Enable 'read -t S' support."
65 number of seconds. 66 default n
67 depends on CONFIG_ASH
68 help
69 'read -t S' will return a value after S seconds have passed.
70 This implementation will allow fractional seconds, expressed
71 as a decimal fraction, e.g. 'read -t 2.5 foo'.
66 72
67config CONFIG_ASH_ALIAS 73config CONFIG_ASH_ALIAS
68 bool " Enable alias support" 74 bool " Enable alias support"
diff --git a/shell/ash.c b/shell/ash.c
index 5f6f7c6d3..7271535aa 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -105,7 +105,7 @@
105#undef JOBS 105#undef JOBS
106#endif 106#endif
107 107
108#if JOBS 108#if JOBS || defined(CONFIG_ASH_READ_NCHARS)
109#include <termios.h> 109#include <termios.h>
110#endif 110#endif
111 111
@@ -12598,34 +12598,80 @@ readcmd(int argc, char **argv)
12598 char *prompt; 12598 char *prompt;
12599 const char *ifs; 12599 const char *ifs;
12600 char *p; 12600 char *p;
12601#if defined(CONFIG_ASH_TIMEOUT)
12602 fd_set set;
12603 int timeout;
12604 struct timeval timeout_struct;
12605 struct termios tty, old_tty;
12606#endif
12607 int startword; 12601 int startword;
12608 int status; 12602 int status;
12609 int i; 12603 int i;
12604#if defined(CONFIG_ASH_READ_NCHARS)
12605 int nch_flag = 0;
12606 int nchars = 0;
12607 int silent = 0;
12608 struct termios tty, old_tty;
12609#endif
12610#if defined(CONFIG_ASH_READ_TIMEOUT)
12611 fd_set set;
12612 struct timeval ts;
12613
12614 ts.tv_sec = ts.tv_usec = 0;
12615#endif
12610 12616
12611 rflag = 0; 12617 rflag = 0;
12612 prompt = NULL; 12618 prompt = NULL;
12613#if defined(CONFIG_ASH_TIMEOUT) 12619#if defined(CONFIG_ASH_READ_NCHARS) && defined(CONFIG_ASH_READ_TIMEOUT)
12614 timeout = 0; 12620 while ((i = nextopt("p:rt:n:s")) != '\0')
12615 12621#elif defined(CONFIG_ASH_READ_NCHARS)
12622 while ((i = nextopt("p:rn:s")) != '\0')
12623#elif defined(CONFIG_ASH_READ_TIMEOUT)
12616 while ((i = nextopt("p:rt:")) != '\0') 12624 while ((i = nextopt("p:rt:")) != '\0')
12617#else 12625#else
12618 while ((i = nextopt("p:r")) != '\0') 12626 while ((i = nextopt("p:r")) != '\0')
12619#endif 12627#endif
12620 { 12628 {
12621 if (i == 'p') 12629 switch(i) {
12630 case 'p':
12622 prompt = optionarg; 12631 prompt = optionarg;
12623 else if (i == 'r') 12632 break;
12624 rflag = 1; 12633#if defined(CONFIG_ASH_READ_NCHARS)
12625#if defined(CONFIG_ASH_TIMEOUT) 12634 case 'n':
12626 else 12635 nchars = strtol(optionarg, &p, 10);
12627 timeout = atoi(optionarg); 12636 if (*p)
12637 error("invalid count");
12638 nch_flag = (nchars > 0);
12639 break;
12640 case 's':
12641 silent = 1;
12642 break;
12628#endif 12643#endif
12644#if defined(CONFIG_ASH_READ_TIMEOUT)
12645 case 't':
12646 ts.tv_sec = strtol(optionarg, &p, 10);
12647 ts.tv_usec = 0;
12648 if (*p == '.') {
12649 char *p2;
12650 if (*++p) {
12651 int scale;
12652 ts.tv_usec = strtol(p, &p2, 10);
12653 if (*p2)
12654 error("invalid timeout");
12655 scale = p2 - p;
12656 /* normalize to usec */
12657 if (scale > 6)
12658 error("invalid timeout");
12659 while (scale++ < 6)
12660 ts.tv_usec *= 10;
12661 }
12662 } else if (*p) {
12663 error("invalid timeout");
12664 }
12665 if ( ! ts.tv_sec && ! ts.tv_usec)
12666 error("invalid timeout");
12667 break;
12668#endif
12669 case 'r':
12670 rflag = 1;
12671 break;
12672 default:
12673 break;
12674 }
12629 } 12675 }
12630 if (prompt && isatty(0)) { 12676 if (prompt && isatty(0)) {
12631 out2str(prompt); 12677 out2str(prompt);
@@ -12634,49 +12680,42 @@ readcmd(int argc, char **argv)
12634 error("arg count"); 12680 error("arg count");
12635 if ((ifs = bltinlookup("IFS")) == NULL) 12681 if ((ifs = bltinlookup("IFS")) == NULL)
12636 ifs = defifs; 12682 ifs = defifs;
12637#if defined(CONFIG_ASH_TIMEOUT) 12683#if defined(CONFIG_ASH_READ_NCHARS)
12638 c = 0; 12684 if (nch_flag || silent) {
12639#endif
12640 status = 0;
12641 startword = 1;
12642 backslash = 0;
12643
12644 STARTSTACKSTR(p);
12645#if defined(CONFIG_ASH_TIMEOUT)
12646 if (timeout > 0) {
12647 tcgetattr(0, &tty); 12685 tcgetattr(0, &tty);
12648 old_tty = tty; 12686 old_tty = tty;
12687 if (nch_flag) {
12688 tty.c_lflag &= ~ICANON;
12689 tty.c_cc[VMIN] = nchars;
12690 }
12691 if (silent) {
12692 tty.c_lflag &= ~(ECHO|ECHOK|ECHONL);
12649 12693
12650 /* cfmakeraw(...) disables too much; we just do this instead. */ 12694 }
12651 tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
12652 tcsetattr(0, TCSANOW, &tty); 12695 tcsetattr(0, TCSANOW, &tty);
12653 12696 }
12697#endif
12698#if defined(CONFIG_ASH_READ_TIMEOUT)
12699 if (ts.tv_sec || ts.tv_usec) {
12654 FD_ZERO (&set); 12700 FD_ZERO (&set);
12655 FD_SET (0, &set); 12701 FD_SET (0, &set);
12656 12702
12657 timeout_struct.tv_sec = timeout; 12703 i = select (FD_SETSIZE, &set, NULL, NULL, &ts);
12658 timeout_struct.tv_usec = 0; 12704 if (!i) {
12659 12705#if defined(CONFIG_ASH_READ_NCHARS)
12660 if ((i = select (FD_SETSIZE, &set, NULL, NULL, &timeout_struct)) == 1) 12706 if (nch_flag)
12661 { 12707 tcsetattr(0, TCSANOW, &old_tty);
12662 read(0, &c, 1); 12708#endif
12663 if(c == '\n' || c == 4) /* Handle newlines and EOF */ 12709 return 1;
12664 i = 0; /* Don't read further... */
12665 else
12666 STPUTC(c, p); /* Keep reading... */
12667 } 12710 }
12668 tcsetattr(0, TCSANOW, &old_tty); 12711 }
12669 12712#endif
12670 /* Echo the character so the user knows it was read... 12713 status = 0;
12671 Yes, this can be done by setting the ECHO flag, but that 12714 startword = 1;
12672 echoes ^D and other control characters at this state */ 12715 backslash = 0;
12673 if(c != 0) 12716 STARTSTACKSTR(p);
12674 write(1, &c, 1); 12717#if defined(CONFIG_ASH_READ_NCHARS)
12675 12718 while (!nch_flag || nchars--)
12676 } else
12677 i = 1;
12678
12679 for (;i == 1;)
12680#else 12719#else
12681 for (;;) 12720 for (;;)
12682#endif 12721#endif
@@ -12714,6 +12753,11 @@ put:
12714 STPUTC(c, p); 12753 STPUTC(c, p);
12715 } 12754 }
12716 } 12755 }
12756#if defined(CONFIG_ASH_READ_NCHARS)
12757 if (nch_flag || silent)
12758 tcsetattr(0, TCSANOW, &old_tty);
12759#endif
12760
12717 STACKSTRNUL(p); 12761 STACKSTRNUL(p);
12718 /* Remove trailing blanks */ 12762 /* Remove trailing blanks */
12719 while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL) 12763 while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)