diff options
author | Ron Yorston <rmy@pobox.com> | 2023-01-05 08:56:27 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2023-01-05 08:56:27 +0000 |
commit | e5e4a2fec5435192d1672e6db2f335cb5e89f877 (patch) | |
tree | 08cb827a40817ea4824bc9336d57eda669c4d4b2 | |
parent | 4343f3926355f55fc023203c992527fc34bf609e (diff) | |
parent | b1884deb514c35289d37e7bfbf23f770b0bd09b3 (diff) | |
download | busybox-w32-e5e4a2fec5435192d1672e6db2f335cb5e89f877.tar.gz busybox-w32-e5e4a2fec5435192d1672e6db2f335cb5e89f877.tar.bz2 busybox-w32-e5e4a2fec5435192d1672e6db2f335cb5e89f877.zip |
Merge branch 'busybox' into merge
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | Makefile.flags | 3 | ||||
-rw-r--r-- | archival/unzip.c | 2 | ||||
-rw-r--r-- | coreutils/dd.c | 20 | ||||
-rw-r--r-- | coreutils/mv.c | 4 | ||||
-rw-r--r-- | editors/sed.c | 17 | ||||
-rw-r--r-- | findutils/xargs.c | 85 | ||||
-rw-r--r-- | include/libbb.h | 8 | ||||
-rw-r--r-- | libbb/Config.src | 22 | ||||
-rw-r--r-- | libbb/lineedit.c | 24 | ||||
-rw-r--r-- | libbb/loop.c | 175 | ||||
-rw-r--r-- | networking/udhcp/Config.src | 7 | ||||
-rw-r--r-- | networking/udhcp/common.h | 3 | ||||
-rw-r--r-- | networking/udhcp/d6_common.h | 41 | ||||
-rw-r--r-- | networking/udhcp/d6_dhcpc.c | 17 | ||||
-rw-r--r-- | networking/udhcp/d6_packet.c | 15 | ||||
-rw-r--r-- | networking/udhcp/d6_socket.c | 13 | ||||
-rw-r--r-- | networking/udhcp/packet.c | 1 | ||||
-rw-r--r-- | procps/pgrep.c | 15 | ||||
-rw-r--r-- | shell/ash.c | 10 | ||||
-rw-r--r-- | shell/hush.c | 19 | ||||
-rwxr-xr-x | testsuite/mount.tests | 14 | ||||
-rwxr-xr-x | testsuite/sha1sum.tests | 2 | ||||
-rwxr-xr-x | testsuite/tree.tests | 38 | ||||
-rw-r--r-- | util-linux/fbset.c | 6 | ||||
-rw-r--r-- | util-linux/hexdump_xxd.c | 13 | ||||
-rw-r--r-- | util-linux/more.c | 3 |
27 files changed, 397 insertions, 182 deletions
@@ -1,5 +1,5 @@ | |||
1 | VERSION = 1 | 1 | VERSION = 1 |
2 | PATCHLEVEL = 36 | 2 | PATCHLEVEL = 37 |
3 | SUBLEVEL = 0 | 3 | SUBLEVEL = 0 |
4 | EXTRAVERSION = .git | 4 | EXTRAVERSION = .git |
5 | NAME = Unnamed | 5 | NAME = 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) | |||
196 | ifneq (,$(findstring linux,$(shell $(CC) $(CFLAGS) -dumpmachine))) | 196 | ifneq (,$(findstring linux,$(shell $(CC) $(CFLAGS) -dumpmachine))) |
197 | LDLIBS += resolv | 197 | LDLIBS += resolv |
198 | endif | 198 | endif |
199 | ifneq (,$(findstring gnu,$(shell $(CC) $(CFLAGS) -dumpmachine))) | ||
200 | LDLIBS += resolv | ||
201 | endif | ||
199 | endif | 202 | endif |
200 | 203 | ||
201 | ifeq ($(CONFIG_EFENCE),y) | 204 | ifeq ($(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) \ |
122 | do { if (BB_BIG_ENDIAN) { \ | 122 | do { 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 | ||
206 | static int clear_O_DIRECT(int fd) | 207 | static 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 | ||
219 | static ssize_t dd_read(void *ibuf, size_t ibs) | 221 | static 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 | ||
103 | struct sed_FILE { | 103 | struct 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 |
228 | void sed_free_and_close_stuff(void); | 237 | void 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 */ | ||
153 | enum { | ||
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 |
152 | static int wait_for_slot(int *idx) | 190 | static 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 */ | ||
653 | enum { | ||
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 | |||
686 | int xargs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 696 | int xargs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
687 | int xargs_main(int argc UNUSED_PARAM, char **argv) | 697 | int 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 | |||
373 | choice | ||
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 | |||
384 | config LOOP_CONFIGURE | ||
385 | bool "use LOOP_CONFIGURE, needs kernel >= 5.8" | ||
386 | |||
387 | config NO_LOOP_CONFIGURE | ||
388 | bool "use LOOP_SET_FD + LOOP_SET_STATUS" | ||
389 | |||
390 | config TRY_LOOP_CONFIGURE | ||
391 | bool "try LOOP_CONFIGURE, fall back to LOOP_SET_FD + LOOP_SET_STATUS" | ||
392 | |||
393 | endchoice | ||
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 | ||
252 | static 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 | |||
260 | static NOINLINE const char *get_homedir_or_NULL(void) | 252 | static 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 | ||
271 | static 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 |
279 | static size_t load_string(const char *src) | 281 | static 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 | ||
99 | static 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 | ||
115 | struct 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 | |||
123 | static 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 | |||
92 | config UDHCPC_DEFAULT_SCRIPT | 92 | config 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 | ||
101 | config 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: |
102 | INSERT | 107 | INSERT |
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; | |||
370 | void udhcp_sp_fd_set(struct pollfd *pfds, int extra_fd) FAST_FUNC; | 370 | void udhcp_sp_fd_set(struct pollfd *pfds, int extra_fd) FAST_FUNC; |
371 | int udhcp_sp_read(void) FAST_FUNC; | 371 | int udhcp_sp_read(void) FAST_FUNC; |
372 | 372 | ||
373 | int udhcp_read_interface(const char *interface, int *ifindex, uint32_t *nip, uint8_t *mac) FAST_FUNC; | 373 | int udhcp_read_interface(const char *interface, |
374 | int *ifindex, uint32_t *nip, uint8_t *mac) FAST_FUNC; | ||
374 | 375 | ||
375 | int udhcp_listen_socket(/*uint32_t ip,*/ int port, const char *inf) FAST_FUNC; | 376 | int 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) | |||
548 | static int d6_mcast_from_client_data_ifindex(struct d6_packet *packet, uint8_t *end) | 548 | static 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 | ||
30 | int FAST_FUNC d6_recv_kernel_packet(struct in6_addr *peer_ipv6 | 30 | int 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 | ||
66 | enum { | 67 | enum { |
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 | ||
100 | int pgrep_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 107 | int 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 |
10610 | static const char *get_builtin_name(int i) FAST_FUNC; | 10610 | static 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 |
11161 | static const char * FAST_FUNC | 11165 | static const char * FAST_FUNC |
11162 | get_builtin_name(int i) | 11166 | get_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 | ||
2463 | static int set_local_var0(char *str) | ||
2464 | { | ||
2465 | return set_local_var(str, 0); | ||
2466 | } | ||
2467 | |||
2463 | static void FAST_FUNC set_local_var_from_halves(const char *name, const char *val) | 2468 | static 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 |
8192 | static const char * FAST_FUNC get_builtin_name(int i) | 8197 | static 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 | |||
104 | mount -o remount,ro z1 || { echo 'mount -o remount,ro error'; exit 1; } | 104 | mount -o remount,ro z1 || { echo 'mount -o remount,ro error'; exit 1; } |
105 | ) | 105 | ) |
106 | umount -d mount.dir/z2 | 106 | umount -d mount.dir/z2 |
107 | ##losetup -d /dev/loop* | 107 | ##sleep 0.1 |
108 | umount -d mount.dir/z1 | 108 | umount -d mount.dir/z1 |
109 | rm -rf mount.dir | 109 | rm -rf mount.dir |
110 | echo DONE | 110 | echo 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: | ||
120 | if 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 | ||
125 | fi | ||
114 | 126 | ||
115 | exit $FAILCOUNT | 127 | exit $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 |
7 | optional FEATURE_MD5_SHA1_SUM_CHECK | ||
7 | testing "sha1sum: one-space separated input for -c" \ | 8 | testing "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 | "" "" |
12 | SKIP= | ||
11 | rm EMPTY | 13 | rm 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\ | |||
18 | mkdir -p tree2.tempdir | 18 | mkdir -p tree2.tempdir |
19 | touch tree2.tempdir/testfile | 19 | touch tree2.tempdir/testfile |
20 | 20 | ||
21 | optional UNICODE_SUPPORT | ||
22 | |||
21 | testing "tree single file" \ | 23 | testing "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\ | |||
77 | tree3.tempdir\n\ | 79 | tree3.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 |