aboutsummaryrefslogtreecommitdiff
path: root/shell/shell_common.c
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2018-08-05 15:42:29 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2018-08-05 18:11:15 +0200
commit19358cc31317dca4642417066c1445ce00438e18 (patch)
tree08b922ba5bbfe026432dc814341bc855892f90dd /shell/shell_common.c
parentfd6f295a98956b7f495ba09a56528ef9e0d51398 (diff)
downloadbusybox-w32-19358cc31317dca4642417066c1445ce00438e18.tar.gz
busybox-w32-19358cc31317dca4642417066c1445ce00438e18.tar.bz2
busybox-w32-19358cc31317dca4642417066c1445ce00438e18.zip
ash,hush: fold shell_builtin_read() way-too-many params into a struct param
function old new delta getoptscmd 587 584 -3 readcmd 240 224 -16 shell_builtin_read 1426 1399 -27 builtin_read 210 182 -28 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/4 up/down: 0/-74) Total: -74 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell/shell_common.c')
-rw-r--r--shell/shell_common.c55
1 files changed, 26 insertions, 29 deletions
diff --git a/shell/shell_common.c b/shell/shell_common.c
index 0a07296f3..f2bf5ab65 100644
--- a/shell/shell_common.c
+++ b/shell/shell_common.c
@@ -46,16 +46,7 @@ int FAST_FUNC is_well_formed_var_name(const char *s, char terminator)
46//Here we can simply store "VAR=" at buffer start and store read data directly 46//Here we can simply store "VAR=" at buffer start and store read data directly
47//after "=", then pass buffer to setvar() to consume. 47//after "=", then pass buffer to setvar() to consume.
48const char* FAST_FUNC 48const char* FAST_FUNC
49shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val), 49shell_builtin_read(struct builtin_read_params *params)
50 char **argv,
51 const char *ifs,
52 int read_flags,
53 const char *opt_n,
54 const char *opt_p,
55 const char *opt_t,
56 const char *opt_u,
57 const char *opt_d
58)
59{ 50{
60 struct pollfd pfd[1]; 51 struct pollfd pfd[1];
61#define fd (pfd[0].fd) /* -u FD */ 52#define fd (pfd[0].fd) /* -u FD */
@@ -70,9 +61,13 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val),
70 int bufpos; /* need to be able to hold -1 */ 61 int bufpos; /* need to be able to hold -1 */
71 int startword; 62 int startword;
72 smallint backslash; 63 smallint backslash;
64 char **argv;
65 const char *ifs;
66 int read_flags;
73 67
74 errno = err = 0; 68 errno = err = 0;
75 69
70 argv = params->argv;
76 pp = argv; 71 pp = argv;
77 while (*pp) { 72 while (*pp) {
78 if (!is_well_formed_var_name(*pp, '\0')) { 73 if (!is_well_formed_var_name(*pp, '\0')) {
@@ -84,29 +79,29 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val),
84 } 79 }
85 80
86 nchars = 0; /* if != 0, -n is in effect */ 81 nchars = 0; /* if != 0, -n is in effect */
87 if (opt_n) { 82 if (params->opt_n) {
88 nchars = bb_strtou(opt_n, NULL, 10); 83 nchars = bb_strtou(params->opt_n, NULL, 10);
89 if (nchars < 0 || errno) 84 if (nchars < 0 || errno)
90 return "invalid count"; 85 return "invalid count";
91 /* note: "-n 0": off (bash 3.2 does this too) */ 86 /* note: "-n 0": off (bash 3.2 does this too) */
92 } 87 }
93 88
94 end_ms = 0; 89 end_ms = 0;
95 if (opt_t && !ENABLE_FEATURE_SH_READ_FRAC) { 90 if (params->opt_t && !ENABLE_FEATURE_SH_READ_FRAC) {
96 end_ms = bb_strtou(opt_t, NULL, 10); 91 end_ms = bb_strtou(params->opt_t, NULL, 10);
97 if (errno) 92 if (errno)
98 return "invalid timeout"; 93 return "invalid timeout";
99 if (end_ms > UINT_MAX / 2048) /* be safely away from overflow */ 94 if (end_ms > UINT_MAX / 2048) /* be safely away from overflow */
100 end_ms = UINT_MAX / 2048; 95 end_ms = UINT_MAX / 2048;
101 end_ms *= 1000; 96 end_ms *= 1000;
102 } 97 }
103 if (opt_t && ENABLE_FEATURE_SH_READ_FRAC) { 98 if (params->opt_t && ENABLE_FEATURE_SH_READ_FRAC) {
104 /* bash 4.3 (maybe earlier) supports -t N.NNNNNN */ 99 /* bash 4.3 (maybe earlier) supports -t N.NNNNNN */
105 char *p; 100 char *p;
106 /* Eat up to three fractional digits */ 101 /* Eat up to three fractional digits */
107 int frac_digits = 3 + 1; 102 int frac_digits = 3 + 1;
108 103
109 end_ms = bb_strtou(opt_t, &p, 10); 104 end_ms = bb_strtou(params->opt_t, &p, 10);
110 if (end_ms > UINT_MAX / 2048) /* be safely away from overflow */ 105 if (end_ms > UINT_MAX / 2048) /* be safely away from overflow */
111 end_ms = UINT_MAX / 2048; 106 end_ms = UINT_MAX / 2048;
112 107
@@ -128,13 +123,13 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val),
128 } 123 }
129 124
130 fd = STDIN_FILENO; 125 fd = STDIN_FILENO;
131 if (opt_u) { 126 if (params->opt_u) {
132 fd = bb_strtou(opt_u, NULL, 10); 127 fd = bb_strtou(params->opt_u, NULL, 10);
133 if (fd < 0 || errno) 128 if (fd < 0 || errno)
134 return "invalid file descriptor"; 129 return "invalid file descriptor";
135 } 130 }
136 131
137 if (opt_t && end_ms == 0) { 132 if (params->opt_t && end_ms == 0) {
138 /* "If timeout is 0, read returns immediately, without trying 133 /* "If timeout is 0, read returns immediately, without trying
139 * to read any data. The exit status is 0 if input is available 134 * to read any data. The exit status is 0 if input is available
140 * on the specified file descriptor, non-zero otherwise." 135 * on the specified file descriptor, non-zero otherwise."
@@ -147,14 +142,16 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val),
147 return (const char *)(uintptr_t)(r <= 0); 142 return (const char *)(uintptr_t)(r <= 0);
148 } 143 }
149 144
150 if (opt_p && isatty(fd)) { 145 if (params->opt_p && isatty(fd)) {
151 fputs(opt_p, stderr); 146 fputs(params->opt_p, stderr);
152 fflush_all(); 147 fflush_all();
153 } 148 }
154 149
150 ifs = params->ifs;
155 if (ifs == NULL) 151 if (ifs == NULL)
156 ifs = defifs; 152 ifs = defifs;
157 153
154 read_flags = params->read_flags;
158 if (nchars || (read_flags & BUILTIN_READ_SILENT)) { 155 if (nchars || (read_flags & BUILTIN_READ_SILENT)) {
159 tcgetattr(fd, &tty); 156 tcgetattr(fd, &tty);
160 old_tty = tty; 157 old_tty = tty;
@@ -181,11 +178,11 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val),
181 retval = (const char *)(uintptr_t)0; 178 retval = (const char *)(uintptr_t)0;
182 startword = 1; 179 startword = 1;
183 backslash = 0; 180 backslash = 0;
184 if (opt_t) 181 if (params->opt_t)
185 end_ms += (unsigned)monotonic_ms(); 182 end_ms += (unsigned)monotonic_ms();
186 buffer = NULL; 183 buffer = NULL;
187 bufpos = 0; 184 bufpos = 0;
188 delim = opt_d ? *opt_d : '\n'; 185 delim = params->opt_d ? params->opt_d[0] : '\n';
189 do { 186 do {
190 char c; 187 char c;
191 int timeout; 188 int timeout;
@@ -194,7 +191,7 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val),
194 buffer = xrealloc(buffer, bufpos + 0x101); 191 buffer = xrealloc(buffer, bufpos + 0x101);
195 192
196 timeout = -1; 193 timeout = -1;
197 if (opt_t) { 194 if (params->opt_t) {
198 timeout = end_ms - (unsigned)monotonic_ms(); 195 timeout = end_ms - (unsigned)monotonic_ms();
199 /* ^^^^^^^^^^^^^ all values are unsigned, 196 /* ^^^^^^^^^^^^^ all values are unsigned,
200 * wrapping math is used here, good even if 197 * wrapping math is used here, good even if
@@ -246,7 +243,7 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val),
246 * without variable names (bash compat). 243 * without variable names (bash compat).
247 * Thus, "read" and "read REPLY" are not the same. 244 * Thus, "read" and "read REPLY" are not the same.
248 */ 245 */
249 if (!opt_d && argv[0]) { 246 if (!params->opt_d && argv[0]) {
250/* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05 */ 247/* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05 */
251 const char *is_ifs = strchr(ifs, c); 248 const char *is_ifs = strchr(ifs, c);
252 if (startword && is_ifs) { 249 if (startword && is_ifs) {
@@ -261,7 +258,7 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val),
261 if (argv[1] != NULL && is_ifs) { 258 if (argv[1] != NULL && is_ifs) {
262 buffer[bufpos] = '\0'; 259 buffer[bufpos] = '\0';
263 bufpos = 0; 260 bufpos = 0;
264 setvar(*argv, buffer); 261 params->setvar(*argv, buffer);
265 argv++; 262 argv++;
266 /* can we skip one non-space ifs char? (2: yes) */ 263 /* can we skip one non-space ifs char? (2: yes) */
267 startword = isspace(c) ? 2 : 1; 264 startword = isspace(c) ? 2 : 1;
@@ -313,14 +310,14 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val),
313 } 310 }
314 311
315 /* Use the remainder as a value for the next variable */ 312 /* Use the remainder as a value for the next variable */
316 setvar(*argv, buffer); 313 params->setvar(*argv, buffer);
317 /* Set the rest to "" */ 314 /* Set the rest to "" */
318 while (*++argv) 315 while (*++argv)
319 setvar(*argv, ""); 316 params->setvar(*argv, "");
320 } else { 317 } else {
321 /* Note: no $IFS removal */ 318 /* Note: no $IFS removal */
322 buffer[bufpos] = '\0'; 319 buffer[bufpos] = '\0';
323 setvar("REPLY", buffer); 320 params->setvar("REPLY", buffer);
324 } 321 }
325 322
326 ret: 323 ret: