← Commit list

02eb934b0

Paul Fox
Paul Fox
2005-09-07
SOURCE BUG Duration: 6s

Subject

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.

SOURCE BUG

This commit was genuinely broken at the time (not related to our build system): scripts/config/mkconfigs.c (2005-08-01 - 2006-10-05 arasi) uretilen bbconfigopts.h icine .config satirlarini kacissiz, ham newline'larla gömüyordu - gecerli C degildi, busybox'un kendi bb_mkdep araci bile parse edemiyordu (7d219aab7 ile duzeltildi, mkconfigs shell scripte cevrildi)

→ Bu hatanin tam hikayesini ve duzeltme diffini gor

Binary

No binary (build failed)

Architecture & Compiler Flags

Architecture: x86_64-linux-gnu Compiler: gcc (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0

—

Build Log

(log yok)

Commit Diff GitHub →

shell/Config.in+13 -7
@@ -53,16 +53,22 @@ config CONFIG_ASH_JOB_CONTROL
help
Enable job control in the ash shell.
-config CONFIG_ASH_TIMEOUT
- bool " Enable read timeout support."
+config CONFIG_ASH_READ_NCHARS
+ bool " Enable 'read -n N' and 'read -s' support"
default n
- depends on CONFIG_ASH_JOB_CONTROL
+ depends on CONFIG_ASH
help
- This option provides read -t <seconds> support.
+ 'read -n N' will return a value after N characters have been read.
+ 'read -s' will read without echoing the user's input.
- read builtin which allows the function to pass control back
- if no character input is read from the terminal within a set
- number of seconds.
+config CONFIG_ASH_READ_TIMEOUT
+ bool " Enable 'read -t S' support."
+ default n
+ depends on CONFIG_ASH
+ help
+ 'read -t S' will return a value after S seconds have passed.
+ This implementation will allow fractional seconds, expressed
+ as a decimal fraction, e.g. 'read -t 2.5 foo'.
config CONFIG_ASH_ALIAS
bool " Enable alias support"
shell/ash.c+95 -51
@@ -105,7 +105,7 @@
#undef JOBS
#endif
-#if JOBS
+#if JOBS || defined(CONFIG_ASH_READ_NCHARS)
#include <termios.h>
#endif
@@ -12598,34 +12598,80 @@ readcmd(int argc, char **argv)
char *prompt;
const char *ifs;
char *p;
-#if defined(CONFIG_ASH_TIMEOUT)
- fd_set set;
- int timeout;
- struct timeval timeout_struct;
- struct termios tty, old_tty;
-#endif
int startword;
int status;
int i;
+#if defined(CONFIG_ASH_READ_NCHARS)
+ int nch_flag = 0;
+ int nchars = 0;
+ int silent = 0;
+ struct termios tty, old_tty;
+#endif
+#if defined(CONFIG_ASH_READ_TIMEOUT)
+ fd_set set;
+ struct timeval ts;
+
+ ts.tv_sec = ts.tv_usec = 0;
+#endif
rflag = 0;
prompt = NULL;
-#if defined(CONFIG_ASH_TIMEOUT)
- timeout = 0;
-
+#if defined(CONFIG_ASH_READ_NCHARS) && defined(CONFIG_ASH_READ_TIMEOUT)
+ while ((i = nextopt("p:rt:n:s")) != '\0')
+#elif defined(CONFIG_ASH_READ_NCHARS)
+ while ((i = nextopt("p:rn:s")) != '\0')
+#elif defined(CONFIG_ASH_READ_TIMEOUT)
while ((i = nextopt("p:rt:")) != '\0')
#else
while ((i = nextopt("p:r")) != '\0')
#endif
{
- if (i == 'p')
+ switch(i) {
+ case 'p':
prompt = optionarg;
- else if (i == 'r')
- rflag = 1;
-#if defined(CONFIG_ASH_TIMEOUT)
- else
- timeout = atoi(optionarg);
+ break;
+#if defined(CONFIG_ASH_READ_NCHARS)
+ case 'n':
+ nchars = strtol(optionarg, &p, 10);
+ if (*p)
+ error("invalid count");
+ nch_flag = (nchars > 0);
+ break;
+ case 's':
+ silent = 1;
+ break;
#endif
+#if defined(CONFIG_ASH_READ_TIMEOUT)
+ case 't':
+ ts.tv_sec = strtol(optionarg, &p, 10);
+ ts.tv_usec = 0;
+ if (*p == '.') {
+ char *p2;
+ if (*++p) {
+ int scale;
+ ts.tv_usec = strtol(p, &p2, 10);
+ if (*p2)
+ error("invalid timeout");
+ scale = p2 - p;
+ /* normalize to usec */
+ if (scale > 6)
+ error("invalid timeout");
+ while (scale++ < 6)
+ ts.tv_usec *= 10;
+ }
+ } else if (*p) {
+ error("invalid timeout");
+ }
+ if ( ! ts.tv_sec && ! ts.tv_usec)
+ error("invalid timeout");
+ break;
+#endif
+ case 'r':
+ rflag = 1;
+ break;
+ default:
+ break;
+ }
}
if (prompt && isatty(0)) {
out2str(prompt);
@@ -12634,49 +12680,42 @@ readcmd(int argc, char **argv)
error("arg count");
if ((ifs = bltinlookup("IFS")) == NULL)
ifs = defifs;
-#if defined(CONFIG_ASH_TIMEOUT)
- c = 0;
-#endif
- status = 0;
- startword = 1;
- backslash = 0;
-
- STARTSTACKSTR(p);
-#if defined(CONFIG_ASH_TIMEOUT)
- if (timeout > 0) {
+#if defined(CONFIG_ASH_READ_NCHARS)
+ if (nch_flag || silent) {
tcgetattr(0, &tty);
old_tty = tty;
+ if (nch_flag) {
+ tty.c_lflag &= ~ICANON;
+ tty.c_cc[VMIN] = nchars;
+ }
+ if (silent) {
+ tty.c_lflag &= ~(ECHO|ECHOK|ECHONL);
- /* cfmakeraw(...) disables too much; we just do this instead. */
- tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
+ }
tcsetattr(0, TCSANOW, &tty);
-
+ }
+#endif
+#if defined(CONFIG_ASH_READ_TIMEOUT)
+ if (ts.tv_sec || ts.tv_usec) {
FD_ZERO (&set);
FD_SET (0, &set);
- timeout_struct.tv_sec = timeout;
- timeout_struct.tv_usec = 0;
-
- if ((i = select (FD_SETSIZE, &set, NULL, NULL, &timeout_struct)) == 1)
- {
- read(0, &c, 1);
- if(c == '\n' || c == 4) /* Handle newlines and EOF */
- i = 0; /* Don't read further... */
- else
- STPUTC(c, p); /* Keep reading... */
+ i = select (FD_SETSIZE, &set, NULL, NULL, &ts);
+ if (!i) {
+#if defined(CONFIG_ASH_READ_NCHARS)
+ if (nch_flag)
+ tcsetattr(0, TCSANOW, &old_tty);
+#endif
+ return 1;
}
- tcsetattr(0, TCSANOW, &old_tty);
-
- /* Echo the character so the user knows it was read...
- Yes, this can be done by setting the ECHO flag, but that
- echoes ^D and other control characters at this state */
- if(c != 0)
- write(1, &c, 1);
-
- } else
- i = 1;
-
- for (;i == 1;)
+ }
+#endif
+ status = 0;
+ startword = 1;
+ backslash = 0;
+ STARTSTACKSTR(p);
+#if defined(CONFIG_ASH_READ_NCHARS)
+ while (!nch_flag || nchars--)
#else
for (;;)
#endif
@@ -12714,6 +12753,11 @@ put:
STPUTC(c, p);
}
}
+#if defined(CONFIG_ASH_READ_NCHARS)
+ if (nch_flag || silent)
+ tcsetattr(0, TCSANOW, &old_tty);
+#endif
+
STACKSTRNUL(p);
/* Remove trailing blanks */
while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)