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 |
