From 852e8dd734662d80aa82be802b066130af85b261 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 26 May 2016 21:35:46 +0200 Subject: arping: avoid use of ether_ntoa(). Closes 8926 This is the only non-debug use of ether_ntoa(). By not using it, we reduce bss: function old new delta arping_main 1568 1665 +97 static.asc 18 - -18 ether_ntoa 57 - -57 ------------------------------------------------------------------------------ (add/remove: 0/2 grow/shrink: 1/0 up/down: 97/-75) Total: 22 bytes text data bss dec hex filename 911020 493 7352 918865 e0551 busybox_old 911069 493 7336 918898 e0572 busybox_unstripped Also, "standard" arping zero-pads MAC. ether_ntoa() does not. Signed-off-by: Denys Vlasenko --- networking/arping.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/networking/arping.c b/networking/arping.c index 6b0de4de2..4f207eaa5 100644 --- a/networking/arping.c +++ b/networking/arping.c @@ -231,20 +231,23 @@ static void recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM) if (!(option_mask32 & QUIET)) { int s_printed = 0; - printf("%scast re%s from %s [%s]", + printf("%scast re%s from %s [%02x:%02x:%02x:%02x:%02x:%02x]", FROM->sll_pkttype == PACKET_HOST ? "Uni" : "Broad", ah->ar_op == htons(ARPOP_REPLY) ? "ply" : "quest", inet_ntoa(src_ip), - ether_ntoa((struct ether_addr *) p)); + p[0], p[1], p[2], p[3], p[4], p[5] + ); if (dst_ip.s_addr != src.s_addr) { printf("for %s ", inet_ntoa(dst_ip)); s_printed = 1; } if (memcmp(p + ah->ar_hln + 4, me.sll_addr, ah->ar_hln)) { + unsigned char *pp = p + ah->ar_hln + 4; if (!s_printed) printf("for "); - printf("[%s]", - ether_ntoa((struct ether_addr *) p + ah->ar_hln + 4)); + printf("[%02x:%02x:%02x:%02x:%02x:%02x]", + pp[0], pp[1], pp[2], pp[3], pp[4], pp[5] + ); } if (last) { -- cgit v1.2.3-55-g6feb From 877dedb8251be47b3614a371434081ae9b7b358b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 27 May 2016 00:46:38 +0200 Subject: cp: add -u/--update and --remove-destination Based on the patch by wdlkmpx@gmail.com function old new delta copy_file 1546 1644 +98 add_partition 1270 1362 +92 ask_and_unlink 95 133 +38 do_iproute 132 157 +25 decode_one_format 710 715 +5 cp_main 369 374 +5 ubirename_main 198 202 +4 read_package_field 232 230 -2 bb_make_directory 421 412 -9 packed_usage 30505 30476 -29 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 7/3 up/down: 267/-40) Total: 227 bytes Signed-off-by: Denys Vlasenko --- coreutils/cp.c | 30 ++++++++++++++++++------------ include/libbb.h | 24 +++++++++++++++++------- libbb/copy_file.c | 21 +++++++++++++++++++++ 3 files changed, 56 insertions(+), 19 deletions(-) diff --git a/coreutils/cp.c b/coreutils/cp.c index 247ed0fda..2630c0d59 100644 --- a/coreutils/cp.c +++ b/coreutils/cp.c @@ -31,6 +31,7 @@ //usage: "\n -f Overwrite" //usage: "\n -i Prompt before overwrite" //usage: "\n -l,-s Create (sym)links" +//usage: "\n -u Copy only newer files" #include "libbb.h" #include "libcoreutils/coreutils.h" @@ -49,12 +50,10 @@ int cp_main(int argc, char **argv) int flags; int status; enum { - OPT_a = 1 << (sizeof(FILEUTILS_CP_OPTSTR)-1), - OPT_r = 1 << (sizeof(FILEUTILS_CP_OPTSTR)), - OPT_P = 1 << (sizeof(FILEUTILS_CP_OPTSTR)+1), - OPT_v = 1 << (sizeof(FILEUTILS_CP_OPTSTR)+2), + FILEUTILS_CP_OPTNUM = sizeof(FILEUTILS_CP_OPTSTR)-1, #if ENABLE_FEATURE_CP_LONG_OPTIONS - OPT_parents = 1 << (sizeof(FILEUTILS_CP_OPTSTR)+3), + /*OPT_rmdest = FILEUTILS_RMDEST = 1 << FILEUTILS_CP_OPTNUM */ + OPT_parents = 1 << (FILEUTILS_CP_OPTNUM+1), #endif }; @@ -76,10 +75,12 @@ int cp_main(int argc, char **argv) "recursive\0" No_argument "R" "symbolic-link\0" No_argument "s" "verbose\0" No_argument "v" - "parents\0" No_argument "\xff" + "update\0" No_argument "u" + "remove-destination\0" No_argument "\xff" + "parents\0" No_argument "\xfe" ; #endif - flags = getopt32(argv, FILEUTILS_CP_OPTSTR "arPv"); + flags = getopt32(argv, FILEUTILS_CP_OPTSTR); /* Options of cp from GNU coreutils 6.10: * -a, --archive * -f, --force @@ -94,6 +95,11 @@ int cp_main(int argc, char **argv) * -d same as --no-dereference --preserve=links * -p same as --preserve=mode,ownership,timestamps * -c same as --preserve=context + * -u, --update + * copy only when the SOURCE file is newer than the destination + * file or when the destination file is missing + * --remove-destination + * remove each existing destination file before attempting to open * --parents * use full source file name under DIRECTORY * NOT SUPPORTED IN BBOX: @@ -106,8 +112,6 @@ int cp_main(int argc, char **argv) * preserve attributes (default: mode,ownership,timestamps), * if possible additional attributes: security context,links,all * --no-preserve=ATTR_LIST - * --remove-destination - * remove each existing destination file before attempting to open * --sparse=WHEN * control creation of sparse files * --strip-trailing-slashes @@ -118,9 +122,6 @@ int cp_main(int argc, char **argv) * copy all SOURCE arguments into DIRECTORY * -T, --no-target-directory * treat DEST as a normal file - * -u, --update - * copy only when the SOURCE file is newer than the destination - * file or when the destination file is missing * -x, --one-file-system * stay on this file system * -Z, --context=CONTEXT @@ -156,11 +157,16 @@ int cp_main(int argc, char **argv) return EXIT_FAILURE; #if ENABLE_FEATURE_CP_LONG_OPTIONS + //bb_error_msg("flags:%x FILEUTILS_RMDEST:%x OPT_parents:%x", + // flags, FILEUTILS_RMDEST, OPT_parents); if (flags & OPT_parents) { if (!(d_flags & 2)) { bb_error_msg_and_die("with --parents, the destination must be a directory"); } } + if (flags & FILEUTILS_RMDEST) { + flags |= FILEUTILS_FORCE; + } #endif /* ...if neither is a directory... */ diff --git a/include/libbb.h b/include/libbb.h index fd40ef74c..a21f4204a 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -351,7 +351,7 @@ extern char *strrstr(const char *haystack, const char *needle) FAST_FUNC; //TODO: supply a pointer to char[11] buffer (avoid statics)? extern const char *bb_mode_string(mode_t mode) FAST_FUNC; extern int is_directory(const char *name, int followLinks) FAST_FUNC; -enum { /* DO NOT CHANGE THESE VALUES! cp.c, mv.c, install.c depend on them. */ +enum { /* cp.c, mv.c, install.c depend on these values. CAREFUL when changing them! */ FILEUTILS_PRESERVE_STATUS = 1 << 0, /* -p */ FILEUTILS_DEREFERENCE = 1 << 1, /* !-d */ FILEUTILS_RECUR = 1 << 2, /* -R */ @@ -361,15 +361,25 @@ enum { /* DO NOT CHANGE THESE VALUES! cp.c, mv.c, install.c depend on them. */ FILEUTILS_MAKE_SOFTLINK = 1 << 6, /* -s */ FILEUTILS_DEREF_SOFTLINK = 1 << 7, /* -L */ FILEUTILS_DEREFERENCE_L0 = 1 << 8, /* -H */ + /* -a = -pdR (mapped in cp.c) */ + /* -r = -dR (mapped in cp.c) */ + /* -P = -d (mapped in cp.c) */ + FILEUTILS_VERBOSE = (1 << 12) * ENABLE_FEATURE_VERBOSE, /* -v */ + FILEUTILS_UPDATE = 1 << 13, /* -u */ #if ENABLE_SELINUX - FILEUTILS_PRESERVE_SECURITY_CONTEXT = 1 << 9, /* -c */ - FILEUTILS_SET_SECURITY_CONTEXT = 1 << 10, + FILEUTILS_PRESERVE_SECURITY_CONTEXT = 1 << 14, /* -c */ #endif - FILEUTILS_IGNORE_CHMOD_ERR = 1 << 11, - /* -v */ - FILEUTILS_VERBOSE = (1 << 12) * ENABLE_FEATURE_VERBOSE, + FILEUTILS_RMDEST = 1 << (15 - !ENABLE_SELINUX), /* --remove-destination */ + /* + * Hole. cp may have some bits set here, + * they should not affect remove_file()/copy_file() + */ +#if ENABLE_SELINUX + FILEUTILS_SET_SECURITY_CONTEXT = 1 << 30, +#endif + FILEUTILS_IGNORE_CHMOD_ERR = 1 << 31, }; -#define FILEUTILS_CP_OPTSTR "pdRfilsLH" IF_SELINUX("c") +#define FILEUTILS_CP_OPTSTR "pdRfilsLHarPvu" IF_SELINUX("c") extern int remove_file(const char *path, int flags) FAST_FUNC; /* NB: without FILEUTILS_RECUR in flags, it will basically "cat" * the source, not copy (unless "source" is a directory). diff --git a/libbb/copy_file.c b/libbb/copy_file.c index a4be875d2..23bcf2e82 100644 --- a/libbb/copy_file.c +++ b/libbb/copy_file.c @@ -64,6 +64,11 @@ static int ask_and_unlink(const char *dest, int flags) bb_perror_msg("can't create '%s'", dest); return -1; /* error */ } +#if ENABLE_FEATURE_CP_LONG_OPTIONS + if (flags & FILEUTILS_RMDEST) + if (flags & FILEUTILS_VERBOSE) + printf("removed '%s'\n", dest); +#endif return 1; /* ok (to try again) */ } @@ -210,6 +215,22 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags) goto preserve_mode_ugid_time; } + if (dest_exists) { + if (flags & FILEUTILS_UPDATE) { + if (source_stat.st_mtime <= dest_stat.st_mtime) { + return 0; /* source file must be newer */ + } + } +#if ENABLE_FEATURE_CP_LONG_OPTIONS + if (flags & FILEUTILS_RMDEST) { + ovr = ask_and_unlink(dest, flags); + if (ovr <= 0) + return ovr; + dest_exists = 0; + } +#endif + } + if (flags & (FILEUTILS_MAKE_SOFTLINK|FILEUTILS_MAKE_HARDLINK)) { int (*lf)(const char *oldpath, const char *newpath); make_links: -- cgit v1.2.3-55-g6feb From 8e95068c7f28fe2a1e31b01636e3ed29eed09ef8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 31 May 2016 02:42:49 +0200 Subject: Make busybox an optional applet If it's disabled, code shrinks by about 900 bytes: function old new delta usr_bin 10 - -10 usr_sbin 11 - -11 install_dir 20 - -20 applet_install_loc 184 - -184 run_applet_and_exit 686 21 -665 ------------------------------------------------------------------------------ (add/remove: 0/4 grow/shrink: 0/1 up/down: 0/-890) Total: -890 bytes text data bss dec hex filename 911327 493 7336 919156 e0674 busybox_old 909848 493 7336 917677 e00ad busybox_unstripped but busybox executable by itself does not say anything useful: $ busybox busybox: applet not found Based on the patch by Ron Yorston Signed-off-by: Denys Vlasenko --- Config.in | 12 ++++++++++++ libbb/appletlib.c | 10 +++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/Config.in b/Config.in index 0a0b5d7cb..3d1870966 100644 --- a/Config.in +++ b/Config.in @@ -116,9 +116,21 @@ config FEATURE_COMPRESS_USAGE and have very little memory, this might not be a win. Otherwise, you probably want this. +config BUSYBOX + bool "Include busybox applet" + default y + help + The busybox applet provides general help regarding busybox and + allows the included applets to be listed. It's also required + if applet links are to be installed at runtime. + + If you can live without these features disabling this will save + some space. + config FEATURE_INSTALLER bool "Support --install [-s] to install applet links at runtime" default y + depends on BUSYBOX help Enable 'busybox --install [-s]' support. This will allow you to use busybox at runtime to create hard links or symlinks for all the diff --git a/libbb/appletlib.c b/libbb/appletlib.c index b682e6b85..281123c37 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -701,7 +701,7 @@ static void install_links(const char *busybox, int use_symbolic_links, continue; } } -# else +# elif ENABLE_BUSYBOX static void install_links(const char *busybox UNUSED_PARAM, int use_symbolic_links UNUSED_PARAM, char *custom_install_dir UNUSED_PARAM) @@ -709,6 +709,7 @@ static void install_links(const char *busybox UNUSED_PARAM, } # endif +# if ENABLE_BUSYBOX /* If we were called as "busybox..." */ static int busybox_main(char **argv) { @@ -784,10 +785,10 @@ static int busybox_main(char **argv) const char *a = applet_names; dup2(1, 2); while (*a) { -# if ENABLE_FEATURE_INSTALLER +# if ENABLE_FEATURE_INSTALLER if (argv[1][6]) /* --list-full? */ full_write2_str(install_dir[APPLET_INSTALL_LOC(i)] + 1); -# endif +# endif full_write2_str(a); full_write2_str("\n"); i++; @@ -843,6 +844,7 @@ static int busybox_main(char **argv) /* POSIX: "If a command is not found, the exit status shall be 127" */ exit(127); } +# endif void FAST_FUNC run_applet_no_and_exit(int applet_no, char **argv) { @@ -886,8 +888,10 @@ void FAST_FUNC run_applet_and_exit(const char *name, char **argv) { int applet; +# if ENABLE_BUSYBOX if (is_prefixed_with(name, "busybox")) exit(busybox_main(argv)); +# endif /* find_applet_by_name() search is more expensive, so goes second */ applet = find_applet_by_name(name); if (applet >= 0) -- cgit v1.2.3-55-g6feb From b684d1b1864ba9d7968de5565823f8e42f1dc448 Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Thu, 19 May 2016 17:31:59 +0200 Subject: libbb: fix time parsing of [[CC]YY]MMDDhhmm[.SS]. Closes 8951 If SS is not given a value, it is assumed to be zero. http://pubs.opengroup.org/onlinepubs/9699919799/utilities/touch.html Signed-off-by: Natanael Copa Signed-off-by: Denys Vlasenko --- libbb/time.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libbb/time.c b/libbb/time.c index aa19a47d4..82e6cb172 100644 --- a/libbb/time.c +++ b/libbb/time.c @@ -186,6 +186,7 @@ void FAST_FUNC parse_datestr(const char *date_str, struct tm *ptm) } else { bb_error_msg_and_die(bb_msg_invalid_date, date_str); } + ptm->tm_sec = 0; /* assume zero if [.SS] is not given */ if (end == '.') { /* xxx.SS */ if (sscanf(strchr(date_str, '.') + 1, "%u%c", -- cgit v1.2.3-55-g6feb From e4caf1dd9ce8569371a0eeb77ccf02a572dc0f11 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 6 Jun 2016 02:26:49 +0200 Subject: ntpd: retry initial DNS resolution (forever, no timeout for now). Some users start ntpd on boot, and don't babysit it. If it dies because DNS is not yet up and therefore NTP servers can't be found, users are not happy. Example behavior with a peer name which can't be resolved: ntpd: bad address 'qwe.rty.ghj.kl' ...5 sec... ntpd: bad address 'qwe.rty.ghj.kl' ntpd: bad address 'qwe.rty.ghj.kl' ntpd: bad address 'qwe.rty.ghj.kl' ntpd: bad address 'qwe.rty.ghj.kl' ntpd: bad address 'qwe.rty.ghj.kl' ntpd: bad address 'qwe.rty.ghj.kl' ntpd: bad address 'qwe.rty.ghj.kl' ntpd: bad address 'qwe.rty.ghj.kl' ntpd: bad address 'qwe.rty.ghj.kl' ... Based on the patch by Kaarle Ritvanen function old new delta resolve_peer_hostname - 81 +81 ntpd_main 1130 1061 -69 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/1 up/down: 81/-69) Total: 12 bytes Signed-off-by: Denys Vlasenko --- networking/ntpd.c | 47 ++++++++++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/networking/ntpd.c b/networking/ntpd.c index 410318979..98158a304 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c @@ -267,7 +267,6 @@ typedef struct { typedef struct { len_and_sockaddr *p_lsa; - char *p_hostname; char *p_dotted; int p_fd; int datapoint_idx; @@ -293,6 +292,7 @@ typedef struct { datapoint_t filter_datapoint[NUM_DATAPOINTS]; /* last sent packet: */ msg_t p_xmt_msg; + char p_hostname[1]; } peer_t; @@ -764,15 +764,39 @@ reset_peer_stats(peer_t *p, double offset) VERB6 bb_error_msg("%s->lastpkt_recv_time=%f", p->p_dotted, p->lastpkt_recv_time); } +static void +resolve_peer_hostname(peer_t *p, int loop_on_fail) +{ + len_and_sockaddr *lsa; + + again: + lsa = host2sockaddr(p->p_hostname, 123); + if (!lsa) { + /* error message already emitted by host2sockaddr() */ + if (!loop_on_fail) + return; +//FIXME: do this to avoid infinite looping on typo in a hostname? +//well... in which case, what is a good value for loop_on_fail? + //if (--loop_on_fail == 0) + // xfunc_die(); + sleep(5); + goto again; + } + free(p->p_lsa); + free(p->p_dotted); + p->p_lsa = lsa; + p->p_dotted = xmalloc_sockaddr2dotted_noport(&lsa->u.sa); +} + static void add_peers(const char *s) { llist_t *item; peer_t *p; - p = xzalloc(sizeof(*p)); - p->p_lsa = xhost2sockaddr(s, 123); - p->p_dotted = xmalloc_sockaddr2dotted_noport(&p->p_lsa->u.sa); + p = xzalloc(sizeof(*p) + strlen(s)); + strcpy(p->p_hostname, s); + resolve_peer_hostname(p, /*loop_on_fail=*/ 1); /* Names like N..pool.ntp.org are randomly resolved * to a pool of machines. Sometimes different N's resolve to the same IP. @@ -789,7 +813,6 @@ add_peers(const char *s) } } - p->p_hostname = xstrdup(s); p->p_fd = -1; p->p_xmt_msg.m_status = MODE_CLIENT | (NTP_VERSION << 3); p->next_action_time = G.cur_time; /* = set_next(p, 0); */ @@ -2338,18 +2361,8 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv) p->p_dotted, p->reachable_bits, timeout); /* What if don't see it because it changed its IP? */ - if (p->reachable_bits == 0) { - len_and_sockaddr *lsa = host2sockaddr(p->p_hostname, 123); - if (lsa) { - char *dotted = xmalloc_sockaddr2dotted_noport(&lsa->u.sa); - //if (strcmp(dotted, p->p_dotted) != 0) - // bb_error_msg("peer IP changed"); - free(p->p_lsa); - free(p->p_dotted); - p->p_lsa = lsa; - p->p_dotted = dotted; - } - } + if (p->reachable_bits == 0) + resolve_peer_hostname(p, /*loop_on_fail=*/ 0); set_next(p, timeout); } -- cgit v1.2.3-55-g6feb From ba12081a9e9b2d90d1924546bc9097abf52cf2b5 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Tue, 7 Jun 2016 10:26:24 +0100 Subject: Allow "busybox " to work when busybox is disabled A recent commit made it possible to disable BusyBox's --install and --list options. However it also stopped "busybox " from working. Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- libbb/appletlib.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 281123c37..b6fe1dad2 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -956,6 +956,10 @@ int main(int argc UNUSED_PARAM, char **argv) #else lbb_prepare("busybox" IF_FEATURE_INDIVIDUAL(, argv)); +#if !ENABLE_BUSYBOX + if (argv[1] && is_prefixed_with(bb_basename(argv[0]), "busybox")) + argv++; +#endif applet_name = argv[0]; if (applet_name[0] == '-') applet_name++; -- cgit v1.2.3-55-g6feb From ce824aecf216536beed00d7817a614ffb8572239 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Tue, 7 Jun 2016 12:12:07 +0100 Subject: libbb: move common code into run_applet_and_exit Both calls to run_applet_and_exit are followed by the same code to print an error message and return status 127. Remove this duplication and make run_applet_and_exit static. function old new delta run_applet_and_exit 675 667 -8 main 119 92 -27 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-35) Total: -35 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- include/libbb.h | 2 -- libbb/appletlib.c | 21 ++++++++------------- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index a21f4204a..e39021eb1 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1239,8 +1239,6 @@ const struct hwtype *get_hwntype(int type) FAST_FUNC; #ifndef BUILD_INDIVIDUAL extern int find_applet_by_name(const char *name) FAST_FUNC; -/* Returns only if applet is not found. */ -extern void run_applet_and_exit(const char *name, char **argv) FAST_FUNC; extern void run_applet_no_and_exit(int a, char **argv) NORETURN FAST_FUNC; #endif diff --git a/libbb/appletlib.c b/libbb/appletlib.c index b6fe1dad2..480bf50fc 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -52,6 +52,7 @@ #include "usage_compressed.h" +static void run_applet_and_exit(const char *name, char **argv) NORETURN; #if ENABLE_SHOW_USAGE && !ENABLE_FEATURE_COMPRESS_USAGE static const char usage_messages[] ALIGN1 = UNPACKED_USAGE; @@ -837,12 +838,6 @@ static int busybox_main(char **argv) * "#!/bin/busybox"-style wrappers */ applet_name = bb_get_last_path_component_nostrip(argv[0]); run_applet_and_exit(applet_name, argv); - - /*bb_error_msg_and_die("applet not found"); - sucks in printf */ - full_write2_str(applet_name); - full_write2_str(": applet not found\n"); - /* POSIX: "If a command is not found, the exit status shall be 127" */ - exit(127); } # endif @@ -884,7 +879,7 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, char **argv) exit(applet_main[applet_no](argc, argv)); } -void FAST_FUNC run_applet_and_exit(const char *name, char **argv) +static NORETURN void run_applet_and_exit(const char *name, char **argv) { int applet; @@ -896,6 +891,12 @@ void FAST_FUNC run_applet_and_exit(const char *name, char **argv) applet = find_applet_by_name(name); if (applet >= 0) run_applet_no_and_exit(applet, argv); + + /*bb_error_msg_and_die("applet not found"); - links in printf */ + full_write2_str(applet_name); + full_write2_str(": applet not found\n"); + /* POSIX: "If a command is not found, the exit status shall be 127" */ + exit(127); } #endif /* !defined(SINGLE_APPLET_MAIN) */ @@ -968,11 +969,5 @@ int main(int argc UNUSED_PARAM, char **argv) parse_config_file(); /* ...maybe, if FEATURE_SUID_CONFIG */ run_applet_and_exit(applet_name, argv); - - /*bb_error_msg_and_die("applet not found"); - sucks in printf */ - full_write2_str(applet_name); - full_write2_str(": applet not found\n"); - /* POSIX: "If a command is not found, the exit status shall be 127" */ - exit(127); #endif } -- cgit v1.2.3-55-g6feb From 015db5800ca7c6dd2d201eacb2951e72e6782b30 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 19 Jun 2016 18:15:33 +0200 Subject: randomconfig fixes Signed-off-by: Denys Vlasenko --- archival/libarchive/get_header_tar.c | 23 ++++++++++++++++------- archival/tar.c | 6 ++++-- miscutils/Kbuild.src | 9 +++++++-- modutils/modprobe-small.c | 1 - scripts/kconfig/zconf.hash.c_shipped | 14 ++------------ scripts/randomtest | 20 ++++++++++++++++++++ testsuite/busybox.tests | 16 ++++++++++------ testsuite/du/du-m-works | 2 +- util-linux/fbset.c | 5 +++-- util-linux/fdisk_osf.c | 3 ++- util-linux/fdisk_sgi.c | 27 +++++++++++++++------------ 11 files changed, 80 insertions(+), 46 deletions(-) diff --git a/archival/libarchive/get_header_tar.c b/archival/libarchive/get_header_tar.c index ac2be726f..ea91a883e 100644 --- a/archival/libarchive/get_header_tar.c +++ b/archival/libarchive/get_header_tar.c @@ -60,13 +60,21 @@ static unsigned long long getOctal(char *str, int len) } #define GET_OCTAL(a) getOctal((a), sizeof(a)) +#define TAR_EXTD (ENABLE_FEATURE_TAR_GNU_EXTENSIONS || ENABLE_FEATURE_TAR_SELINUX) +#if !TAR_EXTD +#define process_pax_hdr(archive_handle, sz, global) \ + process_pax_hdr(archive_handle, sz) +#endif /* "global" is 0 or 1 */ static void process_pax_hdr(archive_handle_t *archive_handle, unsigned sz, int global) { +#if !TAR_EXTD + unsigned blk_sz = (sz + 511) & (~511); + seek_by_read(archive_handle->src_fd, blk_sz); +#else + unsigned blk_sz = (sz + 511) & (~511); char *buf, *p; - unsigned blk_sz; - blk_sz = (sz + 511) & (~511); p = buf = xmalloc(blk_sz + 1); xread(archive_handle->src_fd, buf, blk_sz); archive_handle->offset += blk_sz; @@ -104,30 +112,31 @@ static void process_pax_hdr(archive_handle_t *archive_handle, unsigned sz, int g p[-1] = '\0'; value = end + 1; -#if ENABLE_FEATURE_TAR_GNU_EXTENSIONS +# if ENABLE_FEATURE_TAR_GNU_EXTENSIONS if (!global && is_prefixed_with(value, "path=")) { value += sizeof("path=") - 1; free(archive_handle->tar__longname); archive_handle->tar__longname = xstrdup(value); continue; } -#endif +# endif -#if ENABLE_FEATURE_TAR_SELINUX +# if ENABLE_FEATURE_TAR_SELINUX /* Scan for SELinux contexts, via "RHT.security.selinux" keyword. * This is what Red Hat's patched version of tar uses. */ -# define SELINUX_CONTEXT_KEYWORD "RHT.security.selinux" +# define SELINUX_CONTEXT_KEYWORD "RHT.security.selinux" if (is_prefixed_with(value, SELINUX_CONTEXT_KEYWORD"=")) { value += sizeof(SELINUX_CONTEXT_KEYWORD"=") - 1; free(archive_handle->tar__sctx[global]); archive_handle->tar__sctx[global] = xstrdup(value); continue; } -#endif +# endif } free(buf); +#endif } char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) diff --git a/archival/tar.c b/archival/tar.c index 346a9404e..7434e22e4 100644 --- a/archival/tar.c +++ b/archival/tar.c @@ -1199,9 +1199,10 @@ int tar_main(int argc UNUSED_PARAM, char **argv) // /* We need to know whether child (gzip/bzip/etc) exits abnormally */ // signal(SIGCHLD, check_errors_in_children); +#if ENABLE_FEATURE_TAR_CREATE /* Create an archive */ if (opt & OPT_CREATE) { -#if SEAMLESS_COMPRESSION +# if SEAMLESS_COMPRESSION const char *zipMode = NULL; if (opt & OPT_COMPRESS) zipMode = "compress"; @@ -1213,7 +1214,7 @@ int tar_main(int argc UNUSED_PARAM, char **argv) zipMode = "lzma"; if (opt & OPT_XZ) zipMode = "xz"; -#endif +# endif /* NB: writeTarFile() closes tar_handle->src_fd */ return writeTarFile(tar_handle->src_fd, verboseFlag, (opt & OPT_DEREFERENCE ? ACTION_FOLLOWLINKS : 0) @@ -1221,6 +1222,7 @@ int tar_main(int argc UNUSED_PARAM, char **argv) tar_handle->accept, tar_handle->reject, zipMode); } +#endif if (opt & OPT_ANY_COMPRESS) { USE_FOR_MMU(IF_DESKTOP(long long) int FAST_FUNC (*xformer)(transformer_state_t *xstate);) diff --git a/miscutils/Kbuild.src b/miscutils/Kbuild.src index 7b449e6e8..503f54904 100644 --- a/miscutils/Kbuild.src +++ b/miscutils/Kbuild.src @@ -25,8 +25,13 @@ lib-$(CONFIG_FLASH_UNLOCK) += flash_lock_unlock.o lib-$(CONFIG_IONICE) += ionice.o lib-$(CONFIG_HDPARM) += hdparm.o lib-$(CONFIG_INOTIFYD) += inotifyd.o -lib-$(CONFIG_FEATURE_LAST_SMALL)+= last.o -lib-$(CONFIG_FEATURE_LAST_FANCY)+= last_fancy.o + +ifeq ($(CONFIG_FEATURE_LAST_FANCY),y) +lib-$(CONFIG_FEATURE_LAST_FANCY) += last_fancy.o +else +lib-$(CONFIG_LAST) += last.o +endif + lib-$(CONFIG_LESS) += less.o lib-$(CONFIG_MAKEDEVS) += makedevs.o lib-$(CONFIG_MAN) += man.o diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c index 9c941064b..ffb46e6be 100644 --- a/modutils/modprobe-small.c +++ b/modutils/modprobe-small.c @@ -21,7 +21,6 @@ extern int init_module(void *module, unsigned long len, const char *options); extern int delete_module(const char *module, unsigned flags); -extern int query_module(const char *name, int which, void *buf, size_t bufsize, size_t *ret); /* linux/include/linux/module.h has limit of 64 chars on module names */ #undef MODULE_NAME_LEN #define MODULE_NAME_LEN 64 diff --git a/scripts/kconfig/zconf.hash.c_shipped b/scripts/kconfig/zconf.hash.c_shipped index d39cf189a..29d9cf6cc 100644 --- a/scripts/kconfig/zconf.hash.c_shipped +++ b/scripts/kconfig/zconf.hash.c_shipped @@ -32,14 +32,7 @@ struct kconf_id; /* maximum key range = 45, duplicates = 0 */ -#ifdef __GNUC__ -__inline -#else -#ifdef __cplusplus -inline -#endif -#endif -static unsigned int +unsigned int kconf_id_hash (register const char *str, register unsigned int len) { static unsigned char asso_values[] = @@ -119,7 +112,7 @@ struct kconf_id_strings_t char kconf_id_strings_str41[sizeof("choice")]; char kconf_id_strings_str46[sizeof("prompt")]; }; -static struct kconf_id_strings_t kconf_id_strings_contents = +struct kconf_id_strings_t kconf_id_strings_contents = { "if", "int", @@ -153,9 +146,6 @@ static struct kconf_id_strings_t kconf_id_strings_contents = "prompt" }; #define kconf_id_strings ((const char *) &kconf_id_strings_contents) -#ifdef __GNUC__ -__inline -#endif struct kconf_id * kconf_id_lookup (register const char *str, register unsigned int len) { diff --git a/scripts/randomtest b/scripts/randomtest index e2513d058..41f252ad7 100755 --- a/scripts/randomtest +++ b/scripts/randomtest @@ -52,9 +52,18 @@ echo '# CONFIG_RFKILL is not set' >>.config if test x"$LIBC" = x"glibc"; then cat .config \ | grep -v CONFIG_STATIC \ + \ + | grep -v CONFIG_FEATURE_2_4_MODULES \ + | grep -v CONFIG_FEATURE_USE_BSS_TAIL \ + | grep -v CONFIG_DEBUG_SANITIZE \ >.config.new mv .config.new .config echo '# CONFIG_STATIC is not set' >>.config + # newer glibc (at least 2.23) no longer supply query_module() ABI. + # People who target 2.4 kernels would likely use older glibc (and older bbox). + echo '# CONFIG_FEATURE_2_4_MODULES is not set' >>.config + echo '# CONFIG_FEATURE_USE_BSS_TAIL is not set' >>.config + echo '# CONFIG_DEBUG_SANITIZE is not set' >>.config fi # If uclibc, build static, and remove some things @@ -68,6 +77,11 @@ if test x"$LIBC" = x"uclibc"; then | grep -v CONFIG_FEATURE_2_4_MODULES \ | grep -v CONFIG_FEATURE_SYNC_FANCY \ | grep -v CONFIG_FEATURE_TOUCH_NODEREF \ + | grep -v CONFIG_NANDWRITE \ + | grep -v CONFIG_NANDDUMP \ + | grep -v CONFIG_BLKDISCARD \ + | grep -v CONFIG_NSENTER \ + | grep -v CONFIG_UNSHARE \ >.config.new mv .config.new .config echo 'CONFIG_STATIC=y' >>.config @@ -76,6 +90,12 @@ if test x"$LIBC" = x"uclibc"; then echo '# CONFIG_FEATURE_2_4_MODULES is not set' >>.config echo '# CONFIG_FEATURE_SYNC_FANCY is not set' >>.config echo '# CONFIG_FEATURE_TOUCH_NODEREF is not set' >>.config + # My uclibc installation does not support some needed APIs... + echo '# CONFIG_NANDWRITE is not set' >>.config + echo '# CONFIG_NANDDUMP is not set' >>.config + echo '# CONFIG_BLKDISCARD is not set' >>.config + echo '# CONFIG_NSENTER is not set' >>.config + echo '# CONFIG_UNSHARE is not set' >>.config fi # If STATIC, remove some things. diff --git a/testsuite/busybox.tests b/testsuite/busybox.tests index 04fea3ea2..545cad5c0 100755 --- a/testsuite/busybox.tests +++ b/testsuite/busybox.tests @@ -6,6 +6,16 @@ . ./testing.sh +ln -s `which busybox` unknown + +testing "busybox as unknown name" "./unknown 2>&1" \ + "unknown: applet not found\n" "" "" +rm unknown + +# We need busybox --help to be enabled for the rest of tests +test x"$CONFIG_BUSYBOX" = x"y" \ +|| { echo "SKIPPED: busybox --help"; exit 0; } + HELPDUMP=`true | busybox 2>&1 | cat` # We need to test under calling the binary under other names. @@ -38,10 +48,4 @@ do done rm busybox-suffix -ln -s `which busybox` unknown - -testing "busybox as unknown name" "./unknown 2>&1" \ - "unknown: applet not found\n" "" "" -rm unknown - exit $FAILCOUNT diff --git a/testsuite/du/du-m-works b/testsuite/du/du-m-works index 9fa7437ac..c96c3b359 100644 --- a/testsuite/du/du-m-works +++ b/testsuite/du/du-m-works @@ -1,4 +1,4 @@ # FEATURE: CONFIG_FEATURE_HUMAN_READABLE dd if=/dev/zero of=file bs=1M count=1 2>/dev/null -test x"`busybox du -m .`" = x"1 ." +test x"`busybox du -m file`" = x"1 ." diff --git a/util-linux/fbset.c b/util-linux/fbset.c index 09e96b763..b75ec1921 100644 --- a/util-linux/fbset.c +++ b/util-linux/fbset.c @@ -164,6 +164,7 @@ static const struct cmdoptions_t { const unsigned char code; } g_cmdoptions[] = { /*"12345678" + NUL */ +//TODO: convert to index_in_strings() { "fb" , 1, CMD_FB }, { "db" , 1, CMD_DB }, { "a" , 0, CMD_ALL }, @@ -416,7 +417,7 @@ int fbset_main(int argc, char **argv) unsigned options = 0; const char *fbdev = DEFAULTFBDEV; - const char *modefile = DEFAULTFBMODE; + IF_FEATURE_FBSET_READMODE(const char *modefile = DEFAULTFBMODE;) char *thisarg; char *mode = mode; /* for compiler */ @@ -444,7 +445,7 @@ int fbset_main(int argc, char **argv) fbdev = argv[1]; break; case CMD_DB: - modefile = argv[1]; + IF_FEATURE_FBSET_READMODE(modefile = argv[1];) break; case CMD_ALL: options |= OPT_ALL; diff --git a/util-linux/fdisk_osf.c b/util-linux/fdisk_osf.c index af04cfcc8..89f1f323c 100644 --- a/util-linux/fdisk_osf.c +++ b/util-linux/fdisk_osf.c @@ -366,10 +366,11 @@ bsd_select(void) } printf("Reading disklabel of %s at sector %u\n", partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR); - if (xbsd_readlabel(xbsd_part) == 0) + if (xbsd_readlabel(xbsd_part) == 0) { if (xbsd_create_disklabel() == 0) return; break; + } } } diff --git a/util-linux/fdisk_sgi.c b/util-linux/fdisk_sgi.c index 23ebc56ef..30def09c6 100644 --- a/util-linux/fdisk_sgi.c +++ b/util-linux/fdisk_sgi.c @@ -504,17 +504,19 @@ verify_sgi(int verbose) if (sgi_get_sysid(Index[0]) == SGI_ENTIRE_DISK) { if ((Index[0] != 10) && verbose) printf("IRIX likes when Partition 11 covers the entire disk\n"); - if ((sgi_get_start_sector(Index[0]) != 0) && verbose) + if ((sgi_get_start_sector(Index[0]) != 0) && verbose) { printf("The entire disk partition should start " "at block 0,\n" "not at diskblock %u\n", sgi_get_start_sector(Index[0])); - if (SGI_DEBUG) /* I do not understand how some disks fulfil it */ + } + if (SGI_DEBUG) { /* I do not understand how some disks fulfil it */ if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose) printf("The entire disk partition is only %u diskblock large,\n" "but the disk is %u diskblocks long\n", sgi_get_num_sectors(Index[0]), lastblock); lastblock = sgi_get_num_sectors(Index[0]); + } } else { if (verbose) printf("One Partition (#11) should cover the entire disk\n"); @@ -669,16 +671,17 @@ sgi_set_volhdr(void) int n; for (n = 8; n < g_partitions; n++) { - if (!sgi_get_num_sectors(n)) { - /* - * 5 cylinders is an arbitrary value I like - * IRIX 5.3 stored files in the volume header - * (like sash, symmon, fx, ide) with ca. 3200 - * sectors. - */ - if (g_heads * g_sectors * 5 < sgi_get_lastblock()) - sgi_set_partition(n, 0, g_heads * g_sectors * 5, SGI_VOLHDR); - break; + if (!sgi_get_num_sectors(n)) { + /* + * 5 cylinders is an arbitrary value I like + * IRIX 5.3 stored files in the volume header + * (like sash, symmon, fx, ide) with ca. 3200 + * sectors. + */ + if (g_heads * g_sectors * 5 < sgi_get_lastblock()) { + sgi_set_partition(n, 0, g_heads * g_sectors * 5, SGI_VOLHDR); + break; + } } } } -- cgit v1.2.3-55-g6feb From bb0bf287d8fcb59a7d44661681576f77845dedbc Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 19 Jun 2016 21:54:04 +0200 Subject: randomconfig fixes 2 Signed-off-by: Denys Vlasenko --- libbb/Kbuild.src | 1 + scripts/randomtest | 2 ++ testsuite/ar.tests | 2 +- testsuite/tar.tests | 4 ++-- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src index b08ce1158..52a90e9a1 100644 --- a/libbb/Kbuild.src +++ b/libbb/Kbuild.src @@ -145,6 +145,7 @@ lib-$(CONFIG_FTPD) += correct_password.o lib-$(CONFIG_PASSWD) += pw_encrypt.o update_passwd.o obscure.o lib-$(CONFIG_CHPASSWD) += pw_encrypt.o update_passwd.o lib-$(CONFIG_CRYPTPW) += pw_encrypt.o +lib-$(CONFIG_MKPASSWD) += pw_encrypt.o lib-$(CONFIG_SULOGIN) += pw_encrypt.o correct_password.o lib-$(CONFIG_VLOCK) += pw_encrypt.o correct_password.o lib-$(CONFIG_SU) += pw_encrypt.o correct_password.o diff --git a/scripts/randomtest b/scripts/randomtest index 41f252ad7..287f1c771 100755 --- a/scripts/randomtest +++ b/scripts/randomtest @@ -115,6 +115,8 @@ fi # Build! nice -n 10 make $MAKEOPTS 2>&1 | tee make.log +grep 'Rerun make' make.log \ +&& nice -n 10 make $MAKEOPTS 2>&1 | tee -a make.log # Return exitcode 1 if busybox executable does not exist test -x busybox diff --git a/testsuite/ar.tests b/testsuite/ar.tests index 0a8eb9b32..ad7b8fe5f 100755 --- a/testsuite/ar.tests +++ b/testsuite/ar.tests @@ -15,7 +15,7 @@ testing "ar creates archives" \ "$(md5sum /dev/null testing "ar replaces things in archives" \ "echo 'blah!' >file1 && echo 'blast!' >file2 && ar cr test.a README file1 file2 && mv file2 file1 && ar cr test.a file1 && ar p test.a file1" \ diff --git a/testsuite/tar.tests b/testsuite/tar.tests index 890a73dd5..e9021662e 100755 --- a/testsuite/tar.tests +++ b/testsuite/tar.tests @@ -266,7 +266,7 @@ SKIP= # The correct implementation unlinks target before # creating the second file. # We test that /tmp/passwd remains empty: -optional UUDECODE FEATURE_SEAMLESS_BZ2 +optional UUDECODE FEATURE_TAR_AUTODETECT FEATURE_SEAMLESS_BZ2 testing "tar does not extract into symlinks" "\ >>/tmp/passwd && uudecode -o input && tar xf input 2>&1 && rm passwd; cat /tmp/passwd; echo \$? " "\ @@ -282,7 +282,7 @@ l4/V8LDoe90yiWJhOJvIypgEfxdyRThQkBVn/bI= " SKIP= # And same with -k -optional UUDECODE FEATURE_SEAMLESS_BZ2 +optional UUDECODE FEATURE_TAR_AUTODETECT FEATURE_SEAMLESS_BZ2 testing "tar -k does not extract into symlinks" "\ >>/tmp/passwd && uudecode -o input && tar xf input -k 2>&1 && rm passwd; cat /tmp/passwd; echo \$? " "\ -- cgit v1.2.3-55-g6feb From 94046d04951e1e67ddfb7919d8f382dbbfc70a12 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 20 Jun 2016 00:36:21 +0200 Subject: randomconfig fixes 3 Signed-off-by: Denys Vlasenko --- findutils/grep.c | 1 + testsuite/du/du-m-works | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/findutils/grep.c b/findutils/grep.c index b072cd441..aeb7977e9 100644 --- a/findutils/grep.c +++ b/findutils/grep.c @@ -686,6 +686,7 @@ int grep_main(int argc UNUSED_PARAM, char **argv) #if ENABLE_FEATURE_GREP_CONTEXT int Copt, opts; #endif + INIT_G(); /* For grep, exitcode of 1 is "not found". Other errors are 2: */ xfunc_error_retval = 2; diff --git a/testsuite/du/du-m-works b/testsuite/du/du-m-works index c96c3b359..d9693c7bf 100644 --- a/testsuite/du/du-m-works +++ b/testsuite/du/du-m-works @@ -1,4 +1,4 @@ # FEATURE: CONFIG_FEATURE_HUMAN_READABLE dd if=/dev/zero of=file bs=1M count=1 2>/dev/null -test x"`busybox du -m file`" = x"1 ." +test x"`busybox du -m file`" = x"1 file" -- cgit v1.2.3-55-g6feb From 0ad872baf30b660ffb87265470d29f14cfc4b2d4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 20 Jun 2016 01:40:19 +0200 Subject: randomconfig fixes 4 Signed-off-by: Denys Vlasenko --- archival/gzip.c | 4 +++- testsuite/tar.tests | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/archival/gzip.c b/archival/gzip.c index f9bb3c742..8f1e4ff29 100644 --- a/archival/gzip.c +++ b/archival/gzip.c @@ -77,13 +77,15 @@ aa: 85.1% -- replaced with aa.gz //kbuild:lib-$(CONFIG_GZIP) += gzip.o //usage:#define gzip_trivial_usage -//usage: "[-cfd" IF_FEATURE_GZIP_LEVELS("123456789") "] [FILE]..." +//usage: "[-cf" IF_GUNZIP("d") IF_FEATURE_GZIP_LEVELS("123456789") "] [FILE]..." //usage:#define gzip_full_usage "\n\n" //usage: "Compress FILEs (or stdin)\n" //usage: IF_FEATURE_GZIP_LEVELS( //usage: "\n -1..9 Compression level" //usage: ) +//usage: IF_GUNZIP( //usage: "\n -d Decompress" +//usage: ) //usage: "\n -c Write to stdout" //usage: "\n -f Force" //usage: diff --git a/testsuite/tar.tests b/testsuite/tar.tests index e9021662e..f19a53da2 100755 --- a/testsuite/tar.tests +++ b/testsuite/tar.tests @@ -24,7 +24,7 @@ tar: short read "" "" SKIP= -optional FEATURE_SEAMLESS_GZ +optional FEATURE_SEAMLESS_GZ GUNZIP # In NOMMU case, "invalid magic" message comes from gunzip child process. # Otherwise, it comes from tar. # Need to fix output up to avoid false positive. -- cgit v1.2.3-55-g6feb From 5c3e060604444b18303f55e631637c28d889704f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 20 Jun 2016 10:59:06 +0200 Subject: modprobe-small: fix bogus handling of unpack errors "modprobe minix; echo $?" Was: modprobe: corrupted data modprobe: read error from 'kernel/fs/minix/minix.ko.xz': No such file or directory modprobe: corrupted data modprobe: read error from 'kernel/fs/minix/minix.ko.xz': No such file or directory modprobe: corrupted data modprobe: read error from 'kernel/fs/minix/minix.ko.xz' modprobe: 'kernel/fs/minix/minix.ko.xz': Success 0 Now: modprobe: corrupted data modprobe: read error from 'kernel/fs/minix/minix.ko.xz' 1 Signed-off-by: Denys Vlasenko --- modutils/modprobe-small.c | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c index ffb46e6be..5936e48cf 100644 --- a/modutils/modprobe-small.c +++ b/modutils/modprobe-small.c @@ -45,6 +45,7 @@ typedef struct module_info { char *pathname; char *aliases; char *deps; + smallint open_read_failed; } module_info; /* @@ -222,7 +223,8 @@ static int load_module(const char *fname, const char *options) #endif } -static void parse_module(module_info *info, const char *pathname) +/* Returns !0 if open/read was unsuccessful */ +static int parse_module(module_info *info, const char *pathname) { char *module_image; char *ptr; @@ -231,6 +233,7 @@ static void parse_module(module_info *info, const char *pathname) dbg1_error_msg("parse_module('%s')", pathname); /* Read (possibly compressed) module */ + errno = 0; len = 64 * 1024 * 1024; /* 64 Mb at most */ module_image = xmalloc_open_zipped_read_close(pathname, &len); /* module_image == NULL is ok here, find_keyword handles it */ @@ -298,9 +301,11 @@ static void parse_module(module_info *info, const char *pathname) dbg2_error_msg("dep:'%s'", ptr); append(ptr); } + free(module_image); info->deps = copy_stringbuf(); - free(module_image); + info->open_read_failed = (module_image == NULL); + return info->open_read_failed; } static FAST_FUNC int fileAction(const char *pathname, @@ -331,7 +336,8 @@ static FAST_FUNC int fileAction(const char *pathname, dbg1_error_msg("'%s' module name matches", pathname); module_found_idx = cur; - parse_module(&modinfo[cur], pathname); + if (parse_module(&modinfo[cur], pathname) != 0) + return TRUE; /* failed to open/read it, no point in trying loading */ if (!(option_mask32 & OPT_r)) { if (load_module(pathname, module_load_options) == 0) { @@ -608,13 +614,14 @@ static int rmmod(const char *filename) #define process_module(a,b) process_module(a) #define cmdline_options "" #endif -static void process_module(char *name, const char *cmdline_options) +static int process_module(char *name, const char *cmdline_options) { char *s, *deps, *options; module_info **infovec; module_info *info; int infoidx; int is_remove = (option_mask32 & OPT_r) != 0; + int exitcode = EXIT_SUCCESS; dbg1_error_msg("process_module('%s','%s')", name, cmdline_options); @@ -628,7 +635,7 @@ static void process_module(char *name, const char *cmdline_options) * (compat note: this allows and strips .ko suffix) */ rmmod(name); - return; + return EXIT_SUCCESS; } /* @@ -639,7 +646,7 @@ static void process_module(char *name, const char *cmdline_options) */ if (!is_remove && already_loaded(name)) { dbg1_error_msg("nothing to do for '%s'", name); - return; + return EXIT_SUCCESS; } options = NULL; @@ -741,6 +748,11 @@ static void process_module(char *name, const char *cmdline_options) dbg1_error_msg("'%s': blacklisted", info->pathname); continue; } + if (info->open_read_failed) { + /* We already tried it, didn't work. Don't try load again */ + exitcode = EXIT_FAILURE; + continue; + } errno = 0; if (load_module(info->pathname, options) != 0) { if (EEXIST != errno) { @@ -752,13 +764,14 @@ static void process_module(char *name, const char *cmdline_options) info->pathname, moderror(errno)); } + exitcode = EXIT_FAILURE; } } ret: free(infovec); free(options); -//TODO: return load attempt result from process_module. -//If dep didn't load ok, continuing makes little sense. + + return exitcode; } #undef cmdline_options @@ -865,6 +878,7 @@ The following options are useful for people managing distributions: int modprobe_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int modprobe_main(int argc UNUSED_PARAM, char **argv) { + int exitcode; struct utsname uts; char applet0 = applet_name[0]; IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(char *options;) @@ -970,21 +984,23 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) bb_error_msg_and_die("can't insert '%s': %s", *argv, moderror(errno)); } - return 0; + return EXIT_SUCCESS; } /* Try to load modprobe.dep.bb */ - if ('r' != applet0) /* not rmmod */ + if ('r' != applet0) { /* not rmmod */ load_dep_bb(); + } /* Load/remove modules. * Only rmmod/modprobe -r loops here, insmod/modprobe has only argv[0] */ + exitcode = EXIT_SUCCESS; do { - process_module(*argv, options); + exitcode |= process_module(*argv, options); } while (*++argv); if (ENABLE_FEATURE_CLEAN_UP) { IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(free(options);) } - return EXIT_SUCCESS; + return exitcode; } -- cgit v1.2.3-55-g6feb From ecf25cb5bce27ca5820e2895d8458f38c406d105 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 20 Jun 2016 11:04:04 +0200 Subject: randomconfig fixes 5: false positive for tar; mount emits corrupted message Signed-off-by: Denys Vlasenko --- testsuite/tar.tests | 2 +- util-linux/mount.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/testsuite/tar.tests b/testsuite/tar.tests index f19a53da2..c44b7ad07 100755 --- a/testsuite/tar.tests +++ b/testsuite/tar.tests @@ -204,7 +204,7 @@ SKIP= # Had a bug where on extract autodetect first "switched off" -z # and then failed to recognize .tgz extension -optional FEATURE_TAR_CREATE FEATURE_SEAMLESS_GZ +optional FEATURE_TAR_CREATE FEATURE_SEAMLESS_GZ GUNZIP testing "tar extract tgz" "\ dd count=1 bs=1M if=/dev/zero of=F0 2>/dev/null tar -czf F0.tgz F0 diff --git a/util-linux/mount.c b/util-linux/mount.c index c76f6ef61..cef4f7415 100644 --- a/util-linux/mount.c +++ b/util-linux/mount.c @@ -2058,7 +2058,7 @@ static int singlemount(struct mntent *mp, int ignore_busy) del_loop(mp->mnt_fsname); if (ENABLE_FEATURE_CLEAN_UP) { free(loopFile); - free(mp->mnt_fsname); + /* No, "rc != 0" needs it: free(mp->mnt_fsname); */ } } -- cgit v1.2.3-55-g6feb From 984b0a613aaf1cdf48c2e2af08c8466a7bad8307 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 20 Jun 2016 11:06:42 +0200 Subject: libarchive: fix xmalloc_open_zipped_read_close() on NOMMU The somewhat new "unpack in memory" code was broken for xmalloc_open_zipped_read_close() on NOMMU: we seek back over signature, but then expect it to be already consumed. Stop seeking back in this case. Signed-off-by: Denys Vlasenko --- archival/bbunzip.c | 2 +- archival/libarchive/decompress_gunzip.c | 4 ++-- archival/libarchive/decompress_unxz.c | 2 +- archival/libarchive/open_transformer.c | 35 ++++++++++++++------------------- include/bb_archive.h | 8 ++++---- 5 files changed, 23 insertions(+), 28 deletions(-) diff --git a/archival/bbunzip.c b/archival/bbunzip.c index b4f754e0b..07ef8617e 100644 --- a/archival/bbunzip.c +++ b/archival/bbunzip.c @@ -121,7 +121,7 @@ int FAST_FUNC bbunpack(char **argv, if (!(option_mask32 & SEAMLESS_MAGIC)) { init_transformer_state(&xstate); - xstate.check_signature = 1; + xstate.signature_skipped = 0; /*xstate.src_fd = STDIN_FILENO; - already is */ xstate.dst_fd = STDOUT_FILENO; status = unpacker(&xstate); diff --git a/archival/libarchive/decompress_gunzip.c b/archival/libarchive/decompress_gunzip.c index 20e4d9ac5..c7fa5b526 100644 --- a/archival/libarchive/decompress_gunzip.c +++ b/archival/libarchive/decompress_gunzip.c @@ -1201,7 +1201,7 @@ unpack_gz_stream(transformer_state_t *xstate) if (check_signature16(xstate, GZIP_MAGIC)) return -1; #else - if (xstate->check_signature) { + if (!xstate->signature_skipped) { uint16_t magic2; if (full_read(xstate->src_fd, &magic2, 2) != 2) { @@ -1210,7 +1210,7 @@ unpack_gz_stream(transformer_state_t *xstate) return -1; } if (magic2 == COMPRESS_MAGIC) { - xstate->check_signature = 0; + xstate->signature_skipped = 2; return unpack_Z_stream(xstate); } if (magic2 != GZIP_MAGIC) diff --git a/archival/libarchive/decompress_unxz.c b/archival/libarchive/decompress_unxz.c index 1f408abfd..cd32cc745 100644 --- a/archival/libarchive/decompress_unxz.c +++ b/archival/libarchive/decompress_unxz.c @@ -55,7 +55,7 @@ unpack_xz_stream(transformer_state_t *xstate) iobuf.out = membuf + BUFSIZ; iobuf.out_size = BUFSIZ; - if (!xstate || xstate->check_signature == 0) { + if (!xstate || xstate->signature_skipped) { /* Preload XZ file signature */ strcpy((char*)membuf, HEADER_MAGIC); iobuf.in_size = HEADER_MAGIC_SIZE; diff --git a/archival/libarchive/open_transformer.c b/archival/libarchive/open_transformer.c index be536a3d7..d93c8366f 100644 --- a/archival/libarchive/open_transformer.c +++ b/archival/libarchive/open_transformer.c @@ -13,16 +13,13 @@ void FAST_FUNC init_transformer_state(transformer_state_t *xstate) int FAST_FUNC check_signature16(transformer_state_t *xstate, unsigned magic16) { - if (xstate->check_signature) { + if (!xstate->signature_skipped) { uint16_t magic2; if (full_read(xstate->src_fd, &magic2, 2) != 2 || magic2 != magic16) { bb_error_msg("invalid magic"); -#if 0 /* possible future extension */ - if (xstate->check_signature > 1) - xfunc_die(); -#endif return -1; } + xstate->signature_skipped = 2; } return 0; } @@ -102,7 +99,7 @@ void check_errors_in_children(int signo) /* transformer(), more than meets the eye */ #if BB_MMU void FAST_FUNC fork_transformer(int fd, - int check_signature, + int signature_skipped, IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate) ) #else @@ -123,7 +120,7 @@ void FAST_FUNC fork_transformer(int fd, const char *transform_prog) IF_DESKTOP(long long) int r; transformer_state_t xstate; init_transformer_state(&xstate); - xstate.check_signature = check_signature; + xstate.signature_skipped = signature_skipped; xstate.src_fd = fd; xstate.dst_fd = fd_pipe.wr; r = transformer(&xstate); @@ -168,12 +165,11 @@ static transformer_state_t *setup_transformer_on_fd(int fd, int fail_if_not_comp uint16_t b16[2]; uint32_t b32[1]; } magic; - int offset; transformer_state_t *xstate; - offset = -2; xstate = xzalloc(sizeof(*xstate)); xstate->src_fd = fd; + xstate->signature_skipped = 2; /* .gz and .bz2 both have 2-byte signature, and their * unpack_XXX_stream wants this header skipped. */ @@ -202,7 +198,7 @@ static transformer_state_t *setup_transformer_on_fd(int fd, int fail_if_not_comp if (ENABLE_FEATURE_SEAMLESS_XZ && magic.b16[0] == XZ_MAGIC1 ) { - offset = -6; + xstate->signature_skipped = 6; xread(fd, magic.b32, sizeof(magic.b32[0])); if (magic.b32[0] == XZ_MAGIC2) { xstate->xformer = unpack_xz_stream; @@ -226,16 +222,7 @@ static transformer_state_t *setup_transformer_on_fd(int fd, int fail_if_not_comp // USE_FOR_NOMMU(xstate->xformer_prog = "cat";) /* fall through to seeking bck over bytes we read earlier */ - USE_FOR_NOMMU(found_magic:) - /* NOMMU version of fork_transformer execs - * an external unzipper that wants - * file position at the start of the file. - */ - xlseek(fd, offset, SEEK_CUR); - - USE_FOR_MMU(found_magic:) - /* In MMU case, if magic was found, seeking back is not necessary */ - + found_magic: return xstate; } @@ -254,6 +241,12 @@ int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_compressed) # if BB_MMU fork_transformer_with_no_sig(xstate->src_fd, xstate->xformer); # else + /* NOMMU version of fork_transformer execs + * an external unzipper that wants + * file position at the start of the file. + */ + xlseek(fd, - xstate->signature_skipped, SEEK_CUR); + xstate->signature_skipped = 0; fork_transformer_with_sig(xstate->src_fd, xstate->xformer, xstate->xformer_prog); # endif free(xstate); @@ -300,6 +293,8 @@ int FAST_FUNC open_zipped(const char *fname, int fail_if_not_compressed) # if BB_MMU fork_transformer_with_no_sig(xstate->src_fd, xstate->xformer); # else + xlseek(fd, - xstate->signature_skipped, SEEK_CUR); + xstate->signature_skipped = 0; fork_transformer_with_sig(xstate->src_fd, xstate->xformer, xstate->xformer_prog); # endif } diff --git a/include/bb_archive.h b/include/bb_archive.h index 10969b567..2b9c5f04c 100644 --- a/include/bb_archive.h +++ b/include/bb_archive.h @@ -211,7 +211,7 @@ void dealloc_bunzip(bunzip_data *bd) FAST_FUNC; /* Meaning and direction (input/output) of the fields are transformer-specific */ typedef struct transformer_state_t { - smallint check_signature; /* most often referenced member */ + smallint signature_skipped; /* most often referenced member */ IF_DESKTOP(long long) int FAST_FUNC (*xformer)(struct transformer_state_t *xstate); USE_FOR_NOMMU(const char *xformer_prog;) @@ -252,11 +252,11 @@ int bbunpack(char **argv, void check_errors_in_children(int signo); #if BB_MMU void fork_transformer(int fd, - int check_signature, + int signature_skipped, IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate) ) FAST_FUNC; -#define fork_transformer_with_sig(fd, transformer, transform_prog) fork_transformer((fd), 1, (transformer)) -#define fork_transformer_with_no_sig(fd, transformer) fork_transformer((fd), 0, (transformer)) +#define fork_transformer_with_sig(fd, transformer, transform_prog) fork_transformer((fd), 0, (transformer)) +#define fork_transformer_with_no_sig(fd, transformer) fork_transformer((fd), 1, (transformer)) #else void fork_transformer(int fd, const char *transform_prog) FAST_FUNC; #define fork_transformer_with_sig(fd, transformer, transform_prog) fork_transformer((fd), (transform_prog)) -- cgit v1.2.3-55-g6feb From df3ec0e2f70d67f1f880bee933985732b455ee76 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 20 Jun 2016 11:42:00 +0200 Subject: libarchive: fix open_zipped() Last commit broke it (on both MMU and NOMMU) Signed-off-by: Denys Vlasenko --- archival/libarchive/open_transformer.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/archival/libarchive/open_transformer.c b/archival/libarchive/open_transformer.c index d93c8366f..dd15a9b1f 100644 --- a/archival/libarchive/open_transformer.c +++ b/archival/libarchive/open_transformer.c @@ -220,7 +220,6 @@ static transformer_state_t *setup_transformer_on_fd(int fd, int fail_if_not_comp */ // USE_FOR_MMU(xstate->xformer = copy_stream;) // USE_FOR_NOMMU(xstate->xformer_prog = "cat";) - /* fall through to seeking bck over bytes we read earlier */ found_magic: return xstate; @@ -289,16 +288,22 @@ int FAST_FUNC open_zipped(const char *fname, int fail_if_not_compressed) return -1; fd = xstate->src_fd; - if (xstate->xformer) { # if BB_MMU - fork_transformer_with_no_sig(xstate->src_fd, xstate->xformer); -# else + if (xstate->xformer) { + fork_transformer_with_no_sig(fd, xstate->xformer); + } else { + /* the file is not compressed */ xlseek(fd, - xstate->signature_skipped, SEEK_CUR); xstate->signature_skipped = 0; - fork_transformer_with_sig(xstate->src_fd, xstate->xformer, xstate->xformer_prog); -# endif } - /* else: the file is not compressed */ +# else + /* NOMMU can't avoid the seek :( */ + xlseek(fd, - xstate->signature_skipped, SEEK_CUR); + xstate->signature_skipped = 0; + if (xstate->xformer) { + fork_transformer_with_sig(fd, xstate->xformer, xstate->xformer_prog); + } /* esle: the file is not compressed */ +# endif free(xstate); return fd; -- cgit v1.2.3-55-g6feb From ea9ebc011b3ee9b86b00646b91e73bb860d340b4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 20 Jun 2016 12:23:35 +0200 Subject: scripts/trylink: libbusybox fix gcc 6.1.1 can emit empty line with spaces Signed-off-by: Denys Vlasenko --- scripts/trylink | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/trylink b/scripts/trylink index 129570a60..145df9959 100755 --- a/scripts/trylink +++ b/scripts/trylink @@ -293,7 +293,7 @@ if test "$CONFIG_FEATURE_INDIVIDUAL" = y; then echo "Linking individual applets against libbusybox (see $sharedlib_dir/*)" gcc -DNAME_MAIN -E -include include/autoconf.h include/applets.h \ | grep -v "^#" \ - | grep -v "^$" \ + | grep -v "^ *$" \ > applet_lst.tmp while read name main junk; do -- cgit v1.2.3-55-g6feb From e24e88697af81800060efc75e67777ef245b15cd Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 20 Jun 2016 16:28:53 +0200 Subject: typo fix Signed-off-by: Denys Vlasenko --- archival/libarchive/open_transformer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/archival/libarchive/open_transformer.c b/archival/libarchive/open_transformer.c index dd15a9b1f..a3018d9ec 100644 --- a/archival/libarchive/open_transformer.c +++ b/archival/libarchive/open_transformer.c @@ -302,7 +302,7 @@ int FAST_FUNC open_zipped(const char *fname, int fail_if_not_compressed) xstate->signature_skipped = 0; if (xstate->xformer) { fork_transformer_with_sig(fd, xstate->xformer, xstate->xformer_prog); - } /* esle: the file is not compressed */ + } /* else: the file is not compressed */ # endif free(xstate); -- cgit v1.2.3-55-g6feb From 7cf45ae10e71d11ca53e7b0220c76562a8045113 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 20 Jun 2016 23:50:26 +0200 Subject: setsid: fix broken -c This did not work: setsid sh -c 'anything' Signed-off-by: Denys Vlasenko --- miscutils/setsid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miscutils/setsid.c b/miscutils/setsid.c index 1b27377b2..9bddc2fcf 100644 --- a/miscutils/setsid.c +++ b/miscutils/setsid.c @@ -29,7 +29,7 @@ int setsid_main(int argc UNUSED_PARAM, char **argv) unsigned opt; opt_complementary = "-1"; /* at least one arg */ - opt = getopt32(argv, "c"); + opt = getopt32(argv, "+c"); /* +: stop on first non-opt */ argv += optind; /* setsid() is allowed only when we are not a process group leader. -- cgit v1.2.3-55-g6feb From 10c0e9178606bb71a071c27dcda3fd2787e8303b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 21 Jun 2016 02:04:16 +0200 Subject: libarchive: fix xmalloc_open_zipped_read_close() Signed-off-by: Denys Vlasenko --- archival/libarchive/open_transformer.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/archival/libarchive/open_transformer.c b/archival/libarchive/open_transformer.c index a3018d9ec..ac7e5db95 100644 --- a/archival/libarchive/open_transformer.c +++ b/archival/libarchive/open_transformer.c @@ -331,6 +331,9 @@ void* FAST_FUNC xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_ } } else { /* File is not compressed */ +//FIXME: avoid seek + xlseek(xstate->src_fd, - xstate->signature_skipped, SEEK_CUR); + xstate->signature_skipped = 0; image = xmalloc_read(xstate->src_fd, maxsz_p); } -- cgit v1.2.3-55-g6feb From c3b34d8b39cae35fec8c6fb644d90dc80e574236 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 21 Jun 2016 00:15:49 +0200 Subject: Bump version to 1.25.0 Signed-off-by: Denys Vlasenko --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d5950230d..572da3d88 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 1 PATCHLEVEL = 25 SUBLEVEL = 0 -EXTRAVERSION = .git +EXTRAVERSION = NAME = Unnamed # *DOCUMENTATION* -- cgit v1.2.3-55-g6feb From 9ca56f9621d9e7265699997d90902fcaf6ed5aad Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 22 Jun 2016 03:10:21 +0200 Subject: Start 1.26.0 development cycle Signed-off-by: Denys Vlasenko --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 572da3d88..5cfc76306 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 1 -PATCHLEVEL = 25 +PATCHLEVEL = 26 SUBLEVEL = 0 -EXTRAVERSION = +EXTRAVERSION = .git NAME = Unnamed # *DOCUMENTATION* -- cgit v1.2.3-55-g6feb From 4d5acd2d4264d0a754d3d11c94825fd69d0c7837 Mon Sep 17 00:00:00 2001 From: Jonas Danielsson Date: Thu, 23 Jun 2016 18:26:32 +0200 Subject: ping: populate icmp_id field for "simple" ping too The ICMP RFC says that identifier and sequence number may be zero. Having them zero for a Echo message, along with a data of zero's as well will result in a Echo reply message with only zero's. Some NAT implementations seem to get the checksum wrong on these packages. Setting a checksum of 0x0 instead of 0xffff. Through NAT: Internet Control Message Protocol Type: 0 (Echo (ping) reply) Code: 0 Checksum: 0x0000 [incorrect, should be 0xffff] Identifier (BE): 0 (0x0000) Identifier (LE): 0 (0x0000) Sequence number (BE): 0 (0x0000) Sequence number (LE): 0 (0x0000) Data (56 bytes) Data: 000000000000000000000000000000000000000000000000... [Length: 56] Without NAT: Internet Control Message Protocol Type: 0 (Echo (ping) reply) Code: 0 Checksum: 0xffff [correct] Identifier (BE): 0 (0x0000) Identifier (LE): 0 (0x0000) Sequence number (BE): 0 (0x0000) Sequence number (LE): 0 (0x0000) [Request frame: 189] [Response time: 0.024 ms] Data (56 bytes) Data: 000000000000000000000000000000000000000000000000... [Length: 56] And this in turn will make some hardware MAC checksum offloading engines drop the packet. (This was seen with a Synopsis MAC, the same one used in for instance the stmmac Ethernet driver in the linux kernel.) This change can be seen as a workaround for bugs in other layers. But just setting an identifier for the Echo message packet will avoid prodding the hornets nest. function old new delta common_ping_main 424 500 +76 Signed-off-by: Jonas Danielsson Signed-off-by: Denys Vlasenko --- networking/ping.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/networking/ping.c b/networking/ping.c index cfe682646..d8767a39f 100644 --- a/networking/ping.c +++ b/networking/ping.c @@ -186,6 +186,7 @@ create_icmp_socket(void) struct globals { char *hostname; char packet[DEFDATALEN + MAXIPLEN + MAXICMPLEN]; + uint16_t myid; } FIX_ALIASING; #define G (*(struct globals*)bb_common_bufsiz1) #define INIT_G() do { setup_common_bufsiz(); } while (0) @@ -204,6 +205,7 @@ static void ping4(len_and_sockaddr *lsa) pkt = (struct icmp *) G.packet; /*memset(pkt, 0, sizeof(G.packet)); already is */ pkt->icmp_type = ICMP_ECHO; + pkt->icmp_id = G.myid; pkt->icmp_cksum = inet_cksum((uint16_t *) pkt, sizeof(G.packet)); xsendto(pingsock, G.packet, DEFDATALEN + ICMP_MINLEN, &lsa->u.sa, lsa->len); @@ -228,6 +230,8 @@ static void ping4(len_and_sockaddr *lsa) struct iphdr *iphdr = (struct iphdr *) G.packet; pkt = (struct icmp *) (G.packet + (iphdr->ihl << 2)); /* skip ip hdr */ + if (pkt->icmp_id != G.myid) + continue; /* not our ping */ if (pkt->icmp_type == ICMP_ECHOREPLY) break; } @@ -246,6 +250,7 @@ static void ping6(len_and_sockaddr *lsa) pkt = (struct icmp6_hdr *) G.packet; /*memset(pkt, 0, sizeof(G.packet)); already is */ pkt->icmp6_type = ICMP6_ECHO_REQUEST; + pkt->icmp6_id = G.myid; sockopt = offsetof(struct icmp6_hdr, icmp6_cksum); setsockopt_int(pingsock, SOL_RAW, IPV6_CHECKSUM, sockopt); @@ -269,6 +274,8 @@ static void ping6(len_and_sockaddr *lsa) continue; } if (c >= ICMP_MINLEN) { /* icmp6_hdr */ + if (pkt->icmp6_id != G.myid) + continue; /* not our ping */ if (pkt->icmp6_type == ICMP6_ECHO_REPLY) break; } @@ -317,6 +324,7 @@ static int common_ping_main(sa_family_t af, char **argv) alarm(5); /* give the host 5000ms to respond */ create_icmp_socket(lsa); + G.myid = (uint16_t) getpid(); #if ENABLE_PING6 if (lsa->u.sa.sa_family == AF_INET6) ping6(lsa); -- cgit v1.2.3-55-g6feb From 59f81976249a85cf02bd73c2395f018033069466 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Thu, 23 Jun 2016 17:19:50 +0200 Subject: i2cdump: don't use common_bufsiz1 Commit e6a2f4cc changed the way common_bufsiz1 works. Now it needs to be initialized before using, but i2cdump wasn't updated by said patch. Since the fact that we're using common_bufsiz1 here isn't obvious (no G_INIT() macro, no other global variables), drop it and simply allocate the integer array required for block reads on the stack. Tested with i2c block read on a Lenovo Thinkpad laptop. Signed-off-by: Bartosz Golaszewski Signed-off-by: Denys Vlasenko --- miscutils/i2c_tools.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miscutils/i2c_tools.c b/miscutils/i2c_tools.c index 57bb72ae7..7731466f7 100644 --- a/miscutils/i2c_tools.c +++ b/miscutils/i2c_tools.c @@ -908,7 +908,7 @@ int i2cdump_main(int argc UNUSED_PARAM, char **argv) int bus_num, bus_addr, mode = I2C_SMBUS_BYTE_DATA, even = 0, pec = 0; unsigned first = 0x00, last = 0xff, opts; - int *block = (int *)bb_common_bufsiz1; + int block[I2CDUMP_NUM_REGS]; char *opt_r_str, *dash; int fd, res; -- cgit v1.2.3-55-g6feb From 8f4faa1e3db91fc7b50d633e6f9b2f04bf978bb2 Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Thu, 23 Jun 2016 10:42:40 +0200 Subject: df: use f_frsize instead of f_bsize for correct sizes Use the correct field f_frsize instead of f_bsize. The statfs f_bsize is the "Optimal transfer block size" while the f_frsize is the "Fragment size (since Linux 2.6)". On some FUSE filesystems those may differ. Fixes bug 9046 URL: https://bugs.busybox.net/show_bug.cgi?id=9046 Signed-off-by: Natanael Copa Signed-off-by: Denys Vlasenko --- coreutils/df.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/coreutils/df.c b/coreutils/df.c index d79c11a6c..06b292018 100644 --- a/coreutils/df.c +++ b/coreutils/df.c @@ -188,7 +188,7 @@ int df_main(int argc UNUSED_PARAM, char **argv) if (opt & OPT_INODE) { s.f_blocks = s.f_files; s.f_bavail = s.f_bfree = s.f_ffree; - s.f_bsize = 1; + s.f_frsize = 1; if (df_disp_hr) df_disp_hr = 1; @@ -246,26 +246,26 @@ int df_main(int argc UNUSED_PARAM, char **argv) #if ENABLE_FEATURE_HUMAN_READABLE printf(" %9s ", - /* f_blocks x f_bsize / df_disp_hr, show one fractional, + /* f_blocks x f_frsize / df_disp_hr, show one fractional, * use suffixes if df_disp_hr == 0 */ - make_human_readable_str(s.f_blocks, s.f_bsize, df_disp_hr)); + make_human_readable_str(s.f_blocks, s.f_frsize, df_disp_hr)); printf(" %9s " + 1, - /* EXPR x f_bsize / df_disp_hr, show one fractional, + /* EXPR x f_frsize / df_disp_hr, show one fractional, * use suffixes if df_disp_hr == 0 */ make_human_readable_str((s.f_blocks - s.f_bfree), - s.f_bsize, df_disp_hr)); + s.f_frsize, df_disp_hr)); printf("%9s %3u%% %s\n", - /* f_bavail x f_bsize / df_disp_hr, show one fractional, + /* f_bavail x f_frsize / df_disp_hr, show one fractional, * use suffixes if df_disp_hr == 0 */ - make_human_readable_str(s.f_bavail, s.f_bsize, df_disp_hr), + make_human_readable_str(s.f_bavail, s.f_frsize, df_disp_hr), blocks_percent_used, mount_point); #else printf(" %9lu %9lu %9lu %3u%% %s\n", - kscale(s.f_blocks, s.f_bsize), - kscale(s.f_blocks - s.f_bfree, s.f_bsize), - kscale(s.f_bavail, s.f_bsize), + kscale(s.f_blocks, s.f_frsize), + kscale(s.f_blocks - s.f_bfree, s.f_frsize), + kscale(s.f_bavail, s.f_frsize), blocks_percent_used, mount_point); #endif } -- cgit v1.2.3-55-g6feb From 5b8c89d1f270909d1a0201478236de6ed89c8ca4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 29 Jun 2016 15:00:52 +0200 Subject: build system: make CONFIG_FEATURE_USE_BSS_TAIL less funky CONFIG_FEATURE_USE_BSS_TAIL code was aliasing bb_common_bufsiz1 to _end. This is unreliable: _end may be not sufficiently aligned. Change code to simply enlarge COMMON_BUFSIZE when we detect that _end has significant amount of space to the end of page. Signed-off-by: Denys Vlasenko --- scripts/generate_BUFSIZ.sh | 100 +++++++++++++-------------------------------- 1 file changed, 28 insertions(+), 72 deletions(-) diff --git a/scripts/generate_BUFSIZ.sh b/scripts/generate_BUFSIZ.sh index 844261906..718788e0b 100755 --- a/scripts/generate_BUFSIZ.sh +++ b/scripts/generate_BUFSIZ.sh @@ -36,11 +36,10 @@ generate_std_and_exit() { } generate_big_and_exit() { - $debug && echo "Configuring: bb_common_bufsiz1[] in _end[], COMMON_BUFSIZE = $1" + $debug && echo "Configuring: bb_common_bufsiz1[] in bss, COMMON_BUFSIZE = $1" { echo "enum { COMMON_BUFSIZE = $1 };" - echo "extern char _end[]; /* linker-provided label */" - echo "#define bb_common_bufsiz1 _end" + echo "extern char bb_common_bufsiz1[];" echo "#define setup_common_bufsiz() ((void)0)" } | regenerate "$common_bufsiz_h" echo "$2" >"$common_bufsiz_h.method" @@ -51,20 +50,10 @@ generate_1k_and_exit() { generate_big_and_exit 1024 "1k" } - -generate_malloc_and_exit() { - $debug && echo "Configuring: bb_common_bufsiz1[] is malloced" - { - echo "enum { COMMON_BUFSIZE = 1024 };" - echo "extern char *const bb_common_bufsiz1;" - echo "void setup_common_bufsiz(void);" - } | regenerate "$common_bufsiz_h" - echo "malloc" >"$common_bufsiz_h.method" - $exitcmd -} - round_down_COMMON_BUFSIZE() { - COMMON_BUFSIZE=$(( ($1-32) & 0xfffffe0 )) + COMMON_BUFSIZE=1024 + test "$1" -le 32 && return + COMMON_BUFSIZE=$(( ($1-32) & 0x0ffffff0 )) COMMON_BUFSIZE=$(( COMMON_BUFSIZE < 1024 ? 1024 : COMMON_BUFSIZE )) } @@ -104,77 +93,44 @@ if $postcompile; then test x"$PAGE_SIZE" = x"" && exit 1 $debug && echo "PAGE_SIZE:0x$PAGE_SIZE $((0x$PAGE_SIZE))" PAGE_SIZE=$((0x$PAGE_SIZE)) - test $PAGE_SIZE -lt 512 && exit 1 + test $PAGE_SIZE -lt 1024 && exit 1 # How much space between _end[] and next page? PAGE_MASK=$((PAGE_SIZE-1)) TAIL_SIZE=$(( (-END) & PAGE_MASK )) $debug && echo "TAIL_SIZE:$TAIL_SIZE bytes" - if test x"$method" = x"1k" || test x"$method" = x"big"; then - if test $TAIL_SIZE -lt 1024; then - # _end[] has no enough space for bb_common_bufsiz1[] - echo "Warning! Space in _end[] is too small ($TAIL_SIZE bytes)!" - echo "Rerun make to build a binary which doesn't use it!" - rm -- "$common_bufsiz_h.1k.OK" 2>/dev/null - { md5sum <.config | cut -d' ' -f1; stat -c "%Y" .config; } >"$common_bufsiz_h.1k.FAIL" - rm busybox_unstripped busybox 2>/dev/null -# Note: here we can do either a "malloc" or "std" build. -# "malloc" gives a bit bigger code: -# text bss filename -# 804355 5385 busybox.std -# 804618 4361 busybox.malloc -# but may have a smaller .bss (not guaranteed!). Use "pmap -x" to verify. - exitcmd="exit 1" - generate_malloc_and_exit - else - PREV_SIZE=1024 - test x"$method" = x"big" && PREV_SIZE=`cat -- "$common_bufsiz_h.1k.OK"` - round_down_COMMON_BUFSIZE $PREV_SIZE - PREV_BUFSIZE=$COMMON_BUFSIZE - - rm -- "$common_bufsiz_h.1k.FAIL" 2>/dev/null - echo $TAIL_SIZE >"$common_bufsiz_h.1k.OK" - round_down_COMMON_BUFSIZE $TAIL_SIZE - # emit message only if COMMON_BUFSIZE is indeed larger - test $COMMON_BUFSIZE -gt $PREV_BUFSIZE \ - && echo "Rerun make to use larger COMMON_BUFSIZE ($COMMON_BUFSIZE)" -#TODO: test $PREV_BUFSIZE -lt $TAIL_SIZE && PANIC!!! -#Code size with COMMON_BUFSIZE > 1024 may be bigger than code with COMMON_BUFSIZE = 1024! -#(currently we just hope "-32 and round down to 32" saves us) - - test $COMMON_BUFSIZE = 1024 && generate_1k_and_exit - generate_big_and_exit $COMMON_BUFSIZE "big" - fi + if test x"$method" = x"1k"; then + { + echo $TAIL_SIZE + md5sum <.config | cut -d' ' -f1 + stat -c "%Y" .config + } >"$common_bufsiz_h.1k.OK" + round_down_COMMON_BUFSIZE $((1024 + TAIL_SIZE)) + # emit message only if COMMON_BUFSIZE is indeed larger + test $COMMON_BUFSIZE -gt 1024 \ + && echo "Rerun make to use larger COMMON_BUFSIZE ($COMMON_BUFSIZE)" + test $COMMON_BUFSIZE = 1024 && generate_1k_and_exit + generate_big_and_exit $COMMON_BUFSIZE "big" fi fi # Based on past success/fail of 1k build, decide next build type if test -f "$common_bufsiz_h.1k.OK"; then - # Previous build succeeded fitting 1k into _end[]. - # Try bigger COMMON_BUFSIZE if possible. - TAIL_SIZE=`cat -- "$common_bufsiz_h.1k.OK"` - round_down_COMMON_BUFSIZE $TAIL_SIZE - test $COMMON_BUFSIZE = 1024 && generate_1k_and_exit - generate_big_and_exit $COMMON_BUFSIZE "big" -fi - -if test -f "$common_bufsiz_h.1k.FAIL"; then - # Previous build FAILED to fit 1k into _end[]. - # Was it with same .config? - oldcfg=`cat -- "$common_bufsiz_h.1k.FAIL"` + # previous 1k build succeeded + oldcfg=`tail -n2 -- "$common_bufsiz_h.1k.OK"` curcfg=`md5sum <.config | cut -d' ' -f1; stat -c "%Y" .config` - # If yes, then build a "malloced" version + # config did not change if test x"$oldcfg" = x"$curcfg"; then - echo "Will not try 1k build, it failed before. Touch .config to override" -# Note: here we can do either a "malloc" or "std" build. - generate_malloc_and_exit + # Try bigger COMMON_BUFSIZE if possible + TAIL_SIZE=`head -n1 -- "$common_bufsiz_h.1k.OK"` + round_down_COMMON_BUFSIZE $((1024 + TAIL_SIZE)) + test $COMMON_BUFSIZE = 1024 && generate_1k_and_exit + generate_big_and_exit $COMMON_BUFSIZE "big" fi - # else: try 1k version - echo "New .config, will try 1k build" - rm -- "$common_bufsiz_h.1k.FAIL" - generate_1k_and_exit + # config did change + rm -rf -- "$common_bufsiz_h.1k.OK" fi # There was no 1k build yet. Try it. -- cgit v1.2.3-55-g6feb From aabb0a93e947a2a3cd180b490ae6664396446f63 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 3 Jul 2016 17:58:54 +0200 Subject: ntpd: daemonize before DNS resolution This resolves the following use case problem: "I start ntpd by default from /etc/init.d There might be no working network connection (not configured properly for whatever reason, hardware problems, whatelse). With busybox 1.25 ntpd seems to loop forever if now NTP servers are found, blocking the boot process and I never get a login to solve a possible pb or to do a first time configuration." Signed-off-by: Denys Vlasenko --- networking/ntpd.c | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/networking/ntpd.c b/networking/ntpd.c index 98158a304..8e7175063 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c @@ -2213,6 +2213,31 @@ static NOINLINE void ntp_init(char **argv) // if (opts & OPT_x) /* disable stepping, only slew is allowed */ // G.time_was_stepped = 1; + +#if ENABLE_FEATURE_NTPD_SERVER + G_listen_fd = -1; + if (opts & OPT_l) { + G_listen_fd = create_and_bind_dgram_or_die(NULL, 123); + if (G.if_name) { + if (setsockopt_bindtodevice(G_listen_fd, G.if_name)) + xfunc_die(); + } + socket_want_pktinfo(G_listen_fd); + setsockopt_int(G_listen_fd, IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY); + } +#endif + /* I hesitate to set -20 prio. -15 should be high enough for timekeeping */ + if (opts & OPT_N) + setpriority(PRIO_PROCESS, 0, -15); + + /* add_peers() calls can retry DNS resolution (possibly forever). + * Daemonize before them, or else boot can stall forever. + */ + if (!(opts & OPT_n)) { + bb_daemonize_or_rexec(DAEMON_DEVNULL_STDIO, argv); + logmode = LOGMODE_NONE; + } + if (peers) { while (peers) add_peers(llist_pop(&peers)); @@ -2241,26 +2266,6 @@ static NOINLINE void ntp_init(char **argv) /* -l but no peers: "stratum 1 server" mode */ G.stratum = 1; } -#if ENABLE_FEATURE_NTPD_SERVER - G_listen_fd = -1; - if (opts & OPT_l) { - G_listen_fd = create_and_bind_dgram_or_die(NULL, 123); - if (opts & OPT_I) { - if (setsockopt_bindtodevice(G_listen_fd, G.if_name)) - xfunc_die(); - } - socket_want_pktinfo(G_listen_fd); - setsockopt_int(G_listen_fd, IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY); - } -#endif - if (!(opts & OPT_n)) { - bb_daemonize_or_rexec(DAEMON_DEVNULL_STDIO, argv); - logmode = LOGMODE_NONE; - } - /* I hesitate to set -20 prio. -15 should be high enough for timekeeping */ - if (opts & OPT_N) - setpriority(PRIO_PROCESS, 0, -15); - /* If network is up, syncronization occurs in ~10 seconds. * We give "ntpd -q" 10 seconds to get first reply, * then another 50 seconds to finish syncing. -- cgit v1.2.3-55-g6feb From 44399e00ffa73270cd7fc108c983d3b1705b9d86 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 3 Jul 2016 20:26:44 +0200 Subject: udhcpc: run "deconfig" script in manual renew state too. closes 9061 The bug was seen when the following is done: # killall 1 udhpc; killall 2 udhpc Performing a DHCP renew state: 2 -> 5 Sending renew... Entering released state state: 5 -> 6 <<<<<<<<<<<<<< not calling script!!!! Signed-off-by: Denys Vlasenko --- networking/udhcp/d6_dhcpc.c | 6 +++++- networking/udhcp/dhcpc.c | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index c77669a31..12f8f1125 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c @@ -793,7 +793,11 @@ static void perform_renew(void) static void perform_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cur_ipv6) { /* send release packet */ - if (state == BOUND || state == RENEWING || state == REBINDING) { + if (state == BOUND + || state == RENEWING + || state == REBINDING + || state == RENEW_REQUESTED + ) { bb_error_msg("unicasting a release"); send_d6_release(server_ipv6, our_cur_ipv6); /* unicast */ d6_run_script(NULL, "deconfig"); diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index fc7b6216d..e58acbaca 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c @@ -1118,7 +1118,11 @@ static void perform_release(uint32_t server_addr, uint32_t requested_ip) struct in_addr temp_addr; /* send release packet */ - if (state == BOUND || state == RENEWING || state == REBINDING) { + if (state == BOUND + || state == RENEWING + || state == REBINDING + || state == RENEW_REQUESTED + ) { temp_addr.s_addr = server_addr; strcpy(buffer, inet_ntoa(temp_addr)); temp_addr.s_addr = requested_ip; -- cgit v1.2.3-55-g6feb From ee772a0d90e2775cbe40072fd5217552c260a9aa Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 4 Jul 2016 17:38:01 +0200 Subject: arp: fix buffer overflow. Closes 9071 function old new delta arp_main 1910 1898 -12 Signed-off-by: Denys Vlasenko --- networking/arp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/networking/arp.c b/networking/arp.c index 9381eb53a..69a5816eb 100644 --- a/networking/arp.c +++ b/networking/arp.c @@ -178,7 +178,7 @@ static int arp_del(char **args) if (flags == 0) flags = 3; - strncpy(req.arp_dev, device, sizeof(req.arp_dev)); + strncpy_IFNAMSIZ(req.arp_dev, device); err = -1; @@ -219,7 +219,7 @@ static void arp_getdevhw(char *ifname, struct sockaddr *sa) struct ifreq ifr; const struct hwtype *xhw; - strcpy(ifr.ifr_name, ifname); + strncpy_IFNAMSIZ(ifr.ifr_name, ifname); ioctl_or_perror_and_die(sockfd, SIOCGIFHWADDR, &ifr, "can't get HW-Address for '%s'", ifname); if (hw_set && (ifr.ifr_hwaddr.sa_family != hw->type)) { @@ -332,7 +332,7 @@ static int arp_set(char **args) /* Fill in the remainder of the request. */ req.arp_flags = flags; - strncpy(req.arp_dev, device, sizeof(req.arp_dev)); + strncpy_IFNAMSIZ(req.arp_dev, device); /* Call the kernel. */ if (option_mask32 & ARP_OPT_v) -- cgit v1.2.3-55-g6feb From 1b0dcc02dd5a101d1a62f2111892a41621be96cf Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Tue, 5 Jul 2016 14:07:50 +0100 Subject: libbb: suppress warning about run_applet_and_exit When busybox is configured to contain a single applet an unnecessary declaration of run_applet_and_exit results in a warning. Move the declaration to avoid this. Reported-by: Lauri Kasanen Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- libbb/appletlib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 480bf50fc..791b81c17 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -52,8 +52,6 @@ #include "usage_compressed.h" -static void run_applet_and_exit(const char *name, char **argv) NORETURN; - #if ENABLE_SHOW_USAGE && !ENABLE_FEATURE_COMPRESS_USAGE static const char usage_messages[] ALIGN1 = UNPACKED_USAGE; #else @@ -711,6 +709,8 @@ static void install_links(const char *busybox UNUSED_PARAM, # endif # if ENABLE_BUSYBOX +static void run_applet_and_exit(const char *name, char **argv) NORETURN; + /* If we were called as "busybox..." */ static int busybox_main(char **argv) { -- cgit v1.2.3-55-g6feb From f4f8fe841cf2df761eaade204a13e6fde6639666 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 5 Jul 2016 21:43:28 +0200 Subject: build system: fix a few warnings for allnoconfig build Not that allnoconfig build is useful in any way... Signed-off-by: Denys Vlasenko --- applets/usage_pod.c | 2 ++ docs/busybox_footer.pod | 2 -- libbb/appletlib.c | 30 +++++++++++++++++------------- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/applets/usage_pod.c b/applets/usage_pod.c index 0b1c4aadb..ccc166aed 100644 --- a/applets/usage_pod.c +++ b/applets/usage_pod.c @@ -90,6 +90,8 @@ int main(void) printf("%s\n\n", usage_array[i].aname); } } + printf("=back\n\n"); + return 0; } diff --git a/docs/busybox_footer.pod b/docs/busybox_footer.pod index c346c736b..92748eb72 100644 --- a/docs/busybox_footer.pod +++ b/docs/busybox_footer.pod @@ -1,5 +1,3 @@ -=back - =head1 LIBC NSS GNU Libc (glibc) uses the Name Service Switch (NSS) to configure the behavior diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 791b81c17..c341817e2 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -841,6 +841,7 @@ static int busybox_main(char **argv) } # endif +# if NUM_APPLETS > 0 void FAST_FUNC run_applet_no_and_exit(int applet_no, char **argv) { int argc = 1; @@ -858,15 +859,15 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, char **argv) * "true" and "false" are also special. */ if (1 -#if defined APPLET_NO_test +# if defined APPLET_NO_test && applet_no != APPLET_NO_test -#endif -#if defined APPLET_NO_true +# endif +# if defined APPLET_NO_true && applet_no != APPLET_NO_true -#endif -#if defined APPLET_NO_false +# endif +# if defined APPLET_NO_false && applet_no != APPLET_NO_false -#endif +# endif ) { if (argc == 2 && strcmp(argv[1], "--help") == 0) { /* Make "foo --help" exit with 0: */ @@ -878,19 +879,22 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, char **argv) check_suid(applet_no); exit(applet_main[applet_no](argc, argv)); } +# endif /* NUM_APPLETS > 0 */ static NORETURN void run_applet_and_exit(const char *name, char **argv) { - int applet; - # if ENABLE_BUSYBOX if (is_prefixed_with(name, "busybox")) exit(busybox_main(argv)); # endif +# if NUM_APPLETS > 0 /* find_applet_by_name() search is more expensive, so goes second */ - applet = find_applet_by_name(name); - if (applet >= 0) - run_applet_no_and_exit(applet, argv); + { + int applet = find_applet_by_name(name); + if (applet >= 0) + run_applet_no_and_exit(applet, argv); + } +# endif /*bb_error_msg_and_die("applet not found"); - links in printf */ full_write2_str(applet_name); @@ -957,10 +961,10 @@ int main(int argc UNUSED_PARAM, char **argv) #else lbb_prepare("busybox" IF_FEATURE_INDIVIDUAL(, argv)); -#if !ENABLE_BUSYBOX +# if !ENABLE_BUSYBOX if (argv[1] && is_prefixed_with(bb_basename(argv[0]), "busybox")) argv++; -#endif +# endif applet_name = argv[0]; if (applet_name[0] == '-') applet_name++; -- cgit v1.2.3-55-g6feb From 1035c92e2d1c017eab7cb10badb7e3b407aeba2d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 6 Jul 2016 15:45:41 +0200 Subject: whois: make it actually work It was doing way too simplistic work of just querying the server, no redirects, no query massaging. This required user to know a lot about whois, and enter at least three queries for each host to get meaningful information. function old new delta whois_main 209 646 +437 Signed-off-by: Denys Vlasenko --- networking/whois.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 124 insertions(+), 13 deletions(-) diff --git a/networking/whois.c b/networking/whois.c index bf330334a..5ef83672d 100644 --- a/networking/whois.c +++ b/networking/whois.c @@ -28,36 +28,147 @@ #include "libbb.h" -static void pipe_out(int fd) +static char *query(const char *host, int port, const char *domain) { + int fd; FILE *fp; - char buf[1024]; + bool success; + char *redir = NULL; + const char *pfx = ""; + char linebuf[1024]; + char *buf = NULL; + unsigned bufpos = 0; + again: + printf("[Querying %s:%d '%s%s']\n", host, port, pfx, domain); + fd = create_and_connect_stream_or_die(host, port); + success = 0; + fdprintf(fd, "%s%s\r\n", pfx, domain); fp = xfdopen_for_read(fd); - while (fgets(buf, sizeof(buf), fp)) { - char *p = strpbrk(buf, "\r\n"); - if (p) - *p = '\0'; - puts(buf); - } + while (fgets(linebuf, sizeof(linebuf), fp)) { + unsigned len = strcspn(linebuf, "\r\n"); + linebuf[len++] = '\n'; + + buf = xrealloc(buf, bufpos + len + 1); + memcpy(buf + bufpos, linebuf, len); + bufpos += len; + + if (!redir || !success) { + trim(linebuf); + str_tolower(linebuf); + if (!success) { + success = is_prefixed_with(linebuf, "domain:") + || is_prefixed_with(linebuf, "domain name:"); + } + else if (!redir) { + char *p = is_prefixed_with(linebuf, "whois server:"); + if (!p) + p = is_prefixed_with(linebuf, "whois:"); + if (p) + redir = xstrdup(skip_whitespace(p)); + } + } + } fclose(fp); /* closes fd too */ + if (!success && !pfx[0]) { + /* + * Looking at jwhois.conf, some whois servers use + * "domain = DOMAIN", "DOMAIN ID " + * and "domain=DOMAIN_WITHOUT_LAST_COMPONENT" + * formats, but those are rare. + * (There are a few even more contrived ones.) + * We are trying only "domain DOMAIN", the typical one. + */ + pfx = "domain "; + bufpos = 0; + goto again; + } + + /* Success */ + if (redir && strcmp(redir, host) == 0) { + /* Redirect to self does not count */ + free(redir); + redir = NULL; + } + if (!redir) { + /* Output saved text */ + printf("[%s]\n", host); + buf[bufpos] = '\0'; + fputs(buf, stdout); + } + free(buf); + return redir; } +static void recursive_query(const char *host, int port, const char *domain) +{ + char *free_me = NULL; + char *redir; + again: + redir = query(host, port, domain); + free(free_me); + if (redir) { + printf("[Redirected to %s]\n", redir); + host = free_me = redir; + port = 43; + goto again; + } +} + +/* One of "big" whois implementations has these options: + * + * $ whois --help + * jwhois version 4.0, Copyright (C) 1999-2007 Free Software Foundation, Inc. + * -v, --verbose verbose debug output + * -c FILE, --config=FILE use FILE as configuration file + * -h HOST, --host=HOST explicitly query HOST + * -n, --no-redirect disable content redirection + * -s, --no-whoisservers disable whois-servers.net service support + * -a, --raw disable reformatting of the query + * -i, --display-redirections display all redirects instead of hiding them + * -p PORT, --port=PORT use port number PORT (in conjunction with HOST) + * -r, --rwhois force an rwhois query to be made + * --rwhois-display=DISPLAY sets the display option in rwhois queries + * --rwhois-limit=LIMIT sets the maximum number of matches to return + * + * Example of its output: + * $ whois cnn.com + * [Querying whois.verisign-grs.com] + * [Redirected to whois.corporatedomains.com] + * [Querying whois.corporatedomains.com] + * [whois.corporatedomains.com] + * ...text of the reply... + * + * With -i, reply from each server is printed, after all redirects are done: + * [Querying whois.verisign-grs.com] + * [Redirected to whois.corporatedomains.com] + * [Querying whois.corporatedomains.com] + * [whois.verisign-grs.com] + * ...text of the reply... + * [whois.corporatedomains.com] + * ...text of the reply... + * + * With -a, no "DOMAIN" -> "domain DOMAIN" transformation is attempted. + + * With -n, the first reply is shown, redirects are not followed: + * [Querying whois.verisign-grs.com] + * [whois.verisign-grs.com] + * ...text of the reply... + */ + int whois_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int whois_main(int argc UNUSED_PARAM, char **argv) { int port = 43; - const char *host = "whois-servers.net"; + const char *host = "whois.iana.org"; opt_complementary = "-1:p+"; getopt32(argv, "h:p:", &host, &port); - argv += optind; + do { - int fd = create_and_connect_stream_or_die(host, port); - fdprintf(fd, "%s\r\n", *argv); - pipe_out(fd); + recursive_query(host, port, *argv); } while (*++argv); -- cgit v1.2.3-55-g6feb From 0844b5afe2cd60d46b7f2ad0fac8c2818d0780b3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 6 Jul 2016 17:16:27 +0200 Subject: whois: implement -i function old new delta whois_main 654 675 +21 packed_usage 30355 30356 +1 Signed-off-by: Denys Vlasenko --- networking/whois.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/networking/whois.c b/networking/whois.c index 5ef83672d..6ba8dfd20 100644 --- a/networking/whois.c +++ b/networking/whois.c @@ -21,13 +21,18 @@ //kbuild:lib-$(CONFIG_WHOIS) += whois.o //usage:#define whois_trivial_usage -//usage: "[-h SERVER] [-p PORT] NAME..." +//usage: "[-i] [-h SERVER] [-p PORT] NAME..." //usage:#define whois_full_usage "\n\n" //usage: "Query WHOIS info about NAME\n" +//usage: "\n -i Show redirect results too" //usage: "\n -h,-p Server to query" #include "libbb.h" +enum { + OPT_i = (1 << 0), +}; + static char *query(const char *host, int port, const char *domain) { int fd; @@ -53,6 +58,7 @@ static char *query(const char *host, int port, const char *domain) buf = xrealloc(buf, bufpos + len + 1); memcpy(buf + bufpos, linebuf, len); bufpos += len; + buf[bufpos] = '\0'; if (!redir || !success) { trim(linebuf); @@ -73,7 +79,7 @@ static char *query(const char *host, int port, const char *domain) fclose(fp); /* closes fd too */ if (!success && !pfx[0]) { /* - * Looking at jwhois.conf, some whois servers use + * Looking at /etc/jwhois.conf, some whois servers use * "domain = DOMAIN", "DOMAIN ID " * and "domain=DOMAIN_WITHOUT_LAST_COMPONENT" * formats, but those are rare. @@ -91,11 +97,9 @@ static char *query(const char *host, int port, const char *domain) free(redir); redir = NULL; } - if (!redir) { + if (!redir || (option_mask32 & OPT_i)) { /* Output saved text */ - printf("[%s]\n", host); - buf[bufpos] = '\0'; - fputs(buf, stdout); + printf("[%s]\n%s", host, buf ? buf : ""); } free(buf); return redir; @@ -164,7 +168,7 @@ int whois_main(int argc UNUSED_PARAM, char **argv) const char *host = "whois.iana.org"; opt_complementary = "-1:p+"; - getopt32(argv, "h:p:", &host, &port); + getopt32(argv, "ih:p:", &host, &port); argv += optind; do { -- cgit v1.2.3-55-g6feb From 237bedd499c58034a1355484d6d4d906f0180308 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 6 Jul 2016 21:58:02 +0200 Subject: getopt32: add new syntax of 'o:+' and 'o:*' for -o NUM and -o LIST In many cases, this aqllows to drop use of opt_complementary. Approximately -400 bytes: function old new delta getopt32 1423 1502 +79 opt_string 17 18 +1 OPT_STR 24 25 +1 uniq_main 416 406 -10 timeout_main 279 269 -10 sulogin_main 270 260 -10 readprofile_main 1825 1815 -10 ps_main 543 533 -10 pidof_main 245 235 -10 pgrep_main 611 601 -10 od_main 2600 2590 -10 mkfs_minix_main 2684 2674 -10 mkfs_ext2_main 2603 2593 -10 microcom_main 712 702 -10 makemime_main 315 305 -10 ionice_main 282 272 -10 inetd_main 2074 2064 -10 ifplugd_main 1144 1134 -10 halt_main 353 343 -10 getopt_main 636 626 -10 fdisk_main 2854 2844 -10 env_main 206 196 -10 dmesg_main 319 309 -10 conspy_main 1214 1204 -10 awk_main 981 971 -10 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/22 up/down: 81/-220) Total: -139 bytes text data bss dec hex filename 919373 906 14060 934339 e41c3 busybox_old 918969 906 14060 933935 e402f busybox_unstripped Signed-off-by: Denys Vlasenko --- archival/tar.c | 15 ++++----- coreutils/du.c | 8 ++--- coreutils/env.c | 3 +- coreutils/od_bloaty.c | 3 +- coreutils/sort.c | 5 ++- coreutils/split.c | 4 +-- coreutils/tail.c | 4 +-- coreutils/uniq.c | 3 +- debianutils/run_parts.c | 4 +-- editors/awk.c | 8 ++--- editors/diff.c | 4 +-- editors/sed.c | 5 ++- findutils/grep.c | 8 ++--- init/halt.c | 3 +- libbb/getopt32.c | 82 ++++++++++++++++++++++++++++++++------------- libbb/parse_config.c | 4 +-- loginutils/cryptpw.c | 4 +-- loginutils/getty.c | 4 +-- loginutils/sulogin.c | 3 +- mailutils/makemime.c | 3 +- mailutils/popmaildir.c | 4 +-- mailutils/reformime.c | 4 +-- mailutils/sendmail.c | 4 +-- miscutils/conspy.c | 4 +-- miscutils/ionice.c | 3 +- miscutils/microcom.c | 3 +- miscutils/timeout.c | 3 +- miscutils/ubi_tools.c | 8 ++--- networking/arping.c | 4 +-- networking/ftpd.c | 6 ++-- networking/ifplugd.c | 5 ++- networking/inetd.c | 4 +-- networking/nc_bloaty.c | 4 +-- networking/ntpd.c | 4 +-- networking/ping.c | 4 +-- networking/tcpudp.c | 4 +-- networking/telnetd.c | 4 +-- networking/traceroute.c | 4 +-- networking/udhcp/d6_dhcpc.c | 4 +-- networking/udhcp/dhcpc.c | 4 +-- networking/wget.c | 3 +- networking/whois.c | 4 +-- procps/pgrep.c | 3 +- procps/pidof.c | 3 +- procps/ps.c | 3 +- procps/watch.c | 4 +-- runit/chpst.c | 4 +-- runit/sv.c | 4 +-- selinux/setfiles.c | 6 ++-- sysklogd/syslogd.c | 6 ++-- util-linux/dmesg.c | 3 +- util-linux/fdisk.c | 3 +- util-linux/getopt.c | 3 +- util-linux/mkfs_ext2.c | 3 +- util-linux/mkfs_minix.c | 3 +- util-linux/mkfs_reiser.c | 4 +-- util-linux/mount.c | 4 +-- util-linux/readprofile.c | 3 +- 58 files changed, 168 insertions(+), 159 deletions(-) diff --git a/archival/tar.c b/archival/tar.c index 7434e22e4..8e315c610 100644 --- a/archival/tar.c +++ b/archival/tar.c @@ -980,7 +980,6 @@ int tar_main(int argc UNUSED_PARAM, char **argv) /* Prepend '-' to the first argument if required */ opt_complementary = "--:" // first arg is options "tt:vv:" // count -t,-v - IF_FEATURE_TAR_FROM("X::T::") // cumulative lists #if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM "\xff::" // --exclude=PATTERN is a list #endif @@ -1032,13 +1031,13 @@ int tar_main(int argc UNUSED_PARAM, char **argv) #endif opt = getopt32(argv, "txC:f:Oopvk" - IF_FEATURE_TAR_CREATE( "ch" ) - IF_FEATURE_SEAMLESS_BZ2( "j" ) - IF_FEATURE_SEAMLESS_LZMA("a" ) - IF_FEATURE_TAR_FROM( "T:X:") - IF_FEATURE_SEAMLESS_GZ( "z" ) - IF_FEATURE_SEAMLESS_XZ( "J" ) - IF_FEATURE_SEAMLESS_Z( "Z" ) + IF_FEATURE_TAR_CREATE( "ch" ) + IF_FEATURE_SEAMLESS_BZ2( "j" ) + IF_FEATURE_SEAMLESS_LZMA("a" ) + IF_FEATURE_TAR_FROM( "T:*X:*") + IF_FEATURE_SEAMLESS_GZ( "z" ) + IF_FEATURE_SEAMLESS_XZ( "J" ) + IF_FEATURE_SEAMLESS_Z( "Z" ) IF_FEATURE_TAR_NOPRESERVE_TIME("m") IF_FEATURE_TAR_LONG_OPTIONS("\xf9:") // --strip-components , &base_dir // -C dir diff --git a/coreutils/du.c b/coreutils/du.c index 1240bcbbc..5f104736b 100644 --- a/coreutils/du.c +++ b/coreutils/du.c @@ -226,8 +226,8 @@ int du_main(int argc UNUSED_PARAM, char **argv) * ignore -a. This is consistent with -s being equivalent to -d 0. */ #if ENABLE_FEATURE_HUMAN_READABLE - opt_complementary = "h-km:k-hm:m-hk:H-L:L-H:s-d:d-s:d+"; - opt = getopt32(argv, "aHkLsx" "d:" "lc" "hm", &G.max_print_depth); + opt_complementary = "h-km:k-hm:m-hk:H-L:L-H:s-d:d-s"; + opt = getopt32(argv, "aHkLsx" "d:+" "lc" "hm", &G.max_print_depth); argv += optind; if (opt & OPT_h_for_humans) { G.disp_unit = 0; @@ -239,8 +239,8 @@ int du_main(int argc UNUSED_PARAM, char **argv) G.disp_unit = 1024; } #else - opt_complementary = "H-L:L-H:s-d:d-s:d+"; - opt = getopt32(argv, "aHkLsx" "d:" "lc", &G.max_print_depth); + opt_complementary = "H-L:L-H:s-d:d-s"; + opt = getopt32(argv, "aHkLsx" "d:+" "lc", &G.max_print_depth); argv += optind; #if !ENABLE_FEATURE_DU_DEFAULT_BLOCKSIZE_1K if (opt & OPT_k_kbytes) { diff --git a/coreutils/env.c b/coreutils/env.c index 807ef13e9..cdfc30e14 100644 --- a/coreutils/env.c +++ b/coreutils/env.c @@ -54,11 +54,10 @@ int env_main(int argc UNUSED_PARAM, char **argv) unsigned opts; llist_t *unset_env = NULL; - opt_complementary = "u::"; #if ENABLE_FEATURE_ENV_LONG_OPTIONS applet_long_options = env_longopts; #endif - opts = getopt32(argv, "+iu:", &unset_env); + opts = getopt32(argv, "+iu:+", &unset_env); argv += optind; if (argv[0] && LONE_DASH(argv[0])) { opts |= 1; diff --git a/coreutils/od_bloaty.c b/coreutils/od_bloaty.c index c8a654165..f13bdfc11 100644 --- a/coreutils/od_bloaty.c +++ b/coreutils/od_bloaty.c @@ -62,7 +62,7 @@ enum { }; #define OD_GETOPT32() getopt32(argv, \ - "A:N:abcdfhij:lot:vxsS:w::", \ + "A:N:abcdfhij:lot:*vxsS:w:+:", \ /* -w with optional param */ \ /* -S was -s and also had optional parameter */ \ /* but in coreutils 6.3 it was renamed and now has */ \ @@ -1212,7 +1212,6 @@ int od_main(int argc UNUSED_PARAM, char **argv) address_pad_len_char = '7'; /* Parse command line */ - opt_complementary = "w+:t::"; /* -w N, -t is a list */ #if ENABLE_LONG_OPTS applet_long_options = od_longopts; #endif diff --git a/coreutils/sort.c b/coreutils/sort.c index 9139d9f47..34a41999b 100644 --- a/coreutils/sort.c +++ b/coreutils/sort.c @@ -73,7 +73,7 @@ */ /* These are sort types */ -static const char OPT_STR[] ALIGN1 = "ngMucszbrdfimS:T:o:k:t:"; +static const char OPT_STR[] ALIGN1 = "ngMucszbrdfimS:T:o:k:*t:"; enum { FLAG_n = 1, /* Numeric sort */ FLAG_g = 2, /* Sort using strtod() */ @@ -358,8 +358,7 @@ int sort_main(int argc UNUSED_PARAM, char **argv) /* Parse command line options */ /* -o and -t can be given at most once */ - opt_complementary = "o--o:t--t:" /* -t, -o: at most one of each */ - "k::"; /* -k takes list */ + opt_complementary = "o--o:t--t"; /* -t, -o: at most one of each */ opts = getopt32(argv, OPT_STR, &str_ignored, &str_ignored, &str_o, &lst_k, &str_t); /* global b strips leading and trailing spaces */ if (opts & FLAG_b) diff --git a/coreutils/split.c b/coreutils/split.c index e67c3de66..19d58a21b 100644 --- a/coreutils/split.c +++ b/coreutils/split.c @@ -81,8 +81,8 @@ int split_main(int argc UNUSED_PARAM, char **argv) setup_common_bufsiz(); - opt_complementary = "?2:a+"; /* max 2 args; -a N */ - opt = getopt32(argv, "l:b:a:", &count_p, &count_p, &suffix_len); + opt_complementary = "?2"; /* max 2 args; -a N */ + opt = getopt32(argv, "l:b:a:+", &count_p, &count_p, &suffix_len); if (opt & SPLIT_OPT_l) cnt = XATOOFF(count_p); diff --git a/coreutils/tail.c b/coreutils/tail.c index 39f87679e..57ad0f3b7 100644 --- a/coreutils/tail.c +++ b/coreutils/tail.c @@ -121,8 +121,8 @@ int tail_main(int argc, char **argv) #endif /* -s NUM, -F imlies -f */ - IF_FEATURE_FANCY_TAIL(opt_complementary = "s+:Ff";) - opt = getopt32(argv, "fc:n:" IF_FEATURE_FANCY_TAIL("qs:vF"), + IF_FEATURE_FANCY_TAIL(opt_complementary = "Ff";) + opt = getopt32(argv, "fc:n:" IF_FEATURE_FANCY_TAIL("qs:+vF"), &str_c, &str_n IF_FEATURE_FANCY_TAIL(,&sleep_period)); #define FOLLOW (opt & 0x1) #define COUNT_BYTES (opt & 0x2) diff --git a/coreutils/uniq.c b/coreutils/uniq.c index e0133998a..ec7bde418 100644 --- a/coreutils/uniq.c +++ b/coreutils/uniq.c @@ -50,8 +50,7 @@ int uniq_main(int argc UNUSED_PARAM, char **argv) skip_fields = skip_chars = 0; max_chars = INT_MAX; - opt_complementary = "f+:s+:w+"; - opt = getopt32(argv, "cduf:s:w:", &skip_fields, &skip_chars, &max_chars); + opt = getopt32(argv, "cduf:+s:+w:+", &skip_fields, &skip_chars, &max_chars); argv += optind; input_filename = argv[0]; diff --git a/debianutils/run_parts.c b/debianutils/run_parts.c index c671b9252..0bb666abc 100644 --- a/debianutils/run_parts.c +++ b/debianutils/run_parts.c @@ -181,8 +181,8 @@ int run_parts_main(int argc UNUSED_PARAM, char **argv) applet_long_options = runparts_longopts; #endif /* We require exactly one argument: the directory name */ - opt_complementary = "=1:a::"; - getopt32(argv, "a:u:", &arg_list, &umask_p); + opt_complementary = "=1"; + getopt32(argv, "a:*u:", &arg_list, &umask_p); umask(xstrtou_range(umask_p, 8, 0, 07777)); diff --git a/editors/awk.c b/editors/awk.c index 69816464d..d0269b9f4 100644 --- a/editors/awk.c +++ b/editors/awk.c @@ -72,12 +72,9 @@ #define OPTSTR_AWK \ - "F:v:f:" \ - IF_FEATURE_AWK_GNU_EXTENSIONS("e:") \ + "F:v:*f:*" \ + IF_FEATURE_AWK_GNU_EXTENSIONS("e:*") \ "W:" -#define OPTCOMPLSTR_AWK \ - "v::f::" \ - IF_FEATURE_AWK_GNU_EXTENSIONS("e::") enum { OPTBIT_F, /* define field separator */ OPTBIT_v, /* define variable */ @@ -3209,7 +3206,6 @@ int awk_main(int argc, char **argv) *s1 = '='; } } - opt_complementary = OPTCOMPLSTR_AWK; opt = getopt32(argv, OPTSTR_AWK, &opt_F, &list_v, &list_f, IF_FEATURE_AWK_GNU_EXTENSIONS(&list_e,) NULL); argv += optind; argc -= optind; diff --git a/editors/diff.c b/editors/diff.c index ff269360f..75229ad8c 100644 --- a/editors/diff.c +++ b/editors/diff.c @@ -982,11 +982,11 @@ int diff_main(int argc UNUSED_PARAM, char **argv) INIT_G(); /* exactly 2 params; collect multiple -L