aboutsummaryrefslogtreecommitdiff
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
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>
-rw-r--r--shell/ash.c38
-rw-r--r--shell/hush.c33
-rw-r--r--shell/shell_common.c55
-rw-r--r--shell/shell_common.h22
4 files changed, 64 insertions, 84 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 4641dfd19..f74bef6b1 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -13762,38 +13762,35 @@ letcmd(int argc UNUSED_PARAM, char **argv)
13762static int FAST_FUNC 13762static int FAST_FUNC
13763readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) 13763readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13764{ 13764{
13765 char *opt_n = NULL; 13765 struct builtin_read_params params;
13766 char *opt_p = NULL;
13767 char *opt_t = NULL;
13768 char *opt_u = NULL;
13769 char *opt_d = NULL; /* optimized out if !BASH */
13770 int read_flags = 0;
13771 const char *r; 13766 const char *r;
13772 int i; 13767 int i;
13773 13768
13769 memset(&params, 0, sizeof(params));
13770
13774 while ((i = nextopt("p:u:rt:n:sd:")) != '\0') { 13771 while ((i = nextopt("p:u:rt:n:sd:")) != '\0') {
13775 switch (i) { 13772 switch (i) {
13776 case 'p': 13773 case 'p':
13777 opt_p = optionarg; 13774 params.opt_p = optionarg;
13778 break; 13775 break;
13779 case 'n': 13776 case 'n':
13780 opt_n = optionarg; 13777 params.opt_n = optionarg;
13781 break; 13778 break;
13782 case 's': 13779 case 's':
13783 read_flags |= BUILTIN_READ_SILENT; 13780 params.read_flags |= BUILTIN_READ_SILENT;
13784 break; 13781 break;
13785 case 't': 13782 case 't':
13786 opt_t = optionarg; 13783 params.opt_t = optionarg;
13787 break; 13784 break;
13788 case 'r': 13785 case 'r':
13789 read_flags |= BUILTIN_READ_RAW; 13786 params.read_flags |= BUILTIN_READ_RAW;
13790 break; 13787 break;
13791 case 'u': 13788 case 'u':
13792 opt_u = optionarg; 13789 params.opt_u = optionarg;
13793 break; 13790 break;
13794#if BASH_READ_D 13791#if BASH_READ_D
13795 case 'd': 13792 case 'd':
13796 opt_d = optionarg; 13793 params.opt_d = optionarg;
13797 break; 13794 break;
13798#endif 13795#endif
13799 default: 13796 default:
@@ -13801,21 +13798,16 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13801 } 13798 }
13802 } 13799 }
13803 13800
13801 params.argv = argptr;
13802 params.setvar = setvar0;
13803 params.ifs = bltinlookup("IFS"); /* can be NULL */
13804
13804 /* "read -s" needs to save/restore termios, can't allow ^C 13805 /* "read -s" needs to save/restore termios, can't allow ^C
13805 * to jump out of it. 13806 * to jump out of it.
13806 */ 13807 */
13807 again: 13808 again:
13808 INT_OFF; 13809 INT_OFF;
13809 r = shell_builtin_read(setvar0, 13810 r = shell_builtin_read(&params);
13810 argptr,
13811 bltinlookup("IFS"), /* can be NULL */
13812 read_flags,
13813 opt_n,
13814 opt_p,
13815 opt_t,
13816 opt_u,
13817 opt_d
13818 );
13819 INT_ON; 13811 INT_ON;
13820 13812
13821 if ((uintptr_t)r == 1 && errno == EINTR) { 13813 if ((uintptr_t)r == 1 && errno == EINTR) {
diff --git a/shell/hush.c b/shell/hush.c
index 4c8814a01..3c19bceaa 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -10500,40 +10500,29 @@ static int FAST_FUNC builtin_type(char **argv)
10500static int FAST_FUNC builtin_read(char **argv) 10500static int FAST_FUNC builtin_read(char **argv)
10501{ 10501{
10502 const char *r; 10502 const char *r;
10503 char *opt_n = NULL; 10503 struct builtin_read_params params;
10504 char *opt_p = NULL; 10504
10505 char *opt_t = NULL; 10505 memset(&params, 0, sizeof(params));
10506 char *opt_u = NULL;
10507 char *opt_d = NULL; /* optimized out if !BASH */
10508 const char *ifs;
10509 int read_flags;
10510 10506
10511 /* "!": do not abort on errors. 10507 /* "!": do not abort on errors.
10512 * Option string must start with "sr" to match BUILTIN_READ_xxx 10508 * Option string must start with "sr" to match BUILTIN_READ_xxx
10513 */ 10509 */
10514 read_flags = getopt32(argv, 10510 params.read_flags = getopt32(argv,
10515#if BASH_READ_D 10511#if BASH_READ_D
10516 "!srn:p:t:u:d:", &opt_n, &opt_p, &opt_t, &opt_u, &opt_d 10512 "!srn:p:t:u:d:", &params.opt_n, &params.opt_p, &params.opt_t, &params.opt_u, &params.opt_d
10517#else 10513#else
10518 "!srn:p:t:u:", &opt_n, &opt_p, &opt_t, &opt_u 10514 "!srn:p:t:u:", &params.opt_n, &params.opt_p, &params.opt_t, &params.opt_u
10519#endif 10515#endif
10520 ); 10516 );
10521 if (read_flags == (uint32_t)-1) 10517 if ((uint32_t)params.read_flags == (uint32_t)-1)
10522 return EXIT_FAILURE; 10518 return EXIT_FAILURE;
10523 argv += optind; 10519 argv += optind;
10524 ifs = get_local_var_value("IFS"); /* can be NULL */ 10520 params.argv = argv;
10521 params.setvar = set_local_var_from_halves;
10522 params.ifs = get_local_var_value("IFS"); /* can be NULL */
10525 10523
10526 again: 10524 again:
10527 r = shell_builtin_read(set_local_var_from_halves, 10525 r = shell_builtin_read(&params);
10528 argv,
10529 ifs,
10530 read_flags,
10531 opt_n,
10532 opt_p,
10533 opt_t,
10534 opt_u,
10535 opt_d
10536 );
10537 10526
10538 if ((uintptr_t)r == 1 && errno == EINTR) { 10527 if ((uintptr_t)r == 1 && errno == EINTR) {
10539 unsigned sig = check_and_run_traps(); 10528 unsigned sig = check_and_run_traps();
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:
diff --git a/shell/shell_common.h b/shell/shell_common.h
index 875fd9ea7..a1323021d 100644
--- a/shell/shell_common.h
+++ b/shell/shell_common.h
@@ -30,6 +30,17 @@ int FAST_FUNC is_well_formed_var_name(const char *s, char terminator);
30 30
31/* Builtins */ 31/* Builtins */
32 32
33struct builtin_read_params {
34 int read_flags;
35 void FAST_FUNC (*setvar)(const char *name, const char *val);
36 char **argv;
37 const char *ifs;
38 const char *opt_n;
39 const char *opt_p;
40 const char *opt_t;
41 const char *opt_u;
42 const char *opt_d;
43};
33enum { 44enum {
34 BUILTIN_READ_SILENT = 1 << 0, 45 BUILTIN_READ_SILENT = 1 << 0,
35 BUILTIN_READ_RAW = 1 << 1, 46 BUILTIN_READ_RAW = 1 << 1,
@@ -40,16 +51,7 @@ enum {
40// shell_builtin_read(setvar,argv,ifs,read_flags) 51// shell_builtin_read(setvar,argv,ifs,read_flags)
41//#endif 52//#endif
42const char* FAST_FUNC 53const char* FAST_FUNC
43shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val), 54shell_builtin_read(struct builtin_read_params *params);
44 char **argv,
45 const char *ifs,
46 int read_flags,
47 const char *opt_n,
48 const char *opt_p,
49 const char *opt_t,
50 const char *opt_u,
51 const char *opt_d
52);
53 55
54int FAST_FUNC 56int FAST_FUNC
55shell_builtin_ulimit(char **argv); 57shell_builtin_ulimit(char **argv);