aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2016-07-07 14:28:08 +0100
committerRon Yorston <rmy@pobox.com>2016-07-07 14:58:55 +0100
commit613f46218c53c8cabdbf0435653e74e0e0e91e1c (patch)
treeca06a7e7a3e4c861441acb4ea20648d7827fa6ae
parenta0c61c9492723dd31681f878f9c68c92817a476d (diff)
parent237bedd499c58034a1355484d6d4d906f0180308 (diff)
downloadbusybox-w32-613f46218c53c8cabdbf0435653e74e0e0e91e1c.tar.gz
busybox-w32-613f46218c53c8cabdbf0435653e74e0e0e91e1c.tar.bz2
busybox-w32-613f46218c53c8cabdbf0435653e74e0e0e91e1c.zip
Merge branch 'busybox' into merge
-rw-r--r--Config.in12
-rw-r--r--Makefile2
-rw-r--r--applets/usage_pod.c2
-rw-r--r--archival/bbunzip.c2
-rw-r--r--archival/gzip.c4
-rw-r--r--archival/libarchive/decompress_gunzip.c4
-rw-r--r--archival/libarchive/decompress_unxz.c2
-rw-r--r--archival/libarchive/get_header_tar.c23
-rw-r--r--archival/libarchive/open_transformer.c55
-rw-r--r--archival/tar.c21
-rw-r--r--configs/mingw32_defconfig5
-rw-r--r--configs/mingw64_defconfig5
-rw-r--r--coreutils/cp.c30
-rw-r--r--coreutils/df.c20
-rw-r--r--coreutils/du.c8
-rw-r--r--coreutils/env.c3
-rw-r--r--coreutils/od_bloaty.c3
-rw-r--r--coreutils/sort.c5
-rw-r--r--coreutils/split.c4
-rw-r--r--coreutils/tail.c4
-rw-r--r--coreutils/uniq.c3
-rw-r--r--debianutils/run_parts.c4
-rw-r--r--docs/busybox_footer.pod2
-rw-r--r--editors/awk.c8
-rw-r--r--editors/diff.c4
-rw-r--r--editors/sed.c5
-rw-r--r--findutils/grep.c9
-rw-r--r--include/bb_archive.h8
-rw-r--r--include/libbb.h26
-rw-r--r--init/halt.c3
-rw-r--r--libbb/Kbuild.src1
-rw-r--r--libbb/appletlib.c63
-rw-r--r--libbb/copy_file.c21
-rw-r--r--libbb/getopt32.c82
-rw-r--r--libbb/parse_config.c4
-rw-r--r--libbb/time.c1
-rw-r--r--loginutils/cryptpw.c4
-rw-r--r--loginutils/getty.c4
-rw-r--r--loginutils/sulogin.c3
-rw-r--r--mailutils/makemime.c3
-rw-r--r--mailutils/popmaildir.c4
-rw-r--r--mailutils/reformime.c4
-rw-r--r--mailutils/sendmail.c4
-rw-r--r--miscutils/Kbuild.src9
-rw-r--r--miscutils/conspy.c4
-rw-r--r--miscutils/i2c_tools.c2
-rw-r--r--miscutils/ionice.c3
-rw-r--r--miscutils/microcom.c3
-rw-r--r--miscutils/setsid.c2
-rw-r--r--miscutils/timeout.c3
-rw-r--r--miscutils/ubi_tools.c8
-rw-r--r--modutils/modprobe-small.c41
-rw-r--r--networking/arp.c6
-rw-r--r--networking/arping.c15
-rw-r--r--networking/ftpd.c6
-rw-r--r--networking/ifplugd.c5
-rw-r--r--networking/inetd.c4
-rw-r--r--networking/nc_bloaty.c4
-rw-r--r--networking/ntpd.c96
-rw-r--r--networking/ping.c12
-rw-r--r--networking/tcpudp.c4
-rw-r--r--networking/telnetd.c4
-rw-r--r--networking/traceroute.c4
-rw-r--r--networking/udhcp/d6_dhcpc.c10
-rw-r--r--networking/udhcp/dhcpc.c10
-rw-r--r--networking/wget.c3
-rw-r--r--networking/whois.c147
-rw-r--r--procps/pgrep.c3
-rw-r--r--procps/pidof.c3
-rw-r--r--procps/ps.c3
-rw-r--r--procps/watch.c4
-rw-r--r--runit/chpst.c4
-rw-r--r--runit/sv.c4
-rwxr-xr-xscripts/generate_BUFSIZ.sh100
-rw-r--r--scripts/kconfig/zconf.hash.c_shipped14
-rwxr-xr-xscripts/randomtest22
-rwxr-xr-xscripts/trylink2
-rw-r--r--selinux/setfiles.c6
-rw-r--r--sysklogd/syslogd.c6
-rwxr-xr-xtestsuite/ar.tests2
-rwxr-xr-xtestsuite/busybox.tests16
-rw-r--r--testsuite/du/du-m-works2
-rwxr-xr-xtestsuite/tar.tests8
-rw-r--r--util-linux/dmesg.c3
-rw-r--r--util-linux/fbset.c5
-rw-r--r--util-linux/fdisk.c3
-rw-r--r--util-linux/fdisk_osf.c3
-rw-r--r--util-linux/fdisk_sgi.c27
-rw-r--r--util-linux/getopt.c3
-rw-r--r--util-linux/mkfs_ext2.c3
-rw-r--r--util-linux/mkfs_minix.c3
-rw-r--r--util-linux/mkfs_reiser.c4
-rw-r--r--util-linux/mount.c6
-rw-r--r--util-linux/readprofile.c3
94 files changed, 692 insertions, 459 deletions
diff --git a/Config.in b/Config.in
index a504c745e..f9f6a3735 100644
--- a/Config.in
+++ b/Config.in
@@ -130,9 +130,21 @@ config FEATURE_COMPRESS_USAGE
130 and have very little memory, this might not be a win. Otherwise, 130 and have very little memory, this might not be a win. Otherwise,
131 you probably want this. 131 you probably want this.
132 132
133config BUSYBOX
134 bool "Include busybox applet"
135 default y
136 help
137 The busybox applet provides general help regarding busybox and
138 allows the included applets to be listed. It's also required
139 if applet links are to be installed at runtime.
140
141 If you can live without these features disabling this will save
142 some space.
143
133config FEATURE_INSTALLER 144config FEATURE_INSTALLER
134 bool "Support --install [-s] to install applet links at runtime" 145 bool "Support --install [-s] to install applet links at runtime"
135 default y 146 default y
147 depends on BUSYBOX
136 help 148 help
137 Enable 'busybox --install [-s]' support. This will allow you to use 149 Enable 'busybox --install [-s]' support. This will allow you to use
138 busybox at runtime to create hard links or symlinks for all the 150 busybox at runtime to create hard links or symlinks for all the
diff --git a/Makefile b/Makefile
index 40ed634a6..ea8d16f34 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
1VERSION = 1 1VERSION = 1
2PATCHLEVEL = 25 2PATCHLEVEL = 26
3SUBLEVEL = 0 3SUBLEVEL = 0
4EXTRAVERSION = .git 4EXTRAVERSION = .git
5NAME = Unnamed 5NAME = Unnamed
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)
90 printf("%s\n\n", usage_array[i].aname); 90 printf("%s\n\n", usage_array[i].aname);
91 } 91 }
92 } 92 }
93 printf("=back\n\n");
94
93 return 0; 95 return 0;
94} 96}
95 97
diff --git a/archival/bbunzip.c b/archival/bbunzip.c
index aaaf67e03..3a483219d 100644
--- a/archival/bbunzip.c
+++ b/archival/bbunzip.c
@@ -121,7 +121,7 @@ int FAST_FUNC bbunpack(char **argv,
121 121
122 if (!(option_mask32 & SEAMLESS_MAGIC)) { 122 if (!(option_mask32 & SEAMLESS_MAGIC)) {
123 init_transformer_state(&xstate); 123 init_transformer_state(&xstate);
124 xstate.check_signature = 1; 124 xstate.signature_skipped = 0;
125 /*xstate.src_fd = STDIN_FILENO; - already is */ 125 /*xstate.src_fd = STDIN_FILENO; - already is */
126 xstate.dst_fd = STDOUT_FILENO; 126 xstate.dst_fd = STDOUT_FILENO;
127 status = unpacker(&xstate); 127 status = unpacker(&xstate);
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
77//kbuild:lib-$(CONFIG_GZIP) += gzip.o 77//kbuild:lib-$(CONFIG_GZIP) += gzip.o
78 78
79//usage:#define gzip_trivial_usage 79//usage:#define gzip_trivial_usage
80//usage: "[-cfd" IF_FEATURE_GZIP_LEVELS("123456789") "] [FILE]..." 80//usage: "[-cf" IF_GUNZIP("d") IF_FEATURE_GZIP_LEVELS("123456789") "] [FILE]..."
81//usage:#define gzip_full_usage "\n\n" 81//usage:#define gzip_full_usage "\n\n"
82//usage: "Compress FILEs (or stdin)\n" 82//usage: "Compress FILEs (or stdin)\n"
83//usage: IF_FEATURE_GZIP_LEVELS( 83//usage: IF_FEATURE_GZIP_LEVELS(
84//usage: "\n -1..9 Compression level" 84//usage: "\n -1..9 Compression level"
85//usage: ) 85//usage: )
86//usage: IF_GUNZIP(
86//usage: "\n -d Decompress" 87//usage: "\n -d Decompress"
88//usage: )
87//usage: "\n -c Write to stdout" 89//usage: "\n -c Write to stdout"
88//usage: "\n -f Force" 90//usage: "\n -f Force"
89//usage: 91//usage:
diff --git a/archival/libarchive/decompress_gunzip.c b/archival/libarchive/decompress_gunzip.c
index 94dbd7a95..74d364379 100644
--- a/archival/libarchive/decompress_gunzip.c
+++ b/archival/libarchive/decompress_gunzip.c
@@ -1207,7 +1207,7 @@ unpack_gz_stream(transformer_state_t *xstate)
1207 if (check_signature16(xstate, GZIP_MAGIC)) 1207 if (check_signature16(xstate, GZIP_MAGIC))
1208 return -1; 1208 return -1;
1209#else 1209#else
1210 if (xstate->check_signature) { 1210 if (!xstate->signature_skipped) {
1211 uint16_t magic2; 1211 uint16_t magic2;
1212 1212
1213 if (full_read(xstate->src_fd, &magic2, 2) != 2) { 1213 if (full_read(xstate->src_fd, &magic2, 2) != 2) {
@@ -1216,7 +1216,7 @@ unpack_gz_stream(transformer_state_t *xstate)
1216 return -1; 1216 return -1;
1217 } 1217 }
1218 if (magic2 == COMPRESS_MAGIC) { 1218 if (magic2 == COMPRESS_MAGIC) {
1219 xstate->check_signature = 0; 1219 xstate->signature_skipped = 2;
1220 return unpack_Z_stream(xstate); 1220 return unpack_Z_stream(xstate);
1221 } 1221 }
1222 if (magic2 != GZIP_MAGIC) 1222 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)
55 iobuf.out = membuf + BUFSIZ; 55 iobuf.out = membuf + BUFSIZ;
56 iobuf.out_size = BUFSIZ; 56 iobuf.out_size = BUFSIZ;
57 57
58 if (!xstate || xstate->check_signature == 0) { 58 if (!xstate || xstate->signature_skipped) {
59 /* Preload XZ file signature */ 59 /* Preload XZ file signature */
60 strcpy((char*)membuf, HEADER_MAGIC); 60 strcpy((char*)membuf, HEADER_MAGIC);
61 iobuf.in_size = HEADER_MAGIC_SIZE; 61 iobuf.in_size = HEADER_MAGIC_SIZE;
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)
60} 60}
61#define GET_OCTAL(a) getOctal((a), sizeof(a)) 61#define GET_OCTAL(a) getOctal((a), sizeof(a))
62 62
63#define TAR_EXTD (ENABLE_FEATURE_TAR_GNU_EXTENSIONS || ENABLE_FEATURE_TAR_SELINUX)
64#if !TAR_EXTD
65#define process_pax_hdr(archive_handle, sz, global) \
66 process_pax_hdr(archive_handle, sz)
67#endif
63/* "global" is 0 or 1 */ 68/* "global" is 0 or 1 */
64static void process_pax_hdr(archive_handle_t *archive_handle, unsigned sz, int global) 69static void process_pax_hdr(archive_handle_t *archive_handle, unsigned sz, int global)
65{ 70{
71#if !TAR_EXTD
72 unsigned blk_sz = (sz + 511) & (~511);
73 seek_by_read(archive_handle->src_fd, blk_sz);
74#else
75 unsigned blk_sz = (sz + 511) & (~511);
66 char *buf, *p; 76 char *buf, *p;
67 unsigned blk_sz;
68 77
69 blk_sz = (sz + 511) & (~511);
70 p = buf = xmalloc(blk_sz + 1); 78 p = buf = xmalloc(blk_sz + 1);
71 xread(archive_handle->src_fd, buf, blk_sz); 79 xread(archive_handle->src_fd, buf, blk_sz);
72 archive_handle->offset += blk_sz; 80 archive_handle->offset += blk_sz;
@@ -104,30 +112,31 @@ static void process_pax_hdr(archive_handle_t *archive_handle, unsigned sz, int g
104 p[-1] = '\0'; 112 p[-1] = '\0';
105 value = end + 1; 113 value = end + 1;
106 114
107#if ENABLE_FEATURE_TAR_GNU_EXTENSIONS 115# if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
108 if (!global && is_prefixed_with(value, "path=")) { 116 if (!global && is_prefixed_with(value, "path=")) {
109 value += sizeof("path=") - 1; 117 value += sizeof("path=") - 1;
110 free(archive_handle->tar__longname); 118 free(archive_handle->tar__longname);
111 archive_handle->tar__longname = xstrdup(value); 119 archive_handle->tar__longname = xstrdup(value);
112 continue; 120 continue;
113 } 121 }
114#endif 122# endif
115 123
116#if ENABLE_FEATURE_TAR_SELINUX 124# if ENABLE_FEATURE_TAR_SELINUX
117 /* Scan for SELinux contexts, via "RHT.security.selinux" keyword. 125 /* Scan for SELinux contexts, via "RHT.security.selinux" keyword.
118 * This is what Red Hat's patched version of tar uses. 126 * This is what Red Hat's patched version of tar uses.
119 */ 127 */
120# define SELINUX_CONTEXT_KEYWORD "RHT.security.selinux" 128# define SELINUX_CONTEXT_KEYWORD "RHT.security.selinux"
121 if (is_prefixed_with(value, SELINUX_CONTEXT_KEYWORD"=")) { 129 if (is_prefixed_with(value, SELINUX_CONTEXT_KEYWORD"=")) {
122 value += sizeof(SELINUX_CONTEXT_KEYWORD"=") - 1; 130 value += sizeof(SELINUX_CONTEXT_KEYWORD"=") - 1;
123 free(archive_handle->tar__sctx[global]); 131 free(archive_handle->tar__sctx[global]);
124 archive_handle->tar__sctx[global] = xstrdup(value); 132 archive_handle->tar__sctx[global] = xstrdup(value);
125 continue; 133 continue;
126 } 134 }
127#endif 135# endif
128 } 136 }
129 137
130 free(buf); 138 free(buf);
139#endif
131} 140}
132 141
133char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) 142char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
diff --git a/archival/libarchive/open_transformer.c b/archival/libarchive/open_transformer.c
index 7b18aeff4..641256787 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)
13 13
14int FAST_FUNC check_signature16(transformer_state_t *xstate, unsigned magic16) 14int FAST_FUNC check_signature16(transformer_state_t *xstate, unsigned magic16)
15{ 15{
16 if (xstate->check_signature) { 16 if (!xstate->signature_skipped) {
17 uint16_t magic2; 17 uint16_t magic2;
18 if (full_read(xstate->src_fd, &magic2, 2) != 2 || magic2 != magic16) { 18 if (full_read(xstate->src_fd, &magic2, 2) != 2 || magic2 != magic16) {
19 bb_error_msg("invalid magic"); 19 bb_error_msg("invalid magic");
20#if 0 /* possible future extension */
21 if (xstate->check_signature > 1)
22 xfunc_die();
23#endif
24 return -1; 20 return -1;
25 } 21 }
22 xstate->signature_skipped = 2;
26 } 23 }
27 return 0; 24 return 0;
28} 25}
@@ -103,7 +100,7 @@ void check_errors_in_children(int signo)
103/* transformer(), more than meets the eye */ 100/* transformer(), more than meets the eye */
104#if BB_MMU 101#if BB_MMU
105void FAST_FUNC fork_transformer(int fd, 102void FAST_FUNC fork_transformer(int fd,
106 int check_signature, 103 int signature_skipped,
107 IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate) 104 IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate)
108) 105)
109#else 106#else
@@ -124,7 +121,7 @@ void FAST_FUNC fork_transformer(int fd, const char *transform_prog)
124 IF_DESKTOP(long long) int r; 121 IF_DESKTOP(long long) int r;
125 transformer_state_t xstate; 122 transformer_state_t xstate;
126 init_transformer_state(&xstate); 123 init_transformer_state(&xstate);
127 xstate.check_signature = check_signature; 124 xstate.signature_skipped = signature_skipped;
128 xstate.src_fd = fd; 125 xstate.src_fd = fd;
129 xstate.dst_fd = fd_pipe.wr; 126 xstate.dst_fd = fd_pipe.wr;
130 r = transformer(&xstate); 127 r = transformer(&xstate);
@@ -194,12 +191,11 @@ static transformer_state_t *setup_transformer_on_fd(int fd, int fail_if_not_comp
194 uint16_t b16[2]; 191 uint16_t b16[2];
195 uint32_t b32[1]; 192 uint32_t b32[1];
196 } magic; 193 } magic;
197 int offset;
198 transformer_state_t *xstate; 194 transformer_state_t *xstate;
199 195
200 offset = -2;
201 xstate = xzalloc(sizeof(*xstate)); 196 xstate = xzalloc(sizeof(*xstate));
202 xstate->src_fd = fd; 197 xstate->src_fd = fd;
198 xstate->signature_skipped = 2;
203 199
204 /* .gz and .bz2 both have 2-byte signature, and their 200 /* .gz and .bz2 both have 2-byte signature, and their
205 * unpack_XXX_stream wants this header skipped. */ 201 * unpack_XXX_stream wants this header skipped. */
@@ -228,7 +224,7 @@ static transformer_state_t *setup_transformer_on_fd(int fd, int fail_if_not_comp
228 if (ENABLE_FEATURE_SEAMLESS_XZ 224 if (ENABLE_FEATURE_SEAMLESS_XZ
229 && magic.b16[0] == XZ_MAGIC1 225 && magic.b16[0] == XZ_MAGIC1
230 ) { 226 ) {
231 offset = -6; 227 xstate->signature_skipped = 6;
232 xread(fd, magic.b32, sizeof(magic.b32[0])); 228 xread(fd, magic.b32, sizeof(magic.b32[0]));
233 if (magic.b32[0] == XZ_MAGIC2) { 229 if (magic.b32[0] == XZ_MAGIC2) {
234 xstate->xformer = unpack_xz_stream; 230 xstate->xformer = unpack_xz_stream;
@@ -250,18 +246,8 @@ static transformer_state_t *setup_transformer_on_fd(int fd, int fail_if_not_comp
250 */ 246 */
251// USE_FOR_MMU(xstate->xformer = copy_stream;) 247// USE_FOR_MMU(xstate->xformer = copy_stream;)
252// USE_FOR_NOMMU(xstate->xformer_prog = "cat";) 248// USE_FOR_NOMMU(xstate->xformer_prog = "cat";)
253 /* fall through to seeking bck over bytes we read earlier */
254
255 USE_FOR_NOMMU(found_magic:)
256 /* NOMMU version of fork_transformer execs
257 * an external unzipper that wants
258 * file position at the start of the file.
259 */
260 xlseek(fd, offset, SEEK_CUR);
261
262 USE_FOR_MMU(found_magic:)
263 /* In MMU case, if magic was found, seeking back is not necessary */
264 249
250 found_magic:
265 return xstate; 251 return xstate;
266} 252}
267 253
@@ -280,6 +266,12 @@ int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_compressed)
280# if BB_MMU 266# if BB_MMU
281 fork_transformer_with_no_sig(xstate->src_fd, xstate->xformer); 267 fork_transformer_with_no_sig(xstate->src_fd, xstate->xformer);
282# else 268# else
269 /* NOMMU version of fork_transformer execs
270 * an external unzipper that wants
271 * file position at the start of the file.
272 */
273 xlseek(fd, - xstate->signature_skipped, SEEK_CUR);
274 xstate->signature_skipped = 0;
283 fork_transformer_with_sig(xstate->src_fd, xstate->xformer, xstate->xformer_prog); 275 fork_transformer_with_sig(xstate->src_fd, xstate->xformer, xstate->xformer_prog);
284# endif 276# endif
285 free(xstate); 277 free(xstate);
@@ -322,14 +314,22 @@ int FAST_FUNC open_zipped(const char *fname, int fail_if_not_compressed)
322 return -1; 314 return -1;
323 315
324 fd = xstate->src_fd; 316 fd = xstate->src_fd;
325 if (xstate->xformer) {
326# if BB_MMU 317# if BB_MMU
327 fork_transformer_with_no_sig(xstate->src_fd, xstate->xformer); 318 if (xstate->xformer) {
319 fork_transformer_with_no_sig(fd, xstate->xformer);
320 } else {
321 /* the file is not compressed */
322 xlseek(fd, - xstate->signature_skipped, SEEK_CUR);
323 xstate->signature_skipped = 0;
324 }
328# else 325# else
329 fork_transformer_with_sig(xstate->src_fd, xstate->xformer, xstate->xformer_prog); 326 /* NOMMU can't avoid the seek :( */
327 xlseek(fd, - xstate->signature_skipped, SEEK_CUR);
328 xstate->signature_skipped = 0;
329 if (xstate->xformer) {
330 fork_transformer_with_sig(fd, xstate->xformer, xstate->xformer_prog);
331 } /* else: the file is not compressed */
330# endif 332# endif
331 }
332 /* else: the file is not compressed */
333 333
334 free(xstate); 334 free(xstate);
335 return fd; 335 return fd;
@@ -357,6 +357,9 @@ void* FAST_FUNC xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_
357 } 357 }
358 } else { 358 } else {
359 /* File is not compressed */ 359 /* File is not compressed */
360//FIXME: avoid seek
361 xlseek(xstate->src_fd, - xstate->signature_skipped, SEEK_CUR);
362 xstate->signature_skipped = 0;
360 image = xmalloc_read(xstate->src_fd, maxsz_p); 363 image = xmalloc_read(xstate->src_fd, maxsz_p);
361 } 364 }
362 365
diff --git a/archival/tar.c b/archival/tar.c
index c88957734..c87d23597 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -1009,7 +1009,6 @@ int tar_main(int argc UNUSED_PARAM, char **argv)
1009 /* Prepend '-' to the first argument if required */ 1009 /* Prepend '-' to the first argument if required */
1010 opt_complementary = "--:" // first arg is options 1010 opt_complementary = "--:" // first arg is options
1011 "tt:vv:" // count -t,-v 1011 "tt:vv:" // count -t,-v
1012 IF_FEATURE_TAR_FROM("X::T::") // cumulative lists
1013#if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM 1012#if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM
1014 "\xff::" // --exclude=PATTERN is a list 1013 "\xff::" // --exclude=PATTERN is a list
1015#endif 1014#endif
@@ -1061,13 +1060,13 @@ int tar_main(int argc UNUSED_PARAM, char **argv)
1061#endif 1060#endif
1062 opt = getopt32(argv, 1061 opt = getopt32(argv,
1063 "txC:f:Oopvk" 1062 "txC:f:Oopvk"
1064 IF_FEATURE_TAR_CREATE( "ch" ) 1063 IF_FEATURE_TAR_CREATE( "ch" )
1065 IF_FEATURE_SEAMLESS_BZ2( "j" ) 1064 IF_FEATURE_SEAMLESS_BZ2( "j" )
1066 IF_FEATURE_SEAMLESS_LZMA("a" ) 1065 IF_FEATURE_SEAMLESS_LZMA("a" )
1067 IF_FEATURE_TAR_FROM( "T:X:") 1066 IF_FEATURE_TAR_FROM( "T:*X:*")
1068 IF_FEATURE_SEAMLESS_GZ( "z" ) 1067 IF_FEATURE_SEAMLESS_GZ( "z" )
1069 IF_FEATURE_SEAMLESS_XZ( "J" ) 1068 IF_FEATURE_SEAMLESS_XZ( "J" )
1070 IF_FEATURE_SEAMLESS_Z( "Z" ) 1069 IF_FEATURE_SEAMLESS_Z( "Z" )
1071 IF_FEATURE_TAR_NOPRESERVE_TIME("m") 1070 IF_FEATURE_TAR_NOPRESERVE_TIME("m")
1072 IF_FEATURE_TAR_LONG_OPTIONS("\xf9:") // --strip-components 1071 IF_FEATURE_TAR_LONG_OPTIONS("\xf9:") // --strip-components
1073 , &base_dir // -C dir 1072 , &base_dir // -C dir
@@ -1228,9 +1227,10 @@ int tar_main(int argc UNUSED_PARAM, char **argv)
1228 // /* We need to know whether child (gzip/bzip/etc) exits abnormally */ 1227 // /* We need to know whether child (gzip/bzip/etc) exits abnormally */
1229 // signal(SIGCHLD, check_errors_in_children); 1228 // signal(SIGCHLD, check_errors_in_children);
1230 1229
1230#if ENABLE_FEATURE_TAR_CREATE
1231 /* Create an archive */ 1231 /* Create an archive */
1232 if (opt & OPT_CREATE) { 1232 if (opt & OPT_CREATE) {
1233#if SEAMLESS_COMPRESSION 1233# if SEAMLESS_COMPRESSION
1234 const char *zipMode = NULL; 1234 const char *zipMode = NULL;
1235 if (opt & OPT_COMPRESS) 1235 if (opt & OPT_COMPRESS)
1236 zipMode = "compress"; 1236 zipMode = "compress";
@@ -1242,7 +1242,7 @@ int tar_main(int argc UNUSED_PARAM, char **argv)
1242 zipMode = "lzma"; 1242 zipMode = "lzma";
1243 if (opt & OPT_XZ) 1243 if (opt & OPT_XZ)
1244 zipMode = "xz"; 1244 zipMode = "xz";
1245#endif 1245# endif
1246 /* NB: writeTarFile() closes tar_handle->src_fd */ 1246 /* NB: writeTarFile() closes tar_handle->src_fd */
1247 return writeTarFile(tar_handle->src_fd, verboseFlag, 1247 return writeTarFile(tar_handle->src_fd, verboseFlag,
1248 (opt & OPT_DEREFERENCE ? ACTION_FOLLOWLINKS : 0) 1248 (opt & OPT_DEREFERENCE ? ACTION_FOLLOWLINKS : 0)
@@ -1250,6 +1250,7 @@ int tar_main(int argc UNUSED_PARAM, char **argv)
1250 tar_handle->accept, 1250 tar_handle->accept,
1251 tar_handle->reject, zipMode); 1251 tar_handle->reject, zipMode);
1252 } 1252 }
1253#endif
1253 1254
1254 if (opt & OPT_ANY_COMPRESS) { 1255 if (opt & OPT_ANY_COMPRESS) {
1255 USE_FOR_MMU(IF_DESKTOP(long long) int FAST_FUNC (*xformer)(transformer_state_t *xstate);) 1256 USE_FOR_MMU(IF_DESKTOP(long long) int FAST_FUNC (*xformer)(transformer_state_t *xstate);)
diff --git a/configs/mingw32_defconfig b/configs/mingw32_defconfig
index 418529fbb..5b82c2855 100644
--- a/configs/mingw32_defconfig
+++ b/configs/mingw32_defconfig
@@ -1,7 +1,7 @@
1# 1#
2# Automatically generated make config: don't edit 2# Automatically generated make config: don't edit
3# Busybox version: 1.25.0.git 3# Busybox version: 1.26.0.git
4# Mon May 16 09:34:15 2016 4# Thu Jul 7 14:45:07 2016
5# 5#
6CONFIG_HAVE_DOT_CONFIG=y 6CONFIG_HAVE_DOT_CONFIG=y
7# CONFIG_PLATFORM_POSIX is not set 7# CONFIG_PLATFORM_POSIX is not set
@@ -25,6 +25,7 @@ CONFIG_FEATURE_BUFFERS_USE_MALLOC=y
25CONFIG_SHOW_USAGE=y 25CONFIG_SHOW_USAGE=y
26CONFIG_FEATURE_VERBOSE_USAGE=y 26CONFIG_FEATURE_VERBOSE_USAGE=y
27CONFIG_FEATURE_COMPRESS_USAGE=y 27CONFIG_FEATURE_COMPRESS_USAGE=y
28CONFIG_BUSYBOX=y
28CONFIG_FEATURE_INSTALLER=y 29CONFIG_FEATURE_INSTALLER=y
29# CONFIG_INSTALL_NO_USR is not set 30# CONFIG_INSTALL_NO_USR is not set
30# CONFIG_LOCALE_SUPPORT is not set 31# CONFIG_LOCALE_SUPPORT is not set
diff --git a/configs/mingw64_defconfig b/configs/mingw64_defconfig
index aab5463bc..6a89b5b1e 100644
--- a/configs/mingw64_defconfig
+++ b/configs/mingw64_defconfig
@@ -1,7 +1,7 @@
1# 1#
2# Automatically generated make config: don't edit 2# Automatically generated make config: don't edit
3# Busybox version: 1.25.0.git 3# Busybox version: 1.26.0.git
4# Mon May 16 09:34:15 2016 4# Thu Jul 7 14:45:07 2016
5# 5#
6CONFIG_HAVE_DOT_CONFIG=y 6CONFIG_HAVE_DOT_CONFIG=y
7# CONFIG_PLATFORM_POSIX is not set 7# CONFIG_PLATFORM_POSIX is not set
@@ -25,6 +25,7 @@ CONFIG_FEATURE_BUFFERS_USE_MALLOC=y
25CONFIG_SHOW_USAGE=y 25CONFIG_SHOW_USAGE=y
26CONFIG_FEATURE_VERBOSE_USAGE=y 26CONFIG_FEATURE_VERBOSE_USAGE=y
27CONFIG_FEATURE_COMPRESS_USAGE=y 27CONFIG_FEATURE_COMPRESS_USAGE=y
28CONFIG_BUSYBOX=y
28CONFIG_FEATURE_INSTALLER=y 29CONFIG_FEATURE_INSTALLER=y
29# CONFIG_INSTALL_NO_USR is not set 30# CONFIG_INSTALL_NO_USR is not set
30# CONFIG_LOCALE_SUPPORT is not set 31# CONFIG_LOCALE_SUPPORT is not set
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 @@
31//usage: "\n -f Overwrite" 31//usage: "\n -f Overwrite"
32//usage: "\n -i Prompt before overwrite" 32//usage: "\n -i Prompt before overwrite"
33//usage: "\n -l,-s Create (sym)links" 33//usage: "\n -l,-s Create (sym)links"
34//usage: "\n -u Copy only newer files"
34 35
35#include "libbb.h" 36#include "libbb.h"
36#include "libcoreutils/coreutils.h" 37#include "libcoreutils/coreutils.h"
@@ -49,12 +50,10 @@ int cp_main(int argc, char **argv)
49 int flags; 50 int flags;
50 int status; 51 int status;
51 enum { 52 enum {
52 OPT_a = 1 << (sizeof(FILEUTILS_CP_OPTSTR)-1), 53 FILEUTILS_CP_OPTNUM = sizeof(FILEUTILS_CP_OPTSTR)-1,
53 OPT_r = 1 << (sizeof(FILEUTILS_CP_OPTSTR)),
54 OPT_P = 1 << (sizeof(FILEUTILS_CP_OPTSTR)+1),
55 OPT_v = 1 << (sizeof(FILEUTILS_CP_OPTSTR)+2),
56#if ENABLE_FEATURE_CP_LONG_OPTIONS 54#if ENABLE_FEATURE_CP_LONG_OPTIONS
57 OPT_parents = 1 << (sizeof(FILEUTILS_CP_OPTSTR)+3), 55 /*OPT_rmdest = FILEUTILS_RMDEST = 1 << FILEUTILS_CP_OPTNUM */
56 OPT_parents = 1 << (FILEUTILS_CP_OPTNUM+1),
58#endif 57#endif
59 }; 58 };
60 59
@@ -76,10 +75,12 @@ int cp_main(int argc, char **argv)
76 "recursive\0" No_argument "R" 75 "recursive\0" No_argument "R"
77 "symbolic-link\0" No_argument "s" 76 "symbolic-link\0" No_argument "s"
78 "verbose\0" No_argument "v" 77 "verbose\0" No_argument "v"
79 "parents\0" No_argument "\xff" 78 "update\0" No_argument "u"
79 "remove-destination\0" No_argument "\xff"
80 "parents\0" No_argument "\xfe"
80 ; 81 ;
81#endif 82#endif
82 flags = getopt32(argv, FILEUTILS_CP_OPTSTR "arPv"); 83 flags = getopt32(argv, FILEUTILS_CP_OPTSTR);
83 /* Options of cp from GNU coreutils 6.10: 84 /* Options of cp from GNU coreutils 6.10:
84 * -a, --archive 85 * -a, --archive
85 * -f, --force 86 * -f, --force
@@ -94,6 +95,11 @@ int cp_main(int argc, char **argv)
94 * -d same as --no-dereference --preserve=links 95 * -d same as --no-dereference --preserve=links
95 * -p same as --preserve=mode,ownership,timestamps 96 * -p same as --preserve=mode,ownership,timestamps
96 * -c same as --preserve=context 97 * -c same as --preserve=context
98 * -u, --update
99 * copy only when the SOURCE file is newer than the destination
100 * file or when the destination file is missing
101 * --remove-destination
102 * remove each existing destination file before attempting to open
97 * --parents 103 * --parents
98 * use full source file name under DIRECTORY 104 * use full source file name under DIRECTORY
99 * NOT SUPPORTED IN BBOX: 105 * NOT SUPPORTED IN BBOX:
@@ -106,8 +112,6 @@ int cp_main(int argc, char **argv)
106 * preserve attributes (default: mode,ownership,timestamps), 112 * preserve attributes (default: mode,ownership,timestamps),
107 * if possible additional attributes: security context,links,all 113 * if possible additional attributes: security context,links,all
108 * --no-preserve=ATTR_LIST 114 * --no-preserve=ATTR_LIST
109 * --remove-destination
110 * remove each existing destination file before attempting to open
111 * --sparse=WHEN 115 * --sparse=WHEN
112 * control creation of sparse files 116 * control creation of sparse files
113 * --strip-trailing-slashes 117 * --strip-trailing-slashes
@@ -118,9 +122,6 @@ int cp_main(int argc, char **argv)
118 * copy all SOURCE arguments into DIRECTORY 122 * copy all SOURCE arguments into DIRECTORY
119 * -T, --no-target-directory 123 * -T, --no-target-directory
120 * treat DEST as a normal file 124 * treat DEST as a normal file
121 * -u, --update
122 * copy only when the SOURCE file is newer than the destination
123 * file or when the destination file is missing
124 * -x, --one-file-system 125 * -x, --one-file-system
125 * stay on this file system 126 * stay on this file system
126 * -Z, --context=CONTEXT 127 * -Z, --context=CONTEXT
@@ -156,11 +157,16 @@ int cp_main(int argc, char **argv)
156 return EXIT_FAILURE; 157 return EXIT_FAILURE;
157 158
158#if ENABLE_FEATURE_CP_LONG_OPTIONS 159#if ENABLE_FEATURE_CP_LONG_OPTIONS
160 //bb_error_msg("flags:%x FILEUTILS_RMDEST:%x OPT_parents:%x",
161 // flags, FILEUTILS_RMDEST, OPT_parents);
159 if (flags & OPT_parents) { 162 if (flags & OPT_parents) {
160 if (!(d_flags & 2)) { 163 if (!(d_flags & 2)) {
161 bb_error_msg_and_die("with --parents, the destination must be a directory"); 164 bb_error_msg_and_die("with --parents, the destination must be a directory");
162 } 165 }
163 } 166 }
167 if (flags & FILEUTILS_RMDEST) {
168 flags |= FILEUTILS_FORCE;
169 }
164#endif 170#endif
165 171
166 /* ...if neither is a directory... */ 172 /* ...if neither is a directory... */
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)
188 if (opt & OPT_INODE) { 188 if (opt & OPT_INODE) {
189 s.f_blocks = s.f_files; 189 s.f_blocks = s.f_files;
190 s.f_bavail = s.f_bfree = s.f_ffree; 190 s.f_bavail = s.f_bfree = s.f_ffree;
191 s.f_bsize = 1; 191 s.f_frsize = 1;
192 192
193 if (df_disp_hr) 193 if (df_disp_hr)
194 df_disp_hr = 1; 194 df_disp_hr = 1;
@@ -246,26 +246,26 @@ int df_main(int argc UNUSED_PARAM, char **argv)
246 246
247#if ENABLE_FEATURE_HUMAN_READABLE 247#if ENABLE_FEATURE_HUMAN_READABLE
248 printf(" %9s ", 248 printf(" %9s ",
249 /* f_blocks x f_bsize / df_disp_hr, show one fractional, 249 /* f_blocks x f_frsize / df_disp_hr, show one fractional,
250 * use suffixes if df_disp_hr == 0 */ 250 * use suffixes if df_disp_hr == 0 */
251 make_human_readable_str(s.f_blocks, s.f_bsize, df_disp_hr)); 251 make_human_readable_str(s.f_blocks, s.f_frsize, df_disp_hr));
252 252
253 printf(" %9s " + 1, 253 printf(" %9s " + 1,
254 /* EXPR x f_bsize / df_disp_hr, show one fractional, 254 /* EXPR x f_frsize / df_disp_hr, show one fractional,
255 * use suffixes if df_disp_hr == 0 */ 255 * use suffixes if df_disp_hr == 0 */
256 make_human_readable_str((s.f_blocks - s.f_bfree), 256 make_human_readable_str((s.f_blocks - s.f_bfree),
257 s.f_bsize, df_disp_hr)); 257 s.f_frsize, df_disp_hr));
258 258
259 printf("%9s %3u%% %s\n", 259 printf("%9s %3u%% %s\n",
260 /* f_bavail x f_bsize / df_disp_hr, show one fractional, 260 /* f_bavail x f_frsize / df_disp_hr, show one fractional,
261 * use suffixes if df_disp_hr == 0 */ 261 * use suffixes if df_disp_hr == 0 */
262 make_human_readable_str(s.f_bavail, s.f_bsize, df_disp_hr), 262 make_human_readable_str(s.f_bavail, s.f_frsize, df_disp_hr),
263 blocks_percent_used, mount_point); 263 blocks_percent_used, mount_point);
264#else 264#else
265 printf(" %9lu %9lu %9lu %3u%% %s\n", 265 printf(" %9lu %9lu %9lu %3u%% %s\n",
266 kscale(s.f_blocks, s.f_bsize), 266 kscale(s.f_blocks, s.f_frsize),
267 kscale(s.f_blocks - s.f_bfree, s.f_bsize), 267 kscale(s.f_blocks - s.f_bfree, s.f_frsize),
268 kscale(s.f_bavail, s.f_bsize), 268 kscale(s.f_bavail, s.f_frsize),
269 blocks_percent_used, mount_point); 269 blocks_percent_used, mount_point);
270#endif 270#endif
271 } 271 }
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)
226 * ignore -a. This is consistent with -s being equivalent to -d 0. 226 * ignore -a. This is consistent with -s being equivalent to -d 0.
227 */ 227 */
228#if ENABLE_FEATURE_HUMAN_READABLE 228#if ENABLE_FEATURE_HUMAN_READABLE
229 opt_complementary = "h-km:k-hm:m-hk:H-L:L-H:s-d:d-s:d+"; 229 opt_complementary = "h-km:k-hm:m-hk:H-L:L-H:s-d:d-s";
230 opt = getopt32(argv, "aHkLsx" "d:" "lc" "hm", &G.max_print_depth); 230 opt = getopt32(argv, "aHkLsx" "d:+" "lc" "hm", &G.max_print_depth);
231 argv += optind; 231 argv += optind;
232 if (opt & OPT_h_for_humans) { 232 if (opt & OPT_h_for_humans) {
233 G.disp_unit = 0; 233 G.disp_unit = 0;
@@ -239,8 +239,8 @@ int du_main(int argc UNUSED_PARAM, char **argv)
239 G.disp_unit = 1024; 239 G.disp_unit = 1024;
240 } 240 }
241#else 241#else
242 opt_complementary = "H-L:L-H:s-d:d-s:d+"; 242 opt_complementary = "H-L:L-H:s-d:d-s";
243 opt = getopt32(argv, "aHkLsx" "d:" "lc", &G.max_print_depth); 243 opt = getopt32(argv, "aHkLsx" "d:+" "lc", &G.max_print_depth);
244 argv += optind; 244 argv += optind;
245#if !ENABLE_FEATURE_DU_DEFAULT_BLOCKSIZE_1K 245#if !ENABLE_FEATURE_DU_DEFAULT_BLOCKSIZE_1K
246 if (opt & OPT_k_kbytes) { 246 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)
54 unsigned opts; 54 unsigned opts;
55 llist_t *unset_env = NULL; 55 llist_t *unset_env = NULL;
56 56
57 opt_complementary = "u::";
58#if ENABLE_FEATURE_ENV_LONG_OPTIONS 57#if ENABLE_FEATURE_ENV_LONG_OPTIONS
59 applet_long_options = env_longopts; 58 applet_long_options = env_longopts;
60#endif 59#endif
61 opts = getopt32(argv, "+iu:", &unset_env); 60 opts = getopt32(argv, "+iu:+", &unset_env);
62 argv += optind; 61 argv += optind;
63 if (argv[0] && LONE_DASH(argv[0])) { 62 if (argv[0] && LONE_DASH(argv[0])) {
64 opts |= 1; 63 opts |= 1;
diff --git a/coreutils/od_bloaty.c b/coreutils/od_bloaty.c
index a5b3e99f7..b02fb09bd 100644
--- a/coreutils/od_bloaty.c
+++ b/coreutils/od_bloaty.c
@@ -62,7 +62,7 @@ enum {
62}; 62};
63 63
64#define OD_GETOPT32() getopt32(argv, \ 64#define OD_GETOPT32() getopt32(argv, \
65 "A:N:abcdfhij:lot:vxsS:w::", \ 65 "A:N:abcdfhij:lot:*vxsS:w:+:", \
66 /* -w with optional param */ \ 66 /* -w with optional param */ \
67 /* -S was -s and also had optional parameter */ \ 67 /* -S was -s and also had optional parameter */ \
68 /* but in coreutils 6.3 it was renamed and now has */ \ 68 /* but in coreutils 6.3 it was renamed and now has */ \
@@ -1219,7 +1219,6 @@ int od_main(int argc UNUSED_PARAM, char **argv)
1219 address_pad_len_char = '7'; 1219 address_pad_len_char = '7';
1220 1220
1221 /* Parse command line */ 1221 /* Parse command line */
1222 opt_complementary = "w+:t::"; /* -w N, -t is a list */
1223#if ENABLE_LONG_OPTS 1222#if ENABLE_LONG_OPTS
1224 applet_long_options = od_longopts; 1223 applet_long_options = od_longopts;
1225#endif 1224#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 @@
73*/ 73*/
74 74
75/* These are sort types */ 75/* These are sort types */
76static const char OPT_STR[] ALIGN1 = "ngMucszbrdfimS:T:o:k:t:"; 76static const char OPT_STR[] ALIGN1 = "ngMucszbrdfimS:T:o:k:*t:";
77enum { 77enum {
78 FLAG_n = 1, /* Numeric sort */ 78 FLAG_n = 1, /* Numeric sort */
79 FLAG_g = 2, /* Sort using strtod() */ 79 FLAG_g = 2, /* Sort using strtod() */
@@ -358,8 +358,7 @@ int sort_main(int argc UNUSED_PARAM, char **argv)
358 358
359 /* Parse command line options */ 359 /* Parse command line options */
360 /* -o and -t can be given at most once */ 360 /* -o and -t can be given at most once */
361 opt_complementary = "o--o:t--t:" /* -t, -o: at most one of each */ 361 opt_complementary = "o--o:t--t"; /* -t, -o: at most one of each */
362 "k::"; /* -k takes list */
363 opts = getopt32(argv, OPT_STR, &str_ignored, &str_ignored, &str_o, &lst_k, &str_t); 362 opts = getopt32(argv, OPT_STR, &str_ignored, &str_ignored, &str_o, &lst_k, &str_t);
364 /* global b strips leading and trailing spaces */ 363 /* global b strips leading and trailing spaces */
365 if (opts & FLAG_b) 364 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)
81 81
82 setup_common_bufsiz(); 82 setup_common_bufsiz();
83 83
84 opt_complementary = "?2:a+"; /* max 2 args; -a N */ 84 opt_complementary = "?2"; /* max 2 args; -a N */
85 opt = getopt32(argv, "l:b:a:", &count_p, &count_p, &suffix_len); 85 opt = getopt32(argv, "l:b:a:+", &count_p, &count_p, &suffix_len);
86 86
87 if (opt & SPLIT_OPT_l) 87 if (opt & SPLIT_OPT_l)
88 cnt = XATOOFF(count_p); 88 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)
121#endif 121#endif
122 122
123 /* -s NUM, -F imlies -f */ 123 /* -s NUM, -F imlies -f */
124 IF_FEATURE_FANCY_TAIL(opt_complementary = "s+:Ff";) 124 IF_FEATURE_FANCY_TAIL(opt_complementary = "Ff";)
125 opt = getopt32(argv, "fc:n:" IF_FEATURE_FANCY_TAIL("qs:vF"), 125 opt = getopt32(argv, "fc:n:" IF_FEATURE_FANCY_TAIL("qs:+vF"),
126 &str_c, &str_n IF_FEATURE_FANCY_TAIL(,&sleep_period)); 126 &str_c, &str_n IF_FEATURE_FANCY_TAIL(,&sleep_period));
127#define FOLLOW (opt & 0x1) 127#define FOLLOW (opt & 0x1)
128#define COUNT_BYTES (opt & 0x2) 128#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)
50 skip_fields = skip_chars = 0; 50 skip_fields = skip_chars = 0;
51 max_chars = INT_MAX; 51 max_chars = INT_MAX;
52 52
53 opt_complementary = "f+:s+:w+"; 53 opt = getopt32(argv, "cduf:+s:+w:+", &skip_fields, &skip_chars, &max_chars);
54 opt = getopt32(argv, "cduf:s:w:", &skip_fields, &skip_chars, &max_chars);
55 argv += optind; 54 argv += optind;
56 55
57 input_filename = argv[0]; 56 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)
181 applet_long_options = runparts_longopts; 181 applet_long_options = runparts_longopts;
182#endif 182#endif
183 /* We require exactly one argument: the directory name */ 183 /* We require exactly one argument: the directory name */
184 opt_complementary = "=1:a::"; 184 opt_complementary = "=1";
185 getopt32(argv, "a:u:", &arg_list, &umask_p); 185 getopt32(argv, "a:*u:", &arg_list, &umask_p);
186 186
187 umask(xstrtou_range(umask_p, 8, 0, 07777)); 187 umask(xstrtou_range(umask_p, 8, 0, 07777));
188 188
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 @@
1=back
2
3=head1 LIBC NSS 1=head1 LIBC NSS
4 2
5GNU Libc (glibc) uses the Name Service Switch (NSS) to configure the behavior 3GNU Libc (glibc) uses the Name Service Switch (NSS) to configure the behavior
diff --git a/editors/awk.c b/editors/awk.c
index 142ab670f..de3362cff 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -72,12 +72,9 @@
72 72
73 73
74#define OPTSTR_AWK \ 74#define OPTSTR_AWK \
75 "F:v:f:" \ 75 "F:v:*f:*" \
76 IF_FEATURE_AWK_GNU_EXTENSIONS("e:") \ 76 IF_FEATURE_AWK_GNU_EXTENSIONS("e:*") \
77 "W:" 77 "W:"
78#define OPTCOMPLSTR_AWK \
79 "v::f::" \
80 IF_FEATURE_AWK_GNU_EXTENSIONS("e::")
81enum { 78enum {
82 OPTBIT_F, /* define field separator */ 79 OPTBIT_F, /* define field separator */
83 OPTBIT_v, /* define variable */ 80 OPTBIT_v, /* define variable */
@@ -3213,7 +3210,6 @@ int awk_main(int argc, char **argv)
3213 *s1 = '='; 3210 *s1 = '=';
3214 } 3211 }
3215 } 3212 }
3216 opt_complementary = OPTCOMPLSTR_AWK;
3217 opt = getopt32(argv, OPTSTR_AWK, &opt_F, &list_v, &list_f, IF_FEATURE_AWK_GNU_EXTENSIONS(&list_e,) NULL); 3213 opt = getopt32(argv, OPTSTR_AWK, &opt_F, &list_v, &list_f, IF_FEATURE_AWK_GNU_EXTENSIONS(&list_e,) NULL);
3218 argv += optind; 3214 argv += optind;
3219 argc -= optind; 3215 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)
982 INIT_G(); 982 INIT_G();
983 983
984 /* exactly 2 params; collect multiple -L <label>; -U N */ 984 /* exactly 2 params; collect multiple -L <label>; -U N */
985 opt_complementary = "=2:L::U+"; 985 opt_complementary = "=2";
986#if ENABLE_FEATURE_DIFF_LONG_OPTIONS 986#if ENABLE_FEATURE_DIFF_LONG_OPTIONS
987 applet_long_options = diff_longopts; 987 applet_long_options = diff_longopts;
988#endif 988#endif
989 getopt32(argv, "abdiL:NqrsS:tTU:wupBE", 989 getopt32(argv, "abdiL:*NqrsS:tTU:+wupBE",
990 &L_arg, &s_start, &opt_U_context); 990 &L_arg, &s_start, &opt_U_context);
991 argv += optind; 991 argv += optind;
992 while (L_arg) 992 while (L_arg)
diff --git a/editors/sed.c b/editors/sed.c
index b629e060a..2e99dc792 100644
--- a/editors/sed.c
+++ b/editors/sed.c
@@ -1508,8 +1508,7 @@ int sed_main(int argc UNUSED_PARAM, char **argv)
1508 /* do normal option parsing */ 1508 /* do normal option parsing */
1509 opt_e = opt_f = NULL; 1509 opt_e = opt_f = NULL;
1510 opt_i = NULL; 1510 opt_i = NULL;
1511 opt_complementary = "e::f::" /* can occur multiple times */ 1511 opt_complementary = "nn"; /* count -n */
1512 "nn"; /* count -n */
1513 1512
1514 IF_LONG_OPTS(applet_long_options = sed_longopts); 1513 IF_LONG_OPTS(applet_long_options = sed_longopts);
1515 1514
@@ -1518,7 +1517,7 @@ int sed_main(int argc UNUSED_PARAM, char **argv)
1518 * GNU sed 4.2.1 mentions it in neither --help 1517 * GNU sed 4.2.1 mentions it in neither --help
1519 * nor manpage, but does recognize it. 1518 * nor manpage, but does recognize it.
1520 */ 1519 */
1521 opt = getopt32(argv, "i::rEne:f:", &opt_i, &opt_e, &opt_f, 1520 opt = getopt32(argv, "i::rEne:*f:*", &opt_i, &opt_e, &opt_f,
1522 &G.be_quiet); /* counter for -n */ 1521 &G.be_quiet); /* counter for -n */
1523 //argc -= optind; 1522 //argc -= optind;
1524 argv += optind; 1523 argv += optind;
diff --git a/findutils/grep.c b/findutils/grep.c
index e956abbb8..02ce65159 100644
--- a/findutils/grep.c
+++ b/findutils/grep.c
@@ -115,8 +115,8 @@
115//usage:#define fgrep_full_usage "" 115//usage:#define fgrep_full_usage ""
116 116
117#define OPTSTR_GREP \ 117#define OPTSTR_GREP \
118 "lnqvscFiHhe:f:Lorm:wx" \ 118 "lnqvscFiHhe:*f:*Lorm:+wx" \
119 IF_FEATURE_GREP_CONTEXT("A:B:C:") \ 119 IF_FEATURE_GREP_CONTEXT("A:+B:+C:+") \
120 IF_FEATURE_GREP_EGREP_ALIAS("E") \ 120 IF_FEATURE_GREP_EGREP_ALIAS("E") \
121 IF_EXTRA_COMPAT("z") \ 121 IF_EXTRA_COMPAT("z") \
122 "aI" 122 "aI"
@@ -694,6 +694,7 @@ int grep_main(int argc UNUSED_PARAM, char **argv)
694#if ENABLE_FEATURE_GREP_CONTEXT 694#if ENABLE_FEATURE_GREP_CONTEXT
695 int Copt, opts; 695 int Copt, opts;
696#endif 696#endif
697 INIT_G();
697 698
698 /* For grep, exitcode of 1 is "not found". Other errors are 2: */ 699 /* For grep, exitcode of 1 is "not found". Other errors are 2: */
699 xfunc_error_retval = 2; 700 xfunc_error_retval = 2;
@@ -702,7 +703,7 @@ int grep_main(int argc UNUSED_PARAM, char **argv)
702#if ENABLE_FEATURE_GREP_CONTEXT 703#if ENABLE_FEATURE_GREP_CONTEXT
703 /* -H unsets -h; -C unsets -A,-B; -e,-f are lists; 704 /* -H unsets -h; -C unsets -A,-B; -e,-f are lists;
704 * -m,-A,-B,-C have numeric param */ 705 * -m,-A,-B,-C have numeric param */
705 opt_complementary = "H-h:C-AB:e::f::m+:A+:B+:C+"; 706 opt_complementary = "H-h:C-AB";
706 opts = getopt32(argv, 707 opts = getopt32(argv,
707 OPTSTR_GREP, 708 OPTSTR_GREP,
708 &pattern_head, &fopt, &max_matches, 709 &pattern_head, &fopt, &max_matches,
@@ -731,7 +732,7 @@ int grep_main(int argc UNUSED_PARAM, char **argv)
731#else 732#else
732 /* with auto sanity checks */ 733 /* with auto sanity checks */
733 /* -H unsets -h; -c,-q or -l unset -n; -e,-f are lists; -m N */ 734 /* -H unsets -h; -c,-q or -l unset -n; -e,-f are lists; -m N */
734 opt_complementary = "H-h:c-n:q-n:l-n:e::f::m+"; 735 opt_complementary = "H-h:c-n:q-n:l-n:";
735 getopt32(argv, OPTSTR_GREP, 736 getopt32(argv, OPTSTR_GREP,
736 &pattern_head, &fopt, &max_matches); 737 &pattern_head, &fopt, &max_matches);
737#endif 738#endif
diff --git a/include/bb_archive.h b/include/bb_archive.h
index 03f174839..9bbf59bb8 100644
--- a/include/bb_archive.h
+++ b/include/bb_archive.h
@@ -221,7 +221,7 @@ void dealloc_bunzip(bunzip_data *bd) FAST_FUNC;
221 221
222/* Meaning and direction (input/output) of the fields are transformer-specific */ 222/* Meaning and direction (input/output) of the fields are transformer-specific */
223typedef struct transformer_state_t { 223typedef struct transformer_state_t {
224 smallint check_signature; /* most often referenced member */ 224 smallint signature_skipped; /* most often referenced member */
225 225
226 IF_DESKTOP(long long) int FAST_FUNC (*xformer)(struct transformer_state_t *xstate); 226 IF_DESKTOP(long long) int FAST_FUNC (*xformer)(struct transformer_state_t *xstate);
227 USE_FOR_NOMMU(const char *xformer_prog;) 227 USE_FOR_NOMMU(const char *xformer_prog;)
@@ -262,11 +262,11 @@ int bbunpack(char **argv,
262void check_errors_in_children(int signo); 262void check_errors_in_children(int signo);
263#if BB_MMU 263#if BB_MMU
264void fork_transformer(int fd, 264void fork_transformer(int fd,
265 int check_signature, 265 int signature_skipped,
266 IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate) 266 IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate)
267) FAST_FUNC; 267) FAST_FUNC;
268#define fork_transformer_with_sig(fd, transformer, transform_prog) fork_transformer((fd), 1, (transformer)) 268#define fork_transformer_with_sig(fd, transformer, transform_prog) fork_transformer((fd), 0, (transformer))
269#define fork_transformer_with_no_sig(fd, transformer) fork_transformer((fd), 0, (transformer)) 269#define fork_transformer_with_no_sig(fd, transformer) fork_transformer((fd), 1, (transformer))
270#else 270#else
271void fork_transformer(int fd, const char *transform_prog) FAST_FUNC; 271void fork_transformer(int fd, const char *transform_prog) FAST_FUNC;
272#define fork_transformer_with_sig(fd, transformer, transform_prog) fork_transformer((fd), (transform_prog)) 272#define fork_transformer_with_sig(fd, transformer, transform_prog) fork_transformer((fd), (transform_prog))
diff --git a/include/libbb.h b/include/libbb.h
index 9402bb04b..6db03d2df 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -362,7 +362,7 @@ extern char *strrstr(const char *haystack, const char *needle) FAST_FUNC;
362//TODO: supply a pointer to char[11] buffer (avoid statics)? 362//TODO: supply a pointer to char[11] buffer (avoid statics)?
363extern const char *bb_mode_string(mode_t mode) FAST_FUNC; 363extern const char *bb_mode_string(mode_t mode) FAST_FUNC;
364extern int is_directory(const char *name, int followLinks) FAST_FUNC; 364extern int is_directory(const char *name, int followLinks) FAST_FUNC;
365enum { /* DO NOT CHANGE THESE VALUES! cp.c, mv.c, install.c depend on them. */ 365enum { /* cp.c, mv.c, install.c depend on these values. CAREFUL when changing them! */
366 FILEUTILS_PRESERVE_STATUS = 1 << 0, /* -p */ 366 FILEUTILS_PRESERVE_STATUS = 1 << 0, /* -p */
367 FILEUTILS_DEREFERENCE = 1 << 1, /* !-d */ 367 FILEUTILS_DEREFERENCE = 1 << 1, /* !-d */
368 FILEUTILS_RECUR = 1 << 2, /* -R */ 368 FILEUTILS_RECUR = 1 << 2, /* -R */
@@ -372,15 +372,25 @@ enum { /* DO NOT CHANGE THESE VALUES! cp.c, mv.c, install.c depend on them. */
372 FILEUTILS_MAKE_SOFTLINK = 1 << 6, /* -s */ 372 FILEUTILS_MAKE_SOFTLINK = 1 << 6, /* -s */
373 FILEUTILS_DEREF_SOFTLINK = 1 << 7, /* -L */ 373 FILEUTILS_DEREF_SOFTLINK = 1 << 7, /* -L */
374 FILEUTILS_DEREFERENCE_L0 = 1 << 8, /* -H */ 374 FILEUTILS_DEREFERENCE_L0 = 1 << 8, /* -H */
375 /* -a = -pdR (mapped in cp.c) */
376 /* -r = -dR (mapped in cp.c) */
377 /* -P = -d (mapped in cp.c) */
378 FILEUTILS_VERBOSE = (1 << 12) * ENABLE_FEATURE_VERBOSE, /* -v */
379 FILEUTILS_UPDATE = 1 << 13, /* -u */
375#if ENABLE_SELINUX 380#if ENABLE_SELINUX
376 FILEUTILS_PRESERVE_SECURITY_CONTEXT = 1 << 9, /* -c */ 381 FILEUTILS_PRESERVE_SECURITY_CONTEXT = 1 << 14, /* -c */
377 FILEUTILS_SET_SECURITY_CONTEXT = 1 << 10,
378#endif 382#endif
379 FILEUTILS_IGNORE_CHMOD_ERR = 1 << 11, 383 FILEUTILS_RMDEST = 1 << (15 - !ENABLE_SELINUX), /* --remove-destination */
380 /* -v */ 384 /*
381 FILEUTILS_VERBOSE = (1 << 12) * ENABLE_FEATURE_VERBOSE, 385 * Hole. cp may have some bits set here,
386 * they should not affect remove_file()/copy_file()
387 */
388#if ENABLE_SELINUX
389 FILEUTILS_SET_SECURITY_CONTEXT = 1 << 30,
390#endif
391 FILEUTILS_IGNORE_CHMOD_ERR = 1 << 31,
382}; 392};
383#define FILEUTILS_CP_OPTSTR "pdRfilsLH" IF_SELINUX("c") 393#define FILEUTILS_CP_OPTSTR "pdRfilsLHarPvu" IF_SELINUX("c")
384extern int remove_file(const char *path, int flags) FAST_FUNC; 394extern int remove_file(const char *path, int flags) FAST_FUNC;
385/* NB: without FILEUTILS_RECUR in flags, it will basically "cat" 395/* NB: without FILEUTILS_RECUR in flags, it will basically "cat"
386 * the source, not copy (unless "source" is a directory). 396 * the source, not copy (unless "source" is a directory).
@@ -1248,8 +1258,6 @@ const struct hwtype *get_hwntype(int type) FAST_FUNC;
1248 1258
1249#ifndef BUILD_INDIVIDUAL 1259#ifndef BUILD_INDIVIDUAL
1250extern int find_applet_by_name(const char *name) FAST_FUNC; 1260extern int find_applet_by_name(const char *name) FAST_FUNC;
1251/* Returns only if applet is not found. */
1252extern void run_applet_and_exit(const char *name, char **argv) FAST_FUNC;
1253extern void run_applet_no_and_exit(int a, char **argv) NORETURN FAST_FUNC; 1261extern void run_applet_no_and_exit(int a, char **argv) NORETURN FAST_FUNC;
1254#endif 1262#endif
1255 1263
diff --git a/init/halt.c b/init/halt.c
index 572d751b0..29e60657b 100644
--- a/init/halt.c
+++ b/init/halt.c
@@ -113,12 +113,11 @@ int halt_main(int argc UNUSED_PARAM, char **argv)
113 continue; 113 continue;
114 114
115 /* Parse and handle arguments */ 115 /* Parse and handle arguments */
116 opt_complementary = "d+"; /* -d N */
117 /* We support -w even if !ENABLE_FEATURE_WTMP, 116 /* We support -w even if !ENABLE_FEATURE_WTMP,
118 * in order to not break scripts. 117 * in order to not break scripts.
119 * -i (shut down network interfaces) is ignored. 118 * -i (shut down network interfaces) is ignored.
120 */ 119 */
121 flags = getopt32(argv, "d:nfwi", &delay); 120 flags = getopt32(argv, "d:+nfwi", &delay);
122 121
123 sleep(delay); 122 sleep(delay);
124 123
diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src
index 0e14e351e..39d9d907d 100644
--- a/libbb/Kbuild.src
+++ b/libbb/Kbuild.src
@@ -148,6 +148,7 @@ lib-$(CONFIG_FTPD) += correct_password.o
148lib-$(CONFIG_PASSWD) += pw_encrypt.o update_passwd.o obscure.o 148lib-$(CONFIG_PASSWD) += pw_encrypt.o update_passwd.o obscure.o
149lib-$(CONFIG_CHPASSWD) += pw_encrypt.o update_passwd.o 149lib-$(CONFIG_CHPASSWD) += pw_encrypt.o update_passwd.o
150lib-$(CONFIG_CRYPTPW) += pw_encrypt.o 150lib-$(CONFIG_CRYPTPW) += pw_encrypt.o
151lib-$(CONFIG_MKPASSWD) += pw_encrypt.o
151lib-$(CONFIG_SULOGIN) += pw_encrypt.o correct_password.o 152lib-$(CONFIG_SULOGIN) += pw_encrypt.o correct_password.o
152lib-$(CONFIG_VLOCK) += pw_encrypt.o correct_password.o 153lib-$(CONFIG_VLOCK) += pw_encrypt.o correct_password.o
153lib-$(CONFIG_SU) += pw_encrypt.o correct_password.o 154lib-$(CONFIG_SU) += pw_encrypt.o correct_password.o
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index c528c8a2c..28adf2740 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -52,7 +52,6 @@
52 52
53#include "usage_compressed.h" 53#include "usage_compressed.h"
54 54
55
56#if ENABLE_SHOW_USAGE && !ENABLE_FEATURE_COMPRESS_USAGE 55#if ENABLE_SHOW_USAGE && !ENABLE_FEATURE_COMPRESS_USAGE
57static const char usage_messages[] ALIGN1 = UNPACKED_USAGE; 56static const char usage_messages[] ALIGN1 = UNPACKED_USAGE;
58#else 57#else
@@ -730,7 +729,7 @@ static void install_links(const char *busybox,
730 } 729 }
731} 730}
732# endif 731# endif
733# else 732# elif ENABLE_BUSYBOX
734static void install_links(const char *busybox UNUSED_PARAM, 733static void install_links(const char *busybox UNUSED_PARAM,
735 int use_symbolic_links UNUSED_PARAM, 734 int use_symbolic_links UNUSED_PARAM,
736 char *custom_install_dir UNUSED_PARAM) 735 char *custom_install_dir UNUSED_PARAM)
@@ -738,6 +737,9 @@ static void install_links(const char *busybox UNUSED_PARAM,
738} 737}
739# endif 738# endif
740 739
740# if ENABLE_BUSYBOX
741static void run_applet_and_exit(const char *name, char **argv) NORETURN;
742
741/* If we were called as "busybox..." */ 743/* If we were called as "busybox..." */
742static int busybox_main(char **argv) 744static int busybox_main(char **argv)
743{ 745{
@@ -828,10 +830,10 @@ static int busybox_main(char **argv)
828 const char *a = applet_names; 830 const char *a = applet_names;
829 dup2(1, 2); 831 dup2(1, 2);
830 while (*a) { 832 while (*a) {
831# if ENABLE_FEATURE_INSTALLER && !ENABLE_PLATFORM_MINGW32 833# if ENABLE_FEATURE_INSTALLER && !ENABLE_PLATFORM_MINGW32
832 if (argv[1][6]) /* --list-full? */ 834 if (argv[1][6]) /* --list-full? */
833 full_write2_str(install_dir[APPLET_INSTALL_LOC(i)] + 1); 835 full_write2_str(install_dir[APPLET_INSTALL_LOC(i)] + 1);
834# endif 836# endif
835 full_write2_str(a); 837 full_write2_str(a);
836 full_write2_str("\n"); 838 full_write2_str("\n");
837 i++; 839 i++;
@@ -889,14 +891,10 @@ static int busybox_main(char **argv)
889 * "#!/bin/busybox"-style wrappers */ 891 * "#!/bin/busybox"-style wrappers */
890 applet_name = bb_get_last_path_component_nostrip(argv[0]); 892 applet_name = bb_get_last_path_component_nostrip(argv[0]);
891 run_applet_and_exit(applet_name, argv); 893 run_applet_and_exit(applet_name, argv);
892
893 /*bb_error_msg_and_die("applet not found"); - sucks in printf */
894 full_write2_str(applet_name);
895 full_write2_str(": applet not found\n");
896 /* POSIX: "If a command is not found, the exit status shall be 127" */
897 exit(127);
898} 894}
895# endif
899 896
897# if NUM_APPLETS > 0
900void FAST_FUNC run_applet_no_and_exit(int applet_no, char **argv) 898void FAST_FUNC run_applet_no_and_exit(int applet_no, char **argv)
901{ 899{
902 int argc = 1; 900 int argc = 1;
@@ -914,15 +912,15 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, char **argv)
914 * "true" and "false" are also special. 912 * "true" and "false" are also special.
915 */ 913 */
916 if (1 914 if (1
917#if defined APPLET_NO_test 915# if defined APPLET_NO_test
918 && applet_no != APPLET_NO_test 916 && applet_no != APPLET_NO_test
919#endif 917# endif
920#if defined APPLET_NO_true 918# if defined APPLET_NO_true
921 && applet_no != APPLET_NO_true 919 && applet_no != APPLET_NO_true
922#endif 920# endif
923#if defined APPLET_NO_false 921# if defined APPLET_NO_false
924 && applet_no != APPLET_NO_false 922 && applet_no != APPLET_NO_false
925#endif 923# endif
926 ) { 924 ) {
927 if (argc == 2 && strcmp(argv[1], "--help") == 0) { 925 if (argc == 2 && strcmp(argv[1], "--help") == 0) {
928 /* Make "foo --help" exit with 0: */ 926 /* Make "foo --help" exit with 0: */
@@ -934,17 +932,28 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, char **argv)
934 check_suid(applet_no); 932 check_suid(applet_no);
935 exit(applet_main[applet_no](argc, argv)); 933 exit(applet_main[applet_no](argc, argv));
936} 934}
935# endif /* NUM_APPLETS > 0 */
937 936
938void FAST_FUNC run_applet_and_exit(const char *name, char **argv) 937static NORETURN void run_applet_and_exit(const char *name, char **argv)
939{ 938{
940 int applet; 939# if ENABLE_BUSYBOX
941
942 if (is_prefixed_with(name, "busybox")) 940 if (is_prefixed_with(name, "busybox"))
943 exit(busybox_main(argv)); 941 exit(busybox_main(argv));
942# endif
943# if NUM_APPLETS > 0
944 /* find_applet_by_name() search is more expensive, so goes second */ 944 /* find_applet_by_name() search is more expensive, so goes second */
945 applet = find_applet_by_name(name); 945 {
946 if (applet >= 0) 946 int applet = find_applet_by_name(name);
947 run_applet_no_and_exit(applet, argv); 947 if (applet >= 0)
948 run_applet_no_and_exit(applet, argv);
949 }
950# endif
951
952 /*bb_error_msg_and_die("applet not found"); - links in printf */
953 full_write2_str(applet_name);
954 full_write2_str(": applet not found\n");
955 /* POSIX: "If a command is not found, the exit status shall be 127" */
956 exit(127);
948} 957}
949 958
950#endif /* !defined(SINGLE_APPLET_MAIN) */ 959#endif /* !defined(SINGLE_APPLET_MAIN) */
@@ -1017,6 +1026,10 @@ int main(int argc UNUSED_PARAM, char **argv)
1017#else 1026#else
1018 lbb_prepare("busybox" IF_FEATURE_INDIVIDUAL(, argv)); 1027 lbb_prepare("busybox" IF_FEATURE_INDIVIDUAL(, argv));
1019 1028
1029# if !ENABLE_BUSYBOX
1030 if (argv[1] && is_prefixed_with(bb_basename(argv[0]), "busybox"))
1031 argv++;
1032# endif
1020 applet_name = argv[0]; 1033 applet_name = argv[0];
1021 if (applet_name[0] == '-') 1034 if (applet_name[0] == '-')
1022 applet_name++; 1035 applet_name++;
@@ -1048,11 +1061,5 @@ int main(int argc UNUSED_PARAM, char **argv)
1048 parse_config_file(); /* ...maybe, if FEATURE_SUID_CONFIG */ 1061 parse_config_file(); /* ...maybe, if FEATURE_SUID_CONFIG */
1049 1062
1050 run_applet_and_exit(applet_name, argv); 1063 run_applet_and_exit(applet_name, argv);
1051
1052 /*bb_error_msg_and_die("applet not found"); - sucks in printf */
1053 full_write2_str(applet_name);
1054 full_write2_str(": applet not found\n");
1055 /* POSIX: "If a command is not found, the exit status shall be 127" */
1056 exit(127);
1057#endif 1064#endif
1058} 1065}
diff --git a/libbb/copy_file.c b/libbb/copy_file.c
index a427c441f..c52297376 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)
64 bb_perror_msg("can't create '%s'", dest); 64 bb_perror_msg("can't create '%s'", dest);
65 return -1; /* error */ 65 return -1; /* error */
66 } 66 }
67#if ENABLE_FEATURE_CP_LONG_OPTIONS
68 if (flags & FILEUTILS_RMDEST)
69 if (flags & FILEUTILS_VERBOSE)
70 printf("removed '%s'\n", dest);
71#endif
67 return 1; /* ok (to try again) */ 72 return 1; /* ok (to try again) */
68} 73}
69 74
@@ -213,6 +218,22 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags)
213 goto preserve_mode_ugid_time; 218 goto preserve_mode_ugid_time;
214 } 219 }
215 220
221 if (dest_exists) {
222 if (flags & FILEUTILS_UPDATE) {
223 if (source_stat.st_mtime <= dest_stat.st_mtime) {
224 return 0; /* source file must be newer */
225 }
226 }
227#if ENABLE_FEATURE_CP_LONG_OPTIONS
228 if (flags & FILEUTILS_RMDEST) {
229 ovr = ask_and_unlink(dest, flags);
230 if (ovr <= 0)
231 return ovr;
232 dest_exists = 0;
233 }
234#endif
235 }
236
216 if (flags & (FILEUTILS_MAKE_SOFTLINK|FILEUTILS_MAKE_HARDLINK)) { 237 if (flags & (FILEUTILS_MAKE_SOFTLINK|FILEUTILS_MAKE_HARDLINK)) {
217 int (*lf)(const char *oldpath, const char *newpath); 238 int (*lf)(const char *oldpath, const char *newpath);
218 make_links: 239 make_links:
diff --git a/libbb/getopt32.c b/libbb/getopt32.c
index ae019b26b..ed9352191 100644
--- a/libbb/getopt32.c
+++ b/libbb/getopt32.c
@@ -17,23 +17,20 @@
17uint32_t 17uint32_t
18getopt32(char **argv, const char *applet_opts, ...) 18getopt32(char **argv, const char *applet_opts, ...)
19 19
20 The command line options must be declared in const char 20 The command line options are passed as the applet_opts string.
21 *applet_opts as a string of chars, for example:
22
23 flags = getopt32(argv, "rnug");
24 21
25 If one of the given options is found, a flag value is added to 22 If one of the given options is found, a flag value is added to
26 the return value (an unsigned long). 23 the return value.
27 24
28 The flag value is determined by the position of the char in 25 The flag value is determined by the position of the char in
29 applet_opts string. For example, in the above case: 26 applet_opts string. For example:
30 27
31 flags = getopt32(argv, "rnug"); 28 flags = getopt32(argv, "rnug");
32 29
33 "r" will add 1 (bit 0) 30 "r" will set 1 (bit 0)
34 "n" will add 2 (bit 1) 31 "n" will set 2 (bit 1)
35 "u" will add 4 (bit 2) 32 "u" will set 4 (bit 2)
36 "g" will add 8 (bit 3) 33 "g" will set 8 (bit 3)
37 34
38 and so on. You can also look at the return value as a bit 35 and so on. You can also look at the return value as a bit
39 field and each option sets one bit. 36 field and each option sets one bit.
@@ -45,7 +42,7 @@ getopt32(char **argv, const char *applet_opts, ...)
45 (options and their parameters will be moved into argv[] 42 (options and their parameters will be moved into argv[]
46 positions prior to argv[optind]). 43 positions prior to argv[optind]).
47 44
48 ":" If one of the options requires an argument, then add a ":" 45 "o:" If one of the options requires an argument, then add a ":"
49 after the char in applet_opts and provide a pointer to store 46 after the char in applet_opts and provide a pointer to store
50 the argument. For example: 47 the argument. For example:
51 48
@@ -58,15 +55,39 @@ getopt32(char **argv, const char *applet_opts, ...)
58 &pointer_to_arg_for_a, &pointer_to_arg_for_b, 55 &pointer_to_arg_for_a, &pointer_to_arg_for_b,
59 &pointer_to_arg_for_c, &pointer_to_arg_for_d); 56 &pointer_to_arg_for_c, &pointer_to_arg_for_d);
60 57
61 The type of the pointer (char* or llist_t*) may be controlled 58 The type of the pointer may be controlled by "o::" or "o+" in
62 by the "::" special separator that is set in the external string 59 the external string opt_complementary (see below for more info).
63 opt_complementary (see below for more info).
64 60
65 "::" If option can have an *optional* argument, then add a "::" 61 "o::" If option can have an *optional* argument, then add a "::"
66 after its char in applet_opts and provide a pointer to store 62 after its char in applet_opts and provide a pointer to store
67 the argument. Note that optional arguments _must_ 63 the argument. Note that optional arguments _must_
68 immediately follow the option: -oparam, not -o param. 64 immediately follow the option: -oparam, not -o param.
69 65
66 "o:+" This means that the parameter for this option is a nonnegative integer.
67 It will be processed with xatoi_positive() - allowed range
68 is 0..INT_MAX.
69
70 int param; // "unsigned param;" will also work
71 getopt32(argv, "p:+", &param);
72
73 "o:*" This means that the option can occur multiple times. Each occurrence
74 will be saved as a llist_t element instead of char*.
75
76 For example:
77 The grep applet can have one or more "-e pattern" arguments.
78 In this case you should use getopt32() as follows:
79
80 llist_t *patterns = NULL;
81
82 (this pointer must be initializated to NULL if the list is empty
83 as required by llist_add_to_end(llist_t **old_head, char *new_item).)
84
85 getopt32(argv, "e:*", &patterns);
86
87 $ grep -e user -e root /etc/passwd
88 root:x:0:0:root:/root:/bin/bash
89 user:x:500:500::/home/user:/bin/bash
90
70 "+" If the first character in the applet_opts string is a plus, 91 "+" If the first character in the applet_opts string is a plus,
71 then option processing will stop as soon as a non-option is 92 then option processing will stop as soon as a non-option is
72 encountered in the argv array. Useful for applets like env 93 encountered in the argv array. Useful for applets like env
@@ -82,7 +103,7 @@ const char *applet_long_options
82 This struct allows you to define long options: 103 This struct allows you to define long options:
83 104
84 static const char applet_longopts[] ALIGN1 = 105 static const char applet_longopts[] ALIGN1 =
85 //"name\0" has_arg val 106 //"name\0" has_arg val
86 "verbose\0" No_argument "v" 107 "verbose\0" No_argument "v"
87 ; 108 ;
88 applet_long_options = applet_longopts; 109 applet_long_options = applet_longopts;
@@ -90,7 +111,7 @@ const char *applet_long_options
90 The last member of struct option (val) typically is set to 111 The last member of struct option (val) typically is set to
91 matching short option from applet_opts. If there is no matching 112 matching short option from applet_opts. If there is no matching
92 char in applet_opts, then: 113 char in applet_opts, then:
93 - return bit have next position after short options 114 - return bit has next position after short options
94 - if has_arg is not "No_argument", use ptr for arg also 115 - if has_arg is not "No_argument", use ptr for arg also
95 - opt_complementary affects it too 116 - opt_complementary affects it too
96 117
@@ -139,8 +160,8 @@ const char *opt_complementary
139 160
140 llist_t *my_b = NULL; 161 llist_t *my_b = NULL;
141 int verbose_level = 0; 162 int verbose_level = 0;
142 opt_complementary = "vv:b::b-c:c-b"; 163 opt_complementary = "vv:b-c:c-b";
143 f = getopt32(argv, "vb:c", &my_b, &verbose_level); 164 f = getopt32(argv, "vb:*c", &my_b, &verbose_level);
144 if (f & 2) // -c after -b unsets -b flag 165 if (f & 2) // -c after -b unsets -b flag
145 while (my_b) dosomething_with(llist_pop(&my_b)); 166 while (my_b) dosomething_with(llist_pop(&my_b));
146 if (my_b) // but llist is stored if -b is specified 167 if (my_b) // but llist is stored if -b is specified
@@ -233,7 +254,7 @@ Special characters:
233 "x--x" Variation of the above, it means that -x option should occur 254 "x--x" Variation of the above, it means that -x option should occur
234 at most once. 255 at most once.
235 256
236 "a+" A plus after a char in opt_complementary means that the parameter 257 "o+" A plus after a char in opt_complementary means that the parameter
237 for this option is a nonnegative integer. It will be processed 258 for this option is a nonnegative integer. It will be processed
238 with xatoi_positive() - allowed range is 0..INT_MAX. 259 with xatoi_positive() - allowed range is 0..INT_MAX.
239 260
@@ -241,7 +262,7 @@ Special characters:
241 opt_complementary = "p+"; 262 opt_complementary = "p+";
242 getopt32(argv, "p:", &param); 263 getopt32(argv, "p:", &param);
243 264
244 "a::" A double colon after a char in opt_complementary means that the 265 "o::" A double colon after a char in opt_complementary means that the
245 option can occur multiple times. Each occurrence will be saved as 266 option can occur multiple times. Each occurrence will be saved as
246 a llist_t element instead of char*. 267 a llist_t element instead of char*.
247 268
@@ -255,12 +276,17 @@ Special characters:
255 as required by llist_add_to_end(llist_t **old_head, char *new_item).) 276 as required by llist_add_to_end(llist_t **old_head, char *new_item).)
256 277
257 opt_complementary = "e::"; 278 opt_complementary = "e::";
258
259 getopt32(argv, "e:", &patterns); 279 getopt32(argv, "e:", &patterns);
280
260 $ grep -e user -e root /etc/passwd 281 $ grep -e user -e root /etc/passwd
261 root:x:0:0:root:/root:/bin/bash 282 root:x:0:0:root:/root:/bin/bash
262 user:x:500:500::/home/user:/bin/bash 283 user:x:500:500::/home/user:/bin/bash
263 284
285 "o+" and "o::" can be handled by "o:+" and "o:*" specifiers
286 in option string (and it is preferred), but this does not work
287 for "long options only" cases, such as tar --exclude=PATTERN,
288 wget --header=HDR cases.
289
264 "a?b" A "?" between an option and a group of options means that 290 "a?b" A "?" between an option and a group of options means that
265 at least one of them is required to occur if the first option 291 at least one of them is required to occur if the first option
266 occurs in preceding command line arguments. 292 occurs in preceding command line arguments.
@@ -359,10 +385,11 @@ getopt32(char **argv, const char *applet_opts, ...)
359 385
360 va_start(p, applet_opts); 386 va_start(p, applet_opts);
361 387
362 c = 0;
363 on_off = complementary; 388 on_off = complementary;
364 memset(on_off, 0, sizeof(complementary)); 389 memset(on_off, 0, sizeof(complementary));
365 390
391 applet_opts = strcpy(alloca(strlen(applet_opts) + 1), applet_opts);
392
366 /* skip bbox extension */ 393 /* skip bbox extension */
367 first_char = applet_opts[0]; 394 first_char = applet_opts[0];
368 if (first_char == '!') 395 if (first_char == '!')
@@ -372,6 +399,7 @@ getopt32(char **argv, const char *applet_opts, ...)
372 s = (const unsigned char *)applet_opts; 399 s = (const unsigned char *)applet_opts;
373 if (*s == '+' || *s == '-') 400 if (*s == '+' || *s == '-')
374 s++; 401 s++;
402 c = 0;
375 while (*s) { 403 while (*s) {
376 if (c >= 32) 404 if (c >= 32)
377 break; 405 break;
@@ -379,6 +407,13 @@ getopt32(char **argv, const char *applet_opts, ...)
379 on_off->switch_on = (1 << c); 407 on_off->switch_on = (1 << c);
380 if (*++s == ':') { 408 if (*++s == ':') {
381 on_off->optarg = va_arg(p, void **); 409 on_off->optarg = va_arg(p, void **);
410 if (s[1] == '+' || s[1] == '*') {
411 /* 'o:+' or 'o:*' */
412 on_off->param_type = (s[1] == '+') ?
413 PARAM_INT : PARAM_LIST;
414 overlapping_strcpy((char*)s + 1, (char*)s + 2);
415 }
416 /* skip possible 'o::' (or 'o:+:' !) */
382 while (*++s == ':') 417 while (*++s == ':')
383 continue; 418 continue;
384 } 419 }
@@ -431,6 +466,7 @@ getopt32(char **argv, const char *applet_opts, ...)
431 applet_long_options = NULL; 466 applet_long_options = NULL;
432 } 467 }
433#endif /* ENABLE_LONG_OPTS || ENABLE_FEATURE_GETOPT_LONG */ 468#endif /* ENABLE_LONG_OPTS || ENABLE_FEATURE_GETOPT_LONG */
469
434 for (s = (const unsigned char *)opt_complementary; s && *s; s++) { 470 for (s = (const unsigned char *)opt_complementary; s && *s; s++) {
435 t_complementary *pair; 471 t_complementary *pair;
436 unsigned *pair_switch; 472 unsigned *pair_switch;
diff --git a/libbb/parse_config.c b/libbb/parse_config.c
index 1590d9a4c..408439766 100644
--- a/libbb/parse_config.c
+++ b/libbb/parse_config.c
@@ -42,8 +42,8 @@ int parse_main(int argc UNUSED_PARAM, char **argv)
42 int mintokens = 0, ntokens = 128; 42 int mintokens = 0, ntokens = 128;
43 unsigned noout; 43 unsigned noout;
44 44
45 opt_complementary = "-1:n+:m+:f+"; 45 opt_complementary = "-1";
46 noout = 1 & getopt32(argv, "xn:m:d:f:", &ntokens, &mintokens, &delims, &flags); 46 noout = 1 & getopt32(argv, "xn:+m:+d:f:+", &ntokens, &mintokens, &delims, &flags);
47 //argc -= optind; 47 //argc -= optind;
48 argv += optind; 48 argv += optind;
49 49
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)
186 } else { 186 } else {
187 bb_error_msg_and_die(bb_msg_invalid_date, date_str); 187 bb_error_msg_and_die(bb_msg_invalid_date, date_str);
188 } 188 }
189 ptm->tm_sec = 0; /* assume zero if [.SS] is not given */
189 if (end == '.') { 190 if (end == '.') {
190 /* xxx.SS */ 191 /* xxx.SS */
191 if (sscanf(strchr(date_str, '.') + 1, "%u%c", 192 if (sscanf(strchr(date_str, '.') + 1, "%u%c",
diff --git a/loginutils/cryptpw.c b/loginutils/cryptpw.c
index 23a1884f4..9f5f40686 100644
--- a/loginutils/cryptpw.c
+++ b/loginutils/cryptpw.c
@@ -111,8 +111,8 @@ int cryptpw_main(int argc UNUSED_PARAM, char **argv)
111 opt_m = CONFIG_FEATURE_DEFAULT_PASSWD_ALGO; 111 opt_m = CONFIG_FEATURE_DEFAULT_PASSWD_ALGO;
112 opt_S = NULL; 112 opt_S = NULL;
113 /* at most two non-option arguments; -P NUM */ 113 /* at most two non-option arguments; -P NUM */
114 opt_complementary = "?2:P+"; 114 opt_complementary = "?2";
115 getopt32(argv, "sP:S:m:a:", &fd, &opt_S, &opt_m, &opt_m); 115 getopt32(argv, "sP:+S:m:a:", &fd, &opt_S, &opt_m, &opt_m);
116 argv += optind; 116 argv += optind;
117 117
118 /* have no idea how to handle -s... */ 118 /* have no idea how to handle -s... */
diff --git a/loginutils/getty.c b/loginutils/getty.c
index b10bdbdbf..162c1697e 100644
--- a/loginutils/getty.c
+++ b/loginutils/getty.c
@@ -131,7 +131,7 @@ struct globals {
131//usage: "\n" 131//usage: "\n"
132//usage: "\nBAUD_RATE of 0 leaves it unchanged" 132//usage: "\nBAUD_RATE of 0 leaves it unchanged"
133 133
134static const char opt_string[] ALIGN1 = "I:LH:f:hil:mt:wn"; 134static const char opt_string[] ALIGN1 = "I:LH:f:hil:mt:+wn";
135#define F_INITSTRING (1 << 0) /* -I */ 135#define F_INITSTRING (1 << 0) /* -I */
136#define F_LOCAL (1 << 1) /* -L */ 136#define F_LOCAL (1 << 1) /* -L */
137#define F_FAKEHOST (1 << 2) /* -H */ 137#define F_FAKEHOST (1 << 2) /* -H */
@@ -179,7 +179,7 @@ static void parse_args(char **argv)
179 char *ts; 179 char *ts;
180 int flags; 180 int flags;
181 181
182 opt_complementary = "-2:t+"; /* at least 2 args; -t N */ 182 opt_complementary = "-2"; /* at least 2 args; -t N */
183 flags = getopt32(argv, opt_string, 183 flags = getopt32(argv, opt_string,
184 &G.initstring, &G.fakehost, &G.issue, 184 &G.initstring, &G.fakehost, &G.issue,
185 &G.login, &G.timeout 185 &G.login, &G.timeout
diff --git a/loginutils/sulogin.c b/loginutils/sulogin.c
index f32469551..6befea933 100644
--- a/loginutils/sulogin.c
+++ b/loginutils/sulogin.c
@@ -43,8 +43,7 @@ int sulogin_main(int argc UNUSED_PARAM, char **argv)
43 logmode = LOGMODE_BOTH; 43 logmode = LOGMODE_BOTH;
44 openlog(applet_name, 0, LOG_AUTH); 44 openlog(applet_name, 0, LOG_AUTH);
45 45
46 opt_complementary = "t+"; /* -t N */ 46 getopt32(argv, "t:+", &timeout);
47 getopt32(argv, "t:", &timeout);
48 argv += optind; 47 argv += optind;
49 48
50 if (argv[0]) { 49 if (argv[0]) {
diff --git a/mailutils/makemime.c b/mailutils/makemime.c
index 1dadd715f..8e1bc664c 100644
--- a/mailutils/makemime.c
+++ b/mailutils/makemime.c
@@ -184,9 +184,8 @@ int makemime_main(int argc UNUSED_PARAM, char **argv)
184 INIT_G(); 184 INIT_G();
185 185
186 // parse options 186 // parse options
187 opt_complementary = "a::";
188 opts = getopt32(argv, 187 opts = getopt32(argv,
189 "c:e:o:C:N:a:", // "m:j:", 188 "c:e:o:C:N:a:*", // "m:j:",
190 &content_type, NULL, &opt_output, &G.opt_charset, NULL, &opt_headers //, NULL, NULL 189 &content_type, NULL, &opt_output, &G.opt_charset, NULL, &opt_headers //, NULL, NULL
191 ); 190 );
192 //argc -= optind; 191 //argc -= optind;
diff --git a/mailutils/popmaildir.c b/mailutils/popmaildir.c
index 62030331e..69eca6164 100644
--- a/mailutils/popmaildir.c
+++ b/mailutils/popmaildir.c
@@ -107,9 +107,9 @@ int popmaildir_main(int argc UNUSED_PARAM, char **argv)
107 INIT_G(); 107 INIT_G();
108 108
109 // parse options 109 // parse options
110 opt_complementary = "-1:dd:t+:R+:L+:H+"; 110 opt_complementary = "-1:dd";
111 opts = getopt32(argv, 111 opts = getopt32(argv,
112 "bdmVcasTkt:" "R:Z:L:H:" IF_FEATURE_POPMAILDIR_DELIVERY("M:F:"), 112 "bdmVcasTkt:+" "R:+Z:L:+H:+" IF_FEATURE_POPMAILDIR_DELIVERY("M:F:"),
113 &timeout, NULL, NULL, NULL, &opt_nlines 113 &timeout, NULL, NULL, NULL, &opt_nlines
114 IF_FEATURE_POPMAILDIR_DELIVERY(, &delivery, &delivery) // we treat -M and -F the same 114 IF_FEATURE_POPMAILDIR_DELIVERY(, &delivery, &delivery) // we treat -M and -F the same
115 ); 115 );
diff --git a/mailutils/reformime.c b/mailutils/reformime.c
index 86b2cfed3..b967dfbc7 100644
--- a/mailutils/reformime.c
+++ b/mailutils/reformime.c
@@ -265,9 +265,9 @@ int reformime_main(int argc UNUSED_PARAM, char **argv)
265 265
266 // parse options 266 // parse options
267 // N.B. only -x and -X are supported so far 267 // N.B. only -x and -X are supported so far
268 opt_complementary = "x--X:X--x" IF_FEATURE_REFORMIME_COMPAT(":m::"); 268 opt_complementary = "x--X:X--x";
269 opts = getopt32(argv, 269 opts = getopt32(argv,
270 "x:X" IF_FEATURE_REFORMIME_COMPAT("deis:r:c:m:h:o:O:"), 270 "x:X" IF_FEATURE_REFORMIME_COMPAT("deis:r:c:m:*h:o:O:"),
271 &opt_prefix 271 &opt_prefix
272 IF_FEATURE_REFORMIME_COMPAT(, NULL, NULL, &G.opt_charset, NULL, NULL, NULL, NULL) 272 IF_FEATURE_REFORMIME_COMPAT(, NULL, NULL, &G.opt_charset, NULL, NULL, NULL, NULL)
273 ); 273 );
diff --git a/mailutils/sendmail.c b/mailutils/sendmail.c
index 5143fac8f..fb4dbb3da 100644
--- a/mailutils/sendmail.c
+++ b/mailutils/sendmail.c
@@ -247,11 +247,11 @@ int sendmail_main(int argc UNUSED_PARAM, char **argv)
247 247
248 // parse options 248 // parse options
249 // -v is a counter, -H and -S are mutually exclusive, -a is a list 249 // -v is a counter, -H and -S are mutually exclusive, -a is a list
250 opt_complementary = "vv:w+:H--S:S--H:a::"; 250 opt_complementary = "vv:H--S:S--H";
251 // N.B. since -H and -S are mutually exclusive they do not interfere in opt_connect 251 // N.B. since -H and -S are mutually exclusive they do not interfere in opt_connect
252 // -a is for ssmtp (http://downloads.openwrt.org/people/nico/man/man8/ssmtp.8.html) compatibility, 252 // -a is for ssmtp (http://downloads.openwrt.org/people/nico/man/man8/ssmtp.8.html) compatibility,
253 // it is still under development. 253 // it is still under development.
254 opts = getopt32(argv, "tf:o:iw:H:S:a::v", &opt_from, NULL, 254 opts = getopt32(argv, "tf:o:iw:+H:S:a:*:v", &opt_from, NULL,
255 &timeout, &opt_connect, &opt_connect, &list, &verbose); 255 &timeout, &opt_connect, &opt_connect, &list, &verbose);
256 //argc -= optind; 256 //argc -= optind;
257 argv += optind; 257 argv += optind;
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
25lib-$(CONFIG_IONICE) += ionice.o 25lib-$(CONFIG_IONICE) += ionice.o
26lib-$(CONFIG_HDPARM) += hdparm.o 26lib-$(CONFIG_HDPARM) += hdparm.o
27lib-$(CONFIG_INOTIFYD) += inotifyd.o 27lib-$(CONFIG_INOTIFYD) += inotifyd.o
28lib-$(CONFIG_FEATURE_LAST_SMALL)+= last.o 28
29lib-$(CONFIG_FEATURE_LAST_FANCY)+= last_fancy.o 29ifeq ($(CONFIG_FEATURE_LAST_FANCY),y)
30lib-$(CONFIG_FEATURE_LAST_FANCY) += last_fancy.o
31else
32lib-$(CONFIG_LAST) += last.o
33endif
34
30lib-$(CONFIG_LESS) += less.o 35lib-$(CONFIG_LESS) += less.o
31lib-$(CONFIG_MAKEDEVS) += makedevs.o 36lib-$(CONFIG_MAKEDEVS) += makedevs.o
32lib-$(CONFIG_MAN) += man.o 37lib-$(CONFIG_MAN) += man.o
diff --git a/miscutils/conspy.c b/miscutils/conspy.c
index f6468c116..e80158e39 100644
--- a/miscutils/conspy.c
+++ b/miscutils/conspy.c
@@ -388,8 +388,8 @@ int conspy_main(int argc UNUSED_PARAM, char **argv)
388 INIT_G(); 388 INIT_G();
389 strcpy(G.vcsa_name, DEV_VCSA); 389 strcpy(G.vcsa_name, DEV_VCSA);
390 390
391 opt_complementary = "x+:y+"; // numeric params 391 // numeric params
392 opts = getopt32(argv, "vcQsndfFx:y:", &G.x, &G.y); 392 opts = getopt32(argv, "vcQsndfFx:+y:+", &G.x, &G.y);
393 argv += optind; 393 argv += optind;
394 ttynum = 0; 394 ttynum = 0;
395 if (argv[0]) { 395 if (argv[0]) {
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)
908 908
909 int bus_num, bus_addr, mode = I2C_SMBUS_BYTE_DATA, even = 0, pec = 0; 909 int bus_num, bus_addr, mode = I2C_SMBUS_BYTE_DATA, even = 0, pec = 0;
910 unsigned first = 0x00, last = 0xff, opts; 910 unsigned first = 0x00, last = 0xff, opts;
911 int *block = (int *)bb_common_bufsiz1; 911 int block[I2CDUMP_NUM_REGS];
912 char *opt_r_str, *dash; 912 char *opt_r_str, *dash;
913 int fd, res; 913 int fd, res;
914 914
diff --git a/miscutils/ionice.c b/miscutils/ionice.c
index 0c14256ab..5fcb653a8 100644
--- a/miscutils/ionice.c
+++ b/miscutils/ionice.c
@@ -60,9 +60,8 @@ int ionice_main(int argc UNUSED_PARAM, char **argv)
60 }; 60 };
61 61
62 /* Numeric params */ 62 /* Numeric params */
63 opt_complementary = "n+:c+:p+";
64 /* '+': stop at first non-option */ 63 /* '+': stop at first non-option */
65 opt = getopt32(argv, "+n:c:p:", &pri, &ioclass, &pid); 64 opt = getopt32(argv, "+n:+c:+p:+", &pri, &ioclass, &pid);
66 argv += optind; 65 argv += optind;
67 66
68 if (opt & OPT_c) { 67 if (opt & OPT_c) {
diff --git a/miscutils/microcom.c b/miscutils/microcom.c
index d9e8f9187..dfc9771d8 100644
--- a/miscutils/microcom.c
+++ b/miscutils/microcom.c
@@ -64,8 +64,7 @@ int microcom_main(int argc UNUSED_PARAM, char **argv)
64 unsigned opts; 64 unsigned opts;
65 65
66 // fetch options 66 // fetch options
67 opt_complementary = "=1:s+:d+:t+"; // exactly one arg, numeric options 67 opts = getopt32(argv, "Xs:+d:+t:+", &speed, &delay, &timeout);
68 opts = getopt32(argv, "Xs:d:t:", &speed, &delay, &timeout);
69// argc -= optind; 68// argc -= optind;
70 argv += optind; 69 argv += optind;
71 70
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)
29 unsigned opt; 29 unsigned opt;
30 30
31 opt_complementary = "-1"; /* at least one arg */ 31 opt_complementary = "-1"; /* at least one arg */
32 opt = getopt32(argv, "c"); 32 opt = getopt32(argv, "+c"); /* +: stop on first non-opt */
33 argv += optind; 33 argv += optind;
34 34
35 /* setsid() is allowed only when we are not a process group leader. 35 /* setsid() is allowed only when we are not a process group leader.
diff --git a/miscutils/timeout.c b/miscutils/timeout.c
index 9d56593ba..8df9ff0fd 100644
--- a/miscutils/timeout.c
+++ b/miscutils/timeout.c
@@ -52,9 +52,8 @@ int timeout_main(int argc UNUSED_PARAM, char **argv)
52 /* -p option is not documented, it is needed to support NOMMU. */ 52 /* -p option is not documented, it is needed to support NOMMU. */
53 53
54 /* -t SECONDS; -p PARENT_PID */ 54 /* -t SECONDS; -p PARENT_PID */
55 opt_complementary = "t+" USE_FOR_NOMMU(":p+");
56 /* '+': stop at first non-option */ 55 /* '+': stop at first non-option */
57 getopt32(argv, "+s:t:" USE_FOR_NOMMU("p:"), &opt_s, &timeout, &parent); 56 getopt32(argv, "+s:t:+" USE_FOR_NOMMU("p:+"), &opt_s, &timeout, &parent);
58 /*argv += optind; - no, wait for bb_daemonize_or_rexec! */ 57 /*argv += optind; - no, wait for bb_daemonize_or_rexec! */
59 signo = get_signum(opt_s); 58 signo = get_signum(opt_s);
60 if (signo < 0) 59 if (signo < 0)
diff --git a/miscutils/ubi_tools.c b/miscutils/ubi_tools.c
index 4364bc807..8e55e9577 100644
--- a/miscutils/ubi_tools.c
+++ b/miscutils/ubi_tools.c
@@ -134,8 +134,8 @@ int ubi_tools_main(int argc UNUSED_PARAM, char **argv)
134#define OPTION_a (1 << 5) 134#define OPTION_a (1 << 5)
135#define OPTION_t (1 << 6) 135#define OPTION_t (1 << 6)
136 if (do_mkvol) { 136 if (do_mkvol) {
137 opt_complementary = "-1:d+:n+:a+:O+"; 137 opt_complementary = "-1";
138 opts = getopt32(argv, "md:n:N:s:a:t:O:", 138 opts = getopt32(argv, "md:+n:+N:s:a:+t:O:+",
139 &dev_num, &vol_id, 139 &dev_num, &vol_id,
140 &vol_name, &size_bytes_str, &alignment, &type, 140 &vol_name, &size_bytes_str, &alignment, &type,
141 &vid_hdr_offset 141 &vid_hdr_offset
@@ -146,8 +146,8 @@ int ubi_tools_main(int argc UNUSED_PARAM, char **argv)
146 opts = getopt32(argv, "s:at", &size_bytes_str); 146 opts = getopt32(argv, "s:at", &size_bytes_str);
147 opts *= OPTION_s; 147 opts *= OPTION_s;
148 } else { 148 } else {
149 opt_complementary = "-1:m+:d+:n+:a+"; 149 opt_complementary = "-1";
150 opts = getopt32(argv, "m:d:n:N:s:a:t:", 150 opts = getopt32(argv, "m:+d:+n:+N:s:a:+t:",
151 &mtd_num, &dev_num, &vol_id, 151 &mtd_num, &dev_num, &vol_id,
152 &vol_name, &size_bytes_str, &alignment, &type 152 &vol_name, &size_bytes_str, &alignment, &type
153 ); 153 );
diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c
index 9c941064b..5936e48cf 100644
--- a/modutils/modprobe-small.c
+++ b/modutils/modprobe-small.c
@@ -21,7 +21,6 @@
21 21
22extern int init_module(void *module, unsigned long len, const char *options); 22extern int init_module(void *module, unsigned long len, const char *options);
23extern int delete_module(const char *module, unsigned flags); 23extern int delete_module(const char *module, unsigned flags);
24extern int query_module(const char *name, int which, void *buf, size_t bufsize, size_t *ret);
25/* linux/include/linux/module.h has limit of 64 chars on module names */ 24/* linux/include/linux/module.h has limit of 64 chars on module names */
26#undef MODULE_NAME_LEN 25#undef MODULE_NAME_LEN
27#define MODULE_NAME_LEN 64 26#define MODULE_NAME_LEN 64
@@ -46,6 +45,7 @@ typedef struct module_info {
46 char *pathname; 45 char *pathname;
47 char *aliases; 46 char *aliases;
48 char *deps; 47 char *deps;
48 smallint open_read_failed;
49} module_info; 49} module_info;
50 50
51/* 51/*
@@ -223,7 +223,8 @@ static int load_module(const char *fname, const char *options)
223#endif 223#endif
224} 224}
225 225
226static void parse_module(module_info *info, const char *pathname) 226/* Returns !0 if open/read was unsuccessful */
227static int parse_module(module_info *info, const char *pathname)
227{ 228{
228 char *module_image; 229 char *module_image;
229 char *ptr; 230 char *ptr;
@@ -232,6 +233,7 @@ static void parse_module(module_info *info, const char *pathname)
232 dbg1_error_msg("parse_module('%s')", pathname); 233 dbg1_error_msg("parse_module('%s')", pathname);
233 234
234 /* Read (possibly compressed) module */ 235 /* Read (possibly compressed) module */
236 errno = 0;
235 len = 64 * 1024 * 1024; /* 64 Mb at most */ 237 len = 64 * 1024 * 1024; /* 64 Mb at most */
236 module_image = xmalloc_open_zipped_read_close(pathname, &len); 238 module_image = xmalloc_open_zipped_read_close(pathname, &len);
237 /* module_image == NULL is ok here, find_keyword handles it */ 239 /* module_image == NULL is ok here, find_keyword handles it */
@@ -299,9 +301,11 @@ static void parse_module(module_info *info, const char *pathname)
299 dbg2_error_msg("dep:'%s'", ptr); 301 dbg2_error_msg("dep:'%s'", ptr);
300 append(ptr); 302 append(ptr);
301 } 303 }
304 free(module_image);
302 info->deps = copy_stringbuf(); 305 info->deps = copy_stringbuf();
303 306
304 free(module_image); 307 info->open_read_failed = (module_image == NULL);
308 return info->open_read_failed;
305} 309}
306 310
307static FAST_FUNC int fileAction(const char *pathname, 311static FAST_FUNC int fileAction(const char *pathname,
@@ -332,7 +336,8 @@ static FAST_FUNC int fileAction(const char *pathname,
332 336
333 dbg1_error_msg("'%s' module name matches", pathname); 337 dbg1_error_msg("'%s' module name matches", pathname);
334 module_found_idx = cur; 338 module_found_idx = cur;
335 parse_module(&modinfo[cur], pathname); 339 if (parse_module(&modinfo[cur], pathname) != 0)
340 return TRUE; /* failed to open/read it, no point in trying loading */
336 341
337 if (!(option_mask32 & OPT_r)) { 342 if (!(option_mask32 & OPT_r)) {
338 if (load_module(pathname, module_load_options) == 0) { 343 if (load_module(pathname, module_load_options) == 0) {
@@ -609,13 +614,14 @@ static int rmmod(const char *filename)
609#define process_module(a,b) process_module(a) 614#define process_module(a,b) process_module(a)
610#define cmdline_options "" 615#define cmdline_options ""
611#endif 616#endif
612static void process_module(char *name, const char *cmdline_options) 617static int process_module(char *name, const char *cmdline_options)
613{ 618{
614 char *s, *deps, *options; 619 char *s, *deps, *options;
615 module_info **infovec; 620 module_info **infovec;
616 module_info *info; 621 module_info *info;
617 int infoidx; 622 int infoidx;
618 int is_remove = (option_mask32 & OPT_r) != 0; 623 int is_remove = (option_mask32 & OPT_r) != 0;
624 int exitcode = EXIT_SUCCESS;
619 625
620 dbg1_error_msg("process_module('%s','%s')", name, cmdline_options); 626 dbg1_error_msg("process_module('%s','%s')", name, cmdline_options);
621 627
@@ -629,7 +635,7 @@ static void process_module(char *name, const char *cmdline_options)
629 * (compat note: this allows and strips .ko suffix) 635 * (compat note: this allows and strips .ko suffix)
630 */ 636 */
631 rmmod(name); 637 rmmod(name);
632 return; 638 return EXIT_SUCCESS;
633 } 639 }
634 640
635 /* 641 /*
@@ -640,7 +646,7 @@ static void process_module(char *name, const char *cmdline_options)
640 */ 646 */
641 if (!is_remove && already_loaded(name)) { 647 if (!is_remove && already_loaded(name)) {
642 dbg1_error_msg("nothing to do for '%s'", name); 648 dbg1_error_msg("nothing to do for '%s'", name);
643 return; 649 return EXIT_SUCCESS;
644 } 650 }
645 651
646 options = NULL; 652 options = NULL;
@@ -742,6 +748,11 @@ static void process_module(char *name, const char *cmdline_options)
742 dbg1_error_msg("'%s': blacklisted", info->pathname); 748 dbg1_error_msg("'%s': blacklisted", info->pathname);
743 continue; 749 continue;
744 } 750 }
751 if (info->open_read_failed) {
752 /* We already tried it, didn't work. Don't try load again */
753 exitcode = EXIT_FAILURE;
754 continue;
755 }
745 errno = 0; 756 errno = 0;
746 if (load_module(info->pathname, options) != 0) { 757 if (load_module(info->pathname, options) != 0) {
747 if (EEXIST != errno) { 758 if (EEXIST != errno) {
@@ -753,13 +764,14 @@ static void process_module(char *name, const char *cmdline_options)
753 info->pathname, 764 info->pathname,
754 moderror(errno)); 765 moderror(errno));
755 } 766 }
767 exitcode = EXIT_FAILURE;
756 } 768 }
757 } 769 }
758 ret: 770 ret:
759 free(infovec); 771 free(infovec);
760 free(options); 772 free(options);
761//TODO: return load attempt result from process_module. 773
762//If dep didn't load ok, continuing makes little sense. 774 return exitcode;
763} 775}
764#undef cmdline_options 776#undef cmdline_options
765 777
@@ -866,6 +878,7 @@ The following options are useful for people managing distributions:
866int modprobe_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 878int modprobe_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
867int modprobe_main(int argc UNUSED_PARAM, char **argv) 879int modprobe_main(int argc UNUSED_PARAM, char **argv)
868{ 880{
881 int exitcode;
869 struct utsname uts; 882 struct utsname uts;
870 char applet0 = applet_name[0]; 883 char applet0 = applet_name[0];
871 IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(char *options;) 884 IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(char *options;)
@@ -971,21 +984,23 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
971 bb_error_msg_and_die("can't insert '%s': %s", 984 bb_error_msg_and_die("can't insert '%s': %s",
972 *argv, moderror(errno)); 985 *argv, moderror(errno));
973 } 986 }
974 return 0; 987 return EXIT_SUCCESS;
975 } 988 }
976 989
977 /* Try to load modprobe.dep.bb */ 990 /* Try to load modprobe.dep.bb */
978 if ('r' != applet0) /* not rmmod */ 991 if ('r' != applet0) { /* not rmmod */
979 load_dep_bb(); 992 load_dep_bb();
993 }
980 994
981 /* Load/remove modules. 995 /* Load/remove modules.
982 * Only rmmod/modprobe -r loops here, insmod/modprobe has only argv[0] */ 996 * Only rmmod/modprobe -r loops here, insmod/modprobe has only argv[0] */
997 exitcode = EXIT_SUCCESS;
983 do { 998 do {
984 process_module(*argv, options); 999 exitcode |= process_module(*argv, options);
985 } while (*++argv); 1000 } while (*++argv);
986 1001
987 if (ENABLE_FEATURE_CLEAN_UP) { 1002 if (ENABLE_FEATURE_CLEAN_UP) {
988 IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(free(options);) 1003 IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(free(options);)
989 } 1004 }
990 return EXIT_SUCCESS; 1005 return exitcode;
991} 1006}
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)
178 if (flags == 0) 178 if (flags == 0)
179 flags = 3; 179 flags = 3;
180 180
181 strncpy(req.arp_dev, device, sizeof(req.arp_dev)); 181 strncpy_IFNAMSIZ(req.arp_dev, device);
182 182
183 err = -1; 183 err = -1;
184 184
@@ -219,7 +219,7 @@ static void arp_getdevhw(char *ifname, struct sockaddr *sa)
219 struct ifreq ifr; 219 struct ifreq ifr;
220 const struct hwtype *xhw; 220 const struct hwtype *xhw;
221 221
222 strcpy(ifr.ifr_name, ifname); 222 strncpy_IFNAMSIZ(ifr.ifr_name, ifname);
223 ioctl_or_perror_and_die(sockfd, SIOCGIFHWADDR, &ifr, 223 ioctl_or_perror_and_die(sockfd, SIOCGIFHWADDR, &ifr,
224 "can't get HW-Address for '%s'", ifname); 224 "can't get HW-Address for '%s'", ifname);
225 if (hw_set && (ifr.ifr_hwaddr.sa_family != hw->type)) { 225 if (hw_set && (ifr.ifr_hwaddr.sa_family != hw->type)) {
@@ -332,7 +332,7 @@ static int arp_set(char **args)
332 /* Fill in the remainder of the request. */ 332 /* Fill in the remainder of the request. */
333 req.arp_flags = flags; 333 req.arp_flags = flags;
334 334
335 strncpy(req.arp_dev, device, sizeof(req.arp_dev)); 335 strncpy_IFNAMSIZ(req.arp_dev, device);
336 336
337 /* Call the kernel. */ 337 /* Call the kernel. */
338 if (option_mask32 & ARP_OPT_v) 338 if (option_mask32 & ARP_OPT_v)
diff --git a/networking/arping.c b/networking/arping.c
index 6b0de4de2..46bd65e36 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)
231 if (!(option_mask32 & QUIET)) { 231 if (!(option_mask32 & QUIET)) {
232 int s_printed = 0; 232 int s_printed = 0;
233 233
234 printf("%scast re%s from %s [%s]", 234 printf("%scast re%s from %s [%02x:%02x:%02x:%02x:%02x:%02x]",
235 FROM->sll_pkttype == PACKET_HOST ? "Uni" : "Broad", 235 FROM->sll_pkttype == PACKET_HOST ? "Uni" : "Broad",
236 ah->ar_op == htons(ARPOP_REPLY) ? "ply" : "quest", 236 ah->ar_op == htons(ARPOP_REPLY) ? "ply" : "quest",
237 inet_ntoa(src_ip), 237 inet_ntoa(src_ip),
238 ether_ntoa((struct ether_addr *) p)); 238 p[0], p[1], p[2], p[3], p[4], p[5]
239 );
239 if (dst_ip.s_addr != src.s_addr) { 240 if (dst_ip.s_addr != src.s_addr) {
240 printf("for %s ", inet_ntoa(dst_ip)); 241 printf("for %s ", inet_ntoa(dst_ip));
241 s_printed = 1; 242 s_printed = 1;
242 } 243 }
243 if (memcmp(p + ah->ar_hln + 4, me.sll_addr, ah->ar_hln)) { 244 if (memcmp(p + ah->ar_hln + 4, me.sll_addr, ah->ar_hln)) {
245 unsigned char *pp = p + ah->ar_hln + 4;
244 if (!s_printed) 246 if (!s_printed)
245 printf("for "); 247 printf("for ");
246 printf("[%s]", 248 printf("[%02x:%02x:%02x:%02x:%02x:%02x]",
247 ether_ntoa((struct ether_addr *) p + ah->ar_hln + 4)); 249 pp[0], pp[1], pp[2], pp[3], pp[4], pp[5]
250 );
248 } 251 }
249 252
250 if (last) { 253 if (last) {
@@ -292,8 +295,8 @@ int arping_main(int argc UNUSED_PARAM, char **argv)
292 /* Dad also sets quit_on_reply. 295 /* Dad also sets quit_on_reply.
293 * Advert also sets unsolicited. 296 * Advert also sets unsolicited.
294 */ 297 */
295 opt_complementary = "=1:Df:AU:c+"; 298 opt_complementary = "=1:Df:AU";
296 opt = getopt32(argv, "DUAqfbc:w:I:s:", 299 opt = getopt32(argv, "DUAqfbc:+w:I:s:",
297 &count, &str_timeout, &device, &source); 300 &count, &str_timeout, &device, &source);
298 if (opt & 0x80) /* -w: timeout */ 301 if (opt & 0x80) /* -w: timeout */
299 timeout_us = xatou_range(str_timeout, 0, INT_MAX/2000000) * 1000000 + 500000; 302 timeout_us = xatou_range(str_timeout, 0, INT_MAX/2000000) * 1000000 + 500000;
diff --git a/networking/ftpd.c b/networking/ftpd.c
index 360d1e6be..4cbb9b6fe 100644
--- a/networking/ftpd.c
+++ b/networking/ftpd.c
@@ -1130,11 +1130,11 @@ int ftpd_main(int argc UNUSED_PARAM, char **argv)
1130 abs_timeout = 1 * 60 * 60; 1130 abs_timeout = 1 * 60 * 60;
1131 verbose_S = 0; 1131 verbose_S = 0;
1132 G.timeout = 2 * 60; 1132 G.timeout = 2 * 60;
1133 opt_complementary = "t+:T+:vv:SS"; 1133 opt_complementary = "vv:SS";
1134#if BB_MMU 1134#if BB_MMU
1135 opts = getopt32(argv, "vS" IF_FEATURE_FTP_WRITE("w") "t:T:", &G.timeout, &abs_timeout, &G.verbose, &verbose_S); 1135 opts = getopt32(argv, "vS" IF_FEATURE_FTP_WRITE("w") "t:+T:+", &G.timeout, &abs_timeout, &G.verbose, &verbose_S);
1136#else 1136#else
1137 opts = getopt32(argv, "l1AvS" IF_FEATURE_FTP_WRITE("w") "t:T:", &G.timeout, &abs_timeout, &G.verbose, &verbose_S); 1137 opts = getopt32(argv, "l1AvS" IF_FEATURE_FTP_WRITE("w") "t:+T:+", &G.timeout, &abs_timeout, &G.verbose, &verbose_S);
1138 if (opts & (OPT_l|OPT_1)) { 1138 if (opts & (OPT_l|OPT_1)) {
1139 /* Our secret backdoor to ls */ 1139 /* Our secret backdoor to ls */
1140/* TODO: pass --group-directories-first? would be nice, but ls doesn't do that yet */ 1140/* TODO: pass --group-directories-first? would be nice, but ls doesn't do that yet */
diff --git a/networking/ifplugd.c b/networking/ifplugd.c
index f0defb5c8..28c49e218 100644
--- a/networking/ifplugd.c
+++ b/networking/ifplugd.c
@@ -107,9 +107,9 @@ enum {
107#endif 107#endif
108}; 108};
109#if ENABLE_FEATURE_PIDFILE 109#if ENABLE_FEATURE_PIDFILE
110# define OPTION_STR "+ansfFi:r:It:u:d:m:pqlx:Mk" 110# define OPTION_STR "+ansfFi:r:It:+u:+d:+m:pqlx:Mk"
111#else 111#else
112# define OPTION_STR "+ansfFi:r:It:u:d:m:pqlx:M" 112# define OPTION_STR "+ansfFi:r:It:+u:+d:+m:pqlx:M"
113#endif 113#endif
114 114
115enum { // interface status 115enum { // interface status
@@ -560,7 +560,6 @@ int ifplugd_main(int argc UNUSED_PARAM, char **argv)
560 560
561 INIT_G(); 561 INIT_G();
562 562
563 opt_complementary = "t+:u+:d+";
564 opts = getopt32(argv, OPTION_STR, 563 opts = getopt32(argv, OPTION_STR,
565 &G.iface, &G.script_name, &G.poll_time, &G.delay_up, 564 &G.iface, &G.script_name, &G.poll_time, &G.delay_up,
566 &G.delay_down, &G.api_mode, &G.extra_arg); 565 &G.delay_down, &G.api_mode, &G.extra_arg);
diff --git a/networking/inetd.c b/networking/inetd.c
index 8d44b5198..f9295e38b 100644
--- a/networking/inetd.c
+++ b/networking/inetd.c
@@ -1153,8 +1153,8 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
1153 if (real_uid != 0) /* run by non-root user */ 1153 if (real_uid != 0) /* run by non-root user */
1154 config_filename = NULL; 1154 config_filename = NULL;
1155 1155
1156 opt_complementary = "R+:q+"; /* -q N, -R N */ 1156 /* -q N, -R N */
1157 opt = getopt32(argv, "R:feq:", &max_concurrency, &global_queuelen); 1157 opt = getopt32(argv, "R:+feq:+", &max_concurrency, &global_queuelen);
1158 argv += optind; 1158 argv += optind;
1159 //argc -= optind; 1159 //argc -= optind;
1160 if (argv[0]) 1160 if (argv[0])
diff --git a/networking/nc_bloaty.c b/networking/nc_bloaty.c
index 471ae1a12..192e42fe5 100644
--- a/networking/nc_bloaty.c
+++ b/networking/nc_bloaty.c
@@ -794,8 +794,8 @@ int nc_main(int argc UNUSED_PARAM, char **argv)
794 e_found: 794 e_found:
795 795
796 // -g -G -t -r deleted, unimplemented -a deleted too 796 // -g -G -t -r deleted, unimplemented -a deleted too
797 opt_complementary = "?2:vv:ll:w+"; /* max 2 params; -v and -l are counters; -w N */ 797 opt_complementary = "?2:vv:ll"; /* max 2 params; -v and -l are counters; -w N */
798 getopt32(argv, "np:s:uvw:" IF_NC_SERVER("lk") 798 getopt32(argv, "np:s:uvw:+" IF_NC_SERVER("lk")
799 IF_NC_EXTRA("i:o:z"), 799 IF_NC_EXTRA("i:o:z"),
800 &str_p, &str_s, &o_wait 800 &str_p, &str_s, &o_wait
801 IF_NC_EXTRA(, &str_i, &str_o), &o_verbose IF_NC_SERVER(, &cnt_l)); 801 IF_NC_EXTRA(, &str_i, &str_o), &o_verbose IF_NC_SERVER(, &cnt_l));
diff --git a/networking/ntpd.c b/networking/ntpd.c
index 410318979..130cef0af 100644
--- a/networking/ntpd.c
+++ b/networking/ntpd.c
@@ -267,7 +267,6 @@ typedef struct {
267 267
268typedef struct { 268typedef struct {
269 len_and_sockaddr *p_lsa; 269 len_and_sockaddr *p_lsa;
270 char *p_hostname;
271 char *p_dotted; 270 char *p_dotted;
272 int p_fd; 271 int p_fd;
273 int datapoint_idx; 272 int datapoint_idx;
@@ -293,6 +292,7 @@ typedef struct {
293 datapoint_t filter_datapoint[NUM_DATAPOINTS]; 292 datapoint_t filter_datapoint[NUM_DATAPOINTS];
294 /* last sent packet: */ 293 /* last sent packet: */
295 msg_t p_xmt_msg; 294 msg_t p_xmt_msg;
295 char p_hostname[1];
296} peer_t; 296} peer_t;
297 297
298 298
@@ -765,14 +765,38 @@ reset_peer_stats(peer_t *p, double offset)
765} 765}
766 766
767static void 767static void
768resolve_peer_hostname(peer_t *p, int loop_on_fail)
769{
770 len_and_sockaddr *lsa;
771
772 again:
773 lsa = host2sockaddr(p->p_hostname, 123);
774 if (!lsa) {
775 /* error message already emitted by host2sockaddr() */
776 if (!loop_on_fail)
777 return;
778//FIXME: do this to avoid infinite looping on typo in a hostname?
779//well... in which case, what is a good value for loop_on_fail?
780 //if (--loop_on_fail == 0)
781 // xfunc_die();
782 sleep(5);
783 goto again;
784 }
785 free(p->p_lsa);
786 free(p->p_dotted);
787 p->p_lsa = lsa;
788 p->p_dotted = xmalloc_sockaddr2dotted_noport(&lsa->u.sa);
789}
790
791static void
768add_peers(const char *s) 792add_peers(const char *s)
769{ 793{
770 llist_t *item; 794 llist_t *item;
771 peer_t *p; 795 peer_t *p;
772 796
773 p = xzalloc(sizeof(*p)); 797 p = xzalloc(sizeof(*p) + strlen(s));
774 p->p_lsa = xhost2sockaddr(s, 123); 798 strcpy(p->p_hostname, s);
775 p->p_dotted = xmalloc_sockaddr2dotted_noport(&p->p_lsa->u.sa); 799 resolve_peer_hostname(p, /*loop_on_fail=*/ 1);
776 800
777 /* Names like N.<country2chars>.pool.ntp.org are randomly resolved 801 /* Names like N.<country2chars>.pool.ntp.org are randomly resolved
778 * to a pool of machines. Sometimes different N's resolve to the same IP. 802 * to a pool of machines. Sometimes different N's resolve to the same IP.
@@ -789,7 +813,6 @@ add_peers(const char *s)
789 } 813 }
790 } 814 }
791 815
792 p->p_hostname = xstrdup(s);
793 p->p_fd = -1; 816 p->p_fd = -1;
794 p->p_xmt_msg.m_status = MODE_CLIENT | (NTP_VERSION << 3); 817 p->p_xmt_msg.m_status = MODE_CLIENT | (NTP_VERSION << 3);
795 p->next_action_time = G.cur_time; /* = set_next(p, 0); */ 818 p->next_action_time = G.cur_time; /* = set_next(p, 0); */
@@ -2174,11 +2197,11 @@ static NOINLINE void ntp_init(char **argv)
2174 2197
2175 /* Parse options */ 2198 /* Parse options */
2176 peers = NULL; 2199 peers = NULL;
2177 opt_complementary = "dd:p::wn" /* -d: counter; -p: list; -w implies -n */ 2200 opt_complementary = "dd:wn" /* -d: counter; -p: list; -w implies -n */
2178 IF_FEATURE_NTPD_SERVER(":Il"); /* -I implies -l */ 2201 IF_FEATURE_NTPD_SERVER(":Il"); /* -I implies -l */
2179 opts = getopt32(argv, 2202 opts = getopt32(argv,
2180 "nqNx" /* compat */ 2203 "nqNx" /* compat */
2181 "wp:S:"IF_FEATURE_NTPD_SERVER("l") /* NOT compat */ 2204 "wp:*S:"IF_FEATURE_NTPD_SERVER("l") /* NOT compat */
2182 IF_FEATURE_NTPD_SERVER("I:") /* compat */ 2205 IF_FEATURE_NTPD_SERVER("I:") /* compat */
2183 "d" /* compat */ 2206 "d" /* compat */
2184 "46aAbgL", /* compat, ignored */ 2207 "46aAbgL", /* compat, ignored */
@@ -2190,6 +2213,31 @@ static NOINLINE void ntp_init(char **argv)
2190 2213
2191// if (opts & OPT_x) /* disable stepping, only slew is allowed */ 2214// if (opts & OPT_x) /* disable stepping, only slew is allowed */
2192// G.time_was_stepped = 1; 2215// G.time_was_stepped = 1;
2216
2217#if ENABLE_FEATURE_NTPD_SERVER
2218 G_listen_fd = -1;
2219 if (opts & OPT_l) {
2220 G_listen_fd = create_and_bind_dgram_or_die(NULL, 123);
2221 if (G.if_name) {
2222 if (setsockopt_bindtodevice(G_listen_fd, G.if_name))
2223 xfunc_die();
2224 }
2225 socket_want_pktinfo(G_listen_fd);
2226 setsockopt_int(G_listen_fd, IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY);
2227 }
2228#endif
2229 /* I hesitate to set -20 prio. -15 should be high enough for timekeeping */
2230 if (opts & OPT_N)
2231 setpriority(PRIO_PROCESS, 0, -15);
2232
2233 /* add_peers() calls can retry DNS resolution (possibly forever).
2234 * Daemonize before them, or else boot can stall forever.
2235 */
2236 if (!(opts & OPT_n)) {
2237 bb_daemonize_or_rexec(DAEMON_DEVNULL_STDIO, argv);
2238 logmode = LOGMODE_NONE;
2239 }
2240
2193 if (peers) { 2241 if (peers) {
2194 while (peers) 2242 while (peers)
2195 add_peers(llist_pop(&peers)); 2243 add_peers(llist_pop(&peers));
@@ -2218,26 +2266,6 @@ static NOINLINE void ntp_init(char **argv)
2218 /* -l but no peers: "stratum 1 server" mode */ 2266 /* -l but no peers: "stratum 1 server" mode */
2219 G.stratum = 1; 2267 G.stratum = 1;
2220 } 2268 }
2221#if ENABLE_FEATURE_NTPD_SERVER
2222 G_listen_fd = -1;
2223 if (opts & OPT_l) {
2224 G_listen_fd = create_and_bind_dgram_or_die(NULL, 123);
2225 if (opts & OPT_I) {
2226 if (setsockopt_bindtodevice(G_listen_fd, G.if_name))
2227 xfunc_die();
2228 }
2229 socket_want_pktinfo(G_listen_fd);
2230 setsockopt_int(G_listen_fd, IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY);
2231 }
2232#endif
2233 if (!(opts & OPT_n)) {
2234 bb_daemonize_or_rexec(DAEMON_DEVNULL_STDIO, argv);
2235 logmode = LOGMODE_NONE;
2236 }
2237 /* I hesitate to set -20 prio. -15 should be high enough for timekeeping */
2238 if (opts & OPT_N)
2239 setpriority(PRIO_PROCESS, 0, -15);
2240
2241 /* If network is up, syncronization occurs in ~10 seconds. 2269 /* If network is up, syncronization occurs in ~10 seconds.
2242 * We give "ntpd -q" 10 seconds to get first reply, 2270 * We give "ntpd -q" 10 seconds to get first reply,
2243 * then another 50 seconds to finish syncing. 2271 * then another 50 seconds to finish syncing.
@@ -2338,18 +2366,8 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv)
2338 p->p_dotted, p->reachable_bits, timeout); 2366 p->p_dotted, p->reachable_bits, timeout);
2339 2367
2340 /* What if don't see it because it changed its IP? */ 2368 /* What if don't see it because it changed its IP? */
2341 if (p->reachable_bits == 0) { 2369 if (p->reachable_bits == 0)
2342 len_and_sockaddr *lsa = host2sockaddr(p->p_hostname, 123); 2370 resolve_peer_hostname(p, /*loop_on_fail=*/ 0);
2343 if (lsa) {
2344 char *dotted = xmalloc_sockaddr2dotted_noport(&lsa->u.sa);
2345 //if (strcmp(dotted, p->p_dotted) != 0)
2346 // bb_error_msg("peer IP changed");
2347 free(p->p_lsa);
2348 free(p->p_dotted);
2349 p->p_lsa = lsa;
2350 p->p_dotted = dotted;
2351 }
2352 }
2353 2371
2354 set_next(p, timeout); 2372 set_next(p, timeout);
2355 } 2373 }
diff --git a/networking/ping.c b/networking/ping.c
index cfe682646..82d5b7a85 100644
--- a/networking/ping.c
+++ b/networking/ping.c
@@ -186,6 +186,7 @@ create_icmp_socket(void)
186struct globals { 186struct globals {
187 char *hostname; 187 char *hostname;
188 char packet[DEFDATALEN + MAXIPLEN + MAXICMPLEN]; 188 char packet[DEFDATALEN + MAXIPLEN + MAXICMPLEN];
189 uint16_t myid;
189} FIX_ALIASING; 190} FIX_ALIASING;
190#define G (*(struct globals*)bb_common_bufsiz1) 191#define G (*(struct globals*)bb_common_bufsiz1)
191#define INIT_G() do { setup_common_bufsiz(); } while (0) 192#define INIT_G() do { setup_common_bufsiz(); } while (0)
@@ -204,6 +205,7 @@ static void ping4(len_and_sockaddr *lsa)
204 pkt = (struct icmp *) G.packet; 205 pkt = (struct icmp *) G.packet;
205 /*memset(pkt, 0, sizeof(G.packet)); already is */ 206 /*memset(pkt, 0, sizeof(G.packet)); already is */
206 pkt->icmp_type = ICMP_ECHO; 207 pkt->icmp_type = ICMP_ECHO;
208 pkt->icmp_id = G.myid;
207 pkt->icmp_cksum = inet_cksum((uint16_t *) pkt, sizeof(G.packet)); 209 pkt->icmp_cksum = inet_cksum((uint16_t *) pkt, sizeof(G.packet));
208 210
209 xsendto(pingsock, G.packet, DEFDATALEN + ICMP_MINLEN, &lsa->u.sa, lsa->len); 211 xsendto(pingsock, G.packet, DEFDATALEN + ICMP_MINLEN, &lsa->u.sa, lsa->len);
@@ -228,6 +230,8 @@ static void ping4(len_and_sockaddr *lsa)
228 struct iphdr *iphdr = (struct iphdr *) G.packet; 230 struct iphdr *iphdr = (struct iphdr *) G.packet;
229 231
230 pkt = (struct icmp *) (G.packet + (iphdr->ihl << 2)); /* skip ip hdr */ 232 pkt = (struct icmp *) (G.packet + (iphdr->ihl << 2)); /* skip ip hdr */
233 if (pkt->icmp_id != G.myid)
234 continue; /* not our ping */
231 if (pkt->icmp_type == ICMP_ECHOREPLY) 235 if (pkt->icmp_type == ICMP_ECHOREPLY)
232 break; 236 break;
233 } 237 }
@@ -246,6 +250,7 @@ static void ping6(len_and_sockaddr *lsa)
246 pkt = (struct icmp6_hdr *) G.packet; 250 pkt = (struct icmp6_hdr *) G.packet;
247 /*memset(pkt, 0, sizeof(G.packet)); already is */ 251 /*memset(pkt, 0, sizeof(G.packet)); already is */
248 pkt->icmp6_type = ICMP6_ECHO_REQUEST; 252 pkt->icmp6_type = ICMP6_ECHO_REQUEST;
253 pkt->icmp6_id = G.myid;
249 254
250 sockopt = offsetof(struct icmp6_hdr, icmp6_cksum); 255 sockopt = offsetof(struct icmp6_hdr, icmp6_cksum);
251 setsockopt_int(pingsock, SOL_RAW, IPV6_CHECKSUM, sockopt); 256 setsockopt_int(pingsock, SOL_RAW, IPV6_CHECKSUM, sockopt);
@@ -269,6 +274,8 @@ static void ping6(len_and_sockaddr *lsa)
269 continue; 274 continue;
270 } 275 }
271 if (c >= ICMP_MINLEN) { /* icmp6_hdr */ 276 if (c >= ICMP_MINLEN) { /* icmp6_hdr */
277 if (pkt->icmp6_id != G.myid)
278 continue; /* not our ping */
272 if (pkt->icmp6_type == ICMP6_ECHO_REPLY) 279 if (pkt->icmp6_type == ICMP6_ECHO_REPLY)
273 break; 280 break;
274 } 281 }
@@ -317,6 +324,7 @@ static int common_ping_main(sa_family_t af, char **argv)
317 alarm(5); /* give the host 5000ms to respond */ 324 alarm(5); /* give the host 5000ms to respond */
318 325
319 create_icmp_socket(lsa); 326 create_icmp_socket(lsa);
327 G.myid = (uint16_t) getpid();
320#if ENABLE_PING6 328#if ENABLE_PING6
321 if (lsa->u.sa.sa_family == AF_INET6) 329 if (lsa->u.sa.sa_family == AF_INET6)
322 ping6(lsa); 330 ping6(lsa);
@@ -333,7 +341,7 @@ static int common_ping_main(sa_family_t af, char **argv)
333 341
334/* Full(er) version */ 342/* Full(er) version */
335 343
336#define OPT_STRING ("qvc:s:t:w:W:I:np:4" IF_PING6("6")) 344#define OPT_STRING ("qvc:+s:t:+w:+W:+I:np:4" IF_PING6("6"))
337enum { 345enum {
338 OPT_QUIET = 1 << 0, 346 OPT_QUIET = 1 << 0,
339 OPT_VERBOSE = 1 << 1, 347 OPT_VERBOSE = 1 << 1,
@@ -857,7 +865,7 @@ static int common_ping_main(int opt, char **argv)
857 INIT_G(); 865 INIT_G();
858 866
859 /* exactly one argument needed; -v and -q don't mix; -c NUM, -t NUM, -w NUM, -W NUM */ 867 /* exactly one argument needed; -v and -q don't mix; -c NUM, -t NUM, -w NUM, -W NUM */
860 opt_complementary = "=1:q--v:v--q:c+:t+:w+:W+"; 868 opt_complementary = "=1:q--v:v--q";
861 opt |= getopt32(argv, OPT_STRING, &pingcount, &str_s, &opt_ttl, &deadline, &timeout, &str_I, &str_p); 869 opt |= getopt32(argv, OPT_STRING, &pingcount, &str_s, &opt_ttl, &deadline, &timeout, &str_I, &str_p);
862 if (opt & OPT_s) 870 if (opt & OPT_s)
863 datalen = xatou16(str_s); // -s 871 datalen = xatou16(str_s); // -s
diff --git a/networking/tcpudp.c b/networking/tcpudp.c
index 31bc70459..fbd1f1c45 100644
--- a/networking/tcpudp.c
+++ b/networking/tcpudp.c
@@ -232,9 +232,9 @@ int tcpudpsvd_main(int argc UNUSED_PARAM, char **argv)
232 tcp = (applet_name[0] == 't'); 232 tcp = (applet_name[0] == 't');
233 233
234 /* 3+ args, -i at most once, -p implies -h, -v is counter, -b N, -c N */ 234 /* 3+ args, -i at most once, -p implies -h, -v is counter, -b N, -c N */
235 opt_complementary = "-3:i--i:ph:vv:b+:c+"; 235 opt_complementary = "-3:i--i:ph:vv";
236#ifdef SSLSVD 236#ifdef SSLSVD
237 opts = getopt32(argv, "+c:C:i:x:u:l:Eb:hpt:vU:/:Z:K:", 237 opts = getopt32(argv, "+c:+C:i:x:u:l:Eb:+hpt:vU:/:Z:K:",
238 &cmax, &str_C, &instructs, &instructs, &user, &preset_local_hostname, 238 &cmax, &str_C, &instructs, &instructs, &user, &preset_local_hostname,
239 &backlog, &str_t, &ssluser, &root, &cert, &key, &verbose 239 &backlog, &str_t, &ssluser, &root, &cert, &key, &verbose
240 ); 240 );
diff --git a/networking/telnetd.c b/networking/telnetd.c
index 13c36aa46..2fbdc3bb3 100644
--- a/networking/telnetd.c
+++ b/networking/telnetd.c
@@ -496,12 +496,12 @@ int telnetd_main(int argc UNUSED_PARAM, char **argv)
496 INIT_G(); 496 INIT_G();
497 497
498 /* -w NUM, and implies -F. -w and -i don't mix */ 498 /* -w NUM, and implies -F. -w and -i don't mix */
499 IF_FEATURE_TELNETD_INETD_WAIT(opt_complementary = "wF:w+:i--w:w--i";) 499 IF_FEATURE_TELNETD_INETD_WAIT(opt_complementary = "wF:i--w:w--i";)
500 /* Even if !STANDALONE, we accept (and ignore) -i, thus people 500 /* Even if !STANDALONE, we accept (and ignore) -i, thus people
501 * don't need to guess whether it's ok to pass -i to us */ 501 * don't need to guess whether it's ok to pass -i to us */
502 opt = getopt32(argv, "f:l:Ki" 502 opt = getopt32(argv, "f:l:Ki"
503 IF_FEATURE_TELNETD_STANDALONE("p:b:F") 503 IF_FEATURE_TELNETD_STANDALONE("p:b:F")
504 IF_FEATURE_TELNETD_INETD_WAIT("Sw:"), 504 IF_FEATURE_TELNETD_INETD_WAIT("Sw:+"),
505 &G.issuefile, &G.loginpath 505 &G.issuefile, &G.loginpath
506 IF_FEATURE_TELNETD_STANDALONE(, &opt_portnbr, &opt_bindaddr) 506 IF_FEATURE_TELNETD_STANDALONE(, &opt_portnbr, &opt_bindaddr)
507 IF_FEATURE_TELNETD_INETD_WAIT(, &sec_linger) 507 IF_FEATURE_TELNETD_INETD_WAIT(, &sec_linger)
diff --git a/networking/traceroute.c b/networking/traceroute.c
index eee4f8873..e43a36dc7 100644
--- a/networking/traceroute.c
+++ b/networking/traceroute.c
@@ -294,7 +294,7 @@
294 294
295#define OPT_STRING \ 295#define OPT_STRING \
296 "FIlnrdvxt:i:m:p:q:s:w:z:f:" \ 296 "FIlnrdvxt:i:m:p:q:s:w:z:f:" \
297 IF_FEATURE_TRACEROUTE_SOURCE_ROUTE("g:") \ 297 IF_FEATURE_TRACEROUTE_SOURCE_ROUTE("g:*") \
298 "4" IF_TRACEROUTE6("6") 298 "4" IF_TRACEROUTE6("6")
299enum { 299enum {
300 OPT_DONT_FRAGMNT = (1 << 0), /* F */ 300 OPT_DONT_FRAGMNT = (1 << 0), /* F */
@@ -819,7 +819,7 @@ common_traceroute_main(int op, char **argv)
819 INIT_G(); 819 INIT_G();
820 820
821 /* minimum 1 arg */ 821 /* minimum 1 arg */
822 opt_complementary = "-1:x-x" IF_FEATURE_TRACEROUTE_SOURCE_ROUTE(":g::"); 822 opt_complementary = "-1:x-x";
823 op |= getopt32(argv, OPT_STRING 823 op |= getopt32(argv, OPT_STRING
824 , &tos_str, &device, &max_ttl_str, &port_str, &nprobes_str 824 , &tos_str, &device, &max_ttl_str, &port_str, &nprobes_str
825 , &source, &waittime_str, &pausemsecs_str, &first_ttl_str 825 , &source, &waittime_str, &pausemsecs_str, &first_ttl_str
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c
index c77669a31..6ff040d9e 100644
--- a/networking/udhcp/d6_dhcpc.c
+++ b/networking/udhcp/d6_dhcpc.c
@@ -793,7 +793,11 @@ static void perform_renew(void)
793static void perform_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cur_ipv6) 793static void perform_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cur_ipv6)
794{ 794{
795 /* send release packet */ 795 /* send release packet */
796 if (state == BOUND || state == RENEWING || state == REBINDING) { 796 if (state == BOUND
797 || state == RENEWING
798 || state == REBINDING
799 || state == RENEW_REQUESTED
800 ) {
797 bb_error_msg("unicasting a release"); 801 bb_error_msg("unicasting a release");
798 send_d6_release(server_ipv6, our_cur_ipv6); /* unicast */ 802 send_d6_release(server_ipv6, our_cur_ipv6); /* unicast */
799 d6_run_script(NULL, "deconfig"); 803 d6_run_script(NULL, "deconfig");
@@ -940,9 +944,9 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
940 944
941 /* Parse command line */ 945 /* Parse command line */
942 /* O,x: list; -T,-t,-A take numeric param */ 946 /* O,x: list; -T,-t,-A take numeric param */
943 opt_complementary = "O::x::T+:t+:A+" IF_UDHCP_VERBOSE(":vv") ; 947 IF_UDHCP_VERBOSE(opt_complementary = "vv";)
944 IF_LONG_OPTS(applet_long_options = udhcpc6_longopts;) 948 IF_LONG_OPTS(applet_long_options = udhcpc6_longopts;)
945 opt = getopt32(argv, "i:np:qRr:s:T:t:SA:O:ox:f" 949 opt = getopt32(argv, "i:np:qRr:s:T:+t:+SA:+O:*ox:*f"
946 USE_FOR_MMU("b") 950 USE_FOR_MMU("b")
947 ///IF_FEATURE_UDHCPC_ARPING("a") 951 ///IF_FEATURE_UDHCPC_ARPING("a")
948 IF_FEATURE_UDHCP_PORT("P:") 952 IF_FEATURE_UDHCP_PORT("P:")
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index fc7b6216d..8a16e987d 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)
1118 struct in_addr temp_addr; 1118 struct in_addr temp_addr;
1119 1119
1120 /* send release packet */ 1120 /* send release packet */
1121 if (state == BOUND || state == RENEWING || state == REBINDING) { 1121 if (state == BOUND
1122 || state == RENEWING
1123 || state == REBINDING
1124 || state == RENEW_REQUESTED
1125 ) {
1122 temp_addr.s_addr = server_addr; 1126 temp_addr.s_addr = server_addr;
1123 strcpy(buffer, inet_ntoa(temp_addr)); 1127 strcpy(buffer, inet_ntoa(temp_addr));
1124 temp_addr.s_addr = requested_ip; 1128 temp_addr.s_addr = requested_ip;
@@ -1279,9 +1283,9 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1279 1283
1280 /* Parse command line */ 1284 /* Parse command line */
1281 /* O,x: list; -T,-t,-A take numeric param */ 1285 /* O,x: list; -T,-t,-A take numeric param */
1282 opt_complementary = "O::x::T+:t+:A+" IF_UDHCP_VERBOSE(":vv") ; 1286 IF_UDHCP_VERBOSE(opt_complementary = "vv";)
1283 IF_LONG_OPTS(applet_long_options = udhcpc_longopts;) 1287 IF_LONG_OPTS(applet_long_options = udhcpc_longopts;)
1284 opt = getopt32(argv, "CV:H:h:F:i:np:qRr:s:T:t:SA:O:ox:fB" 1288 opt = getopt32(argv, "CV:H:h:F:i:np:qRr:s:T:+t:+SA:+O:*ox:*fB"
1285 USE_FOR_MMU("b") 1289 USE_FOR_MMU("b")
1286 IF_FEATURE_UDHCPC_ARPING("a::") 1290 IF_FEATURE_UDHCPC_ARPING("a::")
1287 IF_FEATURE_UDHCP_PORT("P:") 1291 IF_FEATURE_UDHCP_PORT("P:")
diff --git a/networking/wget.c b/networking/wget.c
index c725edb5b..c886dd391 100644
--- a/networking/wget.c
+++ b/networking/wget.c
@@ -1274,9 +1274,8 @@ IF_DESKTOP( "no-parent\0" No_argument "\xf0")
1274 applet_long_options = wget_longopts; 1274 applet_long_options = wget_longopts;
1275#endif 1275#endif
1276 opt_complementary = "-1" /* at least one URL */ 1276 opt_complementary = "-1" /* at least one URL */
1277 IF_FEATURE_WGET_TIMEOUT(":T+") /* -T NUM */
1278 IF_FEATURE_WGET_LONG_OPTIONS(":\xff::"); /* --header is a list */ 1277 IF_FEATURE_WGET_LONG_OPTIONS(":\xff::"); /* --header is a list */
1279 getopt32(argv, "csqO:P:Y:U:T:" 1278 getopt32(argv, "csqO:P:Y:U:T:+"
1280 /*ignored:*/ "t:" 1279 /*ignored:*/ "t:"
1281 /*ignored:*/ "n::" 1280 /*ignored:*/ "n::"
1282 /* wget has exactly four -n<letter> opts, all of which we can ignore: 1281 /* wget has exactly four -n<letter> opts, all of which we can ignore:
diff --git a/networking/whois.c b/networking/whois.c
index bf330334a..c9dfcf5ee 100644
--- a/networking/whois.c
+++ b/networking/whois.c
@@ -21,43 +21,158 @@
21//kbuild:lib-$(CONFIG_WHOIS) += whois.o 21//kbuild:lib-$(CONFIG_WHOIS) += whois.o
22 22
23//usage:#define whois_trivial_usage 23//usage:#define whois_trivial_usage
24//usage: "[-h SERVER] [-p PORT] NAME..." 24//usage: "[-i] [-h SERVER] [-p PORT] NAME..."
25//usage:#define whois_full_usage "\n\n" 25//usage:#define whois_full_usage "\n\n"
26//usage: "Query WHOIS info about NAME\n" 26//usage: "Query WHOIS info about NAME\n"
27//usage: "\n -i Show redirect results too"
27//usage: "\n -h,-p Server to query" 28//usage: "\n -h,-p Server to query"
28 29
29#include "libbb.h" 30#include "libbb.h"
30 31
31static void pipe_out(int fd) 32enum {
33 OPT_i = (1 << 0),
34};
35
36static char *query(const char *host, int port, const char *domain)
32{ 37{
38 int fd;
33 FILE *fp; 39 FILE *fp;
34 char buf[1024]; 40 bool success;
41 char *redir = NULL;
42 const char *pfx = "";
43 char linebuf[1024];
44 char *buf = NULL;
45 unsigned bufpos = 0;
35 46
47 again:
48 printf("[Querying %s:%d '%s%s']\n", host, port, pfx, domain);
49 fd = create_and_connect_stream_or_die(host, port);
50 success = 0;
51 fdprintf(fd, "%s%s\r\n", pfx, domain);
36 fp = xfdopen_for_read(fd); 52 fp = xfdopen_for_read(fd);
37 while (fgets(buf, sizeof(buf), fp)) {
38 char *p = strpbrk(buf, "\r\n");
39 if (p)
40 *p = '\0';
41 puts(buf);
42 }
43 53
54 while (fgets(linebuf, sizeof(linebuf), fp)) {
55 unsigned len = strcspn(linebuf, "\r\n");
56 linebuf[len++] = '\n';
57
58 buf = xrealloc(buf, bufpos + len + 1);
59 memcpy(buf + bufpos, linebuf, len);
60 bufpos += len;
61 buf[bufpos] = '\0';
62
63 if (!redir || !success) {
64 trim(linebuf);
65 str_tolower(linebuf);
66 if (!success) {
67 success = is_prefixed_with(linebuf, "domain:")
68 || is_prefixed_with(linebuf, "domain name:");
69 }
70 else if (!redir) {
71 char *p = is_prefixed_with(linebuf, "whois server:");
72 if (!p)
73 p = is_prefixed_with(linebuf, "whois:");
74 if (p)
75 redir = xstrdup(skip_whitespace(p));
76 }
77 }
78 }
44 fclose(fp); /* closes fd too */ 79 fclose(fp); /* closes fd too */
80 if (!success && !pfx[0]) {
81 /*
82 * Looking at /etc/jwhois.conf, some whois servers use
83 * "domain = DOMAIN", "DOMAIN ID <DOMAIN>"
84 * and "domain=DOMAIN_WITHOUT_LAST_COMPONENT"
85 * formats, but those are rare.
86 * (There are a few even more contrived ones.)
87 * We are trying only "domain DOMAIN", the typical one.
88 */
89 pfx = "domain ";
90 bufpos = 0;
91 goto again;
92 }
93
94 /* Success */
95 if (redir && strcmp(redir, host) == 0) {
96 /* Redirect to self does not count */
97 free(redir);
98 redir = NULL;
99 }
100 if (!redir || (option_mask32 & OPT_i)) {
101 /* Output saved text */
102 printf("[%s]\n%s", host, buf ? buf : "");
103 }
104 free(buf);
105 return redir;
106}
107
108static void recursive_query(const char *host, int port, const char *domain)
109{
110 char *free_me = NULL;
111 char *redir;
112 again:
113 redir = query(host, port, domain);
114 free(free_me);
115 if (redir) {
116 printf("[Redirected to %s]\n", redir);
117 host = free_me = redir;
118 port = 43;
119 goto again;
120 }
45} 121}
46 122
123/* One of "big" whois implementations has these options:
124 *
125 * $ whois --help
126 * jwhois version 4.0, Copyright (C) 1999-2007 Free Software Foundation, Inc.
127 * -v, --verbose verbose debug output
128 * -c FILE, --config=FILE use FILE as configuration file
129 * -h HOST, --host=HOST explicitly query HOST
130 * -n, --no-redirect disable content redirection
131 * -s, --no-whoisservers disable whois-servers.net service support
132 * -a, --raw disable reformatting of the query
133 * -i, --display-redirections display all redirects instead of hiding them
134 * -p PORT, --port=PORT use port number PORT (in conjunction with HOST)
135 * -r, --rwhois force an rwhois query to be made
136 * --rwhois-display=DISPLAY sets the display option in rwhois queries
137 * --rwhois-limit=LIMIT sets the maximum number of matches to return
138 *
139 * Example of its output:
140 * $ whois cnn.com
141 * [Querying whois.verisign-grs.com]
142 * [Redirected to whois.corporatedomains.com]
143 * [Querying whois.corporatedomains.com]
144 * [whois.corporatedomains.com]
145 * ...text of the reply...
146 *
147 * With -i, reply from each server is printed, after all redirects are done:
148 * [Querying whois.verisign-grs.com]
149 * [Redirected to whois.corporatedomains.com]
150 * [Querying whois.corporatedomains.com]
151 * [whois.verisign-grs.com]
152 * ...text of the reply...
153 * [whois.corporatedomains.com]
154 * ...text of the reply...
155 *
156 * With -a, no "DOMAIN" -> "domain DOMAIN" transformation is attempted.
157
158 * With -n, the first reply is shown, redirects are not followed:
159 * [Querying whois.verisign-grs.com]
160 * [whois.verisign-grs.com]
161 * ...text of the reply...
162 */
163
47int whois_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 164int whois_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
48int whois_main(int argc UNUSED_PARAM, char **argv) 165int whois_main(int argc UNUSED_PARAM, char **argv)
49{ 166{
50 int port = 43; 167 int port = 43;
51 const char *host = "whois-servers.net"; 168 const char *host = "whois.iana.org";
52
53 opt_complementary = "-1:p+";
54 getopt32(argv, "h:p:", &host, &port);
55 169
170 opt_complementary = "-1";
171 getopt32(argv, "ih:p:+", &host, &port);
56 argv += optind; 172 argv += optind;
173
57 do { 174 do {
58 int fd = create_and_connect_stream_or_die(host, port); 175 recursive_query(host, port, *argv);
59 fdprintf(fd, "%s\r\n", *argv);
60 pipe_out(fd);
61 } 176 }
62 while (*++argv); 177 while (*++argv);
63 178
diff --git a/procps/pgrep.c b/procps/pgrep.c
index 1c7c7c48b..1c594cf96 100644
--- a/procps/pgrep.c
+++ b/procps/pgrep.c
@@ -106,8 +106,7 @@ int pgrep_main(int argc UNUSED_PARAM, char **argv)
106 /* Parse remaining options */ 106 /* Parse remaining options */
107 ppid2match = -1; 107 ppid2match = -1;
108 sid2match = -1; 108 sid2match = -1;
109 opt_complementary = "s+:P+"; /* numeric opts */ 109 opt = getopt32(argv, "vlfxons:+P:+", &sid2match, &ppid2match);
110 opt = getopt32(argv, "vlfxons:P:", &sid2match, &ppid2match);
111 argv += optind; 110 argv += optind;
112 111
113 if (pkill && OPT_LIST) { /* -l: print the whole signal list */ 112 if (pkill && OPT_LIST) { /* -l: print the whole signal list */
diff --git a/procps/pidof.c b/procps/pidof.c
index 6d7b59109..6d265667f 100644
--- a/procps/pidof.c
+++ b/procps/pidof.c
@@ -51,13 +51,12 @@ int pidof_main(int argc UNUSED_PARAM, char **argv)
51 unsigned opt; 51 unsigned opt;
52#if ENABLE_FEATURE_PIDOF_OMIT 52#if ENABLE_FEATURE_PIDOF_OMIT
53 llist_t *omits = NULL; /* list of pids to omit */ 53 llist_t *omits = NULL; /* list of pids to omit */
54 opt_complementary = "o::";
55#endif 54#endif
56 55
57 /* do unconditional option parsing */ 56 /* do unconditional option parsing */
58 opt = getopt32(argv, "" 57 opt = getopt32(argv, ""
59 IF_FEATURE_PIDOF_SINGLE ("s") 58 IF_FEATURE_PIDOF_SINGLE ("s")
60 IF_FEATURE_PIDOF_OMIT("o:", &omits)); 59 IF_FEATURE_PIDOF_OMIT("o:*", &omits));
61 60
62#if ENABLE_FEATURE_PIDOF_OMIT 61#if ENABLE_FEATURE_PIDOF_OMIT
63 /* fill omit list. */ 62 /* fill omit list. */
diff --git a/procps/ps.c b/procps/ps.c
index 39cccec82..c9d33daf4 100644
--- a/procps/ps.c
+++ b/procps/ps.c
@@ -609,8 +609,7 @@ int ps_main(int argc UNUSED_PARAM, char **argv)
609 * procps v3.2.7 supports -T and shows tids as SPID column, 609 * procps v3.2.7 supports -T and shows tids as SPID column,
610 * it also supports -L where it shows tids as LWP column. 610 * it also supports -L where it shows tids as LWP column.
611 */ 611 */
612 opt_complementary = "o::"; 612 opt = getopt32(argv, "Zo:*aAdefl"IF_FEATURE_SHOW_THREADS("T"), &opt_o);
613 opt = getopt32(argv, "Zo:aAdefl"IF_FEATURE_SHOW_THREADS("T"), &opt_o);
614 if (opt_o) { 613 if (opt_o) {
615 do { 614 do {
616 parse_o(llist_pop(&opt_o)); 615 parse_o(llist_pop(&opt_o));
diff --git a/procps/watch.c b/procps/watch.c
index 97aa04767..20859c3cd 100644
--- a/procps/watch.c
+++ b/procps/watch.c
@@ -51,9 +51,9 @@ int watch_main(int argc UNUSED_PARAM, char **argv)
51 xopen("/dev/null", O_RDONLY); 51 xopen("/dev/null", O_RDONLY);
52#endif 52#endif
53 53
54 opt_complementary = "-1:n+"; // at least one param; -n NUM 54 opt_complementary = "-1"; // at least one param; -n NUM
55 // "+": stop at first non-option (procps 3.x only) 55 // "+": stop at first non-option (procps 3.x only)
56 opt = getopt32(argv, "+dtn:", &period); 56 opt = getopt32(argv, "+dtn:+", &period);
57 argv += optind; 57 argv += optind;
58 58
59 // watch from both procps 2.x and 3.x does concatenation. Example: 59 // watch from both procps 2.x and 3.x does concatenation. Example:
diff --git a/runit/chpst.c b/runit/chpst.c
index 7fe5151db..3769af25e 100644
--- a/runit/chpst.c
+++ b/runit/chpst.c
@@ -300,8 +300,8 @@ int chpst_main(int argc UNUSED_PARAM, char **argv)
300 // FIXME: can we live with int-sized limits? 300 // FIXME: can we live with int-sized limits?
301 // can we live with 40000 days? 301 // can we live with 40000 days?
302 // if yes -> getopt converts strings to numbers for us 302 // if yes -> getopt converts strings to numbers for us
303 opt_complementary = "-1:a+:c+:d+:f+:l+:m+:o+:p+:r+:s+:t+"; 303 opt_complementary = "-1";
304 opt = getopt32(argv, "+a:c:d:f:l:m:o:p:r:s:t:u:U:e:" 304 opt = getopt32(argv, "+a:+c:+d:+f:+l:+m:+o:+p:+r:+s:+t:+u:U:e:"
305 IF_CHPST("/:n:vP012"), 305 IF_CHPST("/:n:vP012"),
306 &limita, &limitc, &limitd, &limitf, &limitl, 306 &limita, &limitc, &limitd, &limitf, &limitl,
307 &limitm, &limito, &limitp, &limitr, &limits, &limitt, 307 &limitm, &limito, &limitp, &limitr, &limits, &limitt,
diff --git a/runit/sv.c b/runit/sv.c
index 2a256a6b4..37df9a929 100644
--- a/runit/sv.c
+++ b/runit/sv.c
@@ -474,8 +474,8 @@ int sv_main(int argc UNUSED_PARAM, char **argv)
474 x = getenv("SVWAIT"); 474 x = getenv("SVWAIT");
475 if (x) waitsec = xatou(x); 475 if (x) waitsec = xatou(x);
476 476
477 opt_complementary = "w+:vv"; /* -w N, -v is a counter */ 477 opt_complementary = "vv"; /* -w N, -v is a counter */
478 getopt32(argv, "w:v", &waitsec, &verbose); 478 getopt32(argv, "w:+v", &waitsec, &verbose);
479 argv += optind; 479 argv += optind;
480 action = *argv++; 480 action = *argv++;
481 if (!action || !*argv) bb_show_usage(); 481 if (!action || !*argv) bb_show_usage();
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() {
36} 36}
37 37
38generate_big_and_exit() { 38generate_big_and_exit() {
39 $debug && echo "Configuring: bb_common_bufsiz1[] in _end[], COMMON_BUFSIZE = $1" 39 $debug && echo "Configuring: bb_common_bufsiz1[] in bss, COMMON_BUFSIZE = $1"
40 { 40 {
41 echo "enum { COMMON_BUFSIZE = $1 };" 41 echo "enum { COMMON_BUFSIZE = $1 };"
42 echo "extern char _end[]; /* linker-provided label */" 42 echo "extern char bb_common_bufsiz1[];"
43 echo "#define bb_common_bufsiz1 _end"
44 echo "#define setup_common_bufsiz() ((void)0)" 43 echo "#define setup_common_bufsiz() ((void)0)"
45 } | regenerate "$common_bufsiz_h" 44 } | regenerate "$common_bufsiz_h"
46 echo "$2" >"$common_bufsiz_h.method" 45 echo "$2" >"$common_bufsiz_h.method"
@@ -51,20 +50,10 @@ generate_1k_and_exit() {
51 generate_big_and_exit 1024 "1k" 50 generate_big_and_exit 1024 "1k"
52} 51}
53 52
54
55generate_malloc_and_exit() {
56 $debug && echo "Configuring: bb_common_bufsiz1[] is malloced"
57 {
58 echo "enum { COMMON_BUFSIZE = 1024 };"
59 echo "extern char *const bb_common_bufsiz1;"
60 echo "void setup_common_bufsiz(void);"
61 } | regenerate "$common_bufsiz_h"
62 echo "malloc" >"$common_bufsiz_h.method"
63 $exitcmd
64}
65
66round_down_COMMON_BUFSIZE() { 53round_down_COMMON_BUFSIZE() {
67 COMMON_BUFSIZE=$(( ($1-32) & 0xfffffe0 )) 54 COMMON_BUFSIZE=1024
55 test "$1" -le 32 && return
56 COMMON_BUFSIZE=$(( ($1-32) & 0x0ffffff0 ))
68 COMMON_BUFSIZE=$(( COMMON_BUFSIZE < 1024 ? 1024 : COMMON_BUFSIZE )) 57 COMMON_BUFSIZE=$(( COMMON_BUFSIZE < 1024 ? 1024 : COMMON_BUFSIZE ))
69} 58}
70 59
@@ -104,77 +93,44 @@ if $postcompile; then
104 test x"$PAGE_SIZE" = x"" && exit 1 93 test x"$PAGE_SIZE" = x"" && exit 1
105 $debug && echo "PAGE_SIZE:0x$PAGE_SIZE $((0x$PAGE_SIZE))" 94 $debug && echo "PAGE_SIZE:0x$PAGE_SIZE $((0x$PAGE_SIZE))"
106 PAGE_SIZE=$((0x$PAGE_SIZE)) 95 PAGE_SIZE=$((0x$PAGE_SIZE))
107 test $PAGE_SIZE -lt 512 && exit 1 96 test $PAGE_SIZE -lt 1024 && exit 1
108 97
109 # How much space between _end[] and next page? 98 # How much space between _end[] and next page?
110 PAGE_MASK=$((PAGE_SIZE-1)) 99 PAGE_MASK=$((PAGE_SIZE-1))
111 TAIL_SIZE=$(( (-END) & PAGE_MASK )) 100 TAIL_SIZE=$(( (-END) & PAGE_MASK ))
112 $debug && echo "TAIL_SIZE:$TAIL_SIZE bytes" 101 $debug && echo "TAIL_SIZE:$TAIL_SIZE bytes"
113 102
114 if test x"$method" = x"1k" || test x"$method" = x"big"; then 103 if test x"$method" = x"1k"; then
115 if test $TAIL_SIZE -lt 1024; then 104 {
116 # _end[] has no enough space for bb_common_bufsiz1[] 105 echo $TAIL_SIZE
117 echo "Warning! Space in _end[] is too small ($TAIL_SIZE bytes)!" 106 md5sum <.config | cut -d' ' -f1
118 echo "Rerun make to build a binary which doesn't use it!" 107 stat -c "%Y" .config
119 rm -- "$common_bufsiz_h.1k.OK" 2>/dev/null 108 } >"$common_bufsiz_h.1k.OK"
120 { md5sum <.config | cut -d' ' -f1; stat -c "%Y" .config; } >"$common_bufsiz_h.1k.FAIL" 109 round_down_COMMON_BUFSIZE $((1024 + TAIL_SIZE))
121 rm busybox_unstripped busybox 2>/dev/null 110 # emit message only if COMMON_BUFSIZE is indeed larger
122# Note: here we can do either a "malloc" or "std" build. 111 test $COMMON_BUFSIZE -gt 1024 \
123# "malloc" gives a bit bigger code: 112 && echo "Rerun make to use larger COMMON_BUFSIZE ($COMMON_BUFSIZE)"
124# text bss filename 113 test $COMMON_BUFSIZE = 1024 && generate_1k_and_exit
125# 804355 5385 busybox.std 114 generate_big_and_exit $COMMON_BUFSIZE "big"
126# 804618 4361 busybox.malloc
127# but may have a smaller .bss (not guaranteed!). Use "pmap -x" to verify.
128 exitcmd="exit 1"
129 generate_malloc_and_exit
130 else
131 PREV_SIZE=1024
132 test x"$method" = x"big" && PREV_SIZE=`cat -- "$common_bufsiz_h.1k.OK"`
133 round_down_COMMON_BUFSIZE $PREV_SIZE
134 PREV_BUFSIZE=$COMMON_BUFSIZE
135
136 rm -- "$common_bufsiz_h.1k.FAIL" 2>/dev/null
137 echo $TAIL_SIZE >"$common_bufsiz_h.1k.OK"
138 round_down_COMMON_BUFSIZE $TAIL_SIZE
139 # emit message only if COMMON_BUFSIZE is indeed larger
140 test $COMMON_BUFSIZE -gt $PREV_BUFSIZE \
141 && echo "Rerun make to use larger COMMON_BUFSIZE ($COMMON_BUFSIZE)"
142#TODO: test $PREV_BUFSIZE -lt $TAIL_SIZE && PANIC!!!
143#Code size with COMMON_BUFSIZE > 1024 may be bigger than code with COMMON_BUFSIZE = 1024!
144#(currently we just hope "-32 and round down to 32" saves us)
145
146 test $COMMON_BUFSIZE = 1024 && generate_1k_and_exit
147 generate_big_and_exit $COMMON_BUFSIZE "big"
148 fi
149 fi 115 fi
150fi 116fi
151 117
152# Based on past success/fail of 1k build, decide next build type 118# Based on past success/fail of 1k build, decide next build type
153 119
154if test -f "$common_bufsiz_h.1k.OK"; then 120if test -f "$common_bufsiz_h.1k.OK"; then
155 # Previous build succeeded fitting 1k into _end[]. 121 # previous 1k build succeeded
156 # Try bigger COMMON_BUFSIZE if possible. 122 oldcfg=`tail -n2 -- "$common_bufsiz_h.1k.OK"`
157 TAIL_SIZE=`cat -- "$common_bufsiz_h.1k.OK"`
158 round_down_COMMON_BUFSIZE $TAIL_SIZE
159 test $COMMON_BUFSIZE = 1024 && generate_1k_and_exit
160 generate_big_and_exit $COMMON_BUFSIZE "big"
161fi
162
163if test -f "$common_bufsiz_h.1k.FAIL"; then
164 # Previous build FAILED to fit 1k into _end[].
165 # Was it with same .config?
166 oldcfg=`cat -- "$common_bufsiz_h.1k.FAIL"`
167 curcfg=`md5sum <.config | cut -d' ' -f1; stat -c "%Y" .config` 123 curcfg=`md5sum <.config | cut -d' ' -f1; stat -c "%Y" .config`
168 # If yes, then build a "malloced" version 124 # config did not change
169 if test x"$oldcfg" = x"$curcfg"; then 125 if test x"$oldcfg" = x"$curcfg"; then
170 echo "Will not try 1k build, it failed before. Touch .config to override" 126 # Try bigger COMMON_BUFSIZE if possible
171# Note: here we can do either a "malloc" or "std" build. 127 TAIL_SIZE=`head -n1 -- "$common_bufsiz_h.1k.OK"`
172 generate_malloc_and_exit 128 round_down_COMMON_BUFSIZE $((1024 + TAIL_SIZE))
129 test $COMMON_BUFSIZE = 1024 && generate_1k_and_exit
130 generate_big_and_exit $COMMON_BUFSIZE "big"
173 fi 131 fi
174 # else: try 1k version 132 # config did change
175 echo "New .config, will try 1k build" 133 rm -rf -- "$common_bufsiz_h.1k.OK"
176 rm -- "$common_bufsiz_h.1k.FAIL"
177 generate_1k_and_exit
178fi 134fi
179 135
180# There was no 1k build yet. Try it. 136# There was no 1k build yet. Try it.
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 @@
32struct kconf_id; 32struct kconf_id;
33/* maximum key range = 45, duplicates = 0 */ 33/* maximum key range = 45, duplicates = 0 */
34 34
35#ifdef __GNUC__ 35unsigned int
36__inline
37#else
38#ifdef __cplusplus
39inline
40#endif
41#endif
42static unsigned int
43kconf_id_hash (register const char *str, register unsigned int len) 36kconf_id_hash (register const char *str, register unsigned int len)
44{ 37{
45 static unsigned char asso_values[] = 38 static unsigned char asso_values[] =
@@ -119,7 +112,7 @@ struct kconf_id_strings_t
119 char kconf_id_strings_str41[sizeof("choice")]; 112 char kconf_id_strings_str41[sizeof("choice")];
120 char kconf_id_strings_str46[sizeof("prompt")]; 113 char kconf_id_strings_str46[sizeof("prompt")];
121 }; 114 };
122static struct kconf_id_strings_t kconf_id_strings_contents = 115struct kconf_id_strings_t kconf_id_strings_contents =
123 { 116 {
124 "if", 117 "if",
125 "int", 118 "int",
@@ -153,9 +146,6 @@ static struct kconf_id_strings_t kconf_id_strings_contents =
153 "prompt" 146 "prompt"
154 }; 147 };
155#define kconf_id_strings ((const char *) &kconf_id_strings_contents) 148#define kconf_id_strings ((const char *) &kconf_id_strings_contents)
156#ifdef __GNUC__
157__inline
158#endif
159struct kconf_id * 149struct kconf_id *
160kconf_id_lookup (register const char *str, register unsigned int len) 150kconf_id_lookup (register const char *str, register unsigned int len)
161{ 151{
diff --git a/scripts/randomtest b/scripts/randomtest
index e2513d058..287f1c771 100755
--- a/scripts/randomtest
+++ b/scripts/randomtest
@@ -52,9 +52,18 @@ echo '# CONFIG_RFKILL is not set' >>.config
52if test x"$LIBC" = x"glibc"; then 52if test x"$LIBC" = x"glibc"; then
53 cat .config \ 53 cat .config \
54 | grep -v CONFIG_STATIC \ 54 | grep -v CONFIG_STATIC \
55 \
56 | grep -v CONFIG_FEATURE_2_4_MODULES \
57 | grep -v CONFIG_FEATURE_USE_BSS_TAIL \
58 | grep -v CONFIG_DEBUG_SANITIZE \
55 >.config.new 59 >.config.new
56 mv .config.new .config 60 mv .config.new .config
57 echo '# CONFIG_STATIC is not set' >>.config 61 echo '# CONFIG_STATIC is not set' >>.config
62 # newer glibc (at least 2.23) no longer supply query_module() ABI.
63 # People who target 2.4 kernels would likely use older glibc (and older bbox).
64 echo '# CONFIG_FEATURE_2_4_MODULES is not set' >>.config
65 echo '# CONFIG_FEATURE_USE_BSS_TAIL is not set' >>.config
66 echo '# CONFIG_DEBUG_SANITIZE is not set' >>.config
58fi 67fi
59 68
60# If uclibc, build static, and remove some things 69# If uclibc, build static, and remove some things
@@ -68,6 +77,11 @@ if test x"$LIBC" = x"uclibc"; then
68 | grep -v CONFIG_FEATURE_2_4_MODULES \ 77 | grep -v CONFIG_FEATURE_2_4_MODULES \
69 | grep -v CONFIG_FEATURE_SYNC_FANCY \ 78 | grep -v CONFIG_FEATURE_SYNC_FANCY \
70 | grep -v CONFIG_FEATURE_TOUCH_NODEREF \ 79 | grep -v CONFIG_FEATURE_TOUCH_NODEREF \
80 | grep -v CONFIG_NANDWRITE \
81 | grep -v CONFIG_NANDDUMP \
82 | grep -v CONFIG_BLKDISCARD \
83 | grep -v CONFIG_NSENTER \
84 | grep -v CONFIG_UNSHARE \
71 >.config.new 85 >.config.new
72 mv .config.new .config 86 mv .config.new .config
73 echo 'CONFIG_STATIC=y' >>.config 87 echo 'CONFIG_STATIC=y' >>.config
@@ -76,6 +90,12 @@ if test x"$LIBC" = x"uclibc"; then
76 echo '# CONFIG_FEATURE_2_4_MODULES is not set' >>.config 90 echo '# CONFIG_FEATURE_2_4_MODULES is not set' >>.config
77 echo '# CONFIG_FEATURE_SYNC_FANCY is not set' >>.config 91 echo '# CONFIG_FEATURE_SYNC_FANCY is not set' >>.config
78 echo '# CONFIG_FEATURE_TOUCH_NODEREF is not set' >>.config 92 echo '# CONFIG_FEATURE_TOUCH_NODEREF is not set' >>.config
93 # My uclibc installation does not support some needed APIs...
94 echo '# CONFIG_NANDWRITE is not set' >>.config
95 echo '# CONFIG_NANDDUMP is not set' >>.config
96 echo '# CONFIG_BLKDISCARD is not set' >>.config
97 echo '# CONFIG_NSENTER is not set' >>.config
98 echo '# CONFIG_UNSHARE is not set' >>.config
79fi 99fi
80 100
81# If STATIC, remove some things. 101# If STATIC, remove some things.
@@ -95,6 +115,8 @@ fi
95 115
96# Build! 116# Build!
97nice -n 10 make $MAKEOPTS 2>&1 | tee make.log 117nice -n 10 make $MAKEOPTS 2>&1 | tee make.log
118grep 'Rerun make' make.log \
119&& nice -n 10 make $MAKEOPTS 2>&1 | tee -a make.log
98 120
99# Return exitcode 1 if busybox executable does not exist 121# Return exitcode 1 if busybox executable does not exist
100test -x busybox 122test -x busybox
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
293 echo "Linking individual applets against libbusybox (see $sharedlib_dir/*)" 293 echo "Linking individual applets against libbusybox (see $sharedlib_dir/*)"
294 gcc -DNAME_MAIN -E -include include/autoconf.h include/applets.h \ 294 gcc -DNAME_MAIN -E -include include/autoconf.h include/applets.h \
295 | grep -v "^#" \ 295 | grep -v "^#" \
296 | grep -v "^$" \ 296 | grep -v "^ *$" \
297 > applet_lst.tmp 297 > applet_lst.tmp
298 while read name main junk; do 298 while read name main junk; do
299 299
diff --git a/selinux/setfiles.c b/selinux/setfiles.c
index 51a7e63bd..c9597d54e 100644
--- a/selinux/setfiles.c
+++ b/selinux/setfiles.c
@@ -577,13 +577,13 @@ int setfiles_main(int argc UNUSED_PARAM, char **argv)
577 577
578 set_matchpathcon_flags(matchpathcon_flags); 578 set_matchpathcon_flags(matchpathcon_flags);
579 579
580 opt_complementary = "e::vv:v--p:p--v:v--q:q--v"; 580 opt_complementary = "vv:v--p:p--v:v--q:q--v";
581 /* Option order must match OPT_x definitions! */ 581 /* Option order must match OPT_x definitions! */
582 if (applet_name[0] == 'r') { /* restorecon */ 582 if (applet_name[0] == 'r') { /* restorecon */
583 flags = getopt32(argv, "de:f:ilnpqrsvo:FWR", 583 flags = getopt32(argv, "de:*f:ilnpqrsvo:FWR",
584 &exclude_dir, &input_filename, &out_filename, &verbose); 584 &exclude_dir, &input_filename, &out_filename, &verbose);
585 } else { /* setfiles */ 585 } else { /* setfiles */
586 flags = getopt32(argv, "de:f:ilnpqr:svo:FW" 586 flags = getopt32(argv, "de:*f:ilnpqr:svo:FW"
587 IF_FEATURE_SETFILES_CHECK_OPTION("c:"), 587 IF_FEATURE_SETFILES_CHECK_OPTION("c:"),
588 &exclude_dir, &input_filename, &rootpath, &out_filename, 588 &exclude_dir, &input_filename, &rootpath, &out_filename,
589 IF_FEATURE_SETFILES_CHECK_OPTION(&policyfile,) 589 IF_FEATURE_SETFILES_CHECK_OPTION(&policyfile,)
diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c
index a119bdeae..ae0840bff 100644
--- a/sysklogd/syslogd.c
+++ b/sysklogd/syslogd.c
@@ -342,7 +342,7 @@ enum {
342#define OPTION_STR "m:nO:l:S" \ 342#define OPTION_STR "m:nO:l:S" \
343 IF_FEATURE_ROTATE_LOGFILE("s:" ) \ 343 IF_FEATURE_ROTATE_LOGFILE("s:" ) \
344 IF_FEATURE_ROTATE_LOGFILE("b:" ) \ 344 IF_FEATURE_ROTATE_LOGFILE("b:" ) \
345 IF_FEATURE_REMOTE_LOG( "R:" ) \ 345 IF_FEATURE_REMOTE_LOG( "R:*") \
346 IF_FEATURE_REMOTE_LOG( "L" ) \ 346 IF_FEATURE_REMOTE_LOG( "L" ) \
347 IF_FEATURE_IPC_SYSLOG( "C::") \ 347 IF_FEATURE_IPC_SYSLOG( "C::") \
348 IF_FEATURE_SYSLOGD_DUP( "D" ) \ 348 IF_FEATURE_SYSLOGD_DUP( "D" ) \
@@ -1108,8 +1108,8 @@ int syslogd_main(int argc UNUSED_PARAM, char **argv)
1108 1108
1109 INIT_G(); 1109 INIT_G();
1110 1110
1111 /* No non-option params, -R can occur multiple times */ 1111 /* No non-option params */
1112 opt_complementary = "=0" IF_FEATURE_REMOTE_LOG(":R::"); 1112 opt_complementary = "=0";
1113 opts = getopt32(argv, OPTION_STR, OPTION_PARAM); 1113 opts = getopt32(argv, OPTION_STR, OPTION_PARAM);
1114#if ENABLE_FEATURE_REMOTE_LOG 1114#if ENABLE_FEATURE_REMOTE_LOG
1115 while (remoteAddrList) { 1115 while (remoteAddrList) {
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" \
15 "$(md5sum <README)\n" \ 15 "$(md5sum <README)\n" \
16 "" \ 16 "" \
17 "" 17 ""
18rm test.a 18rm test.a 2>/dev/null
19 19
20testing "ar replaces things in archives" \ 20testing "ar replaces things in archives" \
21 "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" \ 21 "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/busybox.tests b/testsuite/busybox.tests
index 04fea3ea2..545cad5c0 100755
--- a/testsuite/busybox.tests
+++ b/testsuite/busybox.tests
@@ -6,6 +6,16 @@
6 6
7. ./testing.sh 7. ./testing.sh
8 8
9ln -s `which busybox` unknown
10
11testing "busybox as unknown name" "./unknown 2>&1" \
12 "unknown: applet not found\n" "" ""
13rm unknown
14
15# We need busybox --help to be enabled for the rest of tests
16test x"$CONFIG_BUSYBOX" = x"y" \
17|| { echo "SKIPPED: busybox --help"; exit 0; }
18
9HELPDUMP=`true | busybox 2>&1 | cat` 19HELPDUMP=`true | busybox 2>&1 | cat`
10 20
11# We need to test under calling the binary under other names. 21# We need to test under calling the binary under other names.
@@ -38,10 +48,4 @@ do
38done 48done
39rm busybox-suffix 49rm busybox-suffix
40 50
41ln -s `which busybox` unknown
42
43testing "busybox as unknown name" "./unknown 2>&1" \
44 "unknown: applet not found\n" "" ""
45rm unknown
46
47exit $FAILCOUNT 51exit $FAILCOUNT
diff --git a/testsuite/du/du-m-works b/testsuite/du/du-m-works
index 9fa7437ac..d9693c7bf 100644
--- a/testsuite/du/du-m-works
+++ b/testsuite/du/du-m-works
@@ -1,4 +1,4 @@
1# FEATURE: CONFIG_FEATURE_HUMAN_READABLE 1# FEATURE: CONFIG_FEATURE_HUMAN_READABLE
2 2
3dd if=/dev/zero of=file bs=1M count=1 2>/dev/null 3dd if=/dev/zero of=file bs=1M count=1 2>/dev/null
4test x"`busybox du -m .`" = x"1 ." 4test x"`busybox du -m file`" = x"1 file"
diff --git a/testsuite/tar.tests b/testsuite/tar.tests
index 890a73dd5..c44b7ad07 100755
--- a/testsuite/tar.tests
+++ b/testsuite/tar.tests
@@ -24,7 +24,7 @@ tar: short read
24"" "" 24"" ""
25SKIP= 25SKIP=
26 26
27optional FEATURE_SEAMLESS_GZ 27optional FEATURE_SEAMLESS_GZ GUNZIP
28# In NOMMU case, "invalid magic" message comes from gunzip child process. 28# In NOMMU case, "invalid magic" message comes from gunzip child process.
29# Otherwise, it comes from tar. 29# Otherwise, it comes from tar.
30# Need to fix output up to avoid false positive. 30# Need to fix output up to avoid false positive.
@@ -204,7 +204,7 @@ SKIP=
204 204
205# Had a bug where on extract autodetect first "switched off" -z 205# Had a bug where on extract autodetect first "switched off" -z
206# and then failed to recognize .tgz extension 206# and then failed to recognize .tgz extension
207optional FEATURE_TAR_CREATE FEATURE_SEAMLESS_GZ 207optional FEATURE_TAR_CREATE FEATURE_SEAMLESS_GZ GUNZIP
208testing "tar extract tgz" "\ 208testing "tar extract tgz" "\
209dd count=1 bs=1M if=/dev/zero of=F0 2>/dev/null 209dd count=1 bs=1M if=/dev/zero of=F0 2>/dev/null
210tar -czf F0.tgz F0 210tar -czf F0.tgz F0
@@ -266,7 +266,7 @@ SKIP=
266# The correct implementation unlinks target before 266# The correct implementation unlinks target before
267# creating the second file. 267# creating the second file.
268# We test that /tmp/passwd remains empty: 268# We test that /tmp/passwd remains empty:
269optional UUDECODE FEATURE_SEAMLESS_BZ2 269optional UUDECODE FEATURE_TAR_AUTODETECT FEATURE_SEAMLESS_BZ2
270testing "tar does not extract into symlinks" "\ 270testing "tar does not extract into symlinks" "\
271>>/tmp/passwd && uudecode -o input && tar xf input 2>&1 && rm passwd; cat /tmp/passwd; echo \$? 271>>/tmp/passwd && uudecode -o input && tar xf input 2>&1 && rm passwd; cat /tmp/passwd; echo \$?
272" "\ 272" "\
@@ -282,7 +282,7 @@ l4/V8LDoe90yiWJhOJvIypgEfxdyRThQkBVn/bI=
282" 282"
283SKIP= 283SKIP=
284# And same with -k 284# And same with -k
285optional UUDECODE FEATURE_SEAMLESS_BZ2 285optional UUDECODE FEATURE_TAR_AUTODETECT FEATURE_SEAMLESS_BZ2
286testing "tar -k does not extract into symlinks" "\ 286testing "tar -k does not extract into symlinks" "\
287>>/tmp/passwd && uudecode -o input && tar xf input -k 2>&1 && rm passwd; cat /tmp/passwd; echo \$? 287>>/tmp/passwd && uudecode -o input && tar xf input -k 2>&1 && rm passwd; cat /tmp/passwd; echo \$?
288" "\ 288" "\
diff --git a/util-linux/dmesg.c b/util-linux/dmesg.c
index e543446c1..50e8a0fce 100644
--- a/util-linux/dmesg.c
+++ b/util-linux/dmesg.c
@@ -34,8 +34,7 @@ int dmesg_main(int argc UNUSED_PARAM, char **argv)
34 OPT_r = 1 << 3 34 OPT_r = 1 << 3
35 }; 35 };
36 36
37 opt_complementary = "s+:n+"; /* numeric */ 37 opts = getopt32(argv, "cs:+n:+r", &len, &level);
38 opts = getopt32(argv, "cs:n:r", &len, &level);
39 if (opts & OPT_n) { 38 if (opts & OPT_n) {
40 if (klogctl(8, NULL, (long) level)) 39 if (klogctl(8, NULL, (long) level))
41 bb_perror_msg_and_die("klogctl"); 40 bb_perror_msg_and_die("klogctl");
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 {
164 const unsigned char code; 164 const unsigned char code;
165} g_cmdoptions[] = { 165} g_cmdoptions[] = {
166 /*"12345678" + NUL */ 166 /*"12345678" + NUL */
167//TODO: convert to index_in_strings()
167 { "fb" , 1, CMD_FB }, 168 { "fb" , 1, CMD_FB },
168 { "db" , 1, CMD_DB }, 169 { "db" , 1, CMD_DB },
169 { "a" , 0, CMD_ALL }, 170 { "a" , 0, CMD_ALL },
@@ -416,7 +417,7 @@ int fbset_main(int argc, char **argv)
416 unsigned options = 0; 417 unsigned options = 0;
417 418
418 const char *fbdev = DEFAULTFBDEV; 419 const char *fbdev = DEFAULTFBDEV;
419 const char *modefile = DEFAULTFBMODE; 420 IF_FEATURE_FBSET_READMODE(const char *modefile = DEFAULTFBMODE;)
420 char *thisarg; 421 char *thisarg;
421 char *mode = mode; /* for compiler */ 422 char *mode = mode; /* for compiler */
422 423
@@ -444,7 +445,7 @@ int fbset_main(int argc, char **argv)
444 fbdev = argv[1]; 445 fbdev = argv[1];
445 break; 446 break;
446 case CMD_DB: 447 case CMD_DB:
447 modefile = argv[1]; 448 IF_FEATURE_FBSET_READMODE(modefile = argv[1];)
448 break; 449 break;
449 case CMD_ALL: 450 case CMD_ALL:
450 options |= OPT_ALL; 451 options |= OPT_ALL;
diff --git a/util-linux/fdisk.c b/util-linux/fdisk.c
index f49ce95a4..6391f9bd9 100644
--- a/util-linux/fdisk.c
+++ b/util-linux/fdisk.c
@@ -2919,8 +2919,7 @@ int fdisk_main(int argc UNUSED_PARAM, char **argv)
2919 2919
2920 close_dev_fd(); /* needed: fd 3 must not stay closed */ 2920 close_dev_fd(); /* needed: fd 3 must not stay closed */
2921 2921
2922 opt_complementary = "b+:C+:H+:S+"; /* numeric params */ 2922 opt = getopt32(argv, "b:+C:+H:+lS:+u" IF_FEATURE_FDISK_BLKSIZE("s"),
2923 opt = getopt32(argv, "b:C:H:lS:u" IF_FEATURE_FDISK_BLKSIZE("s"),
2924 &sector_size, &user_cylinders, &user_heads, &user_sectors); 2923 &sector_size, &user_cylinders, &user_heads, &user_sectors);
2925 argv += optind; 2924 argv += optind;
2926 if (opt & OPT_b) { 2925 if (opt & OPT_b) {
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)
366 } 366 }
367 printf("Reading disklabel of %s at sector %u\n", 367 printf("Reading disklabel of %s at sector %u\n",
368 partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR); 368 partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR);
369 if (xbsd_readlabel(xbsd_part) == 0) 369 if (xbsd_readlabel(xbsd_part) == 0) {
370 if (xbsd_create_disklabel() == 0) 370 if (xbsd_create_disklabel() == 0)
371 return; 371 return;
372 break; 372 break;
373 }
373 } 374 }
374 } 375 }
375 376
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)
504 if (sgi_get_sysid(Index[0]) == SGI_ENTIRE_DISK) { 504 if (sgi_get_sysid(Index[0]) == SGI_ENTIRE_DISK) {
505 if ((Index[0] != 10) && verbose) 505 if ((Index[0] != 10) && verbose)
506 printf("IRIX likes when Partition 11 covers the entire disk\n"); 506 printf("IRIX likes when Partition 11 covers the entire disk\n");
507 if ((sgi_get_start_sector(Index[0]) != 0) && verbose) 507 if ((sgi_get_start_sector(Index[0]) != 0) && verbose) {
508 printf("The entire disk partition should start " 508 printf("The entire disk partition should start "
509 "at block 0,\n" 509 "at block 0,\n"
510 "not at diskblock %u\n", 510 "not at diskblock %u\n",
511 sgi_get_start_sector(Index[0])); 511 sgi_get_start_sector(Index[0]));
512 if (SGI_DEBUG) /* I do not understand how some disks fulfil it */ 512 }
513 if (SGI_DEBUG) { /* I do not understand how some disks fulfil it */
513 if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose) 514 if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose)
514 printf("The entire disk partition is only %u diskblock large,\n" 515 printf("The entire disk partition is only %u diskblock large,\n"
515 "but the disk is %u diskblocks long\n", 516 "but the disk is %u diskblocks long\n",
516 sgi_get_num_sectors(Index[0]), lastblock); 517 sgi_get_num_sectors(Index[0]), lastblock);
517 lastblock = sgi_get_num_sectors(Index[0]); 518 lastblock = sgi_get_num_sectors(Index[0]);
519 }
518 } else { 520 } else {
519 if (verbose) 521 if (verbose)
520 printf("One Partition (#11) should cover the entire disk\n"); 522 printf("One Partition (#11) should cover the entire disk\n");
@@ -669,16 +671,17 @@ sgi_set_volhdr(void)
669 int n; 671 int n;
670 672
671 for (n = 8; n < g_partitions; n++) { 673 for (n = 8; n < g_partitions; n++) {
672 if (!sgi_get_num_sectors(n)) { 674 if (!sgi_get_num_sectors(n)) {
673 /* 675 /*
674 * 5 cylinders is an arbitrary value I like 676 * 5 cylinders is an arbitrary value I like
675 * IRIX 5.3 stored files in the volume header 677 * IRIX 5.3 stored files in the volume header
676 * (like sash, symmon, fx, ide) with ca. 3200 678 * (like sash, symmon, fx, ide) with ca. 3200
677 * sectors. 679 * sectors.
678 */ 680 */
679 if (g_heads * g_sectors * 5 < sgi_get_lastblock()) 681 if (g_heads * g_sectors * 5 < sgi_get_lastblock()) {
680 sgi_set_partition(n, 0, g_heads * g_sectors * 5, SGI_VOLHDR); 682 sgi_set_partition(n, 0, g_heads * g_sectors * 5, SGI_VOLHDR);
681 break; 683 break;
684 }
682 } 685 }
683 } 686 }
684} 687}
diff --git a/util-linux/getopt.c b/util-linux/getopt.c
index b9dadf13c..18d490987 100644
--- a/util-linux/getopt.c
+++ b/util-linux/getopt.c
@@ -397,8 +397,7 @@ int getopt_main(int argc, char **argv)
397 opt = getopt32(argv, "+o:n:qQs:Tu", &optstr, &name, &s_arg); 397 opt = getopt32(argv, "+o:n:qQs:Tu", &optstr, &name, &s_arg);
398#else 398#else
399 applet_long_options = getopt_longopts; 399 applet_long_options = getopt_longopts;
400 opt_complementary = "l::"; 400 opt = getopt32(argv, "+o:n:qQs:Tual:*",
401 opt = getopt32(argv, "+o:n:qQs:Tual:",
402 &optstr, &name, &s_arg, &l_arg); 401 &optstr, &name, &s_arg, &l_arg);
403 /* Effectuate the read options for the applet itself */ 402 /* Effectuate the read options for the applet itself */
404 while (l_arg) { 403 while (l_arg) {
diff --git a/util-linux/mkfs_ext2.c b/util-linux/mkfs_ext2.c
index f91a0b4bf..413e7aa15 100644
--- a/util-linux/mkfs_ext2.c
+++ b/util-linux/mkfs_ext2.c
@@ -244,8 +244,7 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
244 244
245 // using global "option_mask32" instead of local "opts": 245 // using global "option_mask32" instead of local "opts":
246 // we are register starved here 246 // we are register starved here
247 opt_complementary = "-1:b+:i+:I+:m+"; 247 /*opts =*/ getopt32(argv, "cl:b:+f:i:+I:+J:G:N:m:+o:g:L:M:O:r:E:T:U:jnqvFS",
248 /*opts =*/ getopt32(argv, "cl:b:f:i:I:J:G:N:m:o:g:L:M:O:r:E:T:U:jnqvFS",
249 /*lbfi:*/ NULL, &bs, NULL, &bpi, 248 /*lbfi:*/ NULL, &bs, NULL, &bpi,
250 /*IJGN:*/ &user_inodesize, NULL, NULL, NULL, 249 /*IJGN:*/ &user_inodesize, NULL, NULL, NULL,
251 /*mogL:*/ &reserved_percent, NULL, NULL, &label, 250 /*mogL:*/ &reserved_percent, NULL, NULL, &label,
diff --git a/util-linux/mkfs_minix.c b/util-linux/mkfs_minix.c
index 88d797584..aaabf8453 100644
--- a/util-linux/mkfs_minix.c
+++ b/util-linux/mkfs_minix.c
@@ -604,8 +604,7 @@ int mkfs_minix_main(int argc UNUSED_PARAM, char **argv)
604 bb_error_msg_and_die("bad inode size"); 604 bb_error_msg_and_die("bad inode size");
605#endif 605#endif
606 606
607 opt_complementary = "n+"; /* -n N */ 607 opt = getopt32(argv, "ci:l:n:+v", &str_i, &listfile, &G.namelen);
608 opt = getopt32(argv, "ci:l:n:v", &str_i, &listfile, &G.namelen);
609 argv += optind; 608 argv += optind;
610 //if (opt & 1) -c 609 //if (opt & 1) -c
611 if (opt & 2) G.req_nr_inodes = xatoul(str_i); // -i 610 if (opt & 2) G.req_nr_inodes = xatoul(str_i); // -i
diff --git a/util-linux/mkfs_reiser.c b/util-linux/mkfs_reiser.c
index 56c8f0ab5..0a31ee44f 100644
--- a/util-linux/mkfs_reiser.c
+++ b/util-linux/mkfs_reiser.c
@@ -169,8 +169,8 @@ int mkfs_reiser_main(int argc UNUSED_PARAM, char **argv)
169 169
170 // using global "option_mask32" instead of local "opts": 170 // using global "option_mask32" instead of local "opts":
171 // we are register starved here 171 // we are register starved here
172 opt_complementary = "-1:b+"; 172 opt_complementary = "-1";
173 /*opts =*/ getopt32(argv, "b:j:s:o:t:B:h:u:l:fqd", 173 /*opts =*/ getopt32(argv, "b:+j:s:o:t:B:h:u:l:fqd",
174 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &label); 174 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &label);
175 argv += optind; // argv[0] -- device 175 argv += optind; // argv[0] -- device
176 176
diff --git a/util-linux/mount.c b/util-linux/mount.c
index c76f6ef61..13590ceb4 100644
--- a/util-linux/mount.c
+++ b/util-linux/mount.c
@@ -268,7 +268,7 @@ enum {
268}; 268};
269 269
270 270
271#define OPTION_STR "o:t:rwanfvsiO:" IF_FEATURE_MOUNT_OTHERTAB("T:") 271#define OPTION_STR "o:*t:rwanfvsiO:" IF_FEATURE_MOUNT_OTHERTAB("T:")
272enum { 272enum {
273 OPT_o = (1 << 0), 273 OPT_o = (1 << 0),
274 OPT_t = (1 << 1), 274 OPT_t = (1 << 1),
@@ -2058,7 +2058,7 @@ static int singlemount(struct mntent *mp, int ignore_busy)
2058 del_loop(mp->mnt_fsname); 2058 del_loop(mp->mnt_fsname);
2059 if (ENABLE_FEATURE_CLEAN_UP) { 2059 if (ENABLE_FEATURE_CLEAN_UP) {
2060 free(loopFile); 2060 free(loopFile);
2061 free(mp->mnt_fsname); 2061 /* No, "rc != 0" needs it: free(mp->mnt_fsname); */
2062 } 2062 }
2063 } 2063 }
2064 2064
@@ -2167,7 +2167,7 @@ int mount_main(int argc UNUSED_PARAM, char **argv)
2167 2167
2168 // Parse remaining options 2168 // Parse remaining options
2169 // Max 2 params; -o is a list, -v is a counter 2169 // Max 2 params; -o is a list, -v is a counter
2170 opt_complementary = "?2o::" IF_FEATURE_MOUNT_VERBOSE("vv"); 2170 opt_complementary = "?2" IF_FEATURE_MOUNT_VERBOSE("vv");
2171 opt = getopt32(argv, OPTION_STR, &lst_o, &fstype, &O_optmatch 2171 opt = getopt32(argv, OPTION_STR, &lst_o, &fstype, &O_optmatch
2172 IF_FEATURE_MOUNT_OTHERTAB(, &fstabname) 2172 IF_FEATURE_MOUNT_OTHERTAB(, &fstabname)
2173 IF_FEATURE_MOUNT_VERBOSE(, &verbose)); 2173 IF_FEATURE_MOUNT_VERBOSE(, &verbose));
diff --git a/util-linux/readprofile.c b/util-linux/readprofile.c
index a64540464..345b676ba 100644
--- a/util-linux/readprofile.c
+++ b/util-linux/readprofile.c
@@ -99,8 +99,7 @@ int readprofile_main(int argc UNUSED_PARAM, char **argv)
99 proFile = defaultpro; 99 proFile = defaultpro;
100 mapFile = defaultmap; 100 mapFile = defaultmap;
101 101
102 opt_complementary = "M+"; /* -M N */ 102 opt = getopt32(argv, "M:+m:p:nabsirv", &multiplier, &mapFile, &proFile);
103 opt = getopt32(argv, "M:m:p:nabsirv", &multiplier, &mapFile, &proFile);
104 103
105 if (opt & (OPT_M|OPT_r)) { /* mult or reset, or both */ 104 if (opt & (OPT_M|OPT_r)) { /* mult or reset, or both */
106 int fd, to_write; 105 int fd, to_write;