aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2023-01-05 08:56:27 +0000
committerRon Yorston <rmy@pobox.com>2023-01-05 08:56:27 +0000
commite5e4a2fec5435192d1672e6db2f335cb5e89f877 (patch)
tree08cb827a40817ea4824bc9336d57eda669c4d4b2
parent4343f3926355f55fc023203c992527fc34bf609e (diff)
parentb1884deb514c35289d37e7bfbf23f770b0bd09b3 (diff)
downloadbusybox-w32-e5e4a2fec5435192d1672e6db2f335cb5e89f877.tar.gz
busybox-w32-e5e4a2fec5435192d1672e6db2f335cb5e89f877.tar.bz2
busybox-w32-e5e4a2fec5435192d1672e6db2f335cb5e89f877.zip
Merge branch 'busybox' into merge
-rw-r--r--Makefile2
-rw-r--r--Makefile.flags3
-rw-r--r--archival/unzip.c2
-rw-r--r--coreutils/dd.c20
-rw-r--r--coreutils/mv.c4
-rw-r--r--editors/sed.c17
-rw-r--r--findutils/xargs.c85
-rw-r--r--include/libbb.h8
-rw-r--r--libbb/Config.src22
-rw-r--r--libbb/lineedit.c24
-rw-r--r--libbb/loop.c175
-rw-r--r--networking/udhcp/Config.src7
-rw-r--r--networking/udhcp/common.h3
-rw-r--r--networking/udhcp/d6_common.h41
-rw-r--r--networking/udhcp/d6_dhcpc.c17
-rw-r--r--networking/udhcp/d6_packet.c15
-rw-r--r--networking/udhcp/d6_socket.c13
-rw-r--r--networking/udhcp/packet.c1
-rw-r--r--procps/pgrep.c15
-rw-r--r--shell/ash.c10
-rw-r--r--shell/hush.c19
-rwxr-xr-xtestsuite/mount.tests14
-rwxr-xr-xtestsuite/sha1sum.tests2
-rwxr-xr-xtestsuite/tree.tests38
-rw-r--r--util-linux/fbset.c6
-rw-r--r--util-linux/hexdump_xxd.c13
-rw-r--r--util-linux/more.c3
27 files changed, 397 insertions, 182 deletions
diff --git a/Makefile b/Makefile
index 333795e0d..3857dbc95 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
1VERSION = 1 1VERSION = 1
2PATCHLEVEL = 36 2PATCHLEVEL = 37
3SUBLEVEL = 0 3SUBLEVEL = 0
4EXTRAVERSION = .git 4EXTRAVERSION = .git
5NAME = Unnamed 5NAME = Unnamed
diff --git a/Makefile.flags b/Makefile.flags
index bf77c2492..aa6565cf7 100644
--- a/Makefile.flags
+++ b/Makefile.flags
@@ -196,6 +196,9 @@ ifeq ($(CONFIG_FEATURE_NSLOOKUP_BIG),y)
196ifneq (,$(findstring linux,$(shell $(CC) $(CFLAGS) -dumpmachine))) 196ifneq (,$(findstring linux,$(shell $(CC) $(CFLAGS) -dumpmachine)))
197LDLIBS += resolv 197LDLIBS += resolv
198endif 198endif
199ifneq (,$(findstring gnu,$(shell $(CC) $(CFLAGS) -dumpmachine)))
200LDLIBS += resolv
201endif
199endif 202endif
200 203
201ifeq ($(CONFIG_EFENCE),y) 204ifeq ($(CONFIG_EFENCE),y)
diff --git a/archival/unzip.c b/archival/unzip.c
index edfd73652..ff4f6325c 100644
--- a/archival/unzip.c
+++ b/archival/unzip.c
@@ -121,6 +121,8 @@ typedef union {
121#define FIX_ENDIANNESS_ZIP(zip) \ 121#define FIX_ENDIANNESS_ZIP(zip) \
122do { if (BB_BIG_ENDIAN) { \ 122do { if (BB_BIG_ENDIAN) { \
123 (zip).fmt.method = SWAP_LE16((zip).fmt.method ); \ 123 (zip).fmt.method = SWAP_LE16((zip).fmt.method ); \
124 (zip).fmt.modtime = SWAP_LE16((zip).fmt.modtime ); \
125 (zip).fmt.moddate = SWAP_LE16((zip).fmt.moddate ); \
124 (zip).fmt.crc32 = SWAP_LE32((zip).fmt.crc32 ); \ 126 (zip).fmt.crc32 = SWAP_LE32((zip).fmt.crc32 ); \
125 (zip).fmt.cmpsize = SWAP_LE32((zip).fmt.cmpsize ); \ 127 (zip).fmt.cmpsize = SWAP_LE32((zip).fmt.cmpsize ); \
126 (zip).fmt.ucmpsize = SWAP_LE32((zip).fmt.ucmpsize ); \ 128 (zip).fmt.ucmpsize = SWAP_LE32((zip).fmt.ucmpsize ); \
diff --git a/coreutils/dd.c b/coreutils/dd.c
index a3c9ababf..a704ca99b 100644
--- a/coreutils/dd.c
+++ b/coreutils/dd.c
@@ -203,6 +203,7 @@ static void dd_output_status(int UNUSED_PARAM cur_signal)
203} 203}
204 204
205#if ENABLE_FEATURE_DD_IBS_OBS 205#if ENABLE_FEATURE_DD_IBS_OBS
206# ifdef O_DIRECT
206static int clear_O_DIRECT(int fd) 207static int clear_O_DIRECT(int fd)
207{ 208{
208 if (errno == EINVAL) { 209 if (errno == EINVAL) {
@@ -214,6 +215,7 @@ static int clear_O_DIRECT(int fd)
214 } 215 }
215 return 0; 216 return 0;
216} 217}
218# endif
217#endif 219#endif
218 220
219static ssize_t dd_read(void *ibuf, size_t ibs) 221static ssize_t dd_read(void *ibuf, size_t ibs)
@@ -228,8 +230,10 @@ static ssize_t dd_read(void *ibuf, size_t ibs)
228#endif 230#endif
229 n = safe_read(ifd, ibuf, ibs); 231 n = safe_read(ifd, ibuf, ibs);
230#if ENABLE_FEATURE_DD_IBS_OBS 232#if ENABLE_FEATURE_DD_IBS_OBS
233# ifdef O_DIRECT
231 if (n < 0 && (G.flags & FLAG_IDIRECT) && clear_O_DIRECT(ifd)) 234 if (n < 0 && (G.flags & FLAG_IDIRECT) && clear_O_DIRECT(ifd))
232 goto read_again; 235 goto read_again;
236# endif
233#endif 237#endif
234 return n; 238 return n;
235} 239}
@@ -242,8 +246,10 @@ static bool write_and_stats(const void *buf, size_t len, size_t obs,
242 IF_FEATURE_DD_IBS_OBS(write_again:) 246 IF_FEATURE_DD_IBS_OBS(write_again:)
243 n = full_write(ofd, buf, len); 247 n = full_write(ofd, buf, len);
244#if ENABLE_FEATURE_DD_IBS_OBS 248#if ENABLE_FEATURE_DD_IBS_OBS
249# ifdef O_DIRECT
245 if (n < 0 && (G.flags & FLAG_ODIRECT) && clear_O_DIRECT(ofd)) 250 if (n < 0 && (G.flags & FLAG_ODIRECT) && clear_O_DIRECT(ofd))
246 goto write_again; 251 goto write_again;
252# endif
247#endif 253#endif
248 254
249#if ENABLE_FEATURE_DD_THIRD_STATUS_LINE 255#if ENABLE_FEATURE_DD_THIRD_STATUS_LINE
@@ -506,8 +512,13 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
506 if (infile) { 512 if (infile) {
507 int iflag = O_RDONLY; 513 int iflag = O_RDONLY;
508#if ENABLE_FEATURE_DD_IBS_OBS 514#if ENABLE_FEATURE_DD_IBS_OBS
509 if (G.flags & FLAG_IDIRECT) 515 if (G.flags & FLAG_IDIRECT) {
516# ifdef O_DIRECT
510 iflag |= O_DIRECT; 517 iflag |= O_DIRECT;
518# else
519 bb_error_msg_and_die("O_DIRECT not supported on this platform");
520# endif
521 }
511#endif 522#endif
512 xmove_fd(MINGW_SPECIAL(xopen)(infile, iflag), ifd); 523 xmove_fd(MINGW_SPECIAL(xopen)(infile, iflag), ifd);
513#if ENABLE_PLATFORM_MINGW32 524#if ENABLE_PLATFORM_MINGW32
@@ -524,8 +535,13 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
524 if (G.flags & FLAG_APPEND) 535 if (G.flags & FLAG_APPEND)
525 oflag |= O_APPEND; 536 oflag |= O_APPEND;
526#if ENABLE_FEATURE_DD_IBS_OBS 537#if ENABLE_FEATURE_DD_IBS_OBS
527 if (G.flags & FLAG_ODIRECT) 538 if (G.flags & FLAG_ODIRECT) {
539# ifdef O_DIRECT
528 oflag |= O_DIRECT; 540 oflag |= O_DIRECT;
541# else
542 bb_error_msg_and_die("O_DIRECT not supported on this platform");
543# endif
544 }
529#endif 545#endif
530 xmove_fd(xopen(outfile, oflag), ofd); 546 xmove_fd(xopen(outfile, oflag), ofd);
531 547
diff --git a/coreutils/mv.c b/coreutils/mv.c
index fd2422683..cf6169a1e 100644
--- a/coreutils/mv.c
+++ b/coreutils/mv.c
@@ -71,9 +71,9 @@ int mv_main(int argc, char **argv)
71 "no-target-directory\0" No_argument "T" 71 "no-target-directory\0" No_argument "T"
72 "target-directory\0" Required_argument "t" 72 "target-directory\0" Required_argument "t"
73 IF_FEATURE_VERBOSE( 73 IF_FEATURE_VERBOSE(
74 "verbose\0" No_argument "v", 74 "verbose\0" No_argument "v"
75 &last
76 ) 75 )
76 , &last
77 ); 77 );
78 argc -= optind; 78 argc -= optind;
79 argv += optind; 79 argv += optind;
diff --git a/editors/sed.c b/editors/sed.c
index f4a5f7b8a..07f7b7a9b 100644
--- a/editors/sed.c
+++ b/editors/sed.c
@@ -102,7 +102,7 @@ enum {
102 102
103struct sed_FILE { 103struct sed_FILE {
104 struct sed_FILE *next; /* Next (linked list, NULL terminated) */ 104 struct sed_FILE *next; /* Next (linked list, NULL terminated) */
105 const char *fname; 105 char *fname;
106 FILE *fp; 106 FILE *fp;
107}; 107};
108 108
@@ -194,9 +194,6 @@ static void sed_free_and_close_stuff(void)
194 while (sed_cmd) { 194 while (sed_cmd) {
195 sed_cmd_t *sed_cmd_next = sed_cmd->next; 195 sed_cmd_t *sed_cmd_next = sed_cmd->next;
196 196
197 if (sed_cmd->sw_file)
198 fclose(sed_cmd->sw_file);
199
200 /* Used to free regexps, but now there is code 197 /* Used to free regexps, but now there is code
201 * in get_address() which can reuse a regexp 198 * in get_address() which can reuse a regexp
202 * for constructs as /regexp/cmd1;//cmd2 199 * for constructs as /regexp/cmd1;//cmd2
@@ -223,6 +220,18 @@ static void sed_free_and_close_stuff(void)
223 220
224 if (G.current_fp) 221 if (G.current_fp)
225 fclose(G.current_fp); 222 fclose(G.current_fp);
223
224 if (G.FILE_head) {
225 struct sed_FILE *cur = G.FILE_head;
226 do {
227 struct sed_FILE *p;
228 fclose(cur->fp);
229 free(cur->fname);
230 p = cur;
231 cur = cur->next;
232 free(p);
233 } while (cur);
234 }
226} 235}
227#else 236#else
228void sed_free_and_close_stuff(void); 237void sed_free_and_close_stuff(void);
diff --git a/findutils/xargs.c b/findutils/xargs.c
index a0ba89c1e..dd6aa9592 100644
--- a/findutils/xargs.c
+++ b/findutils/xargs.c
@@ -114,6 +114,8 @@ struct globals {
114#endif 114#endif
115 const char *eof_str; 115 const char *eof_str;
116 int idx; 116 int idx;
117 int fd_tty;
118 int fd_stdin;
117#if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL 119#if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL
118 int running_procs; 120 int running_procs;
119 int max_procs; 121 int max_procs;
@@ -147,6 +149,42 @@ struct globals {
147 IF_FEATURE_XARGS_SUPPORT_QUOTES(G.process_stdin__q = '\0';) \ 149 IF_FEATURE_XARGS_SUPPORT_QUOTES(G.process_stdin__q = '\0';) \
148} while (0) 150} while (0)
149 151
152/* Correct regardless of combination of CONFIG_xxx */
153enum {
154 OPTBIT_VERBOSE = 0,
155 OPTBIT_NO_EMPTY,
156 OPTBIT_UPTO_NUMBER,
157 OPTBIT_UPTO_SIZE,
158 OPTBIT_EOF_STRING,
159 OPTBIT_EOF_STRING1,
160 OPTBIT_STDIN_TTY,
161 IF_FEATURE_XARGS_SUPPORT_CONFIRMATION(OPTBIT_INTERACTIVE,)
162 IF_FEATURE_XARGS_SUPPORT_TERMOPT( OPTBIT_TERMINATE ,)
163 IF_FEATURE_XARGS_SUPPORT_ZERO_TERM( OPTBIT_ZEROTERM ,)
164 IF_FEATURE_XARGS_SUPPORT_REPL_STR( OPTBIT_REPLSTR ,)
165 IF_FEATURE_XARGS_SUPPORT_REPL_STR( OPTBIT_REPLSTR1 ,)
166
167 OPT_VERBOSE = 1 << OPTBIT_VERBOSE ,
168 OPT_NO_EMPTY = 1 << OPTBIT_NO_EMPTY ,
169 OPT_UPTO_NUMBER = 1 << OPTBIT_UPTO_NUMBER,
170 OPT_UPTO_SIZE = 1 << OPTBIT_UPTO_SIZE ,
171 OPT_EOF_STRING = 1 << OPTBIT_EOF_STRING , /* GNU: -e[<param>] */
172 OPT_EOF_STRING1 = 1 << OPTBIT_EOF_STRING1, /* SUS: -E<param> */
173 OPT_STDIN_TTY = 1 << OPTBIT_STDIN_TTY,
174 OPT_INTERACTIVE = IF_FEATURE_XARGS_SUPPORT_CONFIRMATION((1 << OPTBIT_INTERACTIVE)) + 0,
175 OPT_TERMINATE = IF_FEATURE_XARGS_SUPPORT_TERMOPT( (1 << OPTBIT_TERMINATE )) + 0,
176 OPT_ZEROTERM = IF_FEATURE_XARGS_SUPPORT_ZERO_TERM( (1 << OPTBIT_ZEROTERM )) + 0,
177 OPT_REPLSTR = IF_FEATURE_XARGS_SUPPORT_REPL_STR( (1 << OPTBIT_REPLSTR )) + 0,
178 OPT_REPLSTR1 = IF_FEATURE_XARGS_SUPPORT_REPL_STR( (1 << OPTBIT_REPLSTR1 )) + 0,
179};
180#define OPTION_STR "+trn:s:e::E:o" \
181 IF_FEATURE_XARGS_SUPPORT_CONFIRMATION("p") \
182 IF_FEATURE_XARGS_SUPPORT_TERMOPT( "x") \
183 IF_FEATURE_XARGS_SUPPORT_ZERO_TERM( "0") \
184 IF_FEATURE_XARGS_SUPPORT_REPL_STR( "I:i::") \
185 IF_FEATURE_XARGS_SUPPORT_PARALLEL( "P:+") \
186 IF_FEATURE_XARGS_SUPPORT_ARGS_FILE( "a:")
187
150 188
151#if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL && ENABLE_PLATFORM_MINGW32 189#if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL && ENABLE_PLATFORM_MINGW32
152static int wait_for_slot(int *idx) 190static int wait_for_slot(int *idx)
@@ -206,6 +244,9 @@ static int xargs_exec(void)
206{ 244{
207 int status; 245 int status;
208 246
247 if (option_mask32 & OPT_STDIN_TTY)
248 xdup2(G.fd_tty, STDIN_FILENO);
249
209#if !ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL 250#if !ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL
210 status = spawn_and_wait(G.args); 251 status = spawn_and_wait(G.args);
211#else 252#else
@@ -310,6 +351,8 @@ static int xargs_exec(void)
310 ret: 351 ret:
311 if (status != 0) 352 if (status != 0)
312 G.xargs_exitcode = status; 353 G.xargs_exitcode = status;
354 if (option_mask32 & OPT_STDIN_TTY)
355 xdup2(G.fd_stdin, STDIN_FILENO);
313 return status; 356 return status;
314} 357}
315 358
@@ -628,6 +671,7 @@ static int xargs_ask_confirmation(void)
628//usage: IF_FEATURE_XARGS_SUPPORT_ARGS_FILE( 671//usage: IF_FEATURE_XARGS_SUPPORT_ARGS_FILE(
629//usage: "\n -a FILE Read from FILE instead of stdin" 672//usage: "\n -a FILE Read from FILE instead of stdin"
630//usage: ) 673//usage: )
674//usage: "\n -o Reopen stdin as /dev/tty"
631//usage: "\n -r Don't run command if input is empty" 675//usage: "\n -r Don't run command if input is empty"
632//usage: "\n -t Print the command on stderr before execution" 676//usage: "\n -t Print the command on stderr before execution"
633//usage: IF_FEATURE_XARGS_SUPPORT_CONFIRMATION( 677//usage: IF_FEATURE_XARGS_SUPPORT_CONFIRMATION(
@@ -649,40 +693,6 @@ static int xargs_ask_confirmation(void)
649//usage: "$ ls | xargs gzip\n" 693//usage: "$ ls | xargs gzip\n"
650//usage: "$ find . -name '*.c' -print | xargs rm\n" 694//usage: "$ find . -name '*.c' -print | xargs rm\n"
651 695
652/* Correct regardless of combination of CONFIG_xxx */
653enum {
654 OPTBIT_VERBOSE = 0,
655 OPTBIT_NO_EMPTY,
656 OPTBIT_UPTO_NUMBER,
657 OPTBIT_UPTO_SIZE,
658 OPTBIT_EOF_STRING,
659 OPTBIT_EOF_STRING1,
660 IF_FEATURE_XARGS_SUPPORT_CONFIRMATION(OPTBIT_INTERACTIVE,)
661 IF_FEATURE_XARGS_SUPPORT_TERMOPT( OPTBIT_TERMINATE ,)
662 IF_FEATURE_XARGS_SUPPORT_ZERO_TERM( OPTBIT_ZEROTERM ,)
663 IF_FEATURE_XARGS_SUPPORT_REPL_STR( OPTBIT_REPLSTR ,)
664 IF_FEATURE_XARGS_SUPPORT_REPL_STR( OPTBIT_REPLSTR1 ,)
665
666 OPT_VERBOSE = 1 << OPTBIT_VERBOSE ,
667 OPT_NO_EMPTY = 1 << OPTBIT_NO_EMPTY ,
668 OPT_UPTO_NUMBER = 1 << OPTBIT_UPTO_NUMBER,
669 OPT_UPTO_SIZE = 1 << OPTBIT_UPTO_SIZE ,
670 OPT_EOF_STRING = 1 << OPTBIT_EOF_STRING , /* GNU: -e[<param>] */
671 OPT_EOF_STRING1 = 1 << OPTBIT_EOF_STRING1, /* SUS: -E<param> */
672 OPT_INTERACTIVE = IF_FEATURE_XARGS_SUPPORT_CONFIRMATION((1 << OPTBIT_INTERACTIVE)) + 0,
673 OPT_TERMINATE = IF_FEATURE_XARGS_SUPPORT_TERMOPT( (1 << OPTBIT_TERMINATE )) + 0,
674 OPT_ZEROTERM = IF_FEATURE_XARGS_SUPPORT_ZERO_TERM( (1 << OPTBIT_ZEROTERM )) + 0,
675 OPT_REPLSTR = IF_FEATURE_XARGS_SUPPORT_REPL_STR( (1 << OPTBIT_REPLSTR )) + 0,
676 OPT_REPLSTR1 = IF_FEATURE_XARGS_SUPPORT_REPL_STR( (1 << OPTBIT_REPLSTR1 )) + 0,
677};
678#define OPTION_STR "+trn:s:e::E:" \
679 IF_FEATURE_XARGS_SUPPORT_CONFIRMATION("p") \
680 IF_FEATURE_XARGS_SUPPORT_TERMOPT( "x") \
681 IF_FEATURE_XARGS_SUPPORT_ZERO_TERM( "0") \
682 IF_FEATURE_XARGS_SUPPORT_REPL_STR( "I:i::") \
683 IF_FEATURE_XARGS_SUPPORT_PARALLEL( "P:+") \
684 IF_FEATURE_XARGS_SUPPORT_ARGS_FILE( "a:")
685
686int xargs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 696int xargs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
687int xargs_main(int argc UNUSED_PARAM, char **argv) 697int xargs_main(int argc UNUSED_PARAM, char **argv)
688{ 698{
@@ -817,6 +827,13 @@ int xargs_main(int argc UNUSED_PARAM, char **argv)
817 store_param(argv[i]); 827 store_param(argv[i]);
818 } 828 }
819 829
830 if (opt & OPT_STDIN_TTY) {
831 G.fd_tty = xopen(CURRENT_TTY, O_RDONLY);
832 close_on_exec_on(G.fd_tty);
833 G.fd_stdin = dup(STDIN_FILENO);
834 close_on_exec_on(G.fd_stdin);
835 }
836
820 initial_idx = G.idx; 837 initial_idx = G.idx;
821 while (1) { 838 while (1) {
822 char *rem; 839 char *rem;
diff --git a/include/libbb.h b/include/libbb.h
index 1b1e5cab1..94f0e40ec 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -2007,9 +2007,15 @@ typedef struct line_input_t {
2007# if ENABLE_SHELL_ASH || ENABLE_SHELL_HUSH 2007# if ENABLE_SHELL_ASH || ENABLE_SHELL_HUSH
2008 /* function to fetch additional application-specific names to match */ 2008 /* function to fetch additional application-specific names to match */
2009 get_exe_name_t *get_exe_name; 2009 get_exe_name_t *get_exe_name;
2010# endif
2011# endif
2012# if (ENABLE_FEATURE_USERNAME_COMPLETION || ENABLE_FEATURE_EDITING_FANCY_PROMPT) \
2013 && (ENABLE_SHELL_ASH || ENABLE_SHELL_HUSH)
2010 /* function to fetch value of shell variable */ 2014 /* function to fetch value of shell variable */
2011 sh_get_var_t *sh_get_var; 2015 sh_get_var_t *sh_get_var;
2012# endif 2016# define EDITING_HAS_sh_get_var 1
2017# else
2018# define EDITING_HAS_sh_get_var 0
2013# endif 2019# endif
2014# if MAX_HISTORY 2020# if MAX_HISTORY
2015 int cnt_history; 2021 int cnt_history;
diff --git a/libbb/Config.src b/libbb/Config.src
index 66a3ffa23..b980f19a9 100644
--- a/libbb/Config.src
+++ b/libbb/Config.src
@@ -369,3 +369,25 @@ config UNICODE_PRESERVE_BROKEN
369 For example, this means that entering 'l', 's', ' ', 0xff, [Enter] 369 For example, this means that entering 'l', 's', ' ', 0xff, [Enter]
370 at shell prompt will list file named 0xff (single char name 370 at shell prompt will list file named 0xff (single char name
371 with char value 255), not file named '?'. 371 with char value 255), not file named '?'.
372
373choice
374 prompt "Use LOOP_CONFIGURE for losetup and loop mounts"
375 default TRY_LOOP_CONFIGURE
376 help
377 LOOP_CONFIGURE is added to Linux 5.8
378 https://lwn.net/Articles/820408/
379 This allows userspace to completely setup a loop device with a single
380 ioctl, removing the in-between state where the device can be partially
381 configured - eg the loop device has a backing file associated with it,
382 but is reading from the wrong offset.
383
384config LOOP_CONFIGURE
385 bool "use LOOP_CONFIGURE, needs kernel >= 5.8"
386
387config NO_LOOP_CONFIGURE
388 bool "use LOOP_SET_FD + LOOP_SET_STATUS"
389
390config TRY_LOOP_CONFIGURE
391 bool "try LOOP_CONFIGURE, fall back to LOOP_SET_FD + LOOP_SET_STATUS"
392
393endchoice
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index b4950688e..bee423553 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -249,14 +249,6 @@ static void get_user_strings(void)
249 } 249 }
250} 250}
251 251
252static const char *get_username_str(void)
253{
254 if (!got_user_strings)
255 get_user_strings();
256 return user_buf ? user_buf : "";
257 /* btw, bash uses "I have no name!" string if uid has no entry */
258}
259
260static NOINLINE const char *get_homedir_or_NULL(void) 252static NOINLINE const char *get_homedir_or_NULL(void)
261{ 253{
262 const char *home; 254 const char *home;
@@ -275,6 +267,16 @@ static NOINLINE const char *get_homedir_or_NULL(void)
275} 267}
276#endif 268#endif
277 269
270#if ENABLE_FEATURE_EDITING_FANCY_PROMPT
271static const char *get_username_str(void)
272{
273 if (!got_user_strings)
274 get_user_strings();
275 return user_buf ? user_buf : "";
276 /* btw, bash uses "I have no name!" string if uid has no entry */
277}
278#endif
279
278#if ENABLE_UNICODE_SUPPORT 280#if ENABLE_UNICODE_SUPPORT
279static size_t load_string(const char *src) 281static size_t load_string(const char *src)
280{ 282{
@@ -2151,13 +2153,13 @@ static void parse_and_put_prompt(const char *prmt_ptr)
2151 case 'W': /* basename of cur dir */ 2153 case 'W': /* basename of cur dir */
2152 if (!cwd_buf) { 2154 if (!cwd_buf) {
2153 const char *home; 2155 const char *home;
2154#if ENABLE_SHELL_ASH 2156# if EDITING_HAS_sh_get_var
2155 cwd_buf = state->sh_get_var 2157 cwd_buf = state->sh_get_var
2156 ? xstrdup(state->sh_get_var("PWD")) 2158 ? xstrdup(state->sh_get_var("PWD"))
2157 : xrealloc_getcwd_or_warn(NULL); 2159 : xrealloc_getcwd_or_warn(NULL);
2158#else 2160# else
2159 cwd_buf = xrealloc_getcwd_or_warn(NULL); 2161 cwd_buf = xrealloc_getcwd_or_warn(NULL);
2160#endif 2162# endif
2161 if (!cwd_buf) 2163 if (!cwd_buf)
2162 cwd_buf = (char *)bb_msg_unknown; 2164 cwd_buf = (char *)bb_msg_unknown;
2163 else if ((home = get_homedir_or_NULL()) != NULL && home[0]) { 2165 else if ((home = get_homedir_or_NULL()) != NULL && home[0]) {
diff --git a/libbb/loop.c b/libbb/loop.c
index cb8fa2442..a0c5d0259 100644
--- a/libbb/loop.c
+++ b/libbb/loop.c
@@ -71,7 +71,7 @@ int FAST_FUNC del_loop(const char *device)
71 71
72 fd = open(device, O_RDONLY); 72 fd = open(device, O_RDONLY);
73 if (fd < 0) 73 if (fd < 0)
74 return 1; 74 return fd; /* -1 */
75 rc = ioctl(fd, LOOP_CLR_FD, 0); 75 rc = ioctl(fd, LOOP_CLR_FD, 0);
76 close(fd); 76 close(fd);
77 77
@@ -96,6 +96,97 @@ int FAST_FUNC get_free_loop(void)
96 return loopdevno; /* can be -1 if error */ 96 return loopdevno; /* can be -1 if error */
97} 97}
98 98
99static int get_next_free_loop(char *dev, int id)
100{
101 int loopdevno;
102
103 loopdevno = get_free_loop();
104 if (loopdevno != -1) {
105 /* loopdevno is -2 (use id) or >= 0 (use id = loopdevno): */
106 if (loopdevno >= 0)
107 id = loopdevno;
108 sprintf(dev, LOOP_FORMAT, id);
109 }
110 return loopdevno;
111}
112
113#if ENABLE_TRY_LOOP_CONFIGURE || ENABLE_LOOP_CONFIGURE
114# define LOOP_CONFIGURE 0x4C0A
115struct bb_loop_config {
116 uint32_t fd;
117 uint32_t block_size;
118 struct loop_info64 info;
119 uint64_t __reserved[8];
120};
121#endif
122
123static int set_loopdev_params(int lfd,
124 int ffd, const char *file,
125 unsigned long long offset,
126 unsigned long long sizelimit,
127 unsigned flags)
128{
129 int rc;
130#if ENABLE_TRY_LOOP_CONFIGURE || ENABLE_LOOP_CONFIGURE
131 struct bb_loop_config lconfig;
132# define loopinfo lconfig.info
133#else
134 bb_loop_info loopinfo;
135#endif
136
137 rc = ioctl(lfd, BB_LOOP_GET_STATUS, &loopinfo);
138
139 /* If device is free, try to claim it */
140 if (rc && errno == ENXIO) {
141#if ENABLE_TRY_LOOP_CONFIGURE || ENABLE_LOOP_CONFIGURE
142 memset(&lconfig, 0, sizeof(lconfig));
143#else
144 memset(&loopinfo, 0, sizeof(loopinfo));
145#endif
146 safe_strncpy((char *)loopinfo.lo_file_name, file, LO_NAME_SIZE);
147 loopinfo.lo_offset = offset;
148 loopinfo.lo_sizelimit = sizelimit;
149 /*
150 * LO_FLAGS_READ_ONLY is not set because RO is controlled
151 * by open type of the lfd.
152 */
153 loopinfo.lo_flags = (flags & ~BB_LO_FLAGS_READ_ONLY);
154
155#if ENABLE_TRY_LOOP_CONFIGURE || ENABLE_LOOP_CONFIGURE
156 lconfig.fd = ffd;
157 rc = ioctl(lfd, LOOP_CONFIGURE, &lconfig);
158 if (rc == 0)
159 return rc; /* SUCCESS! */
160# if ENABLE_TRY_LOOP_CONFIGURE
161 if (errno != EINVAL)
162 return rc; /* error other than old kernel */
163 /* Old kernel, fall through into old way to do it: */
164# endif
165#endif
166#if ENABLE_TRY_LOOP_CONFIGURE || ENABLE_NO_LOOP_CONFIGURE
167 /* Associate free loop device with file */
168 rc = ioctl(lfd, LOOP_SET_FD, ffd);
169 if (rc != 0) {
170 /* Ouch... race: the device already has a fd */
171 return rc;
172 }
173 rc = ioctl(lfd, BB_LOOP_SET_STATUS, &loopinfo);
174 if (rc != 0 && (loopinfo.lo_flags & BB_LO_FLAGS_AUTOCLEAR)) {
175 /* Old kernel, does not support LO_FLAGS_AUTOCLEAR? */
176 /* (this code path is not tested) */
177 loopinfo.lo_flags -= BB_LO_FLAGS_AUTOCLEAR;
178 rc = ioctl(lfd, BB_LOOP_SET_STATUS, &loopinfo);
179 }
180 if (rc == 0)
181 return rc; /* SUCCESS! */
182 /* failure, undo LOOP_SET_FD */
183 ioctl(lfd, LOOP_CLR_FD, 0); // actually, 0 param is unnecessary
184#endif
185 }
186 return -1;
187#undef loopinfo
188}
189
99/* Returns opened fd to the loop device, <0 on error. 190/* Returns opened fd to the loop device, <0 on error.
100 * *device is loop device to use, or if *device==NULL finds a loop device to 191 * *device is loop device to use, or if *device==NULL finds a loop device to
101 * mount it on and sets *device to a strdup of that loop device name. 192 * mount it on and sets *device to a strdup of that loop device name.
@@ -105,7 +196,6 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse
105{ 196{
106 char dev[LOOP_NAMESIZE]; 197 char dev[LOOP_NAMESIZE];
107 char *try; 198 char *try;
108 bb_loop_info loopinfo;
109 struct stat statbuf; 199 struct stat statbuf;
110 int i, lfd, ffd, mode, rc; 200 int i, lfd, ffd, mode, rc;
111 201
@@ -123,30 +213,27 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse
123 213
124 try = *device; 214 try = *device;
125 if (!try) { 215 if (!try) {
126 get_free_loopN:
127 i = get_free_loop();
128 if (i == -1) {
129 close(ffd);
130 return -1; /* no free loop devices */
131 }
132 if (i >= 0) {
133 try = xasprintf(LOOP_FORMAT, i);
134 goto open_lfd;
135 }
136 /* i == -2: no /dev/loop-control. Do an old-style search for a free device */
137 try = dev; 216 try = dev;
138 } 217 }
139 218
140 /* Find a loop device */ 219 /* Find a loop device */
141 /* 0xfffff is a max possible minor number in Linux circa 2010 */ 220 /* 0xfffff is a max possible minor number in Linux circa 2010 */
142 for (i = 0; i <= 0xfffff; i++) { 221 for (i = 0; i <= 0xfffff; i++) {
143 sprintf(dev, LOOP_FORMAT, i); 222 if (!*device) {
223 rc = get_next_free_loop(dev, i);
224 if (rc == -1)
225 break; /* no free loop devices (or other error in LOOP_CTL_GET_FREE) */
226 if (rc >= 0)
227 /* /dev/loop-control gave us the next free /dev/loopN */
228 goto open_lfd;
229 /* else: sequential /dev/loopN, needs to be tested/maybe_created */
230 }
144 231
145 IF_FEATURE_MOUNT_LOOP_CREATE(errno = 0;) 232 IF_FEATURE_MOUNT_LOOP_CREATE(errno = 0;)
146 if (stat(try, &statbuf) != 0 || !S_ISBLK(statbuf.st_mode)) { 233 if (stat(try, &statbuf) != 0 || !S_ISBLK(statbuf.st_mode)) {
147 if (ENABLE_FEATURE_MOUNT_LOOP_CREATE 234 if (ENABLE_FEATURE_MOUNT_LOOP_CREATE
148 && errno == ENOENT 235 && errno == ENOENT
149 && try == dev 236 && (!*device)
150 ) { 237 ) {
151 /* Node doesn't exist, try to create it */ 238 /* Node doesn't exist, try to create it */
152 if (mknod(dev, S_IFBLK|0644, makedev(7, i)) == 0) 239 if (mknod(dev, S_IFBLK|0644, makedev(7, i)) == 0)
@@ -172,55 +259,19 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse
172 goto try_next_loopN; 259 goto try_next_loopN;
173 } 260 }
174 261
175 rc = ioctl(lfd, BB_LOOP_GET_STATUS, &loopinfo); 262 rc = set_loopdev_params(lfd, ffd, file, offset, sizelimit, flags);
176 263 if (rc == 0) {
177 /* If device is free, try to claim it */ 264 /* SUCCESS! */
178 if (rc && errno == ENXIO) { 265 if (!*device)
179 /* Associate free loop device with file */ 266 *device = xstrdup(dev);
180 if (ioctl(lfd, LOOP_SET_FD, ffd)) { 267 /* Note: mount asks for LO_FLAGS_AUTOCLEAR loopdev.
181 /* Ouch. Are we racing with other mount? */ 268 * Closing LO_FLAGS_AUTOCLEARed lfd before mount
182 if (!*device /* yes */ 269 * is wrong (would free the loop device!),
183 && try != dev /* tried a _kernel-offered_ loopN? */ 270 * this is why we return without closing it.
184 ) {
185 free(try);
186 close(lfd);
187//TODO: add "if (--failcount != 0) ..."?
188 goto get_free_loopN;
189 }
190 goto close_and_try_next_loopN;
191 }
192 memset(&loopinfo, 0, sizeof(loopinfo));
193 safe_strncpy((char *)loopinfo.lo_file_name, file, LO_NAME_SIZE);
194 loopinfo.lo_offset = offset;
195 loopinfo.lo_sizelimit = sizelimit;
196 /*
197 * Used by mount to set LO_FLAGS_AUTOCLEAR.
198 * LO_FLAGS_READ_ONLY is not set because RO is controlled by open type of the file.
199 * Note that closing LO_FLAGS_AUTOCLEARed lfd before mount
200 * is wrong (would free the loop device!)
201 */ 271 */
202 loopinfo.lo_flags = (flags & ~BB_LO_FLAGS_READ_ONLY); 272 rc = lfd; /* return this */
203 rc = ioctl(lfd, BB_LOOP_SET_STATUS, &loopinfo); 273 break;
204 if (rc != 0 && (loopinfo.lo_flags & BB_LO_FLAGS_AUTOCLEAR)) {
205 /* Old kernel, does not support LO_FLAGS_AUTOCLEAR? */
206 /* (this code path is not tested) */
207 loopinfo.lo_flags -= BB_LO_FLAGS_AUTOCLEAR;
208 rc = ioctl(lfd, BB_LOOP_SET_STATUS, &loopinfo);
209 }
210 if (rc == 0) {
211 /* SUCCESS! */
212 if (try != dev) /* tried a kernel-offered free loopN? */
213 *device = try; /* malloced */
214 if (!*device) /* was looping in search of free "/dev/loopN"? */
215 *device = xstrdup(dev);
216 rc = lfd; /* return this */
217 break;
218 }
219 /* failure, undo LOOP_SET_FD */
220 ioctl(lfd, LOOP_CLR_FD, 0); // actually, 0 param is unnecessary
221 } 274 }
222 /* else: device is not free (rc == 0) or error other than ENXIO */
223 close_and_try_next_loopN:
224 close(lfd); 275 close(lfd);
225 try_next_loopN: 276 try_next_loopN:
226 rc = -1; 277 rc = -1;
diff --git a/networking/udhcp/Config.src b/networking/udhcp/Config.src
index 8c8c11c26..7ba7f48fc 100644
--- a/networking/udhcp/Config.src
+++ b/networking/udhcp/Config.src
@@ -92,12 +92,17 @@ config FEATURE_UDHCPC_SANITIZEOPT
92config UDHCPC_DEFAULT_SCRIPT 92config UDHCPC_DEFAULT_SCRIPT
93 string "Absolute path to config script" 93 string "Absolute path to config script"
94 default "/usr/share/udhcpc/default.script" 94 default "/usr/share/udhcpc/default.script"
95 depends on UDHCPC || UDHCPC6 95 depends on UDHCPC
96 help 96 help
97 This script is called after udhcpc receives an answer. See 97 This script is called after udhcpc receives an answer. See
98 examples/udhcp for a working example. Normally it is safe 98 examples/udhcp for a working example. Normally it is safe
99 to leave this untouched. 99 to leave this untouched.
100 100
101config UDHCPC6_DEFAULT_SCRIPT
102 string "Absolute path to config script for IPv6"
103 default "/usr/share/udhcpc/default6.script"
104 depends on UDHCPC6
105
101# udhcpc6 config is inserted here: 106# udhcpc6 config is inserted here:
102INSERT 107INSERT
103 108
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h
index 5882238e3..49a0b593d 100644
--- a/networking/udhcp/common.h
+++ b/networking/udhcp/common.h
@@ -370,7 +370,8 @@ void udhcp_sp_setup(void) FAST_FUNC;
370void udhcp_sp_fd_set(struct pollfd *pfds, int extra_fd) FAST_FUNC; 370void udhcp_sp_fd_set(struct pollfd *pfds, int extra_fd) FAST_FUNC;
371int udhcp_sp_read(void) FAST_FUNC; 371int udhcp_sp_read(void) FAST_FUNC;
372 372
373int udhcp_read_interface(const char *interface, int *ifindex, uint32_t *nip, uint8_t *mac) FAST_FUNC; 373int udhcp_read_interface(const char *interface,
374 int *ifindex, uint32_t *nip, uint8_t *mac) FAST_FUNC;
374 375
375int udhcp_listen_socket(/*uint32_t ip,*/ int port, const char *inf) FAST_FUNC; 376int udhcp_listen_socket(/*uint32_t ip,*/ int port, const char *inf) FAST_FUNC;
376 377
diff --git a/networking/udhcp/d6_common.h b/networking/udhcp/d6_common.h
index 9dfde7709..3cbfbb89e 100644
--- a/networking/udhcp/d6_common.h
+++ b/networking/udhcp/d6_common.h
@@ -63,28 +63,45 @@ struct d6_option {
63 63
64#define D6_OPT_CLIENTID 1 64#define D6_OPT_CLIENTID 1
65#define D6_OPT_SERVERID 2 65#define D6_OPT_SERVERID 2
66/* "Identity Association for Non-temporary Addresses",
67 * also known as a "network interface" in plain English */
66#define D6_OPT_IA_NA 3 68#define D6_OPT_IA_NA 3
67#define D6_OPT_IA_TA 4 69/* "Identity Association for the Temporary Addresses".
70 * Presumably this is a "network interface with only link-local addresses".
71 * Why would DHCPv6 server assign such addresses, I have no idea. */
72//#define D6_OPT_IA_TA 4
73/* "IA Address", an IPv6 address */
68#define D6_OPT_IAADDR 5 74#define D6_OPT_IAADDR 5
75/* Option "Option Request Option". From the owners of a doggy dog named Dog? */
69#define D6_OPT_ORO 6 76#define D6_OPT_ORO 6
70#define D6_OPT_PREFERENCE 7 77//#define D6_OPT_PREFERENCE 7
71#define D6_OPT_ELAPSED_TIME 8 78#define D6_OPT_ELAPSED_TIME 8
72#define D6_OPT_RELAY_MSG 9 79//#define D6_OPT_RELAY_MSG 9
73#define D6_OPT_AUTH 11 80//#define D6_OPT_AUTH 11
74#define D6_OPT_UNICAST 12 81/* "The server sends this option to a client to indicate to the client
82 * that it is allowed to unicast messages to the server."
83 * Contains IPv6 address to send packets to. */
84//#define D6_OPT_UNICAST 12
85/* "A Status Code option may appear in the options field of a DHCP
86 * message and/or in the options field of another option." */
75#define D6_OPT_STATUS_CODE 13 87#define D6_OPT_STATUS_CODE 13
76#define D6_OPT_RAPID_COMMIT 14 88/* "A client MAY include this option in a Solicit message if the client
77#define D6_OPT_USER_CLASS 15 89 * is prepared to perform the Solicit-Reply message exchange..." */
78#define D6_OPT_VENDOR_CLASS 16 90//#define D6_OPT_RAPID_COMMIT 14 /* zero-length option */
79#define D6_OPT_VENDOR_OPTS 17 91//#define D6_OPT_USER_CLASS 15
80#define D6_OPT_INTERFACE_ID 18 92//#define D6_OPT_VENDOR_CLASS 16
81#define D6_OPT_RECONF_MSG 19 93//#define D6_OPT_VENDOR_OPTS 17
82#define D6_OPT_RECONF_ACCEPT 20 94//#define D6_OPT_INTERFACE_ID 18
95//#define D6_OPT_RECONF_MSG 19
96//#define D6_OPT_RECONF_ACCEPT 20
83 97
84#define D6_OPT_DNS_SERVERS 23 98#define D6_OPT_DNS_SERVERS 23
85#define D6_OPT_DOMAIN_LIST 24 99#define D6_OPT_DOMAIN_LIST 24
86 100
101/* RFC 3633 "Identity Association for Prefix Delegation".
102 * This option says that client wants to get an IPv6 prefix */
87#define D6_OPT_IA_PD 25 103#define D6_OPT_IA_PD 25
104/* Response from the server comes in this one */
88#define D6_OPT_IAPREFIX 26 105#define D6_OPT_IAPREFIX 26
89 106
90/* RFC 4704 "The DHCPv6 Client FQDN Option" 107/* RFC 4704 "The DHCPv6 Client FQDN Option"
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c
index c7f130a70..cdd06188e 100644
--- a/networking/udhcp/d6_dhcpc.c
+++ b/networking/udhcp/d6_dhcpc.c
@@ -548,7 +548,7 @@ static uint8_t *add_d6_client_options(uint8_t *ptr)
548static int d6_mcast_from_client_data_ifindex(struct d6_packet *packet, uint8_t *end) 548static int d6_mcast_from_client_data_ifindex(struct d6_packet *packet, uint8_t *end)
549{ 549{
550 /* FF02::1:2 is "All_DHCP_Relay_Agents_and_Servers" address */ 550 /* FF02::1:2 is "All_DHCP_Relay_Agents_and_Servers" address */
551 static const uint8_t FF02__1_2[16] = { 551 static const uint8_t FF02__1_2[16] ALIGNED(sizeof(long)) = {
552 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 552 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
553 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 553 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02,
554 }; 554 };
@@ -890,7 +890,6 @@ int send_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cur_ipv6)
890 if (client6_data.ia_pd) 890 if (client6_data.ia_pd)
891 opt_ptr = mempcpy(opt_ptr, client6_data.ia_pd, client6_data.ia_pd->len + 2+2); 891 opt_ptr = mempcpy(opt_ptr, client6_data.ia_pd, client6_data.ia_pd->len + 2+2);
892 /* Client-id */ 892 /* Client-id */
893///vda
894 ci = udhcp_find_option(client_data.options, D6_OPT_CLIENTID, /*dhcpv6:*/ 1); 893 ci = udhcp_find_option(client_data.options, D6_OPT_CLIENTID, /*dhcpv6:*/ 1);
895 if (ci) 894 if (ci)
896 opt_ptr = mempcpy(opt_ptr, ci->data, D6_OPT_DATA + 2+2 + 6); 895 opt_ptr = mempcpy(opt_ptr, ci->data, D6_OPT_DATA + 2+2 + 6);
@@ -1135,7 +1134,7 @@ static void client_background(void)
1135//usage:#define udhcpc6_full_usage "\n" 1134//usage:#define udhcpc6_full_usage "\n"
1136//usage: "\n -i IFACE Interface to use (default "CONFIG_UDHCPC_DEFAULT_INTERFACE")" 1135//usage: "\n -i IFACE Interface to use (default "CONFIG_UDHCPC_DEFAULT_INTERFACE")"
1137//usage: "\n -p FILE Create pidfile" 1136//usage: "\n -p FILE Create pidfile"
1138//usage: "\n -s PROG Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")" 1137//usage: "\n -s PROG Run PROG at DHCP events (default "CONFIG_UDHCPC6_DEFAULT_SCRIPT")"
1139//usage: "\n -B Request broadcast replies" 1138//usage: "\n -B Request broadcast replies"
1140//usage: "\n -t N Send up to N discover packets" 1139//usage: "\n -t N Send up to N discover packets"
1141//usage: "\n -T SEC Pause between packets (default 3)" 1140//usage: "\n -T SEC Pause between packets (default 3)"
@@ -1201,7 +1200,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1201 IF_FEATURE_UDHCP_PORT(SERVER_PORT6 = 547;) 1200 IF_FEATURE_UDHCP_PORT(SERVER_PORT6 = 547;)
1202 IF_FEATURE_UDHCP_PORT(CLIENT_PORT6 = 546;) 1201 IF_FEATURE_UDHCP_PORT(CLIENT_PORT6 = 546;)
1203 client_data.interface = CONFIG_UDHCPC_DEFAULT_INTERFACE; 1202 client_data.interface = CONFIG_UDHCPC_DEFAULT_INTERFACE;
1204 client_data.script = CONFIG_UDHCPC_DEFAULT_SCRIPT; 1203 client_data.script = CONFIG_UDHCPC6_DEFAULT_SCRIPT;
1205 client_data.sockfd = -1; 1204 client_data.sockfd = -1;
1206 1205
1207 /* Make sure fd 0,1,2 are open */ 1206 /* Make sure fd 0,1,2 are open */
@@ -1618,6 +1617,16 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1618 prefix_timeout = 0; 1617 prefix_timeout = 0;
1619 option = d6_find_option(packet.d6_options, packet_end, D6_OPT_STATUS_CODE); 1618 option = d6_find_option(packet.d6_options, packet_end, D6_OPT_STATUS_CODE);
1620 if (option && (option->data[0] | option->data[1]) != 0) { 1619 if (option && (option->data[0] | option->data[1]) != 0) {
1620///FIXME:
1621// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1622// | OPTION_STATUS_CODE | option-len |
1623// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1624// | status-code | |
1625// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
1626// . status-message .
1627// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1628// so why do we think it's NAK if data[0] is zero but data[1] is not? That's wrong...
1629// we should also check that option->len is ok (i.e. not 0), right?
1621 /* return to init state */ 1630 /* return to init state */
1622 bb_info_msg("received DHCP NAK (%u)", option->data[4]); 1631 bb_info_msg("received DHCP NAK (%u)", option->data[4]);
1623 d6_run_script(packet.d6_options, 1632 d6_run_script(packet.d6_options,
diff --git a/networking/udhcp/d6_packet.c b/networking/udhcp/d6_packet.c
index c1949f6e3..142de9b43 100644
--- a/networking/udhcp/d6_packet.c
+++ b/networking/udhcp/d6_packet.c
@@ -27,9 +27,8 @@ void FAST_FUNC d6_dump_packet(struct d6_packet *packet)
27} 27}
28#endif 28#endif
29 29
30int FAST_FUNC d6_recv_kernel_packet(struct in6_addr *peer_ipv6 30int FAST_FUNC d6_recv_kernel_packet(struct in6_addr *peer_ipv6 UNUSED_PARAM,
31 UNUSED_PARAM 31 struct d6_packet *packet, int fd)
32 , struct d6_packet *packet, int fd)
33{ 32{
34 int bytes; 33 int bytes;
35 34
@@ -81,12 +80,22 @@ int FAST_FUNC d6_send_raw_packet_from_client_data_ifindex(
81 dest_sll.sll_halen = 6; 80 dest_sll.sll_halen = 6;
82 memcpy(dest_sll.sll_addr, dest_arp, 6); 81 memcpy(dest_sll.sll_addr, dest_arp, 6);
83 82
83//TODO: is bind() necessary? we sendto() to this destination, should work anyway
84 if (bind(fd, (struct sockaddr *)&dest_sll, sizeof(dest_sll)) < 0) { 84 if (bind(fd, (struct sockaddr *)&dest_sll, sizeof(dest_sll)) < 0) {
85 msg = "bind(%s)"; 85 msg = "bind(%s)";
86 goto ret_close; 86 goto ret_close;
87 } 87 }
88 88
89 packet.ip6.ip6_vfc = (6 << 4); /* 4 bits version, top 4 bits of tclass */ 89 packet.ip6.ip6_vfc = (6 << 4); /* 4 bits version, top 4 bits of tclass */
90// In case we have no IPv6 on our interface at all, we can try
91// to fill "all hosts" mcast address as source:
92// /* FF02::1 is Link-local "All_Nodes" address */
93// packet.ip6.ip6_dst.s6_addr[0] = 0xff;
94// packet.ip6.ip6_dst.s6_addr[1] = 0x02;
95// packet.ip6.ip6_dst.s6_addr[15] = 0x01;
96// Maybe some servers will be able to respond to us this way?
97// Users report that leaving ::0 address there makes servers try to reply to ::0,
98// which doesn't work.
90 if (src_ipv6) 99 if (src_ipv6)
91 packet.ip6.ip6_src = *src_ipv6; /* struct copy */ 100 packet.ip6.ip6_src = *src_ipv6; /* struct copy */
92 packet.ip6.ip6_dst = *dst_ipv6; /* struct copy */ 101 packet.ip6.ip6_dst = *dst_ipv6; /* struct copy */
diff --git a/networking/udhcp/d6_socket.c b/networking/udhcp/d6_socket.c
index 21cf61c6e..acf108367 100644
--- a/networking/udhcp/d6_socket.c
+++ b/networking/udhcp/d6_socket.c
@@ -95,9 +95,6 @@ int FAST_FUNC d6_read_interface(
95 close(fd); 95 close(fd);
96 } 96 }
97 97
98 if (retval == 0)
99 return retval;
100
101 if (retval & (1<<0)) 98 if (retval & (1<<0))
102 bb_error_msg("can't get %s", "MAC"); 99 bb_error_msg("can't get %s", "MAC");
103 if (retval & (1<<1)) 100 if (retval & (1<<1))
@@ -109,6 +106,7 @@ int FAST_FUNC d6_listen_socket(int port, const char *inf)
109{ 106{
110 int fd; 107 int fd;
111 struct sockaddr_in6 addr; 108 struct sockaddr_in6 addr;
109 char *colon;
112 110
113 log2("opening listen socket on *:%d %s", port, inf); 111 log2("opening listen socket on *:%d %s", port, inf);
114 fd = xsocket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); 112 fd = xsocket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
@@ -117,10 +115,17 @@ int FAST_FUNC d6_listen_socket(int port, const char *inf)
117 if (setsockopt_broadcast(fd) == -1) 115 if (setsockopt_broadcast(fd) == -1)
118 bb_simple_perror_msg_and_die("SO_BROADCAST"); 116 bb_simple_perror_msg_and_die("SO_BROADCAST");
119 117
120 /* NB: bug 1032 says this doesn't work on ethernet aliases (ethN:M) */ 118 /* SO_BINDTODEVICE doesn't work on ethernet aliases (ethN:M) */
119 colon = strrchr(inf, ':');
120 if (colon)
121 *colon = '\0';
122
121 if (setsockopt_bindtodevice(fd, inf)) 123 if (setsockopt_bindtodevice(fd, inf))
122 xfunc_die(); /* warning is already printed */ 124 xfunc_die(); /* warning is already printed */
123 125
126 if (colon)
127 *colon = ':';
128
124 memset(&addr, 0, sizeof(addr)); 129 memset(&addr, 0, sizeof(addr));
125 addr.sin6_family = AF_INET6; 130 addr.sin6_family = AF_INET6;
126 addr.sin6_port = htons(port); 131 addr.sin6_port = htons(port);
diff --git a/networking/udhcp/packet.c b/networking/udhcp/packet.c
index 78f580ce9..529978189 100644
--- a/networking/udhcp/packet.c
+++ b/networking/udhcp/packet.c
@@ -133,6 +133,7 @@ int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt,
133 dest_sll.sll_halen = 6; 133 dest_sll.sll_halen = 6;
134 memcpy(dest_sll.sll_addr, dest_arp, 6); 134 memcpy(dest_sll.sll_addr, dest_arp, 6);
135 135
136//TODO: is bind() necessary? we sendto() to this destination, should work anyway
136 if (bind(fd, (struct sockaddr *)&dest_sll, sizeof(dest_sll)) < 0) { 137 if (bind(fd, (struct sockaddr *)&dest_sll, sizeof(dest_sll)) < 0) {
137 msg = "bind(%s)"; 138 msg = "bind(%s)";
138 goto ret_close; 139 goto ret_close;
diff --git a/procps/pgrep.c b/procps/pgrep.c
index 6d25c247e..82e00322f 100644
--- a/procps/pgrep.c
+++ b/procps/pgrep.c
@@ -44,7 +44,7 @@
44//usage: "\n -P Match parent process ID" 44//usage: "\n -P Match parent process ID"
45//usage: 45//usage:
46//usage:#define pkill_trivial_usage 46//usage:#define pkill_trivial_usage
47//usage: "[-l|-SIGNAL] [-xfvno] [-s SID|-P PPID|PATTERN]" 47//usage: "[-l|-SIGNAL] [-xfvnoe] [-s SID|-P PPID|PATTERN]"
48//usage:#define pkill_full_usage "\n\n" 48//usage:#define pkill_full_usage "\n\n"
49//usage: "Send signal to processes selected by regex PATTERN\n" 49//usage: "Send signal to processes selected by regex PATTERN\n"
50//usage: "\n -l List all signals" 50//usage: "\n -l List all signals"
@@ -55,6 +55,7 @@
55//usage: "\n -v Negate the match" 55//usage: "\n -v Negate the match"
56//usage: "\n -n Signal the newest process only" 56//usage: "\n -n Signal the newest process only"
57//usage: "\n -o Signal the oldest process only" 57//usage: "\n -o Signal the oldest process only"
58//usage: "\n -e Display name and PID of the process being killed"
58 59
59#include "libbb.h" 60#include "libbb.h"
60#include "xregex.h" 61#include "xregex.h"
@@ -64,7 +65,7 @@
64#define pkill (ENABLE_PKILL && (!ENABLE_PGREP || applet_name[1] == 'k')) 65#define pkill (ENABLE_PKILL && (!ENABLE_PGREP || applet_name[1] == 'k'))
65 66
66enum { 67enum {
67 /* "vlafxons:+P:+" */ 68 /* "vlafxones:+P:+" */
68 OPTBIT_V = 0, /* must be first, we need OPT_INVERT = 0/1 */ 69 OPTBIT_V = 0, /* must be first, we need OPT_INVERT = 0/1 */
69 OPTBIT_L, 70 OPTBIT_L,
70 OPTBIT_A, 71 OPTBIT_A,
@@ -72,6 +73,7 @@ enum {
72 OPTBIT_X, 73 OPTBIT_X,
73 OPTBIT_O, 74 OPTBIT_O,
74 OPTBIT_N, 75 OPTBIT_N,
76 OPTBIT_E, /* should be pkill-only, do we care? */
75 OPTBIT_S, 77 OPTBIT_S,
76 OPTBIT_P, 78 OPTBIT_P,
77}; 79};
@@ -83,6 +85,7 @@ enum {
83#define OPT_ANCHOR (opt & (1 << OPTBIT_X)) 85#define OPT_ANCHOR (opt & (1 << OPTBIT_X))
84#define OPT_FIRST (opt & (1 << OPTBIT_O)) 86#define OPT_FIRST (opt & (1 << OPTBIT_O))
85#define OPT_LAST (opt & (1 << OPTBIT_N)) 87#define OPT_LAST (opt & (1 << OPTBIT_N))
88#define OPT_ECHO (opt & (1 << OPTBIT_E))
86#define OPT_SID (opt & (1 << OPTBIT_S)) 89#define OPT_SID (opt & (1 << OPTBIT_S))
87#define OPT_PPID (opt & (1 << OPTBIT_P)) 90#define OPT_PPID (opt & (1 << OPTBIT_P))
88 91
@@ -93,8 +96,12 @@ static void act(unsigned pid, char *cmd, int signo)
93 printf("%u %s\n", pid, cmd); 96 printf("%u %s\n", pid, cmd);
94 else 97 else
95 printf("%u\n", pid); 98 printf("%u\n", pid);
96 } else 99 } else {
97 kill(pid, signo); 100 kill(pid, signo);
101 if (option_mask32 & (1 << OPTBIT_E)) {
102 printf("%s killed (pid %u)\n", cmd, pid);
103 }
104 }
98} 105}
99 106
100int pgrep_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 107int pgrep_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
@@ -131,7 +138,7 @@ int pgrep_main(int argc UNUSED_PARAM, char **argv)
131 /* Parse remaining options */ 138 /* Parse remaining options */
132 ppid2match = -1; 139 ppid2match = -1;
133 sid2match = -1; 140 sid2match = -1;
134 opt = getopt32(argv, "vlafxons:+P:+", &sid2match, &ppid2match); 141 opt = getopt32(argv, "vlafxones:+P:+", &sid2match, &ppid2match);
135 argv += optind; 142 argv += optind;
136 143
137 if (pkill && OPT_LIST) { /* -l: print the whole signal list */ 144 if (pkill && OPT_LIST) { /* -l: print the whole signal list */
diff --git a/shell/ash.c b/shell/ash.c
index 13200da0c..6a4b8e273 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -10606,7 +10606,7 @@ evalpipe(union node *n, int flags)
10606} 10606}
10607 10607
10608/* setinteractive needs this forward reference */ 10608/* setinteractive needs this forward reference */
10609#if ENABLE_FEATURE_EDITING 10609#if ENABLE_FEATURE_TAB_COMPLETION
10610static const char *get_builtin_name(int i) FAST_FUNC; 10610static const char *get_builtin_name(int i) FAST_FUNC;
10611#endif 10611#endif
10612 10612
@@ -10643,8 +10643,12 @@ setinteractive(int on)
10643#if ENABLE_FEATURE_EDITING 10643#if ENABLE_FEATURE_EDITING
10644 if (!line_input_state) { 10644 if (!line_input_state) {
10645 line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP); 10645 line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
10646# if ENABLE_FEATURE_TAB_COMPLETION
10646 line_input_state->get_exe_name = get_builtin_name; 10647 line_input_state->get_exe_name = get_builtin_name;
10648# endif
10649# if EDITING_HAS_sh_get_var
10647 line_input_state->sh_get_var = lookupvar; 10650 line_input_state->sh_get_var = lookupvar;
10651# endif
10648 } 10652 }
10649#endif 10653#endif
10650 } 10654 }
@@ -10888,7 +10892,7 @@ mklocal(char *name, int flags)
10888 setvareq(name, flags); 10892 setvareq(name, flags);
10889 else 10893 else
10890 /* "local VAR" unsets VAR: */ 10894 /* "local VAR" unsets VAR: */
10891 setvar0(name, NULL); 10895 unsetvar(name);
10892 } 10896 }
10893 } 10897 }
10894 lvp->vp = vp; 10898 lvp->vp = vp;
@@ -11157,7 +11161,7 @@ find_builtin(const char *name)
11157 return bp; 11161 return bp;
11158} 11162}
11159 11163
11160#if ENABLE_FEATURE_EDITING 11164#if ENABLE_FEATURE_TAB_COMPLETION
11161static const char * FAST_FUNC 11165static const char * FAST_FUNC
11162get_builtin_name(int i) 11166get_builtin_name(int i)
11163{ 11167{
diff --git a/shell/hush.c b/shell/hush.c
index 051b123e7..d111f0cc5 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -2460,10 +2460,15 @@ static int set_local_var(char *str, unsigned flags)
2460 return retval; 2460 return retval;
2461} 2461}
2462 2462
2463static int set_local_var0(char *str)
2464{
2465 return set_local_var(str, 0);
2466}
2467
2463static void FAST_FUNC set_local_var_from_halves(const char *name, const char *val) 2468static void FAST_FUNC set_local_var_from_halves(const char *name, const char *val)
2464{ 2469{
2465 char *var = xasprintf("%s=%s", name, val); 2470 char *var = xasprintf("%s=%s", name, val);
2466 set_local_var(var, /*flag:*/ 0); 2471 set_local_var0(var);
2467} 2472}
2468 2473
2469/* Used at startup and after each cd */ 2474/* Used at startup and after each cd */
@@ -6964,7 +6969,7 @@ static NOINLINE int expand_one_var(o_string *output, int n,
6964 val = NULL; 6969 val = NULL;
6965 } else { 6970 } else {
6966 char *new_var = xasprintf("%s=%s", var, val); 6971 char *new_var = xasprintf("%s=%s", var, val);
6967 set_local_var(new_var, /*flag:*/ 0); 6972 set_local_var0(new_var);
6968 } 6973 }
6969 } 6974 }
6970 } 6975 }
@@ -8188,7 +8193,7 @@ static const struct built_in_command *find_builtin(const char *name)
8188 return find_builtin_helper(name, bltins2, &bltins2[ARRAY_SIZE(bltins2)]); 8193 return find_builtin_helper(name, bltins2, &bltins2[ARRAY_SIZE(bltins2)]);
8189} 8194}
8190 8195
8191#if ENABLE_HUSH_JOB && ENABLE_FEATURE_EDITING 8196#if ENABLE_HUSH_JOB && ENABLE_FEATURE_TAB_COMPLETION
8192static const char * FAST_FUNC get_builtin_name(int i) 8197static const char * FAST_FUNC get_builtin_name(int i)
8193{ 8198{
8194 if (/*i >= 0 && */ i < ARRAY_SIZE(bltins1)) { 8199 if (/*i >= 0 && */ i < ARRAY_SIZE(bltins1)) {
@@ -9373,7 +9378,7 @@ static NOINLINE int run_pipe(struct pipe *pi)
9373 } 9378 }
9374#endif 9379#endif
9375 debug_printf_env("set shell var:'%s'->'%s'\n", *argv, p); 9380 debug_printf_env("set shell var:'%s'->'%s'\n", *argv, p);
9376 if (set_local_var(p, /*flag:*/ 0)) { 9381 if (set_local_var0(p)) {
9377 /* assignment to readonly var / putenv error? */ 9382 /* assignment to readonly var / putenv error? */
9378 rcode = 1; 9383 rcode = 1;
9379 } 9384 }
@@ -9856,7 +9861,7 @@ static int run_list(struct pipe *pi)
9856 } 9861 }
9857 /* Insert next value from for_lcur */ 9862 /* Insert next value from for_lcur */
9858 /* note: *for_lcur already has quotes removed, $var expanded, etc */ 9863 /* note: *for_lcur already has quotes removed, $var expanded, etc */
9859 set_local_var(xasprintf("%s=%s", pi->cmds[0].argv[0], *for_lcur++), /*flag:*/ 0); 9864 set_local_var_from_halves(pi->cmds[0].argv[0], *for_lcur++);
9860 continue; 9865 continue;
9861 } 9866 }
9862 if (rword == RES_IN) { 9867 if (rword == RES_IN) {
@@ -10668,8 +10673,12 @@ int hush_main(int argc, char **argv)
10668 10673
10669# if ENABLE_FEATURE_EDITING 10674# if ENABLE_FEATURE_EDITING
10670 G.line_input_state = new_line_input_t(FOR_SHELL); 10675 G.line_input_state = new_line_input_t(FOR_SHELL);
10676# if ENABLE_FEATURE_TAB_COMPLETION
10671 G.line_input_state->get_exe_name = get_builtin_name; 10677 G.line_input_state->get_exe_name = get_builtin_name;
10678# endif
10679# if EDITING_HAS_sh_get_var
10672 G.line_input_state->sh_get_var = get_local_var_value; 10680 G.line_input_state->sh_get_var = get_local_var_value;
10681# endif
10673# endif 10682# endif
10674# if ENABLE_HUSH_SAVEHISTORY && MAX_HISTORY > 0 10683# if ENABLE_HUSH_SAVEHISTORY && MAX_HISTORY > 0
10675 { 10684 {
diff --git a/testsuite/mount.tests b/testsuite/mount.tests
index b6d5ebe08..7370805cd 100755
--- a/testsuite/mount.tests
+++ b/testsuite/mount.tests
@@ -104,12 +104,24 @@ mount -r -o loop -t ext2 z1/e2img z2 || { echo 'mount -r -o loop error'; e
104mount -o remount,ro z1 || { echo 'mount -o remount,ro error'; exit 1; } 104mount -o remount,ro z1 || { echo 'mount -o remount,ro error'; exit 1; }
105) 105)
106umount -d mount.dir/z2 106umount -d mount.dir/z2
107##losetup -d /dev/loop* 107##sleep 0.1
108umount -d mount.dir/z1 108umount -d mount.dir/z1
109rm -rf mount.dir 109rm -rf mount.dir
110echo DONE 110echo DONE
111" \ 111" \
112"DONE\n" "" "" 112"DONE\n" "" ""
113 113
114# On 5.18.0, "umount -d mount.dir/z1" above fails.
115# (It would work with "sleep 0.1" - looks like z1/e2img
116# is momentarily keeping z1 mountpoint busy, even though
117# the "umount" which freed z1/e2img from being the base
118# of z2 mountpoint has returned).
119# Fixing the mess if it did fail:
120if test -d mount.dir/z1; then
121 ls -ld mount.dir/z1/* mount.dir/z1
122 sleep 1
123 umount -d mount.dir/z1
124 rmdir mount.dir/z1 mount.dir
125fi
114 126
115exit $FAILCOUNT 127exit $FAILCOUNT
diff --git a/testsuite/sha1sum.tests b/testsuite/sha1sum.tests
index 7ad1334c3..e6ddb2a86 100755
--- a/testsuite/sha1sum.tests
+++ b/testsuite/sha1sum.tests
@@ -4,10 +4,12 @@
4 4
5# testing "test name" "cmd" "expected result" "file input" "stdin" 5# testing "test name" "cmd" "expected result" "file input" "stdin"
6>EMPTY 6>EMPTY
7optional FEATURE_MD5_SHA1_SUM_CHECK
7testing "sha1sum: one-space separated input for -c" \ 8testing "sha1sum: one-space separated input for -c" \
8 'echo "da39a3ee5e6b4b0d3255bfef95601890afd80709 EMPTY" | sha1sum -c' \ 9 'echo "da39a3ee5e6b4b0d3255bfef95601890afd80709 EMPTY" | sha1sum -c' \
9 "EMPTY: OK\n" \ 10 "EMPTY: OK\n" \
10 "" "" 11 "" ""
12SKIP=
11rm EMPTY 13rm EMPTY
12 14
13. ./md5sum.tests sha1sum d41337e834377140ae7f98460d71d908598ef04f 15. ./md5sum.tests sha1sum d41337e834377140ae7f98460d71d908598ef04f
diff --git a/testsuite/tree.tests b/testsuite/tree.tests
index 4f4a9e30b..1fa66da80 100755
--- a/testsuite/tree.tests
+++ b/testsuite/tree.tests
@@ -18,6 +18,8 @@ tree.tempdir [error opening dir]\n\
18mkdir -p tree2.tempdir 18mkdir -p tree2.tempdir
19touch tree2.tempdir/testfile 19touch tree2.tempdir/testfile
20 20
21optional UNICODE_SUPPORT
22
21testing "tree single file" \ 23testing "tree single file" \
22 "cd tree2.tempdir && tree" \ 24 "cd tree2.tempdir && tree" \
23 "\ 25 "\
@@ -50,17 +52,17 @@ testing "tree nested directories and files" \
50.\n\ 52.\n\
51├── test1\n\ 53├── test1\n\
52├── test2\n\ 54├── test2\n\
53   ├── a\n\ 55 ├── a\n\
54     ├── testfile1\n\ 56 ├── testfile1\n\
55     ├── testfile2\n\ 57 ├── testfile2\n\
56     ├── testfile3\n\ 58 ├── testfile3\n\
57     └── testfile4 -> ../b/testfile4\n\ 59 └── testfile4 -> ../b/testfile4\n\
58   └── b\n\ 60 └── b\n\
59   ├── test3 -> ../../test3\n\ 61 ├── test3 -> ../../test3\n\
60   └── testfile4\n\ 62 └── testfile4\n\
61└── test3\n\ 63└── test3\n\
62 ├── c\n\ 64 ├── c\n\
63   └── testfile5\n\ 65 └── testfile5\n\
64 └── d\n\ 66 └── d\n\
65 └── testfile6\n\ 67 └── testfile6\n\
66\n\ 68\n\
@@ -77,17 +79,17 @@ tree2.tempdir\n\
77tree3.tempdir\n\ 79tree3.tempdir\n\
78├── test1\n\ 80├── test1\n\
79├── test2\n\ 81├── test2\n\
80   ├── a\n\ 82 ├── a\n\
81     ├── testfile1\n\ 83 ├── testfile1\n\
82     ├── testfile2\n\ 84 ├── testfile2\n\
83     ├── testfile3\n\ 85 ├── testfile3\n\
84     └── testfile4 -> ../b/testfile4\n\ 86 └── testfile4 -> ../b/testfile4\n\
85   └── b\n\ 87 └── b\n\
86   ├── test3 -> ../../test3\n\ 88 ├── test3 -> ../../test3\n\
87   └── testfile4\n\ 89 └── testfile4\n\
88└── test3\n\ 90└── test3\n\
89 ├── c\n\ 91 ├── c\n\
90   └── testfile5\n\ 92 └── testfile5\n\
91 └── d\n\ 93 └── d\n\
92 └── testfile6\n\ 94 └── testfile6\n\
93\n\ 95\n\
diff --git a/util-linux/fbset.c b/util-linux/fbset.c
index 41cc29f37..768ab80eb 100644
--- a/util-linux/fbset.c
+++ b/util-linux/fbset.c
@@ -518,7 +518,13 @@ int fbset_main(int argc, char **argv)
518 case CMD_DEPTH: 518 case CMD_DEPTH:
519 var_set.bits_per_pixel = xatou32(argv[1]); 519 var_set.bits_per_pixel = xatou32(argv[1]);
520 break; 520 break;
521 case CMD_PIXCLOCK:
522 var_set.pixclock = xatou32(argv[1]);
523 break;
521#endif 524#endif
525 default:
526 bb_perror_msg_and_die("option '%s' not handled",
527 g_cmdoptions[i].name);
522 } 528 }
523 switch (g_cmdoptions[i].code) { 529 switch (g_cmdoptions[i].code) {
524 case CMD_FB: 530 case CMD_FB:
diff --git a/util-linux/hexdump_xxd.c b/util-linux/hexdump_xxd.c
index 9173f5d43..9738a76ad 100644
--- a/util-linux/hexdump_xxd.c
+++ b/util-linux/hexdump_xxd.c
@@ -41,7 +41,7 @@
41// -u use upper case hex letters. 41// -u use upper case hex letters.
42 42
43//usage:#define xxd_trivial_usage 43//usage:#define xxd_trivial_usage
44//usage: "[-pri] [-g N] [-c N] [-n LEN] [-s OFS] [-o OFS] [FILE]" 44//usage: "[-pri] [-g N] [-c N] [-l LEN] [-s OFS] [-o OFS] [FILE]"
45//usage:#define xxd_full_usage "\n\n" 45//usage:#define xxd_full_usage "\n\n"
46//usage: "Hex dump FILE (or stdin)\n" 46//usage: "Hex dump FILE (or stdin)\n"
47//usage: "\n -g N Bytes per group" 47//usage: "\n -g N Bytes per group"
@@ -78,7 +78,7 @@ static void write_zeros(off_t count)
78 do { 78 do {
79 unsigned sz = count < COMMON_BUFSIZE ? (unsigned)count : COMMON_BUFSIZE; 79 unsigned sz = count < COMMON_BUFSIZE ? (unsigned)count : COMMON_BUFSIZE;
80 if (fwrite(fillbuf, 1, sz, stdout) != sz) 80 if (fwrite(fillbuf, 1, sz, stdout) != sz)
81 bb_perror_msg_and_die("write error"); 81 bb_simple_perror_msg_and_die("write error");
82 count -= sz; 82 count -= sz;
83 } while (count != 0); 83 } while (count != 0);
84} 84}
@@ -120,7 +120,7 @@ static void reverse(unsigned opt, const char *filename, char *opt_s)
120 if (ofs != cur) { 120 if (ofs != cur) {
121 if (fseeko(stdout, ofs, SEEK_SET) != 0) { 121 if (fseeko(stdout, ofs, SEEK_SET) != 0) {
122 if (ofs < cur) 122 if (ofs < cur)
123 bb_perror_msg_and_die("cannot seek"); 123 bb_simple_perror_msg_and_die("cannot seek");
124 write_zeros(ofs - cur); 124 write_zeros(ofs - cur);
125 } 125 }
126 cur = ofs; 126 cur = ofs;
@@ -229,11 +229,8 @@ int xxd_main(int argc UNUSED_PARAM, char **argv)
229{ 229{
230 char buf[80]; 230 char buf[80];
231 dumper_t *dumper; 231 dumper_t *dumper;
232#if !ENABLE_PLATFORM_MINGW32 232 char *opt_l, *opt_o;
233 char *opt_l, *opt_s, *opt_o; 233 char *opt_s = NULL;
234#else
235 char *opt_l, *opt_s = NULL, *opt_o;
236#endif
237 unsigned bytes = 2; 234 unsigned bytes = 2;
238 unsigned cols = 0; 235 unsigned cols = 0;
239 unsigned opt; 236 unsigned opt;
diff --git a/util-linux/more.c b/util-linux/more.c
index a9ea76ab4..07275131e 100644
--- a/util-linux/more.c
+++ b/util-linux/more.c
@@ -87,11 +87,12 @@ int more_main(int argc UNUSED_PARAM, char **argv)
87 /* Parse options */ 87 /* Parse options */
88 /* Accepted but ignored: */ 88 /* Accepted but ignored: */
89 /* -d Display help instead of ringing bell */ 89 /* -d Display help instead of ringing bell */
90 /* -e Exit immediately after writing the last line */
90 /* -f Count logical lines (IOW: long lines are not folded) */ 91 /* -f Count logical lines (IOW: long lines are not folded) */
91 /* -l Do not pause after any line containing a ^L (form feed) */ 92 /* -l Do not pause after any line containing a ^L (form feed) */
92 /* -s Squeeze blank lines into one */ 93 /* -s Squeeze blank lines into one */
93 /* -u Suppress underlining */ 94 /* -u Suppress underlining */
94 getopt32(argv, "dflsu"); 95 getopt32(argv, "deflsu");
95 argv += optind; 96 argv += optind;
96 97
97 /* Another popular pager, most, detects when stdout 98 /* Another popular pager, most, detects when stdout