aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2025-07-31 18:35:11 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2025-07-31 18:35:11 +0200
commit551bfdb97f45f0277a408ec2d44ee18967b98304 (patch)
tree6aaeb1b0e4319b3eae4a4e5fb0f3a690e6afe914
parenta98b95b715359a8b002d1cb8e1f998a4afa2c73e (diff)
downloadbusybox-w32-551bfdb97f45f0277a408ec2d44ee18967b98304.tar.gz
busybox-w32-551bfdb97f45f0277a408ec2d44ee18967b98304.tar.bz2
busybox-w32-551bfdb97f45f0277a408ec2d44ee18967b98304.zip
ls: implement -q, fix -w0, reduce startup time
function old new delta ls_main 598 660 +62 ls_longopts - 47 +47 G_isatty - 36 +36 print_name 102 134 +32 display_files 358 374 +16 .rodata 105829 105833 +4 vgetopt32 1330 1317 -13 static.ls_longopts 47 - -47 ------------------------------------------------------------------------------ (add/remove: 2/1 grow/shrink: 4/1 up/down: 197/-60) Total: 137 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--coreutils/ls.c171
-rw-r--r--libbb/getopt32.c13
2 files changed, 122 insertions, 62 deletions
diff --git a/coreutils/ls.c b/coreutils/ls.c
index cc809b797..eaccd1a17 100644
--- a/coreutils/ls.c
+++ b/coreutils/ls.c
@@ -126,6 +126,8 @@
126//usage: "\n -F Append indicator (one of */=@|) to names" 126//usage: "\n -F Append indicator (one of */=@|) to names"
127//usage: ) 127//usage: )
128//usage: "\n -l Long format" 128//usage: "\n -l Long format"
129////usage: "\n -g Long format without group column"
130////TODO: support -G too ("suppress owner column", GNUism)
129//usage: "\n -i List inode numbers" 131//usage: "\n -i List inode numbers"
130//usage: "\n -n List numeric UIDs and GIDs instead of names" 132//usage: "\n -n List numeric UIDs and GIDs instead of names"
131//usage: "\n -s List allocated blocks" 133//usage: "\n -s List allocated blocks"
@@ -159,6 +161,8 @@
159//usage: IF_FEATURE_LS_WIDTH( 161//usage: IF_FEATURE_LS_WIDTH(
160//usage: "\n -w N Format N columns wide" 162//usage: "\n -w N Format N columns wide"
161//usage: ) 163//usage: )
164////usage: "\n -Q Double-quote names"
165////usage: "\n -q Replace unprintable chars with '?'"
162//usage: IF_FEATURE_LS_COLOR( 166//usage: IF_FEATURE_LS_COLOR(
163//usage: "\n --color[={always,never,auto}]" 167//usage: "\n --color[={always,never,auto}]"
164//usage: ) 168//usage: )
@@ -196,27 +200,47 @@ SPLIT_SUBDIR = 2,
196 200
197/* -Cadi1l Std options, busybox always supports */ 201/* -Cadi1l Std options, busybox always supports */
198/* -gnsxA Std options, busybox always supports */ 202/* -gnsxA Std options, busybox always supports */
199/* -Q GNU option, busybox always supports */ 203/* -Q GNU option, busybox always supports: */
200/* -k Std option, busybox always supports (by ignoring) */ 204/* -Q, --quote-name */
201/* It means "for -s, show sizes in kbytes" */ 205/* enclose entry names in double quotes */
202/* Seems to only affect "POSIXLY_CORRECT=1 ls -sk" */
203/* since otherwise -s shows kbytes anyway */
204/* -LHRctur Std options, busybox optionally supports */ 206/* -LHRctur Std options, busybox optionally supports */
205/* -Fp Std options, busybox optionally supports */ 207/* -Fp Std options, busybox optionally supports */
206/* -SXvhTw GNU options, busybox optionally supports */ 208/* -SXvhTw GNU options, busybox optionally supports */
207/* -T WIDTH Ignored (we don't use tabs on output) */ 209/* -T WIDTH Ignored (we don't use tabs on output) */
208/* -Z SELinux mandated option, busybox optionally supports */ 210/* -Z SELinux mandated option, busybox optionally supports */
211/* -q Std option, busybox always supports: */
212/* https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html: */
213/* Force each instance of non-printable filename characters and */
214/* <tab> characters to be written as the <question-mark> ('?') */
215/* character. Implementations may provide this option by default */
216/* if the output is to a terminal device. */
217/* -k Std option, busybox always supports (by ignoring) */
218/* It means "for -s, show sizes in kbytes" */
219/* Seems to only affect "POSIXLY_CORRECT=1 ls -sk" */
220/* since otherwise -s shows kbytes anyway */
209#define ls_options \ 221#define ls_options \
210 "Cadi1lgnsxAk" /* 12 opts, total 12 */ \ 222 "Cadi1lgnsxA" /* 11 opts, total 11 */ \
211 IF_FEATURE_LS_FILETYPES("Fp") /* 2, 14 */ \ 223 IF_FEATURE_LS_FILETYPES("Fp") /* 2, 13 */ \
212 IF_FEATURE_LS_RECURSIVE("R") /* 1, 15 */ \ 224 IF_FEATURE_LS_RECURSIVE("R") /* 1, 14 */ \
213 IF_SELINUX("Z") /* 1, 16 */ \ 225 IF_SELINUX("Z") /* 1, 15 */ \
214 "Q" /* 1, 17 */ \ 226 "Q" /* 1, 16 */ \
215 IF_FEATURE_LS_TIMESTAMPS("ctu") /* 3, 20 */ \ 227 IF_FEATURE_LS_TIMESTAMPS("ctu") /* 3, 19 */ \
216 IF_FEATURE_LS_SORTFILES("SXrv") /* 4, 24 */ \ 228 IF_FEATURE_LS_SORTFILES("SXrv") /* 4, 23 */ \
217 IF_FEATURE_LS_FOLLOWLINKS("LH") /* 2, 26 */ \ 229 IF_FEATURE_LS_FOLLOWLINKS("LH") /* 2, 25 */ \
218 IF_FEATURE_HUMAN_READABLE("h") /* 1, 27 */ \ 230 IF_FEATURE_HUMAN_READABLE("h") /* 1, 26 */ \
219 IF_FEATURE_LS_WIDTH("T:w:") /* 2, 29 */ 231 IF_FEATURE_LS_WIDTH("T:w:") /* 2, 28 */ \
232 IF_LONG_OPTS("\xff") /* 1, 29 */ \
233 IF_LONG_OPTS("\xfe") /* 1, 30 */ \
234 IF_LONG_OPTS("\xfd") /* 1, 31 */ \
235 "qk" /* 2, 33 */
236
237#if ENABLE_LONG_OPTS
238static const char ls_longopts[] ALIGN1 =
239 "full-time\0" No_argument "\xff"
240 "group-directories-first\0" No_argument "\xfe"
241 IF_FEATURE_LS_COLOR("color\0" Optional_argument "\xfd")
242;
243#endif
220 244
221enum { 245enum {
222 OPT_C = (1 << 0), 246 OPT_C = (1 << 0),
@@ -230,29 +254,31 @@ enum {
230 OPT_s = (1 << 8), 254 OPT_s = (1 << 8),
231 OPT_x = (1 << 9), 255 OPT_x = (1 << 9),
232 OPT_A = (1 << 10), 256 OPT_A = (1 << 10),
233 //OPT_k = (1 << 11),
234 257
235 OPTBIT_F = 12, 258 OPTBIT_F = 11,
236 OPTBIT_p, /* 13 */ 259 OPTBIT_p, /* 12 */
237 OPTBIT_R = OPTBIT_F + 2 * ENABLE_FEATURE_LS_FILETYPES, 260 OPTBIT_R = OPTBIT_F + 2 * ENABLE_FEATURE_LS_FILETYPES,
238 OPTBIT_Z = OPTBIT_R + 1 * ENABLE_FEATURE_LS_RECURSIVE, 261 OPTBIT_Z = OPTBIT_R + 1 * ENABLE_FEATURE_LS_RECURSIVE,
239 OPTBIT_Q = OPTBIT_Z + 1 * ENABLE_SELINUX, 262 OPTBIT_Q = OPTBIT_Z + 1 * ENABLE_SELINUX,
240 OPTBIT_c, /* 17 */ 263 OPTBIT_c, /* 16 */
241 OPTBIT_t, /* 18 */ 264 OPTBIT_t, /* 17 */
242 OPTBIT_u, /* 19 */ 265 OPTBIT_u, /* 18 */
243 OPTBIT_S = OPTBIT_c + 3 * ENABLE_FEATURE_LS_TIMESTAMPS, 266 OPTBIT_S = OPTBIT_c + 3 * ENABLE_FEATURE_LS_TIMESTAMPS,
244 OPTBIT_X, /* 21 */ 267 OPTBIT_X, /* 20 */
245 OPTBIT_r, /* 22 */ 268 OPTBIT_r, /* 21 */
246 OPTBIT_v, /* 23 */ 269 OPTBIT_v, /* 22 */
247 OPTBIT_L = OPTBIT_S + 4 * ENABLE_FEATURE_LS_SORTFILES, 270 OPTBIT_L = OPTBIT_S + 4 * ENABLE_FEATURE_LS_SORTFILES,
248 OPTBIT_H, /* 25 */ 271 OPTBIT_H, /* 24 */
249 OPTBIT_h = OPTBIT_L + 2 * ENABLE_FEATURE_LS_FOLLOWLINKS, 272 OPTBIT_h = OPTBIT_L + 2 * ENABLE_FEATURE_LS_FOLLOWLINKS,
250 OPTBIT_T = OPTBIT_h + 1 * ENABLE_FEATURE_HUMAN_READABLE, 273 OPTBIT_T = OPTBIT_h + 1 * ENABLE_FEATURE_HUMAN_READABLE,
251 OPTBIT_w, /* 28 */ 274 OPTBIT_w, /* 27 */
252 OPTBIT_full_time = OPTBIT_T + 2 * ENABLE_FEATURE_LS_WIDTH, 275 OPTBIT_full_time = OPTBIT_T + 2 * ENABLE_FEATURE_LS_WIDTH,
253 OPTBIT_dirs_first, 276 OPTBIT_dirs_first,
254 OPTBIT_color, /* 31 */ 277 OPTBIT_color, /* 30 */
255 /* with long opts, we use all 32 bits */ 278 OPTBIT_q = OPTBIT_color + 1, /* 31 */
279 OPTBIT_k = OPTBIT_q + 1, /* 32 */
280 /* with all options enabled, we use all 32 bits and even one extra bit! */
281 /* this works because -k is ignored, and getopt32 allows such "ignore" options past 31th bit */
256 282
257 OPT_F = (1 << OPTBIT_F) * ENABLE_FEATURE_LS_FILETYPES, 283 OPT_F = (1 << OPTBIT_F) * ENABLE_FEATURE_LS_FILETYPES,
258 OPT_p = (1 << OPTBIT_p) * ENABLE_FEATURE_LS_FILETYPES, 284 OPT_p = (1 << OPTBIT_p) * ENABLE_FEATURE_LS_FILETYPES,
@@ -274,6 +300,8 @@ enum {
274 OPT_full_time = (1 << OPTBIT_full_time ) * ENABLE_LONG_OPTS, 300 OPT_full_time = (1 << OPTBIT_full_time ) * ENABLE_LONG_OPTS,
275 OPT_dirs_first = (1 << OPTBIT_dirs_first) * ENABLE_LONG_OPTS, 301 OPT_dirs_first = (1 << OPTBIT_dirs_first) * ENABLE_LONG_OPTS,
276 OPT_color = (1 << OPTBIT_color ) * ENABLE_FEATURE_LS_COLOR, 302 OPT_color = (1 << OPTBIT_color ) * ENABLE_FEATURE_LS_COLOR,
303 OPT_q = (1 << OPTBIT_q),
304 //-k is ignored: OPT_k = (1 << OPTBIT_k),
277}; 305};
278 306
279/* 307/*
@@ -327,6 +355,7 @@ struct globals {
327#endif 355#endif
328 smallint exit_code; 356 smallint exit_code;
329 smallint show_dirname; 357 smallint show_dirname;
358 smallint tty_out;
330#if ENABLE_FEATURE_LS_WIDTH 359#if ENABLE_FEATURE_LS_WIDTH
331 unsigned terminal_width; 360 unsigned terminal_width;
332# define G_terminal_width (G.terminal_width) 361# define G_terminal_width (G.terminal_width)
@@ -343,16 +372,21 @@ struct globals {
343 setup_common_bufsiz(); \ 372 setup_common_bufsiz(); \
344 /* we have to zero it out because of NOEXEC */ \ 373 /* we have to zero it out because of NOEXEC */ \
345 memset(&G, 0, sizeof(G)); \ 374 memset(&G, 0, sizeof(G)); \
346 IF_FEATURE_LS_WIDTH(G_terminal_width = TERMINAL_WIDTH;) \ 375 IF_FEATURE_LS_WIDTH(G_terminal_width = ~0U;) \
347 IF_FEATURE_LS_TIMESTAMPS(time(&G.current_time_t);) \ 376 IF_FEATURE_LS_TIMESTAMPS(time(&G.current_time_t);) \
348} while (0) 377} while (0)
349 378
350#define ESC "\033" 379#define ESC "\033"
351 380
381static int G_isatty(void)
382{
383 if (!G.tty_out) /* not known yet? */
384 G.tty_out = isatty(STDOUT_FILENO) + 1;
385 return (G.tty_out == 2);
386}
352 387
353/*** Output code ***/ 388/*** Output code ***/
354 389
355
356/* FYI type values: 1:fifo 2:char 4:dir 6:blk 8:file 10:link 12:socket 390/* FYI type values: 1:fifo 2:char 4:dir 6:blk 8:file 10:link 12:socket
357 * (various wacky OSes: 13:Sun door 14:BSD whiteout 5:XENIX named file 391 * (various wacky OSes: 13:Sun door 14:BSD whiteout 5:XENIX named file
358 * 3/7:multiplexed char/block device) 392 * 3/7:multiplexed char/block device)
@@ -420,6 +454,9 @@ static unsigned calc_name_len(const char *name)
420 unsigned len; 454 unsigned len;
421 uni_stat_t uni_stat; 455 uni_stat_t uni_stat;
422 456
457 if (!(option_mask32 & OPT_q))
458 return strlen(name);
459
423 // TODO: quote tab as \t, etc, if -Q 460 // TODO: quote tab as \t, etc, if -Q
424 name = printable_string2(&uni_stat, name); 461 name = printable_string2(&uni_stat, name);
425 462
@@ -449,6 +486,11 @@ static unsigned print_name(const char *name)
449 unsigned len; 486 unsigned len;
450 uni_stat_t uni_stat; 487 uni_stat_t uni_stat;
451 488
489 if (!(option_mask32 & OPT_q)) {
490 fputs_stdout(name);
491 return strlen(name);
492 }
493
452 // TODO: quote tab as \t, etc, if -Q 494 // TODO: quote tab as \t, etc, if -Q
453 name = printable_string2(&uni_stat, name); 495 name = printable_string2(&uni_stat, name);
454 496
@@ -646,7 +688,7 @@ static void display_files(struct dnode **dn, unsigned nfiles)
646 unsigned i, ncols, nrows, row, nc; 688 unsigned i, ncols, nrows, row, nc;
647 unsigned column; 689 unsigned column;
648 unsigned nexttab; 690 unsigned nexttab;
649 unsigned column_width = 0; /* used only by coulmnal output */ 691 unsigned column_width = 0; /* used only by columnar output */
650 692
651 if (option_mask32 & (OPT_l|OPT_1)) { 693 if (option_mask32 & (OPT_l|OPT_1)) {
652 ncols = 1; 694 ncols = 1;
@@ -691,6 +733,11 @@ static void display_files(struct dnode **dn, unsigned nfiles)
691 } 733 }
692 nexttab = column + column_width; 734 nexttab = column + column_width;
693 column += display_single(dn[i]); 735 column += display_single(dn[i]);
736 } else {
737 /* if -w999999999, ncols can be very large */
738 //bb_error_msg(" col:%u ncol:%u i:%i", nc, ncols, i); sleep1();
739 /* without "break", we loop millions of times here */
740 break;
694 } 741 }
695 } 742 }
696 putchar('\n'); 743 putchar('\n');
@@ -1090,25 +1137,11 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1090 /* need to initialize since --color has _an optional_ argument */ 1137 /* need to initialize since --color has _an optional_ argument */
1091 const char *color_opt = color_str; /* "always" */ 1138 const char *color_opt = color_str; /* "always" */
1092#endif 1139#endif
1093#if ENABLE_LONG_OPTS
1094 static const char ls_longopts[] ALIGN1 =
1095 "full-time\0" No_argument "\xff"
1096 "group-directories-first\0" No_argument "\xfe"
1097 IF_FEATURE_LS_COLOR("color\0" Optional_argument "\xfd")
1098 ;
1099#endif
1100 1140
1101 INIT_G(); 1141 INIT_G();
1102 1142
1103 init_unicode(); 1143 init_unicode();
1104 1144
1105#if ENABLE_FEATURE_LS_WIDTH
1106 /* obtain the terminal width */
1107 G_terminal_width = get_terminal_width(STDIN_FILENO);
1108 /* go one less... */
1109 G_terminal_width--;
1110#endif
1111
1112 /* process options */ 1145 /* process options */
1113 opt = getopt32long(argv, "^" 1146 opt = getopt32long(argv, "^"
1114 ls_options 1147 ls_options
@@ -1144,6 +1177,17 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1144 exit(0); 1177 exit(0);
1145#endif 1178#endif
1146 1179
1180#if ENABLE_FEATURE_LS_WIDTH
1181 if ((int)G_terminal_width < 0) {
1182 /* obtain the terminal width */
1183 G_terminal_width = get_terminal_width(STDIN_FILENO);
1184 /* go one less... */
1185 G_terminal_width--;
1186 }
1187 if (G_terminal_width == 0) /* -w0 */
1188 G_terminal_width = INT_MAX; /* "infinite" */
1189#endif
1190
1147#if ENABLE_SELINUX 1191#if ENABLE_SELINUX
1148 if (opt & OPT_Z) { 1192 if (opt & OPT_Z) {
1149 if (!is_selinux_enabled()) 1193 if (!is_selinux_enabled())
@@ -1157,7 +1201,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1157 char *p = getenv("LS_COLORS"); 1201 char *p = getenv("LS_COLORS");
1158 /* LS_COLORS is unset, or (not empty && not "none") ? */ 1202 /* LS_COLORS is unset, or (not empty && not "none") ? */
1159 if (!p || (p[0] && strcmp(p, "none") != 0)) { 1203 if (!p || (p[0] && strcmp(p, "none") != 0)) {
1160 if (isatty(STDOUT_FILENO)) { 1204 if (G_isatty()) {
1161 /* check isatty() last because it's expensive (syscall) */ 1205 /* check isatty() last because it's expensive (syscall) */
1162 G_show_color = 1; 1206 G_show_color = 1;
1163 } 1207 }
@@ -1166,15 +1210,19 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1166 if (opt & OPT_color) { 1210 if (opt & OPT_color) {
1167 if (color_opt[0] == 'n') 1211 if (color_opt[0] == 'n')
1168 G_show_color = 0; 1212 G_show_color = 0;
1169 else switch (index_in_substrings(color_str, color_opt)) { 1213 else if (!G_show_color) {
1170 case 3: 1214 /* if() is not needed, but avoids extra isatty() if G_show_color is already set */
1171 case 4: 1215 /* Check --color=COLOR_OPT and maybe set show_color=1 */
1172 case 5: 1216 switch (index_in_substrings(color_str, color_opt)) {
1173 if (!is_TERM_dumb() && isatty(STDOUT_FILENO)) { 1217 case 3: // auto
1174 case 0: 1218 case 4: // tty
1175 case 1: 1219 case 5: // if-tty
1176 case 2: 1220 if (!is_TERM_dumb() && G_isatty()) {
1177 G_show_color = 1; 1221 case 0: // always
1222 case 1: // yes
1223 case 2: // force
1224 G_show_color = 1;
1225 }
1178 } 1226 }
1179 } 1227 }
1180 } 1228 }
@@ -1182,7 +1230,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1182 1230
1183 /* sort out which command line options take precedence */ 1231 /* sort out which command line options take precedence */
1184 if (ENABLE_FEATURE_LS_RECURSIVE && (opt & OPT_d)) 1232 if (ENABLE_FEATURE_LS_RECURSIVE && (opt & OPT_d))
1185 option_mask32 &= ~OPT_R; /* no recurse if listing only dir */ 1233 opt = option_mask32 &= ~OPT_R; /* no recurse if listing only dir */
1186 if (!(opt & OPT_l)) { /* not -l? */ 1234 if (!(opt & OPT_l)) { /* not -l? */
1187 if (ENABLE_FEATURE_LS_TIMESTAMPS && ENABLE_FEATURE_LS_SORTFILES) { 1235 if (ENABLE_FEATURE_LS_TIMESTAMPS && ENABLE_FEATURE_LS_SORTFILES) {
1188 /* when to sort by time? -t[cu] sorts by time even with -l */ 1236 /* when to sort by time? -t[cu] sorts by time even with -l */
@@ -1190,18 +1238,21 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1190 /* without -l, bare -c or -u enable sort too */ 1238 /* without -l, bare -c or -u enable sort too */
1191 /* (with -l, bare -c or -u just select which time to show) */ 1239 /* (with -l, bare -c or -u just select which time to show) */
1192 if (opt & (OPT_c|OPT_u)) { 1240 if (opt & (OPT_c|OPT_u)) {
1193 option_mask32 |= OPT_t; 1241 opt = option_mask32 |= OPT_t;
1194 } 1242 }
1195 } 1243 }
1196 } 1244 }
1197 1245
1198 /* choose a display format if one was not already specified by an option */ 1246 /* choose a display format if one was not already specified by an option */
1199 if (!(option_mask32 & (OPT_l|OPT_1|OPT_x|OPT_C))) 1247 if (!(opt & (OPT_l|OPT_1|OPT_x|OPT_C)))
1200 option_mask32 |= (isatty(STDOUT_FILENO) ? OPT_C : OPT_1); 1248 opt = option_mask32 |= (G_isatty() ? OPT_C : OPT_1);
1249
1250 if (!(opt & OPT_q) && G_isatty())
1251 opt = option_mask32 |= OPT_q;
1201 1252
1202 if (ENABLE_FTPD && applet_name[0] == 'f') { 1253 if (ENABLE_FTPD && applet_name[0] == 'f') {
1203 /* ftpd secret backdoor. dirs first are much nicer */ 1254 /* ftpd secret backdoor. dirs first are much nicer */
1204 option_mask32 |= OPT_dirs_first; 1255 opt = option_mask32 |= OPT_dirs_first;
1205 } 1256 }
1206 1257
1207 argv += optind; 1258 argv += optind;
diff --git a/libbb/getopt32.c b/libbb/getopt32.c
index b5efa19ac..4c05dcb97 100644
--- a/libbb/getopt32.c
+++ b/libbb/getopt32.c
@@ -530,6 +530,7 @@ vgetopt32(char **argv, const char *applet_opts, const char *applet_long_options,
530 * "fake" short options, like this one: 530 * "fake" short options, like this one:
531 * wget $'-\203' "Test: test" http://kernel.org/ 531 * wget $'-\203' "Test: test" http://kernel.org/
532 * (supposed to act as --header, but doesn't) */ 532 * (supposed to act as --header, but doesn't) */
533 next_opt:
533#if ENABLE_LONG_OPTS 534#if ENABLE_LONG_OPTS
534 while ((c = getopt_long(argc, argv, applet_opts, 535 while ((c = getopt_long(argc, argv, applet_opts,
535 long_options, NULL)) != -1) { 536 long_options, NULL)) != -1) {
@@ -544,8 +545,16 @@ vgetopt32(char **argv, const char *applet_opts, const char *applet_long_options,
544 * but we construct long opts so that flag 545 * but we construct long opts so that flag
545 * is always NULL (see above) */ 546 * is always NULL (see above) */
546 if (on_off->opt_char == '\0' /* && c != '\0' */) { 547 if (on_off->opt_char == '\0' /* && c != '\0' */) {
547 /* c is probably '?' - "bad option" */ 548 /* We reached the end of complementary[] and did not find -c */
548 goto error; 549 if (c == '?') /* getopt says: "bad option, or option has no required argument" */
550 goto error;
551 /* if there were options beyond 32 bits (example: ls),
552 * they got no complementary[] slot, and no result bit.
553 * IOW: they must be "accept but ignore" options.
554 * For them, we end up here.
555 */
556 //bb_error_msg("ignored option '%c', skipping", c);
557 goto next_opt;
549 } 558 }
550 } 559 }
551 if (flags & on_off->incongruously) 560 if (flags & on_off->incongruously)