aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2015-10-19 12:53:35 +0100
committerRon Yorston <rmy@pobox.com>2015-10-19 12:53:35 +0100
commit8afe8ee83a274925340473fa4d0a984bdcbee740 (patch)
treeb78ed448cb6a55ba7d0ef8141a9f68b55b8acf11
parentcaab029609633220c417dc0aaa9025fd4b7a169c (diff)
parent3d0805e9e7c45e6c0f9fb5e587d8b4a5a5f3c74c (diff)
downloadbusybox-w32-8afe8ee83a274925340473fa4d0a984bdcbee740.tar.gz
busybox-w32-8afe8ee83a274925340473fa4d0a984bdcbee740.tar.bz2
busybox-w32-8afe8ee83a274925340473fa4d0a984bdcbee740.zip
Merge branch 'busybox' into merge
-rw-r--r--archival/Kbuild.src2
-rw-r--r--archival/cpio.c46
-rw-r--r--archival/libarchive/Kbuild.src2
-rw-r--r--archival/libarchive/common.c9
-rw-r--r--archival/libarchive/decompress_gunzip.c5
-rw-r--r--archival/libarchive/get_header_cpio.c7
-rw-r--r--coreutils/chown.c8
-rw-r--r--coreutils/dd.c4
-rw-r--r--coreutils/du.c37
-rw-r--r--coreutils/od_bloaty.c230
-rw-r--r--debianutils/Config.src75
-rw-r--r--debianutils/Kbuild.src5
-rw-r--r--debianutils/mktemp.c9
-rw-r--r--debianutils/pipe_progress.c9
-rw-r--r--debianutils/run_parts.c34
-rw-r--r--debianutils/start_stop_daemon.c36
-rw-r--r--debianutils/which.c10
-rw-r--r--e2fsprogs/Config.src28
-rw-r--r--e2fsprogs/Kbuild.src6
-rw-r--r--e2fsprogs/chattr.c26
-rw-r--r--e2fsprogs/fsck.c272
-rw-r--r--e2fsprogs/lsattr.c20
-rw-r--r--e2fsprogs/tune2fs.c43
-rw-r--r--editors/sed.c10
-rwxr-xr-xexamples/var_service/dhcp_if_pinger/run44
-rw-r--r--findutils/find.c6
-rw-r--r--findutils/grep.c4
-rw-r--r--include/applets.src.h42
-rw-r--r--include/bb_archive.h3
-rw-r--r--include/libbb.h9
-rw-r--r--libbb/appletlib.c2
-rw-r--r--libbb/human_readable.c11
-rw-r--r--libbb/messages.c2
-rw-r--r--libpwdgrp/uidgid_get.c44
-rw-r--r--loginutils/Config.src237
-rw-r--r--loginutils/Kbuild.src12
-rw-r--r--loginutils/add-remove-shell.c13
-rw-r--r--loginutils/addgroup.c25
-rw-r--r--loginutils/adduser.c51
-rw-r--r--loginutils/chpasswd.c20
-rw-r--r--loginutils/cryptpw.c12
-rw-r--r--loginutils/deluser.c26
-rw-r--r--loginutils/getty.c22
-rw-r--r--loginutils/login.c50
-rw-r--r--loginutils/passwd.c24
-rw-r--r--loginutils/su.c31
-rw-r--r--loginutils/sulogin.c12
-rw-r--r--loginutils/vlock.c16
-rw-r--r--miscutils/hdparm.c7
-rw-r--r--miscutils/taskset.c6
-rw-r--r--networking/Config.src13
-rw-r--r--networking/brctl.c8
-rw-r--r--networking/inetd.c4
-rw-r--r--networking/ip.c19
-rw-r--r--networking/libiproute/Kbuild.src8
-rw-r--r--networking/libiproute/ip_common.h2
-rw-r--r--networking/libiproute/ip_parse_common_args.c2
-rw-r--r--networking/libiproute/ipaddress.c28
-rw-r--r--networking/libiproute/iplink.c27
-rw-r--r--networking/libiproute/ipneigh.c353
-rw-r--r--networking/libiproute/iproute.c72
-rw-r--r--networking/libiproute/iprule.c31
-rw-r--r--networking/libiproute/iptunnel.c34
-rw-r--r--networking/libiproute/utils.c48
-rw-r--r--networking/libiproute/utils.h12
-rw-r--r--networking/nbd-client.c5
-rw-r--r--networking/slattach.c6
-rw-r--r--networking/tc.c12
-rw-r--r--networking/telnet.c4
-rw-r--r--printutils/Config.src18
-rw-r--r--printutils/Kbuild.src4
-rw-r--r--printutils/lpd.c9
-rw-r--r--printutils/lpr.c17
-rw-r--r--procps/top.c36
-rw-r--r--runit/Config.src79
-rw-r--r--runit/Kbuild.src11
-rw-r--r--runit/chpst.c45
-rw-r--r--runit/runsv.c12
-rw-r--r--runit/runsvdir.c22
-rw-r--r--runit/sv.c20
-rw-r--r--runit/svlogd.c13
-rw-r--r--sysklogd/Config.src159
-rw-r--r--sysklogd/Kbuild.src4
-rw-r--r--sysklogd/klogd.c33
-rw-r--r--sysklogd/logger.c13
-rw-r--r--sysklogd/logread.c25
-rw-r--r--sysklogd/syslogd.c101
-rw-r--r--util-linux/mdev.c2
88 files changed, 1716 insertions, 1259 deletions
diff --git a/archival/Kbuild.src b/archival/Kbuild.src
index a6fd2eac0..b3a7d538f 100644
--- a/archival/Kbuild.src
+++ b/archival/Kbuild.src
@@ -4,7 +4,7 @@
4# 4#
5# Licensed under GPLv2, see file LICENSE in this source tree. 5# Licensed under GPLv2, see file LICENSE in this source tree.
6 6
7libs-y += libarchive/ 7libs-y += libarchive/
8 8
9lib-y:= 9lib-y:=
10 10
diff --git a/archival/cpio.c b/archival/cpio.c
index a202069c4..30f66d1f7 100644
--- a/archival/cpio.c
+++ b/archival/cpio.c
@@ -46,7 +46,7 @@
46//kbuild:lib-$(CONFIG_CPIO) += cpio.o 46//kbuild:lib-$(CONFIG_CPIO) += cpio.o
47 47
48//usage:#define cpio_trivial_usage 48//usage:#define cpio_trivial_usage
49//usage: "[-dmvu] [-F FILE]" IF_FEATURE_CPIO_O(" [-H newc]") 49//usage: "[-dmvu] [-F FILE] [-R USER[:GRP]]" IF_FEATURE_CPIO_O(" [-H newc]")
50//usage: " [-ti"IF_FEATURE_CPIO_O("o")"]" IF_FEATURE_CPIO_P(" [-p DIR]") 50//usage: " [-ti"IF_FEATURE_CPIO_O("o")"]" IF_FEATURE_CPIO_P(" [-p DIR]")
51//usage: " [EXTR_FILE]..." 51//usage: " [EXTR_FILE]..."
52//usage:#define cpio_full_usage "\n\n" 52//usage:#define cpio_full_usage "\n\n"
@@ -71,6 +71,7 @@
71//usage: "\n -v Verbose" 71//usage: "\n -v Verbose"
72//usage: "\n -u Overwrite" 72//usage: "\n -u Overwrite"
73//usage: "\n -F FILE Input (-t,-i,-p) or output (-o) file" 73//usage: "\n -F FILE Input (-t,-i,-p) or output (-o) file"
74//usage: "\n -R USER[:GRP] Set owner of created files"
74//usage: IF_FEATURE_CPIO_O( 75//usage: IF_FEATURE_CPIO_O(
75//usage: "\n -H newc Archive format" 76//usage: "\n -H newc Archive format"
76//usage: ) 77//usage: )
@@ -130,7 +131,7 @@
130 -I FILE File to use instead of standard input 131 -I FILE File to use instead of standard input
131 -L, --dereference Dereference symbolic links (copy the files 132 -L, --dereference Dereference symbolic links (copy the files
132 that they point to instead of copying the links) 133 that they point to instead of copying the links)
133 -R, --owner=[USER][:.][GROUP] Set owner of created files 134 -R, --owner=[USER][:.][GRP] Set owner of created files
134 135
135 Options valid in --extract and --pass-through modes: 136 Options valid in --extract and --pass-through modes:
136 -d, --make-directories Create leading directories where needed 137 -d, --make-directories Create leading directories where needed
@@ -150,7 +151,8 @@ enum {
150 OPT_PRESERVE_MTIME = (1 << 6), 151 OPT_PRESERVE_MTIME = (1 << 6),
151 OPT_DEREF = (1 << 7), 152 OPT_DEREF = (1 << 7),
152 OPT_FILE = (1 << 8), 153 OPT_FILE = (1 << 8),
153 OPTBIT_FILE = 8, 154 OPT_OWNER = (1 << 9),
155 OPTBIT_OWNER = 9,
154 IF_FEATURE_CPIO_O(OPTBIT_CREATE ,) 156 IF_FEATURE_CPIO_O(OPTBIT_CREATE ,)
155 IF_FEATURE_CPIO_O(OPTBIT_FORMAT ,) 157 IF_FEATURE_CPIO_O(OPTBIT_FORMAT ,)
156 IF_FEATURE_CPIO_P(OPTBIT_PASSTHROUGH,) 158 IF_FEATURE_CPIO_P(OPTBIT_PASSTHROUGH,)
@@ -163,7 +165,17 @@ enum {
163 OPT_2STDOUT = IF_LONG_OPTS( (1 << OPTBIT_2STDOUT )) + 0, 165 OPT_2STDOUT = IF_LONG_OPTS( (1 << OPTBIT_2STDOUT )) + 0,
164}; 166};
165 167
166#define OPTION_STR "it0uvdmLF:" 168#define OPTION_STR "it0uvdmLF:R:"
169
170struct globals {
171 struct bb_uidgid_t owner_ugid;
172} FIX_ALIASING;
173#define G (*(struct globals*)&bb_common_bufsiz1)
174void BUG_cpio_globals_too_big(void);
175#define INIT_G() do { \
176 G.owner_ugid.uid = -1L; \
177 G.owner_ugid.gid = -1L; \
178} while (0)
167 179
168#if ENABLE_FEATURE_CPIO_O 180#if ENABLE_FEATURE_CPIO_O
169static off_t cpio_pad4(off_t size) 181static off_t cpio_pad4(off_t size)
@@ -181,7 +193,6 @@ static off_t cpio_pad4(off_t size)
181 * It's ok to exit instead of return. */ 193 * It's ok to exit instead of return. */
182static NOINLINE int cpio_o(void) 194static NOINLINE int cpio_o(void)
183{ 195{
184 static const char trailer[] ALIGN1 = "TRAILER!!!";
185 struct name_s { 196 struct name_s {
186 struct name_s *next; 197 struct name_s *next;
187 char name[1]; 198 char name[1];
@@ -223,6 +234,11 @@ static NOINLINE int cpio_o(void)
223 bb_simple_perror_msg_and_die(name); 234 bb_simple_perror_msg_and_die(name);
224 } 235 }
225 236
237 if (G.owner_ugid.uid != (uid_t)-1L)
238 st.st_uid = G.owner_ugid.uid;
239 if (G.owner_ugid.gid != (gid_t)-1L)
240 st.st_gid = G.owner_ugid.gid;
241
226 if (!(S_ISLNK(st.st_mode) || S_ISREG(st.st_mode))) 242 if (!(S_ISLNK(st.st_mode) || S_ISREG(st.st_mode)))
227 st.st_size = 0; /* paranoia */ 243 st.st_size = 0; /* paranoia */
228 244
@@ -275,7 +291,7 @@ static NOINLINE int cpio_o(void)
275 } else { 291 } else {
276 /* If no (more) hardlinks to output, 292 /* If no (more) hardlinks to output,
277 * output "trailer" entry */ 293 * output "trailer" entry */
278 name = trailer; 294 name = cpio_TRAILER;
279 /* st.st_size == 0 is a must, but for uniformity 295 /* st.st_size == 0 is a must, but for uniformity
280 * in the output, we zero out everything */ 296 * in the output, we zero out everything */
281 memset(&st, 0, sizeof(st)); 297 memset(&st, 0, sizeof(st));
@@ -323,7 +339,7 @@ static NOINLINE int cpio_o(void)
323 } 339 }
324 340
325 if (!line) { 341 if (!line) {
326 if (name != trailer) 342 if (name != cpio_TRAILER)
327 goto next_link; 343 goto next_link;
328 /* TODO: GNU cpio pads trailer to 512 bytes, do we want that? */ 344 /* TODO: GNU cpio pads trailer to 512 bytes, do we want that? */
329 return EXIT_SUCCESS; 345 return EXIT_SUCCESS;
@@ -339,6 +355,7 @@ int cpio_main(int argc UNUSED_PARAM, char **argv)
339{ 355{
340 archive_handle_t *archive_handle; 356 archive_handle_t *archive_handle;
341 char *cpio_filename; 357 char *cpio_filename;
358 char *cpio_owner;
342 IF_FEATURE_CPIO_O(const char *cpio_fmt = "";) 359 IF_FEATURE_CPIO_O(const char *cpio_fmt = "";)
343 unsigned opt; 360 unsigned opt;
344 361
@@ -353,12 +370,14 @@ int cpio_main(int argc UNUSED_PARAM, char **argv)
353 "pass-through\0" No_argument "p" 370 "pass-through\0" No_argument "p"
354#endif 371#endif
355#endif 372#endif
373 "owner\0" Required_argument "R"
356 "verbose\0" No_argument "v" 374 "verbose\0" No_argument "v"
357 "quiet\0" No_argument "\xff" 375 "quiet\0" No_argument "\xff"
358 "to-stdout\0" No_argument "\xfe" 376 "to-stdout\0" No_argument "\xfe"
359 ; 377 ;
360#endif 378#endif
361 379
380 INIT_G();
362 archive_handle = init_handle(); 381 archive_handle = init_handle();
363 /* archive_handle->src_fd = STDIN_FILENO; - done by init_handle */ 382 /* archive_handle->src_fd = STDIN_FILENO; - done by init_handle */
364 archive_handle->ah_flags = ARCHIVE_EXTRACT_NEWER; 383 archive_handle->ah_flags = ARCHIVE_EXTRACT_NEWER;
@@ -369,8 +388,17 @@ int cpio_main(int argc UNUSED_PARAM, char **argv)
369 /* -L makes sense only with -o or -p */ 388 /* -L makes sense only with -o or -p */
370 389
371#if !ENABLE_FEATURE_CPIO_O 390#if !ENABLE_FEATURE_CPIO_O
372 opt = getopt32(argv, OPTION_STR, &cpio_filename); 391 opt = getopt32(argv, OPTION_STR, &cpio_filename, &cpio_owner);
392#else
393 opt = getopt32(argv, OPTION_STR "oH:" IF_FEATURE_CPIO_P("p"),
394 &cpio_filename, &cpio_owner, &cpio_fmt);
395#endif
373 argv += optind; 396 argv += optind;
397 if (opt & OPT_OWNER) { /* -R */
398 parse_chown_usergroup_or_die(&G.owner_ugid, cpio_owner);
399 archive_handle->cpio__owner = G.owner_ugid;
400 }
401#if !ENABLE_FEATURE_CPIO_O
374 if (opt & OPT_FILE) { /* -F */ 402 if (opt & OPT_FILE) { /* -F */
375 xmove_fd(xopen(cpio_filename, O_RDONLY), STDIN_FILENO); 403 xmove_fd(xopen(cpio_filename, O_RDONLY), STDIN_FILENO);
376#if ENABLE_PLATFORM_MINGW32 404#if ENABLE_PLATFORM_MINGW32
@@ -379,8 +407,6 @@ int cpio_main(int argc UNUSED_PARAM, char **argv)
379#endif 407#endif
380 } 408 }
381#else 409#else
382 opt = getopt32(argv, OPTION_STR "oH:" IF_FEATURE_CPIO_P("p"), &cpio_filename, &cpio_fmt);
383 argv += optind;
384 if ((opt & (OPT_FILE|OPT_CREATE)) == OPT_FILE) { /* -F without -o */ 410 if ((opt & (OPT_FILE|OPT_CREATE)) == OPT_FILE) { /* -F without -o */
385 xmove_fd(xopen(cpio_filename, O_RDONLY), STDIN_FILENO); 411 xmove_fd(xopen(cpio_filename, O_RDONLY), STDIN_FILENO);
386 } 412 }
diff --git a/archival/libarchive/Kbuild.src b/archival/libarchive/Kbuild.src
index b7faaf77f..b159a786a 100644
--- a/archival/libarchive/Kbuild.src
+++ b/archival/libarchive/Kbuild.src
@@ -4,7 +4,7 @@
4# 4#
5# Licensed under GPLv2 or later, see file LICENSE in this source tree. 5# Licensed under GPLv2 or later, see file LICENSE in this source tree.
6 6
7lib-y:= 7lib-y:= common.o
8 8
9COMMON_FILES:= \ 9COMMON_FILES:= \
10\ 10\
diff --git a/archival/libarchive/common.c b/archival/libarchive/common.c
new file mode 100644
index 000000000..dd69d2222
--- /dev/null
+++ b/archival/libarchive/common.c
@@ -0,0 +1,9 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
4 */
5
6#include "libbb.h"
7#include "bb_archive.h"
8
9const char cpio_TRAILER[] = "TRAILER!!!";
diff --git a/archival/libarchive/decompress_gunzip.c b/archival/libarchive/decompress_gunzip.c
index dced609e5..b6ae7f738 100644
--- a/archival/libarchive/decompress_gunzip.c
+++ b/archival/libarchive/decompress_gunzip.c
@@ -1121,9 +1121,8 @@ static int check_header_gzip(STATE_PARAM transformer_state_t *xstate)
1121 uint8_t os_flags_UNUSED; 1121 uint8_t os_flags_UNUSED;
1122 } PACKED formatted; 1122 } PACKED formatted;
1123 } header; 1123 } header;
1124 struct BUG_header { 1124
1125 char BUG_header[sizeof(header) == 8 ? 1 : -1]; 1125 BUILD_BUG_ON(sizeof(header) != 8);
1126 };
1127 1126
1128 /* 1127 /*
1129 * Rewind bytebuffer. We use the beginning because the header has 8 1128 * Rewind bytebuffer. We use the beginning because the header has 8
diff --git a/archival/libarchive/get_header_cpio.c b/archival/libarchive/get_header_cpio.c
index 7861d1f6f..badd4a841 100644
--- a/archival/libarchive/get_header_cpio.c
+++ b/archival/libarchive/get_header_cpio.c
@@ -52,6 +52,11 @@ char FAST_FUNC get_header_cpio(archive_handle_t *archive_handle)
52 &major, &minor, &namesize) != 10) 52 &major, &minor, &namesize) != 10)
53 bb_error_msg_and_die("damaged cpio file"); 53 bb_error_msg_and_die("damaged cpio file");
54 file_header->mode = mode; 54 file_header->mode = mode;
55 /* "cpio -R USER:GRP" support: */
56 if (archive_handle->cpio__owner.uid != (uid_t)-1L)
57 uid = archive_handle->cpio__owner.uid;
58 if (archive_handle->cpio__owner.gid != (gid_t)-1L)
59 gid = archive_handle->cpio__owner.gid;
55 file_header->uid = uid; 60 file_header->uid = uid;
56 file_header->gid = gid; 61 file_header->gid = gid;
57 file_header->mtime = mtime; 62 file_header->mtime = mtime;
@@ -75,7 +80,7 @@ char FAST_FUNC get_header_cpio(archive_handle_t *archive_handle)
75 /* Update offset amount and skip padding before file contents */ 80 /* Update offset amount and skip padding before file contents */
76 data_align(archive_handle, 4); 81 data_align(archive_handle, 4);
77 82
78 if (strcmp(file_header->name, "TRAILER!!!") == 0) { 83 if (strcmp(file_header->name, cpio_TRAILER) == 0) {
79 /* Always round up. ">> 9" divides by 512 */ 84 /* Always round up. ">> 9" divides by 512 */
80 archive_handle->cpio__blocks = (uoff_t)(archive_handle->offset + 511) >> 9; 85 archive_handle->cpio__blocks = (uoff_t)(archive_handle->offset + 511) >> 9;
81 goto create_hardlinks; 86 goto create_hardlinks;
diff --git a/coreutils/chown.c b/coreutils/chown.c
index 679c0d832..247aa3bf1 100644
--- a/coreutils/chown.c
+++ b/coreutils/chown.c
@@ -11,9 +11,9 @@
11/* http://www.opengroup.org/onlinepubs/007904975/utilities/chown.html */ 11/* http://www.opengroup.org/onlinepubs/007904975/utilities/chown.html */
12 12
13//usage:#define chown_trivial_usage 13//usage:#define chown_trivial_usage
14//usage: "[-Rh"IF_DESKTOP("LHPcvf")"]... OWNER[<.|:>[GROUP]] FILE..." 14//usage: "[-Rh"IF_DESKTOP("LHPcvf")"]... USER[:[GRP]] FILE..."
15//usage:#define chown_full_usage "\n\n" 15//usage:#define chown_full_usage "\n\n"
16//usage: "Change the owner and/or group of each FILE to OWNER and/or GROUP\n" 16//usage: "Change the owner and/or group of each FILE to USER and/or GRP\n"
17//usage: "\n -R Recurse" 17//usage: "\n -R Recurse"
18//usage: "\n -h Affect symlinks instead of symlink targets" 18//usage: "\n -h Affect symlinks instead of symlink targets"
19//usage: IF_DESKTOP( 19//usage: IF_DESKTOP(
@@ -112,10 +112,6 @@ int chown_main(int argc UNUSED_PARAM, char **argv)
112 int opt, flags; 112 int opt, flags;
113 struct param_t param; 113 struct param_t param;
114 114
115 /* Just -1 might not work: uid_t may be unsigned long */
116 param.ugid.uid = -1L;
117 param.ugid.gid = -1L;
118
119#if ENABLE_FEATURE_CHOWN_LONG_OPTIONS 115#if ENABLE_FEATURE_CHOWN_LONG_OPTIONS
120 applet_long_options = chown_longopts; 116 applet_long_options = chown_longopts;
121#endif 117#endif
diff --git a/coreutils/dd.c b/coreutils/dd.c
index 589547e77..ccb91f69d 100644
--- a/coreutils/dd.c
+++ b/coreutils/dd.c
@@ -327,7 +327,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
327 *arg = '\0'; 327 *arg = '\0';
328 n = index_in_strings(conv_words, val); 328 n = index_in_strings(conv_words, val);
329 if (n < 0) 329 if (n < 0)
330 bb_error_msg_and_die(bb_msg_invalid_arg, val, "conv"); 330 bb_error_msg_and_die(bb_msg_invalid_arg_to, val, "conv");
331 G.flags |= (1 << n); 331 G.flags |= (1 << n);
332 if (!arg) /* no ',' left, so this was the last specifier */ 332 if (!arg) /* no ',' left, so this was the last specifier */
333 break; 333 break;
@@ -369,7 +369,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
369 int n; 369 int n;
370 n = index_in_strings(status_words, val); 370 n = index_in_strings(status_words, val);
371 if (n < 0) 371 if (n < 0)
372 bb_error_msg_and_die(bb_msg_invalid_arg, val, "status"); 372 bb_error_msg_and_die(bb_msg_invalid_arg_to, val, "status");
373 G.flags |= FLAG_STATUS << n; 373 G.flags |= FLAG_STATUS << n;
374 /*continue;*/ 374 /*continue;*/
375 } 375 }
diff --git a/coreutils/du.c b/coreutils/du.c
index 9c6ff8800..1889c16bb 100644
--- a/coreutils/du.c
+++ b/coreutils/du.c
@@ -75,7 +75,7 @@ enum {
75 75
76struct globals { 76struct globals {
77#if ENABLE_FEATURE_HUMAN_READABLE 77#if ENABLE_FEATURE_HUMAN_READABLE
78 unsigned long disp_hr; 78 unsigned long disp_unit;
79#else 79#else
80 unsigned disp_k; 80 unsigned disp_k;
81#endif 81#endif
@@ -89,18 +89,27 @@ struct globals {
89#define INIT_G() do { } while (0) 89#define INIT_G() do { } while (0)
90 90
91 91
92/* FIXME? coreutils' du rounds sizes up:
93 * for example, 1025k file is shown as "2" by du -m.
94 * We round to nearest.
95 */
96static void print(unsigned long long size, const char *filename) 92static void print(unsigned long long size, const char *filename)
97{ 93{
98 /* TODO - May not want to defer error checking here. */ 94 /* TODO - May not want to defer error checking here. */
99#if ENABLE_FEATURE_HUMAN_READABLE 95#if ENABLE_FEATURE_HUMAN_READABLE
96# if ENABLE_DESKTOP
97 /* ~30 bytes of code for extra comtat:
98 * coreutils' du rounds sizes up:
99 * for example, 1025k file is shown as "2" by du -m.
100 * We round to nearest if human-readable [too hard to fix],
101 * else (fixed scale such as -m), we round up. To that end,
102 * add yet another half of the unit before displaying:
103 */
104 if (G.disp_unit)
105 size += (G.disp_unit-1) / (unsigned)(512 * 2);
106# endif
100 printf("%s\t%s\n", 107 printf("%s\t%s\n",
101 /* size x 512 / G.disp_hr, show one fractional, 108 /* size x 512 / G.disp_unit.
102 * use suffixes if G.disp_hr == 0 */ 109 * If G.disp_unit == 0, show one fractional
103 make_human_readable_str(size, 512, G.disp_hr), 110 * and use suffixes
111 */
112 make_human_readable_str(size, 512, G.disp_unit),
104 filename); 113 filename);
105#else 114#else
106 if (G.disp_k) { 115 if (G.disp_k) {
@@ -199,10 +208,10 @@ int du_main(int argc UNUSED_PARAM, char **argv)
199 INIT_G(); 208 INIT_G();
200 209
201#if ENABLE_FEATURE_HUMAN_READABLE 210#if ENABLE_FEATURE_HUMAN_READABLE
202 IF_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(G.disp_hr = 1024;) 211 IF_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(G.disp_unit = 1024;)
203 IF_NOT_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(G.disp_hr = 512;) 212 IF_NOT_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(G.disp_unit = 512;)
204 if (getenv("POSIXLY_CORRECT")) /* TODO - a new libbb function? */ 213 if (getenv("POSIXLY_CORRECT")) /* TODO - a new libbb function? */
205 G.disp_hr = 512; 214 G.disp_unit = 512;
206#else 215#else
207 IF_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(G.disp_k = 1;) 216 IF_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(G.disp_k = 1;)
208 /* IF_NOT_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(G.disp_k = 0;) - G is pre-zeroed */ 217 /* IF_NOT_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(G.disp_k = 0;) - G is pre-zeroed */
@@ -220,13 +229,13 @@ int du_main(int argc UNUSED_PARAM, char **argv)
220 opt = getopt32(argv, "aHkLsx" "d:" "lc" "hm", &G.max_print_depth); 229 opt = getopt32(argv, "aHkLsx" "d:" "lc" "hm", &G.max_print_depth);
221 argv += optind; 230 argv += optind;
222 if (opt & OPT_h_for_humans) { 231 if (opt & OPT_h_for_humans) {
223 G.disp_hr = 0; 232 G.disp_unit = 0;
224 } 233 }
225 if (opt & OPT_m_mbytes) { 234 if (opt & OPT_m_mbytes) {
226 G.disp_hr = 1024*1024; 235 G.disp_unit = 1024*1024;
227 } 236 }
228 if (opt & OPT_k_kbytes) { 237 if (opt & OPT_k_kbytes) {
229 G.disp_hr = 1024; 238 G.disp_unit = 1024;
230 } 239 }
231#else 240#else
232 opt_complementary = "H-L:L-H:s-d:d-s:d+"; 241 opt_complementary = "H-L:L-H:s-d:d-s:d+";
diff --git a/coreutils/od_bloaty.c b/coreutils/od_bloaty.c
index 1e7c5bfa0..3e0423a3d 100644
--- a/coreutils/od_bloaty.c
+++ b/coreutils/od_bloaty.c
@@ -66,7 +66,7 @@ enum {
66 /* -S was -s and also had optional parameter */ \ 66 /* -S was -s and also had optional parameter */ \
67 /* but in coreutils 6.3 it was renamed and now has */ \ 67 /* but in coreutils 6.3 it was renamed and now has */ \
68 /* _mandatory_ parameter */ \ 68 /* _mandatory_ parameter */ \
69 &str_A, &str_N, &str_j, &lst_t, &str_S, &bytes_per_block) 69 &str_A, &str_N, &str_j, &lst_t, &str_S, &G.bytes_per_block)
70 70
71 71
72/* Check for 0x7f is a coreutils 6.3 addition */ 72/* Check for 0x7f is a coreutils 6.3 addition */
@@ -181,38 +181,52 @@ struct ERR_width_bytes_has_bad_size {
181 char ERR_width_bytes_has_bad_size[ARRAY_SIZE(width_bytes) == N_SIZE_SPECS ? 1 : -1]; 181 char ERR_width_bytes_has_bad_size[ARRAY_SIZE(width_bytes) == N_SIZE_SPECS ? 1 : -1];
182}; 182};
183 183
184static smallint exit_code; 184struct globals {
185 smallint exit_code;
185 186
186static unsigned string_min; 187 unsigned string_min;
187 188
188/* An array of specs describing how to format each input block. */ 189 /* An array of specs describing how to format each input block. */
189static size_t n_specs; 190 unsigned n_specs;
190static struct tspec *spec; 191 struct tspec *spec;
191 192
192/* Function that accepts an address and an optional following char, 193 /* Function that accepts an address and an optional following char,
193 and prints the address and char to stdout. */ 194 and prints the address and char to stdout. */
194static void (*format_address)(off_t, char); 195 void (*format_address)(off_t, char);
195/* The difference between the old-style pseudo starting address and 196
196 the number of bytes to skip. */ 197 /* The difference between the old-style pseudo starting address and
198 the number of bytes to skip. */
197#if ENABLE_LONG_OPTS 199#if ENABLE_LONG_OPTS
198static off_t pseudo_offset; 200 off_t pseudo_offset;
199#else 201# define G_pseudo_offset G.pseudo_offset
200enum { pseudo_offset = 0 };
201#endif 202#endif
202/* When zero, MAX_BYTES_TO_FORMAT and END_OFFSET are ignored, and all 203 /* When zero, MAX_BYTES_TO_FORMAT and END_OFFSET are ignored, and all
203 input is formatted. */ 204 input is formatted. */
204 205
205/* The number of input bytes formatted per output line. It must be 206 /* The number of input bytes formatted per output line. It must be
206 a multiple of the least common multiple of the sizes associated with 207 a multiple of the least common multiple of the sizes associated with
207 the specified output types. It should be as large as possible, but 208 the specified output types. It should be as large as possible, but
208 no larger than 16 -- unless specified with the -w option. */ 209 no larger than 16 -- unless specified with the -w option. */
209static unsigned bytes_per_block = 32; /* have to use unsigned, not size_t */ 210 unsigned bytes_per_block; /* have to use unsigned, not size_t */
210 211
211/* A NULL-terminated list of the file-arguments from the command line. */ 212 /* A NULL-terminated list of the file-arguments from the command line. */
212static const char *const *file_list; 213 const char *const *file_list;
214
215 /* The input stream associated with the current file. */
216 FILE *in_stream;
217
218 bool not_first;
219 bool prev_pair_equal;
220} FIX_ALIASING;
221#if !ENABLE_LONG_OPTS
222enum { G_pseudo_offset = 0 };
223#endif
224#define G (*(struct globals*)&bb_common_bufsiz1)
225#define INIT_G() do { \
226 BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
227 G.bytes_per_block = 32; \
228} while (0)
213 229
214/* The input stream associated with the current file. */
215static FILE *in_stream;
216 230
217#define MAX_INTEGRAL_TYPE_SIZE sizeof(ulonglong_t) 231#define MAX_INTEGRAL_TYPE_SIZE sizeof(ulonglong_t)
218static const unsigned char integral_type_size[MAX_INTEGRAL_TYPE_SIZE + 1] ALIGN1 = { 232static const unsigned char integral_type_size[MAX_INTEGRAL_TYPE_SIZE + 1] ALIGN1 = {
@@ -483,17 +497,17 @@ static void
483open_next_file(void) 497open_next_file(void)
484{ 498{
485 while (1) { 499 while (1) {
486 if (!*file_list) 500 if (!*G.file_list)
487 return; 501 return;
488 in_stream = fopen_or_warn_stdin(*file_list++); 502 G.in_stream = fopen_or_warn_stdin(*G.file_list++);
489 if (in_stream) { 503 if (G.in_stream) {
490 break; 504 break;
491 } 505 }
492 exit_code = 1; 506 G.exit_code = 1;
493 } 507 }
494 508
495 if ((option_mask32 & (OPT_N|OPT_S)) == OPT_N) 509 if ((option_mask32 & (OPT_N|OPT_S)) == OPT_N)
496 setbuf(in_stream, NULL); 510 setbuf(G.in_stream, NULL);
497} 511}
498 512
499/* Test whether there have been errors on in_stream, and close it if 513/* Test whether there have been errors on in_stream, and close it if
@@ -506,16 +520,16 @@ open_next_file(void)
506static void 520static void
507check_and_close(void) 521check_and_close(void)
508{ 522{
509 if (in_stream) { 523 if (G.in_stream) {
510 if (ferror(in_stream)) { 524 if (ferror(G.in_stream)) {
511 bb_error_msg("%s: read error", (in_stream == stdin) 525 bb_error_msg("%s: read error", (G.in_stream == stdin)
512 ? bb_msg_standard_input 526 ? bb_msg_standard_input
513 : file_list[-1] 527 : G.file_list[-1]
514 ); 528 );
515 exit_code = 1; 529 G.exit_code = 1;
516 } 530 }
517 fclose_if_not_stdin(in_stream); 531 fclose_if_not_stdin(G.in_stream);
518 in_stream = NULL; 532 G.in_stream = NULL;
519 } 533 }
520 534
521 if (ferror(stdout)) { 535 if (ferror(stdout)) {
@@ -751,9 +765,9 @@ decode_format_string(const char *s)
751 765
752 assert(s != next); 766 assert(s != next);
753 s = next; 767 s = next;
754 spec = xrealloc_vector(spec, 4, n_specs); 768 G.spec = xrealloc_vector(G.spec, 4, G.n_specs);
755 memcpy(&spec[n_specs], &tspec, sizeof(spec[0])); 769 memcpy(&G.spec[G.n_specs], &tspec, sizeof(G.spec[0]));
756 n_specs++; 770 G.n_specs++;
757 } 771 }
758} 772}
759 773
@@ -770,7 +784,7 @@ skip(off_t n_skip)
770 if (n_skip == 0) 784 if (n_skip == 0)
771 return; 785 return;
772 786
773 while (in_stream) { /* !EOF */ 787 while (G.in_stream) { /* !EOF */
774 struct stat file_stats; 788 struct stat file_stats;
775 789
776 /* First try seeking. For large offsets, this extra work is 790 /* First try seeking. For large offsets, this extra work is
@@ -788,15 +802,15 @@ skip(off_t n_skip)
788 If the number of bytes left to skip is at least 802 If the number of bytes left to skip is at least
789 as large as the size of the current file, we can 803 as large as the size of the current file, we can
790 decrement n_skip and go on to the next file. */ 804 decrement n_skip and go on to the next file. */
791 if (fstat(fileno(in_stream), &file_stats) == 0 805 if (fstat(fileno(G.in_stream), &file_stats) == 0
792 && S_ISREG(file_stats.st_mode) && file_stats.st_size > 0 806 && S_ISREG(file_stats.st_mode) && file_stats.st_size > 0
793 ) { 807 ) {
794 if (file_stats.st_size < n_skip) { 808 if (file_stats.st_size < n_skip) {
795 n_skip -= file_stats.st_size; 809 n_skip -= file_stats.st_size;
796 /* take "check & close / open_next" route */ 810 /* take "check & close / open_next" route */
797 } else { 811 } else {
798 if (fseeko(in_stream, n_skip, SEEK_CUR) != 0) 812 if (fseeko(G.in_stream, n_skip, SEEK_CUR) != 0)
799 exit_code = 1; 813 G.exit_code = 1;
800 return; 814 return;
801 } 815 }
802 } else { 816 } else {
@@ -809,7 +823,7 @@ skip(off_t n_skip)
809 while (n_skip > 0) { 823 while (n_skip > 0) {
810 if (n_skip < n_bytes_to_read) 824 if (n_skip < n_bytes_to_read)
811 n_bytes_to_read = n_skip; 825 n_bytes_to_read = n_skip;
812 n_bytes_read = fread(buf, 1, n_bytes_to_read, in_stream); 826 n_bytes_read = fread(buf, 1, n_bytes_to_read, G.in_stream);
813 n_skip -= n_bytes_read; 827 n_skip -= n_bytes_read;
814 if (n_bytes_read != n_bytes_to_read) 828 if (n_bytes_read != n_bytes_to_read)
815 break; /* EOF on this file or error */ 829 break; /* EOF on this file or error */
@@ -862,7 +876,7 @@ static void
862format_address_label(off_t address, char c) 876format_address_label(off_t address, char c)
863{ 877{
864 format_address_std(address, ' '); 878 format_address_std(address, ' ');
865 format_address_paren(address + pseudo_offset, c); 879 format_address_paren(address + G_pseudo_offset, c);
866} 880}
867#endif 881#endif
868 882
@@ -893,36 +907,34 @@ static void
893write_block(off_t current_offset, size_t n_bytes, 907write_block(off_t current_offset, size_t n_bytes,
894 const char *prev_block, const char *curr_block) 908 const char *prev_block, const char *curr_block)
895{ 909{
896 static char first = 1; 910 unsigned i;
897 static char prev_pair_equal = 0;
898 size_t i;
899 911
900 if (!(option_mask32 & OPT_v) 912 if (!(option_mask32 & OPT_v)
901 && !first 913 && G.not_first
902 && n_bytes == bytes_per_block 914 && n_bytes == G.bytes_per_block
903 && memcmp(prev_block, curr_block, bytes_per_block) == 0 915 && memcmp(prev_block, curr_block, G.bytes_per_block) == 0
904 ) { 916 ) {
905 if (prev_pair_equal) { 917 if (G.prev_pair_equal) {
906 /* The two preceding blocks were equal, and the current 918 /* The two preceding blocks were equal, and the current
907 block is the same as the last one, so print nothing. */ 919 block is the same as the last one, so print nothing. */
908 } else { 920 } else {
909 puts("*"); 921 puts("*");
910 prev_pair_equal = 1; 922 G.prev_pair_equal = 1;
911 } 923 }
912 } else { 924 } else {
913 first = 0; 925 G.not_first = 1;
914 prev_pair_equal = 0; 926 G.prev_pair_equal = 0;
915 for (i = 0; i < n_specs; i++) { 927 for (i = 0; i < G.n_specs; i++) {
916 if (i == 0) 928 if (i == 0)
917 format_address(current_offset, '\0'); 929 G.format_address(current_offset, '\0');
918 else 930 else
919 printf("%*s", address_pad_len_char - '0', ""); 931 printf("%*s", address_pad_len_char - '0', "");
920 (*spec[i].print_function) (n_bytes, curr_block, spec[i].fmt_string); 932 (*G.spec[i].print_function) (n_bytes, curr_block, G.spec[i].fmt_string);
921 if (spec[i].hexl_mode_trailer) { 933 if (G.spec[i].hexl_mode_trailer) {
922 /* space-pad out to full line width, then dump the trailer */ 934 /* space-pad out to full line width, then dump the trailer */
923 unsigned datum_width = width_bytes[spec[i].size]; 935 unsigned datum_width = width_bytes[G.spec[i].size];
924 unsigned blank_fields = (bytes_per_block - n_bytes) / datum_width; 936 unsigned blank_fields = (G.bytes_per_block - n_bytes) / datum_width;
925 unsigned field_width = spec[i].field_width + 1; 937 unsigned field_width = G.spec[i].field_width + 1;
926 printf("%*s", blank_fields * field_width, ""); 938 printf("%*s", blank_fields * field_width, "");
927 dump_hexl_mode_trailer(n_bytes, curr_block); 939 dump_hexl_mode_trailer(n_bytes, curr_block);
928 } 940 }
@@ -934,19 +946,19 @@ write_block(off_t current_offset, size_t n_bytes,
934static void 946static void
935read_block(size_t n, char *block, size_t *n_bytes_in_buffer) 947read_block(size_t n, char *block, size_t *n_bytes_in_buffer)
936{ 948{
937 assert(0 < n && n <= bytes_per_block); 949 assert(0 < n && n <= G.bytes_per_block);
938 950
939 *n_bytes_in_buffer = 0; 951 *n_bytes_in_buffer = 0;
940 952
941 if (n == 0) 953 if (n == 0)
942 return; 954 return;
943 955
944 while (in_stream != NULL) { /* EOF. */ 956 while (G.in_stream != NULL) { /* EOF. */
945 size_t n_needed; 957 size_t n_needed;
946 size_t n_read; 958 size_t n_read;
947 959
948 n_needed = n - *n_bytes_in_buffer; 960 n_needed = n - *n_bytes_in_buffer;
949 n_read = fread(block + *n_bytes_in_buffer, 1, n_needed, in_stream); 961 n_read = fread(block + *n_bytes_in_buffer, 1, n_needed, G.in_stream);
950 *n_bytes_in_buffer += n_read; 962 *n_bytes_in_buffer += n_read;
951 if (n_read == n_needed) 963 if (n_read == n_needed)
952 break; 964 break;
@@ -965,8 +977,8 @@ get_lcm(void)
965 size_t i; 977 size_t i;
966 int l_c_m = 1; 978 int l_c_m = 1;
967 979
968 for (i = 0; i < n_specs; i++) 980 for (i = 0; i < G.n_specs; i++)
969 l_c_m = lcm(l_c_m, width_bytes[(int) spec[i].size]); 981 l_c_m = lcm(l_c_m, width_bytes[(int) G.spec[i].size]);
970 return l_c_m; 982 return l_c_m;
971} 983}
972 984
@@ -987,8 +999,8 @@ dump(off_t current_offset, off_t end_offset)
987 int idx; 999 int idx;
988 size_t n_bytes_read; 1000 size_t n_bytes_read;
989 1001
990 block[0] = xmalloc(2 * bytes_per_block); 1002 block[0] = xmalloc(2 * G.bytes_per_block);
991 block[1] = block[0] + bytes_per_block; 1003 block[1] = block[0] + G.bytes_per_block;
992 1004
993 idx = 0; 1005 idx = 0;
994 if (option_mask32 & OPT_N) { 1006 if (option_mask32 & OPT_N) {
@@ -998,21 +1010,21 @@ dump(off_t current_offset, off_t end_offset)
998 n_bytes_read = 0; 1010 n_bytes_read = 0;
999 break; 1011 break;
1000 } 1012 }
1001 n_needed = MIN(end_offset - current_offset, (off_t) bytes_per_block); 1013 n_needed = MIN(end_offset - current_offset, (off_t) G.bytes_per_block);
1002 read_block(n_needed, block[idx], &n_bytes_read); 1014 read_block(n_needed, block[idx], &n_bytes_read);
1003 if (n_bytes_read < bytes_per_block) 1015 if (n_bytes_read < G.bytes_per_block)
1004 break; 1016 break;
1005 assert(n_bytes_read == bytes_per_block); 1017 assert(n_bytes_read == G.bytes_per_block);
1006 write_block(current_offset, n_bytes_read, block[idx ^ 1], block[idx]); 1018 write_block(current_offset, n_bytes_read, block[idx ^ 1], block[idx]);
1007 current_offset += n_bytes_read; 1019 current_offset += n_bytes_read;
1008 idx ^= 1; 1020 idx ^= 1;
1009 } 1021 }
1010 } else { 1022 } else {
1011 while (1) { 1023 while (1) {
1012 read_block(bytes_per_block, block[idx], &n_bytes_read); 1024 read_block(G.bytes_per_block, block[idx], &n_bytes_read);
1013 if (n_bytes_read < bytes_per_block) 1025 if (n_bytes_read < G.bytes_per_block)
1014 break; 1026 break;
1015 assert(n_bytes_read == bytes_per_block); 1027 assert(n_bytes_read == G.bytes_per_block);
1016 write_block(current_offset, n_bytes_read, block[idx ^ 1], block[idx]); 1028 write_block(current_offset, n_bytes_read, block[idx ^ 1], block[idx]);
1017 current_offset += n_bytes_read; 1029 current_offset += n_bytes_read;
1018 idx ^= 1; 1030 idx ^= 1;
@@ -1035,7 +1047,7 @@ dump(off_t current_offset, off_t end_offset)
1035 current_offset += n_bytes_read; 1047 current_offset += n_bytes_read;
1036 } 1048 }
1037 1049
1038 format_address(current_offset, '\n'); 1050 G.format_address(current_offset, '\n');
1039 1051
1040 if ((option_mask32 & OPT_N) && current_offset >= end_offset) 1052 if ((option_mask32 & OPT_N) && current_offset >= end_offset)
1041 check_and_close(); 1053 check_and_close();
@@ -1066,16 +1078,16 @@ dump(off_t current_offset, off_t end_offset)
1066static void 1078static void
1067dump_strings(off_t address, off_t end_offset) 1079dump_strings(off_t address, off_t end_offset)
1068{ 1080{
1069 unsigned bufsize = MAX(100, string_min); 1081 unsigned bufsize = MAX(100, G.string_min);
1070 unsigned char *buf = xmalloc(bufsize); 1082 unsigned char *buf = xmalloc(bufsize);
1071 1083
1072 while (1) { 1084 while (1) {
1073 size_t i; 1085 size_t i;
1074 int c; 1086 int c;
1075 1087
1076 /* See if the next 'string_min' chars are all printing chars. */ 1088 /* See if the next 'G.string_min' chars are all printing chars. */
1077 tryline: 1089 tryline:
1078 if ((option_mask32 & OPT_N) && (end_offset - string_min <= address)) 1090 if ((option_mask32 & OPT_N) && (end_offset - G.string_min <= address))
1079 break; 1091 break;
1080 i = 0; 1092 i = 0;
1081 while (!(option_mask32 & OPT_N) || address < end_offset) { 1093 while (!(option_mask32 & OPT_N) || address < end_offset) {
@@ -1084,8 +1096,8 @@ dump_strings(off_t address, off_t end_offset)
1084 buf = xrealloc(buf, bufsize); 1096 buf = xrealloc(buf, bufsize);
1085 } 1097 }
1086 1098
1087 while (in_stream) { /* !EOF */ 1099 while (G.in_stream) { /* !EOF */
1088 c = fgetc(in_stream); 1100 c = fgetc(G.in_stream);
1089 if (c != EOF) 1101 if (c != EOF)
1090 goto got_char; 1102 goto got_char;
1091 check_and_close(); 1103 check_and_close();
@@ -1102,12 +1114,12 @@ dump_strings(off_t address, off_t end_offset)
1102 buf[i++] = c; /* String continues; store it all. */ 1114 buf[i++] = c; /* String continues; store it all. */
1103 } 1115 }
1104 1116
1105 if (i < string_min) /* Too short! */ 1117 if (i < G.string_min) /* Too short! */
1106 goto tryline; 1118 goto tryline;
1107 1119
1108 /* If we get here, the string is all printable and NUL-terminated */ 1120 /* If we get here, the string is all printable and NUL-terminated */
1109 buf[i] = 0; 1121 buf[i] = 0;
1110 format_address(address - i - 1, ' '); 1122 G.format_address(address - i - 1, ' ');
1111 1123
1112 for (i = 0; (c = buf[i]); i++) { 1124 for (i = 0; (c = buf[i]); i++) {
1113 switch (c) { 1125 switch (c) {
@@ -1125,7 +1137,7 @@ dump_strings(off_t address, off_t end_offset)
1125 } 1137 }
1126 1138
1127 /* We reach this point only if we search through 1139 /* We reach this point only if we search through
1128 (max_bytes_to_format - string_min) bytes before reaching EOF. */ 1140 (max_bytes_to_format - G.string_min) bytes before reaching EOF. */
1129 check_and_close(); 1141 check_and_close();
1130 ret: 1142 ret:
1131 free(buf); 1143 free(buf);
@@ -1197,8 +1209,10 @@ int od_main(int argc UNUSED_PARAM, char **argv)
1197 /* The maximum number of bytes that will be formatted. */ 1209 /* The maximum number of bytes that will be formatted. */
1198 off_t max_bytes_to_format = 0; 1210 off_t max_bytes_to_format = 0;
1199 1211
1200 spec = NULL; 1212 INIT_G();
1201 format_address = format_address_std; 1213
1214 /*G.spec = NULL; - already is */
1215 G.format_address = format_address_std;
1202 address_base_char = 'o'; 1216 address_base_char = 'o';
1203 address_pad_len_char = '7'; 1217 address_pad_len_char = '7';
1204 1218
@@ -1224,7 +1238,7 @@ int od_main(int argc UNUSED_PARAM, char **argv)
1224 bb_error_msg_and_die("bad output address radix " 1238 bb_error_msg_and_die("bad output address radix "
1225 "'%c' (must be [doxn])", str_A[0]); 1239 "'%c' (must be [doxn])", str_A[0]);
1226 pos = p - doxn; 1240 pos = p - doxn;
1227 if (pos == 3) format_address = format_address_none; 1241 if (pos == 3) G.format_address = format_address_none;
1228 address_base_char = doxn_address_base_char[pos]; 1242 address_base_char = doxn_address_base_char[pos];
1229 address_pad_len_char = doxn_address_pad_len_char[pos]; 1243 address_pad_len_char = doxn_address_pad_len_char[pos];
1230 } 1244 }
@@ -1247,11 +1261,11 @@ int od_main(int argc UNUSED_PARAM, char **argv)
1247 if (opt & OPT_x) decode_format_string("x2"); 1261 if (opt & OPT_x) decode_format_string("x2");
1248 if (opt & OPT_s) decode_format_string("d2"); 1262 if (opt & OPT_s) decode_format_string("d2");
1249 if (opt & OPT_S) { 1263 if (opt & OPT_S) {
1250 string_min = xstrtou_sfx(str_S, 0, bkm_suffixes); 1264 G.string_min = xstrtou_sfx(str_S, 0, bkm_suffixes);
1251 } 1265 }
1252 1266
1253 // Bloat: 1267 // Bloat:
1254 //if ((option_mask32 & OPT_S) && n_specs > 0) 1268 //if ((option_mask32 & OPT_S) && G.n_specs > 0)
1255 // bb_error_msg_and_die("no type may be specified when dumping strings"); 1269 // bb_error_msg_and_die("no type may be specified when dumping strings");
1256 1270
1257 /* If the --traditional option is used, there may be from 1271 /* If the --traditional option is used, there may be from
@@ -1307,14 +1321,14 @@ int od_main(int argc UNUSED_PARAM, char **argv)
1307 } 1321 }
1308 1322
1309 if (pseudo_start >= 0) { 1323 if (pseudo_start >= 0) {
1310 if (format_address == format_address_none) { 1324 if (G.format_address == format_address_none) {
1311 address_base_char = 'o'; 1325 address_base_char = 'o';
1312 address_pad_len_char = '7'; 1326 address_pad_len_char = '7';
1313 format_address = format_address_paren; 1327 G.format_address = format_address_paren;
1314 } else { 1328 } else {
1315 format_address = format_address_label; 1329 G.format_address = format_address_label;
1316 } 1330 }
1317 pseudo_offset = pseudo_start - n_bytes_to_skip; 1331 G_pseudo_offset = pseudo_start - n_bytes_to_skip;
1318 } 1332 }
1319 } 1333 }
1320 /* else: od --traditional (without args) */ 1334 /* else: od --traditional (without args) */
@@ -1327,45 +1341,45 @@ int od_main(int argc UNUSED_PARAM, char **argv)
1327 bb_error_msg_and_die("SKIP + SIZE is too large"); 1341 bb_error_msg_and_die("SKIP + SIZE is too large");
1328 } 1342 }
1329 1343
1330 if (n_specs == 0) { 1344 if (G.n_specs == 0) {
1331 decode_format_string("o2"); 1345 decode_format_string("o2");
1332 /*n_specs = 1; - done by decode_format_string */ 1346 /*G.n_specs = 1; - done by decode_format_string */
1333 } 1347 }
1334 1348
1335 /* If no files were listed on the command line, 1349 /* If no files were listed on the command line,
1336 set the global pointer FILE_LIST so that it 1350 set the global pointer FILE_LIST so that it
1337 references the null-terminated list of one name: "-". */ 1351 references the null-terminated list of one name: "-". */
1338 file_list = bb_argv_dash; 1352 G.file_list = bb_argv_dash;
1339 if (argv[0]) { 1353 if (argv[0]) {
1340 /* Set the global pointer FILE_LIST so that it 1354 /* Set the global pointer FILE_LIST so that it
1341 references the first file-argument on the command-line. */ 1355 references the first file-argument on the command-line. */
1342 file_list = (char const *const *) argv; 1356 G.file_list = (char const *const *) argv;
1343 } 1357 }
1344 1358
1345 /* Open the first input file */ 1359 /* Open the first input file */
1346 open_next_file(); 1360 open_next_file();
1347 /* Skip over any unwanted header bytes */ 1361 /* Skip over any unwanted header bytes */
1348 skip(n_bytes_to_skip); 1362 skip(n_bytes_to_skip);
1349 if (!in_stream) 1363 if (!G.in_stream)
1350 return EXIT_FAILURE; 1364 return EXIT_FAILURE;
1351 1365
1352 /* Compute output block length */ 1366 /* Compute output block length */
1353 l_c_m = get_lcm(); 1367 l_c_m = get_lcm();
1354 1368
1355 if (opt & OPT_w) { /* -w: width */ 1369 if (opt & OPT_w) { /* -w: width */
1356 if (!bytes_per_block || bytes_per_block % l_c_m != 0) { 1370 if (!G.bytes_per_block || G.bytes_per_block % l_c_m != 0) {
1357 bb_error_msg("warning: invalid width %u; using %d instead", 1371 bb_error_msg("warning: invalid width %u; using %d instead",
1358 (unsigned)bytes_per_block, l_c_m); 1372 (unsigned)G.bytes_per_block, l_c_m);
1359 bytes_per_block = l_c_m; 1373 G.bytes_per_block = l_c_m;
1360 } 1374 }
1361 } else { 1375 } else {
1362 bytes_per_block = l_c_m; 1376 G.bytes_per_block = l_c_m;
1363 if (l_c_m < DEFAULT_BYTES_PER_BLOCK) 1377 if (l_c_m < DEFAULT_BYTES_PER_BLOCK)
1364 bytes_per_block *= DEFAULT_BYTES_PER_BLOCK / l_c_m; 1378 G.bytes_per_block *= DEFAULT_BYTES_PER_BLOCK / l_c_m;
1365 } 1379 }
1366 1380
1367#ifdef DEBUG 1381#ifdef DEBUG
1368 for (i = 0; i < n_specs; i++) { 1382 for (i = 0; i < G.n_specs; i++) {
1369 printf("%d: fmt=\"%s\" width=%d\n", 1383 printf("%d: fmt=\"%s\" width=%d\n",
1370 i, spec[i].fmt_string, width_bytes[spec[i].size]); 1384 i, spec[i].fmt_string, width_bytes[spec[i].size]);
1371 } 1385 }
@@ -1379,5 +1393,5 @@ int od_main(int argc UNUSED_PARAM, char **argv)
1379 if (fclose(stdin)) 1393 if (fclose(stdin))
1380 bb_perror_msg_and_die(bb_msg_standard_input); 1394 bb_perror_msg_and_die(bb_msg_standard_input);
1381 1395
1382 return exit_code; 1396 return G.exit_code;
1383} 1397}
diff --git a/debianutils/Config.src b/debianutils/Config.src
index cbc09b5ce..61daeb047 100644
--- a/debianutils/Config.src
+++ b/debianutils/Config.src
@@ -7,79 +7,4 @@ menu "Debian Utilities"
7 7
8INSERT 8INSERT
9 9
10config MKTEMP
11 bool "mktemp"
12 default y
13 help
14 mktemp is used to create unique temporary files
15
16config PIPE_PROGRESS
17 bool "pipe_progress"
18 default y
19 help
20 Display a dot to indicate pipe activity.
21
22config RUN_PARTS
23 bool "run-parts"
24 default y
25 help
26 run-parts is a utility designed to run all the scripts in a directory.
27
28 It is useful to set up a directory like cron.daily, where you need to
29 execute all the scripts in that directory.
30
31 In this implementation of run-parts some features (such as report
32 mode) are not implemented.
33
34 Unless you know that run-parts is used in some of your scripts
35 you can safely say N here.
36
37config FEATURE_RUN_PARTS_LONG_OPTIONS
38 bool "Enable long options"
39 default y
40 depends on RUN_PARTS && LONG_OPTS
41 help
42 Support long options for the run-parts applet.
43
44config FEATURE_RUN_PARTS_FANCY
45 bool "Support additional arguments"
46 default y
47 depends on RUN_PARTS
48 help
49 Support additional options:
50 -l --list print the names of the all matching files (not
51 limited to executables), but don't actually run them.
52
53config START_STOP_DAEMON
54 bool "start-stop-daemon"
55 default y
56 help
57 start-stop-daemon is used to control the creation and
58 termination of system-level processes, usually the ones
59 started during the startup of the system.
60
61config FEATURE_START_STOP_DAEMON_FANCY
62 bool "Support additional arguments"
63 default y
64 depends on START_STOP_DAEMON
65 help
66 Support additional arguments.
67 -o|--oknodo ignored since we exit with 0 anyway
68 -v|--verbose
69 -N|--nicelevel N
70
71config FEATURE_START_STOP_DAEMON_LONG_OPTIONS
72 bool "Enable long options"
73 default y
74 depends on START_STOP_DAEMON && LONG_OPTS
75 help
76 Support long options for the start-stop-daemon applet.
77
78config WHICH
79 bool "which"
80 default y
81 help
82 which is used to find programs in your PATH and
83 print out their pathnames.
84
85endmenu 10endmenu
diff --git a/debianutils/Kbuild.src b/debianutils/Kbuild.src
index d41b5c8e4..6b4fb7470 100644
--- a/debianutils/Kbuild.src
+++ b/debianutils/Kbuild.src
@@ -7,8 +7,3 @@
7lib-y:= 7lib-y:=
8 8
9INSERT 9INSERT
10lib-$(CONFIG_MKTEMP) += mktemp.o
11lib-$(CONFIG_PIPE_PROGRESS) += pipe_progress.o
12lib-$(CONFIG_RUN_PARTS) += run_parts.o
13lib-$(CONFIG_START_STOP_DAEMON) += start_stop_daemon.o
14lib-$(CONFIG_WHICH) += which.o
diff --git a/debianutils/mktemp.c b/debianutils/mktemp.c
index 983d7a246..65353697a 100644
--- a/debianutils/mktemp.c
+++ b/debianutils/mktemp.c
@@ -30,6 +30,15 @@
30 * a directory: $TMPDIR, if set; else the directory specified via 30 * a directory: $TMPDIR, if set; else the directory specified via
31 * -p; else /tmp [deprecated] 31 * -p; else /tmp [deprecated]
32 */ 32 */
33//config:config MKTEMP
34//config: bool "mktemp"
35//config: default y
36//config: help
37//config: mktemp is used to create unique temporary files
38
39//applet:IF_MKTEMP(APPLET(mktemp, BB_DIR_BIN, BB_SUID_DROP))
40
41//kbuild:lib-$(CONFIG_MKTEMP) += mktemp.o
33 42
34//usage:#define mktemp_trivial_usage 43//usage:#define mktemp_trivial_usage
35//usage: "[-dt] [-p DIR] [TEMPLATE]" 44//usage: "[-dt] [-p DIR] [TEMPLATE]"
diff --git a/debianutils/pipe_progress.c b/debianutils/pipe_progress.c
index 2c7444f31..21d330b59 100644
--- a/debianutils/pipe_progress.c
+++ b/debianutils/pipe_progress.c
@@ -6,6 +6,15 @@
6 * 6 *
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config PIPE_PROGRESS
10//config: bool "pipe_progress"
11//config: default y
12//config: help
13//config: Display a dot to indicate pipe activity.
14
15//applet:IF_PIPE_PROGRESS(APPLET(pipe_progress, BB_DIR_BIN, BB_SUID_DROP))
16
17//kbuild:lib-$(CONFIG_PIPE_PROGRESS) += pipe_progress.o
9 18
10//usage:#define pipe_progress_trivial_usage NOUSAGE_STR 19//usage:#define pipe_progress_trivial_usage NOUSAGE_STR
11//usage:#define pipe_progress_full_usage "" 20//usage:#define pipe_progress_full_usage ""
diff --git a/debianutils/run_parts.c b/debianutils/run_parts.c
index dd6fe7d49..13617c6e1 100644
--- a/debianutils/run_parts.c
+++ b/debianutils/run_parts.c
@@ -22,6 +22,40 @@
22 * report mode. As the original run-parts support only long options, I've 22 * report mode. As the original run-parts support only long options, I've
23 * broken compatibility because the BusyBox policy doesn't allow them. 23 * broken compatibility because the BusyBox policy doesn't allow them.
24 */ 24 */
25//config:config RUN_PARTS
26//config: bool "run-parts"
27//config: default y
28//config: help
29//config: run-parts is a utility designed to run all the scripts in a directory.
30//config:
31//config: It is useful to set up a directory like cron.daily, where you need to
32//config: execute all the scripts in that directory.
33//config:
34//config: In this implementation of run-parts some features (such as report
35//config: mode) are not implemented.
36//config:
37//config: Unless you know that run-parts is used in some of your scripts
38//config: you can safely say N here.
39//config:
40//config:config FEATURE_RUN_PARTS_LONG_OPTIONS
41//config: bool "Enable long options"
42//config: default y
43//config: depends on RUN_PARTS && LONG_OPTS
44//config: help
45//config: Support long options for the run-parts applet.
46//config:
47//config:config FEATURE_RUN_PARTS_FANCY
48//config: bool "Support additional arguments"
49//config: default y
50//config: depends on RUN_PARTS
51//config: help
52//config: Support additional options:
53//config: -l --list print the names of the all matching files (not
54//config: limited to executables), but don't actually run them.
55
56//applet:IF_RUN_PARTS(APPLET_ODDNAME(run-parts, run_parts, BB_DIR_BIN, BB_SUID_DROP, run_parts))
57
58//kbuild:lib-$(CONFIG_RUN_PARTS) += run_parts.o
25 59
26//usage:#define run_parts_trivial_usage 60//usage:#define run_parts_trivial_usage
27//usage: "[-a ARG]... [-u UMASK] " 61//usage: "[-a ARG]... [-u UMASK] "
diff --git a/debianutils/start_stop_daemon.c b/debianutils/start_stop_daemon.c
index 7dadc3c9e..d7c730f45 100644
--- a/debianutils/start_stop_daemon.c
+++ b/debianutils/start_stop_daemon.c
@@ -56,6 +56,34 @@ Misc options:
56 -q,--quiet Quiet 56 -q,--quiet Quiet
57 -v,--verbose Verbose 57 -v,--verbose Verbose
58*/ 58*/
59//config:config START_STOP_DAEMON
60//config: bool "start-stop-daemon"
61//config: default y
62//config: help
63//config: start-stop-daemon is used to control the creation and
64//config: termination of system-level processes, usually the ones
65//config: started during the startup of the system.
66//config:
67//config:config FEATURE_START_STOP_DAEMON_FANCY
68//config: bool "Support additional arguments"
69//config: default y
70//config: depends on START_STOP_DAEMON
71//config: help
72//config: Support additional arguments.
73//config: -o|--oknodo ignored since we exit with 0 anyway
74//config: -v|--verbose
75//config: -N|--nicelevel N
76//config:
77//config:config FEATURE_START_STOP_DAEMON_LONG_OPTIONS
78//config: bool "Enable long options"
79//config: default y
80//config: depends on START_STOP_DAEMON && LONG_OPTS
81//config: help
82//config: Support long options for the start-stop-daemon applet.
83
84//applet:IF_START_STOP_DAEMON(APPLET_ODDNAME(start-stop-daemon, start_stop_daemon, BB_DIR_SBIN, BB_SUID_DROP, start_stop_daemon))
85
86//kbuild:lib-$(CONFIG_START_STOP_DAEMON) += start_stop_daemon.o
59 87
60//usage:#define start_stop_daemon_trivial_usage 88//usage:#define start_stop_daemon_trivial_usage
61//usage: "[OPTIONS] [-S|-K] ... [-- ARGS...]" 89//usage: "[OPTIONS] [-S|-K] ... [-- ARGS...]"
@@ -511,15 +539,15 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv)
511 write_pidfile(pidfile); 539 write_pidfile(pidfile);
512 } 540 }
513 if (opt & OPT_c) { 541 if (opt & OPT_c) {
514 struct bb_uidgid_t ugid = { -1, -1 }; 542 struct bb_uidgid_t ugid;
515 parse_chown_usergroup_or_die(&ugid, chuid); 543 parse_chown_usergroup_or_die(&ugid, chuid);
516 if (ugid.uid != (uid_t) -1) { 544 if (ugid.uid != (uid_t) -1L) {
517 struct passwd *pw = xgetpwuid(ugid.uid); 545 struct passwd *pw = xgetpwuid(ugid.uid);
518 if (ugid.gid != (gid_t) -1) 546 if (ugid.gid != (gid_t) -1L)
519 pw->pw_gid = ugid.gid; 547 pw->pw_gid = ugid.gid;
520 /* initgroups, setgid, setuid: */ 548 /* initgroups, setgid, setuid: */
521 change_identity(pw); 549 change_identity(pw);
522 } else if (ugid.gid != (gid_t) -1) { 550 } else if (ugid.gid != (gid_t) -1L) {
523 xsetgid(ugid.gid); 551 xsetgid(ugid.gid);
524 setgroups(1, &ugid.gid); 552 setgroups(1, &ugid.gid);
525 } 553 }
diff --git a/debianutils/which.c b/debianutils/which.c
index ace5b82dd..86dd5c352 100644
--- a/debianutils/which.c
+++ b/debianutils/which.c
@@ -5,6 +5,16 @@
5 * 5 *
6 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 6 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
7 */ 7 */
8//config:config WHICH
9//config: bool "which"
10//config: default y
11//config: help
12//config: which is used to find programs in your PATH and
13//config: print out their pathnames.
14
15//applet:IF_WHICH(APPLET(which, BB_DIR_USR_BIN, BB_SUID_DROP))
16
17//kbuild:lib-$(CONFIG_WHICH) += which.o
8 18
9//usage:#define which_trivial_usage 19//usage:#define which_trivial_usage
10//usage: "[COMMAND]..." 20//usage: "[COMMAND]..."
diff --git a/e2fsprogs/Config.src b/e2fsprogs/Config.src
index 743e1e11f..a20d849e6 100644
--- a/e2fsprogs/Config.src
+++ b/e2fsprogs/Config.src
@@ -7,12 +7,6 @@ menu "Linux Ext2 FS Progs"
7 7
8INSERT 8INSERT
9 9
10config CHATTR
11 bool "chattr"
12 default y
13 help
14 chattr changes the file attributes on a second extended file system.
15
16### config E2FSCK 10### config E2FSCK
17### bool "e2fsck" 11### bool "e2fsck"
18### default y 12### default y
@@ -22,21 +16,6 @@ config CHATTR
22### The normal compat symlinks 'fsck.ext2' and 'fsck.ext3' are also 16### The normal compat symlinks 'fsck.ext2' and 'fsck.ext3' are also
23### provided. 17### provided.
24 18
25config FSCK
26 bool "fsck"
27 default y
28 help
29 fsck is used to check and optionally repair one or more filesystems.
30 In actuality, fsck is simply a front-end for the various file system
31 checkers (fsck.fstype) available under Linux.
32
33config LSATTR
34 bool "lsattr"
35 default y
36 select PLATFORM_LINUX
37 help
38 lsattr lists the file attributes on a second extended file system.
39
40### config MKE2FS 19### config MKE2FS
41### bool "mke2fs" 20### bool "mke2fs"
42### default y 21### default y
@@ -44,13 +23,6 @@ config LSATTR
44### mke2fs is used to create an ext2/ext3 filesystem. The normal compat 23### mke2fs is used to create an ext2/ext3 filesystem. The normal compat
45### symlinks 'mkfs.ext2' and 'mkfs.ext3' are also provided. 24### symlinks 'mkfs.ext2' and 'mkfs.ext3' are also provided.
46 25
47config TUNE2FS
48 bool "tune2fs"
49 default n # off: it is too limited compared to upstream version
50 help
51 tune2fs allows the system administrator to adjust various tunable
52 filesystem parameters on Linux ext2/ext3 filesystems.
53
54### config E2LABEL 26### config E2LABEL
55### bool "e2label" 27### bool "e2label"
56### default y 28### default y
diff --git a/e2fsprogs/Kbuild.src b/e2fsprogs/Kbuild.src
index b7a14c381..6b4fb7470 100644
--- a/e2fsprogs/Kbuild.src
+++ b/e2fsprogs/Kbuild.src
@@ -7,9 +7,3 @@
7lib-y:= 7lib-y:=
8 8
9INSERT 9INSERT
10
11lib-$(CONFIG_CHATTR) += chattr.o e2fs_lib.o
12lib-$(CONFIG_LSATTR) += lsattr.o e2fs_lib.o
13
14lib-$(CONFIG_FSCK) += fsck.o
15lib-$(CONFIG_TUNE2FS) += tune2fs.o
diff --git a/e2fsprogs/chattr.c b/e2fsprogs/chattr.c
index f1cc8389f..043f39591 100644
--- a/e2fsprogs/chattr.c
+++ b/e2fsprogs/chattr.c
@@ -9,24 +9,22 @@
9 * This file can be redistributed under the terms of the GNU General 9 * This file can be redistributed under the terms of the GNU General
10 * Public License 10 * Public License
11 */ 11 */
12//config:config CHATTR
13//config: bool "chattr"
14//config: default y
15//config: help
16//config: chattr changes the file attributes on a second extended file system.
12 17
13/* 18//applet:IF_CHATTR(APPLET(chattr, BB_DIR_BIN, BB_SUID_DROP))
14 * History: 19
15 * 93/10/30 - Creation 20//kbuild:lib-$(CONFIG_CHATTR) += chattr.o e2fs_lib.o
16 * 93/11/13 - Replace stat() calls by lstat() to avoid loops
17 * 94/02/27 - Integrated in Ted's distribution
18 * 98/12/29 - Ignore symlinks when working recursively (G M Sipe)
19 * 98/12/29 - Display version info only when -V specified (G M Sipe)
20 */
21 21
22//usage:#define chattr_trivial_usage 22//usage:#define chattr_trivial_usage
23//usage: "[-R] [-+=AacDdijsStTu] [-v VERSION] [FILE]..." 23//usage: "[-R] [-+=AacDdijsStTu] [-v VERSION] [FILE]..."
24//usage:#define chattr_full_usage "\n\n" 24//usage:#define chattr_full_usage "\n\n"
25//usage: "Change file attributes on an ext2 fs\n" 25//usage: "Change ext2 file attributes\n"
26//usage: "\nModifiers:" 26//usage: "\nModifiers:"
27//usage: "\n - Remove attributes" 27//usage: "\n -,+,= Remove/add/set attributes"
28//usage: "\n + Add attributes"
29//usage: "\n = Set attributes"
30//usage: "\nAttributes:" 28//usage: "\nAttributes:"
31//usage: "\n A Don't track atime" 29//usage: "\n A Don't track atime"
32//usage: "\n a Append mode only" 30//usage: "\n a Append mode only"
@@ -36,11 +34,11 @@
36//usage: "\n i Cannot be modified (immutable)" 34//usage: "\n i Cannot be modified (immutable)"
37//usage: "\n j Write all data to journal first" 35//usage: "\n j Write all data to journal first"
38//usage: "\n s Zero disk storage when deleted" 36//usage: "\n s Zero disk storage when deleted"
39//usage: "\n S Write file contents synchronously" 37//usage: "\n S Write synchronously"
40//usage: "\n t Disable tail-merging of partial blocks with other files" 38//usage: "\n t Disable tail-merging of partial blocks with other files"
41//usage: "\n u Allow file to be undeleted" 39//usage: "\n u Allow file to be undeleted"
42//usage: "\n -R Recurse" 40//usage: "\n -R Recurse"
43//usage: "\n -v Set the file's version/generation number" 41//usage: "\n -v VER Set version/generation number"
44 42
45#include "libbb.h" 43#include "libbb.h"
46#include "e2fs_lib.h" 44#include "e2fs_lib.h"
diff --git a/e2fsprogs/fsck.c b/e2fsprogs/fsck.c
index d2d312e5c..627d2be31 100644
--- a/e2fsprogs/fsck.c
+++ b/e2fsprogs/fsck.c
@@ -33,9 +33,20 @@
33 * spawns actual fsck.something for each filesystem to check. 33 * spawns actual fsck.something for each filesystem to check.
34 * It doesn't guess filesystem types from on-disk format. 34 * It doesn't guess filesystem types from on-disk format.
35 */ 35 */
36//config:config FSCK
37//config: bool "fsck"
38//config: default y
39//config: help
40//config: fsck is used to check and optionally repair one or more filesystems.
41//config: In actuality, fsck is simply a front-end for the various file system
42//config: checkers (fsck.fstype) available under Linux.
43
44//applet:IF_FSCK(APPLET(fsck, BB_DIR_SBIN, BB_SUID_DROP))
45
46//kbuild:lib-$(CONFIG_FSCK) += fsck.o
36 47
37//usage:#define fsck_trivial_usage 48//usage:#define fsck_trivial_usage
38//usage: "[-ANPRTV] [-C FD] [-t FSTYPE] [FS_OPTS] [BLOCKDEV]..." 49//usage: "[-ANPRTV] [-t FSTYPE] [FS_OPTS] [BLOCKDEV]..."
39//usage:#define fsck_full_usage "\n\n" 50//usage:#define fsck_full_usage "\n\n"
40//usage: "Check and repair filesystems\n" 51//usage: "Check and repair filesystems\n"
41//usage: "\n -A Walk /etc/fstab and check all filesystems" 52//usage: "\n -A Walk /etc/fstab and check all filesystems"
@@ -44,7 +55,8 @@
44//usage: "\n -R With -A, skip the root filesystem" 55//usage: "\n -R With -A, skip the root filesystem"
45//usage: "\n -T Don't show title on startup" 56//usage: "\n -T Don't show title on startup"
46//usage: "\n -V Verbose" 57//usage: "\n -V Verbose"
47//usage: "\n -C n Write status information to specified filedescriptor" 58//DO_PROGRESS_INDICATOR is off:
59////usage: "\n -C FD Write status information to specified file descriptor"
48//usage: "\n -t TYPE List of filesystem types to check" 60//usage: "\n -t TYPE List of filesystem types to check"
49 61
50#include "libbb.h" 62#include "libbb.h"
@@ -125,35 +137,42 @@ static const char really_wanted[] ALIGN1 =
125 137
126#define BASE_MD "/dev/md" 138#define BASE_MD "/dev/md"
127 139
128static char **args; 140struct globals {
129static int num_args; 141 char **args;
130static int verbose; 142 int num_args;
143 int verbose;
131 144
132#define FS_TYPE_FLAG_NORMAL 0 145#define FS_TYPE_FLAG_NORMAL 0
133#define FS_TYPE_FLAG_OPT 1 146#define FS_TYPE_FLAG_OPT 1
134#define FS_TYPE_FLAG_NEGOPT 2 147#define FS_TYPE_FLAG_NEGOPT 2
135static char **fs_type_list; 148 char **fs_type_list;
136static uint8_t *fs_type_flag; 149 uint8_t *fs_type_flag;
137static smallint fs_type_negated; 150 smallint fs_type_negated;
138 151
139static smallint noexecute; 152 smallint noexecute;
140static smallint serialize; 153 smallint serialize;
141static smallint skip_root; 154 smallint skip_root;
142/* static smallint like_mount; */ 155 /* smallint like_mount; */
143static smallint parallel_root; 156 smallint parallel_root;
144static smallint force_all_parallel; 157 smallint force_all_parallel;
158 smallint kill_sent;
145 159
146#if DO_PROGRESS_INDICATOR 160#if DO_PROGRESS_INDICATOR
147static smallint progress; 161 smallint progress;
148static int progress_fd; 162 int progress_fd;
149#endif 163#endif
150 164
151static int num_running; 165 int num_running;
152static int max_running; 166 int max_running;
153static char *fstype; 167 char *fstype;
154static struct fs_info *filesys_info; 168 struct fs_info *filesys_info;
155static struct fs_info *filesys_last; 169 struct fs_info *filesys_last;
156static struct fsck_instance *instance_list; 170 struct fsck_instance *instance_list;
171} FIX_ALIASING;
172#define G (*(struct globals*)&bb_common_bufsiz1)
173#define INIT_G() do { \
174 BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
175} while (0)
157 176
158/* 177/*
159 * Return the "base device" given a particular device; this is used to 178 * Return the "base device" given a particular device; this is used to
@@ -302,11 +321,11 @@ static struct fs_info *create_fs_device(const char *device, const char *mntpnt,
302 /*fs->flags = 0; */ 321 /*fs->flags = 0; */
303 /*fs->next = NULL; */ 322 /*fs->next = NULL; */
304 323
305 if (!filesys_info) 324 if (!G.filesys_info)
306 filesys_info = fs; 325 G.filesys_info = fs;
307 else 326 else
308 filesys_last->next = fs; 327 G.filesys_last->next = fs;
309 filesys_last = fs; 328 G.filesys_last = fs;
310 329
311 return fs; 330 return fs;
312} 331}
@@ -316,6 +335,7 @@ static void load_fs_info(const char *filename)
316{ 335{
317 FILE *fstab; 336 FILE *fstab;
318 struct mntent mte; 337 struct mntent mte;
338 char buf[1024];
319 339
320 fstab = setmntent(filename, "r"); 340 fstab = setmntent(filename, "r");
321 if (!fstab) { 341 if (!fstab) {
@@ -324,7 +344,7 @@ static void load_fs_info(const char *filename)
324 } 344 }
325 345
326 // Loop through entries 346 // Loop through entries
327 while (getmntent_r(fstab, &mte, bb_common_bufsiz1, COMMON_BUFSIZE)) { 347 while (getmntent_r(fstab, &mte, buf, sizeof(buf))) {
328 //bb_info_msg("CREATE[%s][%s][%s][%s][%d]", mte.mnt_fsname, mte.mnt_dir, 348 //bb_info_msg("CREATE[%s][%s][%s][%s][%d]", mte.mnt_fsname, mte.mnt_dir,
329 // mte.mnt_type, mte.mnt_opts, 349 // mte.mnt_type, mte.mnt_opts,
330 // mte.mnt_passno); 350 // mte.mnt_passno);
@@ -340,7 +360,7 @@ static struct fs_info *lookup(char *filesys)
340{ 360{
341 struct fs_info *fs; 361 struct fs_info *fs;
342 362
343 for (fs = filesys_info; fs; fs = fs->next) { 363 for (fs = G.filesys_info; fs; fs = fs->next) {
344 if (strcmp(filesys, fs->device) == 0 364 if (strcmp(filesys, fs->device) == 0
345 || (fs->mountpt && strcmp(filesys, fs->mountpt) == 0) 365 || (fs->mountpt && strcmp(filesys, fs->mountpt) == 0)
346 ) 366 )
@@ -355,7 +375,7 @@ static int progress_active(void)
355{ 375{
356 struct fsck_instance *inst; 376 struct fsck_instance *inst;
357 377
358 for (inst = instance_list; inst; inst = inst->next) { 378 for (inst = G.instance_list; inst; inst = inst->next) {
359 if (inst->flags & FLAG_DONE) 379 if (inst->flags & FLAG_DONE)
360 continue; 380 continue;
361 if (inst->flags & FLAG_PROGRESS) 381 if (inst->flags & FLAG_PROGRESS)
@@ -371,19 +391,17 @@ static int progress_active(void)
371 */ 391 */
372static void kill_all_if_got_signal(void) 392static void kill_all_if_got_signal(void)
373{ 393{
374 static smallint kill_sent;
375
376 struct fsck_instance *inst; 394 struct fsck_instance *inst;
377 395
378 if (!bb_got_signal || kill_sent) 396 if (!bb_got_signal || G.kill_sent)
379 return; 397 return;
380 398
381 for (inst = instance_list; inst; inst = inst->next) { 399 for (inst = G.instance_list; inst; inst = inst->next) {
382 if (inst->flags & FLAG_DONE) 400 if (inst->flags & FLAG_DONE)
383 continue; 401 continue;
384 kill(inst->pid, SIGTERM); 402 kill(inst->pid, SIGTERM);
385 } 403 }
386 kill_sent = 1; 404 G.kill_sent = 1;
387} 405}
388 406
389/* 407/*
@@ -398,9 +416,9 @@ static int wait_one(int flags)
398 struct fsck_instance *inst, *prev; 416 struct fsck_instance *inst, *prev;
399 pid_t pid; 417 pid_t pid;
400 418
401 if (!instance_list) 419 if (!G.instance_list)
402 return -1; 420 return -1;
403 /* if (noexecute) { already returned -1; } */ 421 /* if (G.noexecute) { already returned -1; } */
404 422
405 while (1) { 423 while (1) {
406 pid = waitpid(-1, &status, flags); 424 pid = waitpid(-1, &status, flags);
@@ -418,7 +436,7 @@ static int wait_one(int flags)
418 continue; 436 continue;
419 } 437 }
420 prev = NULL; 438 prev = NULL;
421 inst = instance_list; 439 inst = G.instance_list;
422 do { 440 do {
423 if (inst->pid == pid) 441 if (inst->pid == pid)
424 goto child_died; 442 goto child_died;
@@ -428,9 +446,8 @@ static int wait_one(int flags)
428 } 446 }
429 child_died: 447 child_died:
430 448
431 if (WIFEXITED(status)) 449 status = WEXITSTATUS(status);
432 status = WEXITSTATUS(status); 450 if (WIFSIGNALED(status)) {
433 else if (WIFSIGNALED(status)) {
434 sig = WTERMSIG(status); 451 sig = WTERMSIG(status);
435 status = EXIT_UNCORRECTED; 452 status = EXIT_UNCORRECTED;
436 if (sig != SIGINT) { 453 if (sig != SIGINT) {
@@ -439,16 +456,12 @@ static int wait_one(int flags)
439 inst->prog, inst->device, sig); 456 inst->prog, inst->device, sig);
440 status = EXIT_ERROR; 457 status = EXIT_ERROR;
441 } 458 }
442 } else {
443 printf("%s %s: status is %x, should never happen\n",
444 inst->prog, inst->device, status);
445 status = EXIT_ERROR;
446 } 459 }
447 460
448#if DO_PROGRESS_INDICATOR 461#if DO_PROGRESS_INDICATOR
449 if (progress && (inst->flags & FLAG_PROGRESS) && !progress_active()) { 462 if (progress && (inst->flags & FLAG_PROGRESS) && !progress_active()) {
450 struct fsck_instance *inst2; 463 struct fsck_instance *inst2;
451 for (inst2 = instance_list; inst2; inst2 = inst2->next) { 464 for (inst2 = G.instance_list; inst2; inst2 = inst2->next) {
452 if (inst2->flags & FLAG_DONE) 465 if (inst2->flags & FLAG_DONE)
453 continue; 466 continue;
454 if (strcmp(inst2->type, "ext2") != 0 467 if (strcmp(inst2->type, "ext2") != 0
@@ -475,11 +488,11 @@ static int wait_one(int flags)
475 if (prev) 488 if (prev)
476 prev->next = inst->next; 489 prev->next = inst->next;
477 else 490 else
478 instance_list = inst->next; 491 G.instance_list = inst->next;
479 if (verbose > 1) 492 if (G.verbose > 1)
480 printf("Finished with %s (exit status %d)\n", 493 printf("Finished with %s (exit status %d)\n",
481 inst->device, status); 494 inst->device, status);
482 num_running--; 495 G.num_running--;
483 free_instance(inst); 496 free_instance(inst);
484 497
485 return status; 498 return status;
@@ -515,51 +528,51 @@ static void execute(const char *type, const char *device,
515 struct fsck_instance *inst; 528 struct fsck_instance *inst;
516 pid_t pid; 529 pid_t pid;
517 530
518 args[0] = xasprintf("fsck.%s", type); 531 G.args[0] = xasprintf("fsck.%s", type);
519 532
520#if DO_PROGRESS_INDICATOR 533#if DO_PROGRESS_INDICATOR
521 if (progress && !progress_active()) { 534 if (progress && !progress_active()) {
522 if (strcmp(type, "ext2") == 0 535 if (strcmp(type, "ext2") == 0
523 || strcmp(type, "ext3") == 0 536 || strcmp(type, "ext3") == 0
524 ) { 537 ) {
525 args[XXX] = xasprintf("-C%d", progress_fd); /* 1 */ 538 G.args[XXX] = xasprintf("-C%d", progress_fd); /* 1 */
526 inst->flags |= FLAG_PROGRESS; 539 inst->flags |= FLAG_PROGRESS;
527 } 540 }
528 } 541 }
529#endif 542#endif
530 543
531 args[num_args - 2] = (char*)device; 544 G.args[G.num_args - 2] = (char*)device;
532 /* args[num_args - 1] = NULL; - already is */ 545 /* G.args[G.num_args - 1] = NULL; - already is */
533 546
534 if (verbose || noexecute) { 547 if (G.verbose || G.noexecute) {
535 printf("[%s (%d) -- %s]", args[0], num_running, 548 printf("[%s (%d) -- %s]", G.args[0], G.num_running,
536 mntpt ? mntpt : device); 549 mntpt ? mntpt : device);
537 for (i = 0; args[i]; i++) 550 for (i = 0; G.args[i]; i++)
538 printf(" %s", args[i]); 551 printf(" %s", G.args[i]);
539 bb_putchar('\n'); 552 bb_putchar('\n');
540 } 553 }
541 554
542 /* Fork and execute the correct program. */ 555 /* Fork and execute the correct program. */
543 pid = -1; 556 pid = -1;
544 if (!noexecute) { 557 if (!G.noexecute) {
545 pid = spawn(args); 558 pid = spawn(G.args);
546 if (pid < 0) 559 if (pid < 0)
547 bb_simple_perror_msg(args[0]); 560 bb_simple_perror_msg(G.args[0]);
548 } 561 }
549 562
550#if DO_PROGRESS_INDICATOR 563#if DO_PROGRESS_INDICATOR
551 free(args[XXX]); 564 free(G.args[XXX]);
552#endif 565#endif
553 566
554 /* No child, so don't record an instance */ 567 /* No child, so don't record an instance */
555 if (pid <= 0) { 568 if (pid <= 0) {
556 free(args[0]); 569 free(G.args[0]);
557 return; 570 return;
558 } 571 }
559 572
560 inst = xzalloc(sizeof(*inst)); 573 inst = xzalloc(sizeof(*inst));
561 inst->pid = pid; 574 inst->pid = pid;
562 inst->prog = args[0]; 575 inst->prog = G.args[0];
563 inst->device = xstrdup(device); 576 inst->device = xstrdup(device);
564 inst->base_device = base_device(device); 577 inst->base_device = base_device(device);
565#if DO_PROGRESS_INDICATOR 578#if DO_PROGRESS_INDICATOR
@@ -568,8 +581,8 @@ static void execute(const char *type, const char *device,
568 581
569 /* Add to the list of running fsck's. 582 /* Add to the list of running fsck's.
570 * (was adding to the end, but adding to the front is simpler...) */ 583 * (was adding to the end, but adding to the front is simpler...) */
571 inst->next = instance_list; 584 inst->next = G.instance_list;
572 instance_list = inst; 585 G.instance_list = inst;
573} 586}
574 587
575/* 588/*
@@ -588,27 +601,27 @@ static void fsck_device(struct fs_info *fs /*, int interactive */)
588 601
589 if (strcmp(fs->type, "auto") != 0) { 602 if (strcmp(fs->type, "auto") != 0) {
590 type = fs->type; 603 type = fs->type;
591 if (verbose > 2) 604 if (G.verbose > 2)
592 bb_info_msg("using filesystem type '%s' %s", 605 bb_info_msg("using filesystem type '%s' %s",
593 type, "from fstab"); 606 type, "from fstab");
594 } else if (fstype 607 } else if (G.fstype
595 && (fstype[0] != 'n' || fstype[1] != 'o') /* != "no" */ 608 && (G.fstype[0] != 'n' || G.fstype[1] != 'o') /* != "no" */
596 && !is_prefixed_with(fstype, "opts=") 609 && !is_prefixed_with(G.fstype, "opts=")
597 && !is_prefixed_with(fstype, "loop") 610 && !is_prefixed_with(G.fstype, "loop")
598 && !strchr(fstype, ',') 611 && !strchr(G.fstype, ',')
599 ) { 612 ) {
600 type = fstype; 613 type = G.fstype;
601 if (verbose > 2) 614 if (G.verbose > 2)
602 bb_info_msg("using filesystem type '%s' %s", 615 bb_info_msg("using filesystem type '%s' %s",
603 type, "from -t"); 616 type, "from -t");
604 } else { 617 } else {
605 type = "auto"; 618 type = "auto";
606 if (verbose > 2) 619 if (G.verbose > 2)
607 bb_info_msg("using filesystem type '%s' %s", 620 bb_info_msg("using filesystem type '%s' %s",
608 type, "(default)"); 621 type, "(default)");
609 } 622 }
610 623
611 num_running++; 624 G.num_running++;
612 execute(type, fs->device, fs->mountpt /*, interactive */); 625 execute(type, fs->device, fs->mountpt /*, interactive */);
613} 626}
614 627
@@ -621,13 +634,13 @@ static int device_already_active(char *device)
621 struct fsck_instance *inst; 634 struct fsck_instance *inst;
622 char *base; 635 char *base;
623 636
624 if (force_all_parallel) 637 if (G.force_all_parallel)
625 return 0; 638 return 0;
626 639
627#ifdef BASE_MD 640#ifdef BASE_MD
628 /* Don't check a soft raid disk with any other disk */ 641 /* Don't check a soft raid disk with any other disk */
629 if (instance_list 642 if (G.instance_list
630 && (is_prefixed_with(instance_list->device, BASE_MD) 643 && (is_prefixed_with(G.instance_list->device, BASE_MD)
631 || is_prefixed_with(device, BASE_MD)) 644 || is_prefixed_with(device, BASE_MD))
632 ) { 645 ) {
633 return 1; 646 return 1;
@@ -640,9 +653,9 @@ static int device_already_active(char *device)
640 * already active if there are any fsck instances running. 653 * already active if there are any fsck instances running.
641 */ 654 */
642 if (!base) 655 if (!base)
643 return (instance_list != NULL); 656 return (G.instance_list != NULL);
644 657
645 for (inst = instance_list; inst; inst = inst->next) { 658 for (inst = G.instance_list; inst; inst = inst->next) {
646 if (!inst->base_device || !strcmp(base, inst->base_device)) { 659 if (!inst->base_device || !strcmp(base, inst->base_device)) {
647 free(base); 660 free(base);
648 return 1; 661 return 1;
@@ -687,17 +700,17 @@ static int fs_match(struct fs_info *fs)
687 int n, ret, checked_type; 700 int n, ret, checked_type;
688 char *cp; 701 char *cp;
689 702
690 if (!fs_type_list) 703 if (!G.fs_type_list)
691 return 1; 704 return 1;
692 705
693 ret = 0; 706 ret = 0;
694 checked_type = 0; 707 checked_type = 0;
695 n = 0; 708 n = 0;
696 while (1) { 709 while (1) {
697 cp = fs_type_list[n]; 710 cp = G.fs_type_list[n];
698 if (!cp) 711 if (!cp)
699 break; 712 break;
700 switch (fs_type_flag[n]) { 713 switch (G.fs_type_flag[n]) {
701 case FS_TYPE_FLAG_NORMAL: 714 case FS_TYPE_FLAG_NORMAL:
702 checked_type++; 715 checked_type++;
703 if (strcmp(cp, fs->type) == 0) 716 if (strcmp(cp, fs->type) == 0)
@@ -717,7 +730,7 @@ static int fs_match(struct fs_info *fs)
717 if (checked_type == 0) 730 if (checked_type == 0)
718 return 1; 731 return 1;
719 732
720 return (fs_type_negated ? !ret : ret); 733 return (G.fs_type_negated ? !ret : ret);
721} 734}
722 735
723/* Check if we should ignore this filesystem. */ 736/* Check if we should ignore this filesystem. */
@@ -753,7 +766,7 @@ static int check_all(void)
753 smallint pass_done; 766 smallint pass_done;
754 int passno; 767 int passno;
755 768
756 if (verbose) 769 if (G.verbose)
757 puts("Checking all filesystems"); 770 puts("Checking all filesystems");
758 771
759 /* 772 /*
@@ -761,17 +774,17 @@ static int check_all(void)
761 * which should be ignored as done, and resolve any "auto" 774 * which should be ignored as done, and resolve any "auto"
762 * filesystem types (done as a side-effect of calling ignore()). 775 * filesystem types (done as a side-effect of calling ignore()).
763 */ 776 */
764 for (fs = filesys_info; fs; fs = fs->next) 777 for (fs = G.filesys_info; fs; fs = fs->next)
765 if (ignore(fs)) 778 if (ignore(fs))
766 fs->flags |= FLAG_DONE; 779 fs->flags |= FLAG_DONE;
767 780
768 /* 781 /*
769 * Find and check the root filesystem. 782 * Find and check the root filesystem.
770 */ 783 */
771 if (!parallel_root) { 784 if (!G.parallel_root) {
772 for (fs = filesys_info; fs; fs = fs->next) { 785 for (fs = G.filesys_info; fs; fs = fs->next) {
773 if (LONE_CHAR(fs->mountpt, '/')) { 786 if (LONE_CHAR(fs->mountpt, '/')) {
774 if (!skip_root && !ignore(fs)) { 787 if (!G.skip_root && !ignore(fs)) {
775 fsck_device(fs /*, 1*/); 788 fsck_device(fs /*, 1*/);
776 status |= wait_many(FLAG_WAIT_ALL); 789 status |= wait_many(FLAG_WAIT_ALL);
777 if (status > EXIT_NONDESTRUCT) 790 if (status > EXIT_NONDESTRUCT)
@@ -787,8 +800,8 @@ static int check_all(void)
787 * filesystem listed twice. 800 * filesystem listed twice.
788 * "Skip root" will skip _all_ root entries. 801 * "Skip root" will skip _all_ root entries.
789 */ 802 */
790 if (skip_root) 803 if (G.skip_root)
791 for (fs = filesys_info; fs; fs = fs->next) 804 for (fs = G.filesys_info; fs; fs = fs->next)
792 if (LONE_CHAR(fs->mountpt, '/')) 805 if (LONE_CHAR(fs->mountpt, '/'))
793 fs->flags |= FLAG_DONE; 806 fs->flags |= FLAG_DONE;
794 807
@@ -798,7 +811,7 @@ static int check_all(void)
798 not_done_yet = 0; 811 not_done_yet = 0;
799 pass_done = 1; 812 pass_done = 1;
800 813
801 for (fs = filesys_info; fs; fs = fs->next) { 814 for (fs = G.filesys_info; fs; fs = fs->next) {
802 if (bb_got_signal) 815 if (bb_got_signal)
803 break; 816 break;
804 if (fs->flags & FLAG_DONE) 817 if (fs->flags & FLAG_DONE)
@@ -824,7 +837,7 @@ static int check_all(void)
824 /* 837 /*
825 * Spawn off the fsck process 838 * Spawn off the fsck process
826 */ 839 */
827 fsck_device(fs /*, serialize*/); 840 fsck_device(fs /*, G.serialize*/);
828 fs->flags |= FLAG_DONE; 841 fs->flags |= FLAG_DONE;
829 842
830 /* 843 /*
@@ -832,8 +845,8 @@ static int check_all(void)
832 * have a limit on the number of fsck's extant 845 * have a limit on the number of fsck's extant
833 * at one time, apply that limit. 846 * at one time, apply that limit.
834 */ 847 */
835 if (serialize 848 if (G.serialize
836 || (max_running && (num_running >= max_running)) 849 || (G.num_running >= G.max_running)
837 ) { 850 ) {
838 pass_done = 0; 851 pass_done = 0;
839 break; 852 break;
@@ -841,12 +854,12 @@ static int check_all(void)
841 } 854 }
842 if (bb_got_signal) 855 if (bb_got_signal)
843 break; 856 break;
844 if (verbose > 1) 857 if (G.verbose > 1)
845 printf("--waiting-- (pass %d)\n", passno); 858 printf("--waiting-- (pass %d)\n", passno);
846 status |= wait_many(pass_done ? FLAG_WAIT_ALL : 859 status |= wait_many(pass_done ? FLAG_WAIT_ALL :
847 FLAG_WAIT_ATLEAST_ONE); 860 FLAG_WAIT_ATLEAST_ONE);
848 if (pass_done) { 861 if (pass_done) {
849 if (verbose > 1) 862 if (G.verbose > 1)
850 puts("----------------------------------"); 863 puts("----------------------------------");
851 passno++; 864 passno++;
852 } else 865 } else
@@ -874,9 +887,9 @@ static void compile_fs_type(char *fs_type)
874 s++; 887 s++;
875 } 888 }
876 889
877 fs_type_list = xzalloc(num * sizeof(fs_type_list[0])); 890 G.fs_type_list = xzalloc(num * sizeof(G.fs_type_list[0]));
878 fs_type_flag = xzalloc(num * sizeof(fs_type_flag[0])); 891 G.fs_type_flag = xzalloc(num * sizeof(G.fs_type_flag[0]));
879 fs_type_negated = -1; /* not yet known is it negated or not */ 892 G.fs_type_negated = -1; /* not yet known is it negated or not */
880 893
881 num = 0; 894 num = 0;
882 s = fs_type; 895 s = fs_type;
@@ -898,18 +911,18 @@ static void compile_fs_type(char *fs_type)
898 if (is_prefixed_with(s, "opts=")) { 911 if (is_prefixed_with(s, "opts=")) {
899 s += 5; 912 s += 5;
900 loop_special_case: 913 loop_special_case:
901 fs_type_flag[num] = negate ? FS_TYPE_FLAG_NEGOPT : FS_TYPE_FLAG_OPT; 914 G.fs_type_flag[num] = negate ? FS_TYPE_FLAG_NEGOPT : FS_TYPE_FLAG_OPT;
902 } else { 915 } else {
903 if (fs_type_negated == -1) 916 if (G.fs_type_negated == -1)
904 fs_type_negated = negate; 917 G.fs_type_negated = negate;
905 if (fs_type_negated != negate) 918 if (G.fs_type_negated != negate)
906 bb_error_msg_and_die( 919 bb_error_msg_and_die(
907"either all or none of the filesystem types passed to -t must be prefixed " 920"either all or none of the filesystem types passed to -t must be prefixed "
908"with 'no' or '!'"); 921"with 'no' or '!'");
909 } 922 }
910 comma = strchr(s, ','); 923 comma = strchrnul(s, ',');
911 fs_type_list[num++] = comma ? xstrndup(s, comma-s) : xstrdup(s); 924 G.fs_type_list[num++] = xstrndup(s, comma-s);
912 if (!comma) 925 if (*comma == '\0')
913 break; 926 break;
914 s = comma + 1; 927 s = comma + 1;
915 } 928 }
@@ -917,8 +930,8 @@ static void compile_fs_type(char *fs_type)
917 930
918static char **new_args(void) 931static char **new_args(void)
919{ 932{
920 args = xrealloc_vector(args, 2, num_args); 933 G.args = xrealloc_vector(G.args, 2, G.num_args);
921 return &args[num_args++]; 934 return &G.args[G.num_args++];
922} 935}
923 936
924int fsck_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 937int fsck_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
@@ -935,6 +948,8 @@ int fsck_main(int argc UNUSED_PARAM, char **argv)
935 smallint doall; 948 smallint doall;
936 smallint notitle; 949 smallint notitle;
937 950
951 INIT_G();
952
938 /* we want wait() to be interruptible */ 953 /* we want wait() to be interruptible */
939 signal_no_SA_RESTART_empty_mask(SIGINT, record_signo); 954 signal_no_SA_RESTART_empty_mask(SIGINT, record_signo);
940 signal_no_SA_RESTART_empty_mask(SIGTERM, record_signo); 955 signal_no_SA_RESTART_empty_mask(SIGTERM, record_signo);
@@ -944,8 +959,8 @@ int fsck_main(int argc UNUSED_PARAM, char **argv)
944 opts_for_fsck = doall = notitle = 0; 959 opts_for_fsck = doall = notitle = 0;
945 devices = NULL; 960 devices = NULL;
946 num_devices = 0; 961 num_devices = 0;
947 new_args(); /* args[0] = NULL, will be replaced by fsck.<type> */ 962 new_args(); /* G.args[0] = NULL, will be replaced by fsck.<type> */
948 /* instance_list = NULL; - in bss, so already zeroed */ 963 /* G.instance_list = NULL; - in bss, so already zeroed */
949 964
950 while (*++argv) { 965 while (*++argv) {
951 int j; 966 int j;
@@ -994,13 +1009,13 @@ int fsck_main(int argc UNUSED_PARAM, char **argv)
994 goto next_arg; 1009 goto next_arg;
995#endif 1010#endif
996 case 'V': 1011 case 'V':
997 verbose++; 1012 G.verbose++;
998 break; 1013 break;
999 case 'N': 1014 case 'N':
1000 noexecute = 1; 1015 G.noexecute = 1;
1001 break; 1016 break;
1002 case 'R': 1017 case 'R':
1003 skip_root = 1; 1018 G.skip_root = 1;
1004 break; 1019 break;
1005 case 'T': 1020 case 'T':
1006 notitle = 1; 1021 notitle = 1;
@@ -1009,13 +1024,13 @@ int fsck_main(int argc UNUSED_PARAM, char **argv)
1009 like_mount = 1; 1024 like_mount = 1;
1010 break; */ 1025 break; */
1011 case 'P': 1026 case 'P':
1012 parallel_root = 1; 1027 G.parallel_root = 1;
1013 break; 1028 break;
1014 case 's': 1029 case 's':
1015 serialize = 1; 1030 G.serialize = 1;
1016 break; 1031 break;
1017 case 't': 1032 case 't':
1018 if (fstype) 1033 if (G.fstype)
1019 bb_show_usage(); 1034 bb_show_usage();
1020 if (arg[++j]) 1035 if (arg[++j])
1021 tmp = &arg[j]; 1036 tmp = &arg[j];
@@ -1023,8 +1038,8 @@ int fsck_main(int argc UNUSED_PARAM, char **argv)
1023 tmp = *argv; 1038 tmp = *argv;
1024 else 1039 else
1025 bb_show_usage(); 1040 bb_show_usage();
1026 fstype = xstrdup(tmp); 1041 G.fstype = xstrdup(tmp);
1027 compile_fs_type(fstype); 1042 compile_fs_type(G.fstype);
1028 goto next_arg; 1043 goto next_arg;
1029 case '?': 1044 case '?':
1030 bb_show_usage(); 1045 bb_show_usage();
@@ -1045,12 +1060,13 @@ int fsck_main(int argc UNUSED_PARAM, char **argv)
1045 } 1060 }
1046 } 1061 }
1047 if (getenv("FSCK_FORCE_ALL_PARALLEL")) 1062 if (getenv("FSCK_FORCE_ALL_PARALLEL"))
1048 force_all_parallel = 1; 1063 G.force_all_parallel = 1;
1049 tmp = getenv("FSCK_MAX_INST"); 1064 tmp = getenv("FSCK_MAX_INST");
1065 G.max_running = INT_MAX;
1050 if (tmp) 1066 if (tmp)
1051 max_running = xatoi(tmp); 1067 G.max_running = xatoi(tmp);
1052 new_args(); /* args[num_args - 2] will be replaced by <device> */ 1068 new_args(); /* G.args[G.num_args - 2] will be replaced by <device> */
1053 new_args(); /* args[num_args - 1] is the last, NULL element */ 1069 new_args(); /* G.args[G.num_args - 1] is the last, NULL element */
1054 1070
1055 if (!notitle) 1071 if (!notitle)
1056 puts("fsck (busybox "BB_VER", "BB_BT")"); 1072 puts("fsck (busybox "BB_VER", "BB_BT")");
@@ -1062,10 +1078,10 @@ int fsck_main(int argc UNUSED_PARAM, char **argv)
1062 fstab = "/etc/fstab"; 1078 fstab = "/etc/fstab";
1063 load_fs_info(fstab); 1079 load_fs_info(fstab);
1064 1080
1065 /*interactive = (num_devices == 1) | serialize;*/ 1081 /*interactive = (num_devices == 1) | G.serialize;*/
1066 1082
1067 if (num_devices == 0) 1083 if (num_devices == 0)
1068 /*interactive =*/ serialize = doall = 1; 1084 /*interactive =*/ G.serialize = doall = 1;
1069 if (doall) 1085 if (doall)
1070 return check_all(); 1086 return check_all();
1071 1087
@@ -1081,13 +1097,13 @@ int fsck_main(int argc UNUSED_PARAM, char **argv)
1081 fs = create_fs_device(devices[i], "", "auto", NULL, -1); 1097 fs = create_fs_device(devices[i], "", "auto", NULL, -1);
1082 fsck_device(fs /*, interactive */); 1098 fsck_device(fs /*, interactive */);
1083 1099
1084 if (serialize 1100 if (G.serialize
1085 || (max_running && (num_running >= max_running)) 1101 || (G.num_running >= G.max_running)
1086 ) { 1102 ) {
1087 int exit_status = wait_one(0); 1103 int exit_status = wait_one(0);
1088 if (exit_status >= 0) 1104 if (exit_status >= 0)
1089 status |= exit_status; 1105 status |= exit_status;
1090 if (verbose > 1) 1106 if (G.verbose > 1)
1091 puts("----------------------------------"); 1107 puts("----------------------------------");
1092 } 1108 }
1093 } 1109 }
diff --git a/e2fsprogs/lsattr.c b/e2fsprogs/lsattr.c
index 1312fe754..d2348b5f7 100644
--- a/e2fsprogs/lsattr.c
+++ b/e2fsprogs/lsattr.c
@@ -9,24 +9,26 @@
9 * This file can be redistributed under the terms of the GNU General 9 * This file can be redistributed under the terms of the GNU General
10 * Public License 10 * Public License
11 */ 11 */
12//config:config LSATTR
13//config: bool "lsattr"
14//config: default y
15//config: select PLATFORM_LINUX
16//config: help
17//config: lsattr lists the file attributes on a second extended file system.
12 18
13/* 19//applet:IF_LSATTR(APPLET(lsattr, BB_DIR_BIN, BB_SUID_DROP))
14 * History: 20
15 * 93/10/30 - Creation 21//kbuild:lib-$(CONFIG_LSATTR) += lsattr.o e2fs_lib.o
16 * 93/11/13 - Replace stat() calls by lstat() to avoid loops
17 * 94/02/27 - Integrated in Ted's distribution
18 * 98/12/29 - Display version info only when -V specified (G M Sipe)
19 */
20 22
21//usage:#define lsattr_trivial_usage 23//usage:#define lsattr_trivial_usage
22//usage: "[-Radlv] [FILE]..." 24//usage: "[-Radlv] [FILE]..."
23//usage:#define lsattr_full_usage "\n\n" 25//usage:#define lsattr_full_usage "\n\n"
24//usage: "List file attributes on an ext2 fs\n" 26//usage: "List ext2 file attributes\n"
25//usage: "\n -R Recurse" 27//usage: "\n -R Recurse"
26//usage: "\n -a Don't hide entries starting with ." 28//usage: "\n -a Don't hide entries starting with ."
27//usage: "\n -d List directory entries instead of contents" 29//usage: "\n -d List directory entries instead of contents"
28//usage: "\n -l List long flag names" 30//usage: "\n -l List long flag names"
29//usage: "\n -v List the file's version/generation number" 31//usage: "\n -v List version/generation number"
30 32
31#include "libbb.h" 33#include "libbb.h"
32#include "e2fs_lib.h" 34#include "e2fs_lib.h"
diff --git a/e2fsprogs/tune2fs.c b/e2fsprogs/tune2fs.c
index 46a745ee4..c9f88b39d 100644
--- a/e2fsprogs/tune2fs.c
+++ b/e2fsprogs/tune2fs.c
@@ -6,6 +6,33 @@
6 * 6 *
7 * Licensed under GPLv2, see file LICENSE in this source tree. 7 * Licensed under GPLv2, see file LICENSE in this source tree.
8 */ 8 */
9//config:config TUNE2FS
10//config: bool "tune2fs"
11//config: default n # off: it is too limited compared to upstream version
12//config: help
13//config: tune2fs allows the system administrator to adjust various tunable
14//config: filesystem parameters on Linux ext2/ext3 filesystems.
15
16//applet:IF_TUNE2FS(APPLET(tune2fs, BB_DIR_SBIN, BB_SUID_DROP))
17
18//kbuild:lib-$(CONFIG_TUNE2FS) += tune2fs.o
19
20//usage:#define tune2fs_trivial_usage
21//usage: "[-c MAX_MOUNT_COUNT] "
22////usage: "[-e errors-behavior] [-g group] "
23//usage: "[-i DAYS] "
24////usage: "[-j] [-J journal-options] [-l] [-s sparse-flag] "
25////usage: "[-m reserved-blocks-percent] [-o [^]mount-options[,...]] "
26////usage: "[-r reserved-blocks-count] [-u user] "
27//usage: "[-C MOUNT_COUNT] "
28//usage: "[-L LABEL] "
29////usage: "[-M last-mounted-dir] [-O [^]feature[,...]] "
30////usage: "[-T last-check-time] [-U UUID] "
31//usage: "BLOCKDEV"
32//usage:
33//usage:#define tune2fs_full_usage "\n\n"
34//usage: "Adjust filesystem options on ext[23] filesystems"
35
9#include "libbb.h" 36#include "libbb.h"
10#include <linux/fs.h> 37#include <linux/fs.h>
11#include "bb_e2fs_defs.h" 38#include "bb_e2fs_defs.h"
@@ -27,22 +54,6 @@ do { \
27#define FETCH_LE32(field) \ 54#define FETCH_LE32(field) \
28 (sizeof(field) == 4 ? SWAP_LE32(field) : BUG_wrong_field_size()) 55 (sizeof(field) == 4 ? SWAP_LE32(field) : BUG_wrong_field_size())
29 56
30//usage:#define tune2fs_trivial_usage
31//usage: "[-c MAX_MOUNT_COUNT] "
32////usage: "[-e errors-behavior] [-g group] "
33//usage: "[-i DAYS] "
34////usage: "[-j] [-J journal-options] [-l] [-s sparse-flag] "
35////usage: "[-m reserved-blocks-percent] [-o [^]mount-options[,...]] "
36////usage: "[-r reserved-blocks-count] [-u user] "
37//usage: "[-C MOUNT_COUNT] "
38//usage: "[-L LABEL] "
39////usage: "[-M last-mounted-dir] [-O [^]feature[,...]] "
40////usage: "[-T last-check-time] [-U UUID] "
41//usage: "BLOCKDEV"
42//usage:
43//usage:#define tune2fs_full_usage "\n\n"
44//usage: "Adjust filesystem options on ext[23] filesystems"
45
46enum { 57enum {
47 OPT_L = 1 << 0, // label 58 OPT_L = 1 << 0, // label
48 OPT_c = 1 << 1, // max mount count 59 OPT_c = 1 << 1, // max mount count
diff --git a/editors/sed.c b/editors/sed.c
index 7bbf820d8..a8c35388b 100644
--- a/editors/sed.c
+++ b/editors/sed.c
@@ -162,10 +162,8 @@ struct globals {
162 } pipeline; 162 } pipeline;
163} FIX_ALIASING; 163} FIX_ALIASING;
164#define G (*(struct globals*)&bb_common_bufsiz1) 164#define G (*(struct globals*)&bb_common_bufsiz1)
165struct BUG_G_too_big {
166 char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1];
167};
168#define INIT_G() do { \ 165#define INIT_G() do { \
166 BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
169 G.sed_cmd_tail = &G.sed_cmd_head; \ 167 G.sed_cmd_tail = &G.sed_cmd_head; \
170} while (0) 168} while (0)
171 169
@@ -501,9 +499,11 @@ static const char *parse_cmd_args(sed_cmd_t *sed_cmd, const char *cmdstr)
501 IDX_rbrace, 499 IDX_rbrace,
502 IDX_nul 500 IDX_nul
503 }; 501 };
504 struct chk { char chk[sizeof(cmd_letters)-1 == IDX_nul ? 1 : -1]; }; 502 unsigned idx;
503
504 BUILD_BUG_ON(sizeof(cmd_letters)-1 != IDX_nul);
505 505
506 unsigned idx = strchrnul(cmd_letters, sed_cmd->cmd) - cmd_letters; 506 idx = strchrnul(cmd_letters, sed_cmd->cmd) - cmd_letters;
507 507
508 /* handle (s)ubstitution command */ 508 /* handle (s)ubstitution command */
509 if (idx == IDX_s) { 509 if (idx == IDX_s) {
diff --git a/examples/var_service/dhcp_if_pinger/run b/examples/var_service/dhcp_if_pinger/run
index 20b2fc516..1868510d1 100755
--- a/examples/var_service/dhcp_if_pinger/run
+++ b/examples/var_service/dhcp_if_pinger/run
@@ -1,23 +1,47 @@
1#!/bin/sh 1#!/bin/sh
2 2
3delay=67 3# How often to test, seconds
4 4ping_time=67
5# "One ping, must have reply in 1 sec"
6ping_opts="-c1 -W1 -w1"
7# If ping failed, how soon to retry
8retry_time=5
9# Reinit after this many consecutive ping error
10max_fail=5
11# Interface whose DHCP data to use
5if=${PWD##*/dhcp_} 12if=${PWD##*/dhcp_}
6if=${if%%_pinger} 13if=${if%%_pinger}
7 14
15msg() {
16 echo "`date '+%Y-%m-%d %H:%M:%S'` $*" >>"$0.log"
17}
18
8if test -f "$0.log"; then 19if test -f "$0.log"; then
9 tail -999 "$0.log" >"$0.log.new" 20 tail -999 "$0.log" >"$0.log.new"
10 mv "$0.log.new" "$0.log" 21 mv "$0.log.new" "$0.log"
11fi 22fi
12 23
13test -f "/var/service/dhcp_$if/dhcp_$if.out" || exec env - sleep "$delay" 24test -f "/var/service/dhcp_$if/dhcp_$if.out" || exec env - sleep "$ping_time"
14. "/var/service/dhcp_$if/dhcp_$if.out"
15test x"$router" != x"" || exec env - sleep "$delay"
16 25
17#echo "`date '+%Y-%m-%d %H:%M:%S'` Testing ping -c3 $router" >>"$0.log" 26. "/var/service/dhcp_$if/dhcp_$if.out"
18ping -c3 "$router" && exec env - sleep "$delay" 27test x"$router" != x"" || exec env - sleep "$ping_time"
19 28
20echo "`date '+%Y-%m-%d %H:%M:%S'` Restarting /var/service/dhcp_$if" >>"$0.log" 29#msg "Pinging $router"
21sv t "/var/service/dhcp_$if" 30failcnt=0
31while true; do
32 ping $ping_opts "$router" && exec env - sleep "$ping_time"
33 : $((failcnt++))
34 msg "Failed to ping $router, fail count:$failcnt"
35 test $failcnt -ge $max_fail && break
36 env - sleep "$retry_time"
37done
22 38
23exec env - sleep "$delay" 39test -d "/var/service/dhcp_$if" && {
40 msg "Restarting /var/service/dhcp_$if"
41 sv t "/var/service/dhcp_$if"
42}
43test -d "/var/service/supplicant_$if" && {
44 msg "Restarting /var/service/supplicant_$if"
45 sv t "/var/service/supplicant_$if"
46}
47exec env - sleep "$ping_time"
diff --git a/findutils/find.c b/findutils/find.c
index bd7ccc323..a0d4853de 100644
--- a/findutils/find.c
+++ b/findutils/find.c
@@ -423,9 +423,7 @@ struct globals {
423} FIX_ALIASING; 423} FIX_ALIASING;
424#define G (*(struct globals*)&bb_common_bufsiz1) 424#define G (*(struct globals*)&bb_common_bufsiz1)
425#define INIT_G() do { \ 425#define INIT_G() do { \
426 struct G_sizecheck { \ 426 BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
427 char G_sizecheck[sizeof(G) > COMMON_BUFSIZE ? -1 : 1]; \
428 }; \
429 /* we have to zero it out because of NOEXEC */ \ 427 /* we have to zero it out because of NOEXEC */ \
430 memset(&G, 0, sizeof(G)); \ 428 memset(&G, 0, sizeof(G)); \
431 IF_FEATURE_FIND_MAXDEPTH(G.minmaxdepth[1] = INT_MAX;) \ 429 IF_FEATURE_FIND_MAXDEPTH(G.minmaxdepth[1] = INT_MAX;) \
@@ -884,7 +882,7 @@ static int find_type(const char *type)
884 mask = S_IFSOCK; 882 mask = S_IFSOCK;
885 883
886 if (mask == 0 || type[1] != '\0') 884 if (mask == 0 || type[1] != '\0')
887 bb_error_msg_and_die(bb_msg_invalid_arg, type, "-type"); 885 bb_error_msg_and_die(bb_msg_invalid_arg_to, type, "-type");
888 886
889 return mask; 887 return mask;
890} 888}
diff --git a/findutils/grep.c b/findutils/grep.c
index 0336b2927..e163e6562 100644
--- a/findutils/grep.c
+++ b/findutils/grep.c
@@ -211,9 +211,7 @@ struct globals {
211} FIX_ALIASING; 211} FIX_ALIASING;
212#define G (*(struct globals*)&bb_common_bufsiz1) 212#define G (*(struct globals*)&bb_common_bufsiz1)
213#define INIT_G() do { \ 213#define INIT_G() do { \
214 struct G_sizecheck { \ 214 BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
215 char G_sizecheck[sizeof(G) > COMMON_BUFSIZE ? -1 : 1]; \
216 }; \
217} while (0) 215} while (0)
218#define max_matches (G.max_matches ) 216#define max_matches (G.max_matches )
219#if !ENABLE_EXTRA_COMPAT 217#if !ENABLE_EXTRA_COMPAT
diff --git a/include/applets.src.h b/include/applets.src.h
index dac83e7fb..5b597202e 100644
--- a/include/applets.src.h
+++ b/include/applets.src.h
@@ -76,8 +76,6 @@ INSERT
76IF_TEST(APPLET_NOFORK([, test, BB_DIR_USR_BIN, BB_SUID_DROP, test)) 76IF_TEST(APPLET_NOFORK([, test, BB_DIR_USR_BIN, BB_SUID_DROP, test))
77IF_TEST(APPLET_NOFORK([[, test, BB_DIR_USR_BIN, BB_SUID_DROP, test)) 77IF_TEST(APPLET_NOFORK([[, test, BB_DIR_USR_BIN, BB_SUID_DROP, test))
78IF_ACPID(APPLET(acpid, BB_DIR_SBIN, BB_SUID_DROP)) 78IF_ACPID(APPLET(acpid, BB_DIR_SBIN, BB_SUID_DROP))
79IF_ADDGROUP(APPLET(addgroup, BB_DIR_USR_SBIN, BB_SUID_DROP))
80IF_ADDUSER(APPLET(adduser, BB_DIR_USR_SBIN, BB_SUID_DROP))
81IF_ADJTIMEX(APPLET(adjtimex, BB_DIR_SBIN, BB_SUID_DROP)) 79IF_ADJTIMEX(APPLET(adjtimex, BB_DIR_SBIN, BB_SUID_DROP))
82IF_ARP(APPLET(arp, BB_DIR_SBIN, BB_SUID_DROP)) 80IF_ARP(APPLET(arp, BB_DIR_SBIN, BB_SUID_DROP))
83IF_ARPING(APPLET(arping, BB_DIR_USR_SBIN, BB_SUID_DROP)) 81IF_ARPING(APPLET(arping, BB_DIR_USR_SBIN, BB_SUID_DROP))
@@ -90,13 +88,10 @@ IF_CAL(APPLET(cal, BB_DIR_USR_BIN, BB_SUID_DROP))
90IF_CAT(APPLET_NOFORK(cat, cat, BB_DIR_BIN, BB_SUID_DROP, cat)) 88IF_CAT(APPLET_NOFORK(cat, cat, BB_DIR_BIN, BB_SUID_DROP, cat))
91IF_CATV(APPLET(catv, BB_DIR_BIN, BB_SUID_DROP)) 89IF_CATV(APPLET(catv, BB_DIR_BIN, BB_SUID_DROP))
92IF_CHAT(APPLET(chat, BB_DIR_USR_SBIN, BB_SUID_DROP)) 90IF_CHAT(APPLET(chat, BB_DIR_USR_SBIN, BB_SUID_DROP))
93IF_CHATTR(APPLET(chattr, BB_DIR_BIN, BB_SUID_DROP))
94IF_CHCON(APPLET(chcon, BB_DIR_USR_BIN, BB_SUID_DROP)) 91IF_CHCON(APPLET(chcon, BB_DIR_USR_BIN, BB_SUID_DROP))
95IF_CHGRP(APPLET_NOEXEC(chgrp, chgrp, BB_DIR_BIN, BB_SUID_DROP, chgrp)) 92IF_CHGRP(APPLET_NOEXEC(chgrp, chgrp, BB_DIR_BIN, BB_SUID_DROP, chgrp))
96IF_CHMOD(APPLET_NOEXEC(chmod, chmod, BB_DIR_BIN, BB_SUID_DROP, chmod)) 93IF_CHMOD(APPLET_NOEXEC(chmod, chmod, BB_DIR_BIN, BB_SUID_DROP, chmod))
97IF_CHOWN(APPLET_NOEXEC(chown, chown, BB_DIR_BIN, BB_SUID_DROP, chown)) 94IF_CHOWN(APPLET_NOEXEC(chown, chown, BB_DIR_BIN, BB_SUID_DROP, chown))
98IF_CHPASSWD(APPLET(chpasswd, BB_DIR_USR_SBIN, BB_SUID_DROP))
99IF_CHPST(APPLET(chpst, BB_DIR_USR_BIN, BB_SUID_DROP))
100IF_CHROOT(APPLET(chroot, BB_DIR_USR_SBIN, BB_SUID_DROP)) 95IF_CHROOT(APPLET(chroot, BB_DIR_USR_SBIN, BB_SUID_DROP))
101IF_CHRT(APPLET(chrt, BB_DIR_USR_BIN, BB_SUID_DROP)) 96IF_CHRT(APPLET(chrt, BB_DIR_USR_BIN, BB_SUID_DROP))
102IF_CHVT(APPLET(chvt, BB_DIR_USR_BIN, BB_SUID_DROP)) 97IF_CHVT(APPLET(chvt, BB_DIR_USR_BIN, BB_SUID_DROP))
@@ -106,13 +101,10 @@ IF_COMM(APPLET(comm, BB_DIR_USR_BIN, BB_SUID_DROP))
106IF_CP(APPLET_NOEXEC(cp, cp, BB_DIR_BIN, BB_SUID_DROP, cp)) 101IF_CP(APPLET_NOEXEC(cp, cp, BB_DIR_BIN, BB_SUID_DROP, cp))
107/* Needs to be run by root or be suid root - needs to change /var/spool/cron* files: */ 102/* Needs to be run by root or be suid root - needs to change /var/spool/cron* files: */
108IF_CRONTAB(APPLET(crontab, BB_DIR_USR_BIN, BB_SUID_REQUIRE)) 103IF_CRONTAB(APPLET(crontab, BB_DIR_USR_BIN, BB_SUID_REQUIRE))
109IF_CRYPTPW(APPLET(cryptpw, BB_DIR_USR_BIN, BB_SUID_DROP))
110IF_CUT(APPLET_NOEXEC(cut, cut, BB_DIR_USR_BIN, BB_SUID_DROP, cut)) 104IF_CUT(APPLET_NOEXEC(cut, cut, BB_DIR_USR_BIN, BB_SUID_DROP, cut))
111IF_DC(APPLET(dc, BB_DIR_USR_BIN, BB_SUID_DROP)) 105IF_DC(APPLET(dc, BB_DIR_USR_BIN, BB_SUID_DROP))
112IF_DD(APPLET_NOEXEC(dd, dd, BB_DIR_BIN, BB_SUID_DROP, dd)) 106IF_DD(APPLET_NOEXEC(dd, dd, BB_DIR_BIN, BB_SUID_DROP, dd))
113IF_DEALLOCVT(APPLET(deallocvt, BB_DIR_USR_BIN, BB_SUID_DROP)) 107IF_DEALLOCVT(APPLET(deallocvt, BB_DIR_USR_BIN, BB_SUID_DROP))
114IF_DELGROUP(APPLET_ODDNAME(delgroup, deluser, BB_DIR_USR_SBIN, BB_SUID_DROP, delgroup))
115IF_DELUSER(APPLET(deluser, BB_DIR_USR_SBIN, BB_SUID_DROP))
116IF_DEVFSD(APPLET(devfsd, BB_DIR_SBIN, BB_SUID_DROP)) 108IF_DEVFSD(APPLET(devfsd, BB_DIR_SBIN, BB_SUID_DROP))
117IF_DEVMEM(APPLET(devmem, BB_DIR_SBIN, BB_SUID_DROP)) 109IF_DEVMEM(APPLET(devmem, BB_DIR_SBIN, BB_SUID_DROP))
118IF_DF(APPLET(df, BB_DIR_BIN, BB_SUID_DROP)) 110IF_DF(APPLET(df, BB_DIR_BIN, BB_SUID_DROP))
@@ -130,8 +122,6 @@ IF_DUMPLEASES(APPLET(dumpleases, BB_DIR_USR_BIN, BB_SUID_DROP))
130IF_ECHO(APPLET_NOFORK(echo, echo, BB_DIR_BIN, BB_SUID_DROP, echo)) 122IF_ECHO(APPLET_NOFORK(echo, echo, BB_DIR_BIN, BB_SUID_DROP, echo))
131IF_EJECT(APPLET(eject, BB_DIR_USR_BIN, BB_SUID_DROP)) 123IF_EJECT(APPLET(eject, BB_DIR_USR_BIN, BB_SUID_DROP))
132IF_ENV(APPLET_NOEXEC(env, env, BB_DIR_USR_BIN, BB_SUID_DROP, env)) 124IF_ENV(APPLET_NOEXEC(env, env, BB_DIR_USR_BIN, BB_SUID_DROP, env))
133IF_ENVDIR(APPLET_ODDNAME(envdir, chpst, BB_DIR_USR_BIN, BB_SUID_DROP, envdir))
134IF_ENVUIDGID(APPLET_ODDNAME(envuidgid, chpst, BB_DIR_USR_BIN, BB_SUID_DROP, envuidgid))
135IF_ETHER_WAKE(APPLET_ODDNAME(ether-wake, ether_wake, BB_DIR_USR_SBIN, BB_SUID_DROP, ether_wake)) 125IF_ETHER_WAKE(APPLET_ODDNAME(ether-wake, ether_wake, BB_DIR_USR_SBIN, BB_SUID_DROP, ether_wake))
136IF_EXPAND(APPLET(expand, BB_DIR_USR_BIN, BB_SUID_DROP)) 126IF_EXPAND(APPLET(expand, BB_DIR_USR_BIN, BB_SUID_DROP))
137IF_EXPR(APPLET(expr, BB_DIR_USR_BIN, BB_SUID_DROP)) 127IF_EXPR(APPLET(expr, BB_DIR_USR_BIN, BB_SUID_DROP))
@@ -153,7 +143,6 @@ IF_FLOCK(APPLET(flock, BB_DIR_USR_BIN, BB_SUID_DROP))
153IF_FOLD(APPLET_NOEXEC(fold, fold, BB_DIR_USR_BIN, BB_SUID_DROP, fold)) 143IF_FOLD(APPLET_NOEXEC(fold, fold, BB_DIR_USR_BIN, BB_SUID_DROP, fold))
154IF_FREE(APPLET(free, BB_DIR_USR_BIN, BB_SUID_DROP)) 144IF_FREE(APPLET(free, BB_DIR_USR_BIN, BB_SUID_DROP))
155IF_FREERAMDISK(APPLET(freeramdisk, BB_DIR_SBIN, BB_SUID_DROP)) 145IF_FREERAMDISK(APPLET(freeramdisk, BB_DIR_SBIN, BB_SUID_DROP))
156IF_FSCK(APPLET(fsck, BB_DIR_SBIN, BB_SUID_DROP))
157//IF_E2FSCK(APPLET_ODDNAME(fsck.ext2, e2fsck, BB_DIR_SBIN, BB_SUID_DROP, fsck_ext2)) 146//IF_E2FSCK(APPLET_ODDNAME(fsck.ext2, e2fsck, BB_DIR_SBIN, BB_SUID_DROP, fsck_ext2))
158//IF_E2FSCK(APPLET_ODDNAME(fsck.ext3, e2fsck, BB_DIR_SBIN, BB_SUID_DROP, fsck_ext3)) 147//IF_E2FSCK(APPLET_ODDNAME(fsck.ext3, e2fsck, BB_DIR_SBIN, BB_SUID_DROP, fsck_ext3))
159IF_FSCK_MINIX(APPLET_ODDNAME(fsck.minix, fsck_minix, BB_DIR_SBIN, BB_SUID_DROP, fsck_minix)) 148IF_FSCK_MINIX(APPLET_ODDNAME(fsck.minix, fsck_minix, BB_DIR_SBIN, BB_SUID_DROP, fsck_minix))
@@ -165,7 +154,6 @@ IF_FUSER(APPLET(fuser, BB_DIR_USR_BIN, BB_SUID_DROP))
165IF_GETENFORCE(APPLET(getenforce, BB_DIR_USR_SBIN, BB_SUID_DROP)) 154IF_GETENFORCE(APPLET(getenforce, BB_DIR_USR_SBIN, BB_SUID_DROP))
166IF_GETOPT(APPLET(getopt, BB_DIR_BIN, BB_SUID_DROP)) 155IF_GETOPT(APPLET(getopt, BB_DIR_BIN, BB_SUID_DROP))
167IF_GETSEBOOL(APPLET(getsebool, BB_DIR_USR_SBIN, BB_SUID_DROP)) 156IF_GETSEBOOL(APPLET(getsebool, BB_DIR_USR_SBIN, BB_SUID_DROP))
168IF_GETTY(APPLET(getty, BB_DIR_SBIN, BB_SUID_DROP))
169IF_HD(APPLET_NOEXEC(hd, hexdump, BB_DIR_USR_BIN, BB_SUID_DROP, hd)) 157IF_HD(APPLET_NOEXEC(hd, hexdump, BB_DIR_USR_BIN, BB_SUID_DROP, hd))
170IF_HDPARM(APPLET(hdparm, BB_DIR_SBIN, BB_SUID_DROP)) 158IF_HDPARM(APPLET(hdparm, BB_DIR_SBIN, BB_SUID_DROP))
171IF_HEAD(APPLET_NOEXEC(head, head, BB_DIR_USR_BIN, BB_SUID_DROP, head)) 159IF_HEAD(APPLET_NOEXEC(head, head, BB_DIR_USR_BIN, BB_SUID_DROP, head))
@@ -201,7 +189,6 @@ IF_KBD_MODE(APPLET(kbd_mode, BB_DIR_BIN, BB_SUID_DROP))
201IF_KILL(APPLET(kill, BB_DIR_BIN, BB_SUID_DROP)) 189IF_KILL(APPLET(kill, BB_DIR_BIN, BB_SUID_DROP))
202IF_KILLALL(APPLET_ODDNAME(killall, kill, BB_DIR_USR_BIN, BB_SUID_DROP, killall)) 190IF_KILLALL(APPLET_ODDNAME(killall, kill, BB_DIR_USR_BIN, BB_SUID_DROP, killall))
203IF_KILLALL5(APPLET_ODDNAME(killall5, kill, BB_DIR_USR_SBIN, BB_SUID_DROP, killall5)) 191IF_KILLALL5(APPLET_ODDNAME(killall5, kill, BB_DIR_USR_SBIN, BB_SUID_DROP, killall5))
204IF_KLOGD(APPLET(klogd, BB_DIR_SBIN, BB_SUID_DROP))
205IF_LAST(APPLET(last, BB_DIR_USR_BIN, BB_SUID_DROP)) 192IF_LAST(APPLET(last, BB_DIR_USR_BIN, BB_SUID_DROP))
206//IF_LENGTH(APPLET_NOFORK(length, length, BB_DIR_USR_BIN, BB_SUID_DROP, length)) 193//IF_LENGTH(APPLET_NOFORK(length, length, BB_DIR_USR_BIN, BB_SUID_DROP, length))
207IF_LESS(APPLET(less, BB_DIR_USR_BIN, BB_SUID_DROP)) 194IF_LESS(APPLET(less, BB_DIR_USR_BIN, BB_SUID_DROP))
@@ -211,17 +198,9 @@ IF_LN(APPLET_NOEXEC(ln, ln, BB_DIR_BIN, BB_SUID_DROP, ln))
211IF_LOAD_POLICY(APPLET(load_policy, BB_DIR_USR_SBIN, BB_SUID_DROP)) 198IF_LOAD_POLICY(APPLET(load_policy, BB_DIR_USR_SBIN, BB_SUID_DROP))
212IF_LOADFONT(APPLET(loadfont, BB_DIR_USR_SBIN, BB_SUID_DROP)) 199IF_LOADFONT(APPLET(loadfont, BB_DIR_USR_SBIN, BB_SUID_DROP))
213IF_LOADKMAP(APPLET(loadkmap, BB_DIR_SBIN, BB_SUID_DROP)) 200IF_LOADKMAP(APPLET(loadkmap, BB_DIR_SBIN, BB_SUID_DROP))
214IF_LOGGER(APPLET(logger, BB_DIR_USR_BIN, BB_SUID_DROP))
215/* Needs to be run by root or be suid root - needs to change uid and gid: */
216IF_LOGIN(APPLET(login, BB_DIR_BIN, BB_SUID_REQUIRE))
217IF_LOGNAME(APPLET_NOFORK(logname, logname, BB_DIR_USR_BIN, BB_SUID_DROP, logname)) 201IF_LOGNAME(APPLET_NOFORK(logname, logname, BB_DIR_USR_BIN, BB_SUID_DROP, logname))
218IF_LOGREAD(APPLET(logread, BB_DIR_SBIN, BB_SUID_DROP))
219IF_LOSETUP(APPLET(losetup, BB_DIR_SBIN, BB_SUID_DROP)) 202IF_LOSETUP(APPLET(losetup, BB_DIR_SBIN, BB_SUID_DROP))
220IF_LPD(APPLET(lpd, BB_DIR_USR_SBIN, BB_SUID_DROP))
221IF_LPQ(APPLET_ODDNAME(lpq, lpqr, BB_DIR_USR_BIN, BB_SUID_DROP, lpq))
222IF_LPR(APPLET_ODDNAME(lpr, lpqr, BB_DIR_USR_BIN, BB_SUID_DROP, lpr))
223IF_LS(APPLET_NOEXEC(ls, ls, BB_DIR_BIN, BB_SUID_DROP, ls)) 203IF_LS(APPLET_NOEXEC(ls, ls, BB_DIR_BIN, BB_SUID_DROP, ls))
224IF_LSATTR(APPLET(lsattr, BB_DIR_BIN, BB_SUID_DROP))
225IF_LSPCI(APPLET(lspci, BB_DIR_USR_BIN, BB_SUID_DROP)) 204IF_LSPCI(APPLET(lspci, BB_DIR_USR_BIN, BB_SUID_DROP))
226IF_LSUSB(APPLET(lsusb, BB_DIR_USR_BIN, BB_SUID_DROP)) 205IF_LSUSB(APPLET(lsusb, BB_DIR_USR_BIN, BB_SUID_DROP))
227IF_MAKEDEVS(APPLET(makedevs, BB_DIR_SBIN, BB_SUID_DROP)) 206IF_MAKEDEVS(APPLET(makedevs, BB_DIR_SBIN, BB_SUID_DROP))
@@ -240,9 +219,7 @@ IF_MKFS_MINIX(APPLET_ODDNAME(mkfs.minix, mkfs_minix, BB_DIR_SBIN, BB_SUID_DROP,
240IF_MKFS_REISER(APPLET_ODDNAME(mkfs.reiser, mkfs_reiser, BB_DIR_SBIN, BB_SUID_DROP, mkfs_reiser)) 219IF_MKFS_REISER(APPLET_ODDNAME(mkfs.reiser, mkfs_reiser, BB_DIR_SBIN, BB_SUID_DROP, mkfs_reiser))
241IF_MKFS_VFAT(APPLET_ODDNAME(mkfs.vfat, mkfs_vfat, BB_DIR_SBIN, BB_SUID_DROP, mkfs_vfat)) 220IF_MKFS_VFAT(APPLET_ODDNAME(mkfs.vfat, mkfs_vfat, BB_DIR_SBIN, BB_SUID_DROP, mkfs_vfat))
242IF_MKNOD(APPLET_NOEXEC(mknod, mknod, BB_DIR_BIN, BB_SUID_DROP, mknod)) 221IF_MKNOD(APPLET_NOEXEC(mknod, mknod, BB_DIR_BIN, BB_SUID_DROP, mknod))
243IF_CRYPTPW(APPLET_ODDNAME(mkpasswd, cryptpw, BB_DIR_USR_BIN, BB_SUID_DROP, mkpasswd))
244IF_MKSWAP(APPLET(mkswap, BB_DIR_SBIN, BB_SUID_DROP)) 222IF_MKSWAP(APPLET(mkswap, BB_DIR_SBIN, BB_SUID_DROP))
245IF_MKTEMP(APPLET(mktemp, BB_DIR_BIN, BB_SUID_DROP))
246IF_MORE(APPLET(more, BB_DIR_BIN, BB_SUID_DROP)) 223IF_MORE(APPLET(more, BB_DIR_BIN, BB_SUID_DROP))
247/* On full-blown systems, requires suid for user mounts. 224/* On full-blown systems, requires suid for user mounts.
248 * But it's not unthinkable to have it available in non-suid flavor on some systems, 225 * But it's not unthinkable to have it available in non-suid flavor on some systems,
@@ -262,11 +239,8 @@ IF_NTPD(APPLET(ntpd, BB_DIR_USR_SBIN, BB_SUID_DROP))
262IF_OD(APPLET(od, BB_DIR_USR_BIN, BB_SUID_DROP)) 239IF_OD(APPLET(od, BB_DIR_USR_BIN, BB_SUID_DROP))
263IF_OPENVT(APPLET(openvt, BB_DIR_USR_BIN, BB_SUID_DROP)) 240IF_OPENVT(APPLET(openvt, BB_DIR_USR_BIN, BB_SUID_DROP))
264//IF_PARSE(APPLET(parse, BB_DIR_USR_BIN, BB_SUID_DROP)) 241//IF_PARSE(APPLET(parse, BB_DIR_USR_BIN, BB_SUID_DROP))
265/* Needs to be run by root or be suid root - needs to change /etc/{passwd,shadow}: */
266IF_PASSWD(APPLET(passwd, BB_DIR_USR_BIN, BB_SUID_REQUIRE))
267IF_PGREP(APPLET(pgrep, BB_DIR_USR_BIN, BB_SUID_DROP)) 242IF_PGREP(APPLET(pgrep, BB_DIR_USR_BIN, BB_SUID_DROP))
268IF_PIDOF(APPLET(pidof, BB_DIR_BIN, BB_SUID_DROP)) 243IF_PIDOF(APPLET(pidof, BB_DIR_BIN, BB_SUID_DROP))
269IF_PIPE_PROGRESS(APPLET(pipe_progress, BB_DIR_BIN, BB_SUID_DROP))
270IF_PIVOT_ROOT(APPLET(pivot_root, BB_DIR_SBIN, BB_SUID_DROP)) 244IF_PIVOT_ROOT(APPLET(pivot_root, BB_DIR_SBIN, BB_SUID_DROP))
271IF_PKILL(APPLET_ODDNAME(pkill, pgrep, BB_DIR_USR_BIN, BB_SUID_DROP, pkill)) 245IF_PKILL(APPLET_ODDNAME(pkill, pgrep, BB_DIR_USR_BIN, BB_SUID_DROP, pkill))
272IF_POPMAILDIR(APPLET(popmaildir, BB_DIR_USR_SBIN, BB_SUID_DROP)) 246IF_POPMAILDIR(APPLET(popmaildir, BB_DIR_USR_SBIN, BB_SUID_DROP))
@@ -291,11 +265,8 @@ IF_RM(APPLET_NOFORK(rm, rm, BB_DIR_BIN, BB_SUID_DROP, rm))
291IF_RMDIR(APPLET_NOFORK(rmdir, rmdir, BB_DIR_BIN, BB_SUID_DROP, rmdir)) 265IF_RMDIR(APPLET_NOFORK(rmdir, rmdir, BB_DIR_BIN, BB_SUID_DROP, rmdir))
292IF_ROUTE(APPLET(route, BB_DIR_SBIN, BB_SUID_DROP)) 266IF_ROUTE(APPLET(route, BB_DIR_SBIN, BB_SUID_DROP))
293IF_RTCWAKE(APPLET(rtcwake, BB_DIR_USR_SBIN, BB_SUID_DROP)) 267IF_RTCWAKE(APPLET(rtcwake, BB_DIR_USR_SBIN, BB_SUID_DROP))
294IF_RUN_PARTS(APPLET_ODDNAME(run-parts, run_parts, BB_DIR_BIN, BB_SUID_DROP, run_parts))
295IF_RUNCON(APPLET(runcon, BB_DIR_USR_BIN, BB_SUID_DROP)) 268IF_RUNCON(APPLET(runcon, BB_DIR_USR_BIN, BB_SUID_DROP))
296IF_RUNLEVEL(APPLET(runlevel, BB_DIR_SBIN, BB_SUID_DROP)) 269IF_RUNLEVEL(APPLET(runlevel, BB_DIR_SBIN, BB_SUID_DROP))
297IF_RUNSV(APPLET(runsv, BB_DIR_USR_BIN, BB_SUID_DROP))
298IF_RUNSVDIR(APPLET(runsvdir, BB_DIR_USR_BIN, BB_SUID_DROP))
299IF_RX(APPLET(rx, BB_DIR_USR_BIN, BB_SUID_DROP)) 270IF_RX(APPLET(rx, BB_DIR_USR_BIN, BB_SUID_DROP))
300IF_SCRIPT(APPLET(script, BB_DIR_USR_BIN, BB_SUID_DROP)) 271IF_SCRIPT(APPLET(script, BB_DIR_USR_BIN, BB_SUID_DROP))
301IF_SCRIPTREPLAY(APPLET(scriptreplay, BB_DIR_BIN, BB_SUID_DROP)) 272IF_SCRIPTREPLAY(APPLET(scriptreplay, BB_DIR_BIN, BB_SUID_DROP))
@@ -312,7 +283,6 @@ IF_SETKEYCODES(APPLET(setkeycodes, BB_DIR_USR_BIN, BB_SUID_DROP))
312IF_SETLOGCONS(APPLET(setlogcons, BB_DIR_USR_SBIN, BB_SUID_DROP)) 283IF_SETLOGCONS(APPLET(setlogcons, BB_DIR_USR_SBIN, BB_SUID_DROP))
313IF_SETSEBOOL(APPLET(setsebool, BB_DIR_USR_SBIN, BB_SUID_DROP)) 284IF_SETSEBOOL(APPLET(setsebool, BB_DIR_USR_SBIN, BB_SUID_DROP))
314IF_SETSID(APPLET(setsid, BB_DIR_USR_BIN, BB_SUID_DROP)) 285IF_SETSID(APPLET(setsid, BB_DIR_USR_BIN, BB_SUID_DROP))
315IF_SETUIDGID(APPLET_ODDNAME(setuidgid, chpst, BB_DIR_USR_BIN, BB_SUID_DROP, setuidgid))
316IF_SHA1SUM(APPLET_NOEXEC(sha1sum, md5_sha1_sum, BB_DIR_USR_BIN, BB_SUID_DROP, sha1sum)) 286IF_SHA1SUM(APPLET_NOEXEC(sha1sum, md5_sha1_sum, BB_DIR_USR_BIN, BB_SUID_DROP, sha1sum))
317IF_SHA3SUM(APPLET_NOEXEC(sha3sum, md5_sha1_sum, BB_DIR_USR_BIN, BB_SUID_DROP, sha3sum)) 287IF_SHA3SUM(APPLET_NOEXEC(sha3sum, md5_sha1_sum, BB_DIR_USR_BIN, BB_SUID_DROP, sha3sum))
318IF_SHA256SUM(APPLET_NOEXEC(sha256sum, md5_sha1_sum, BB_DIR_USR_BIN, BB_SUID_DROP, sha256sum)) 288IF_SHA256SUM(APPLET_NOEXEC(sha256sum, md5_sha1_sum, BB_DIR_USR_BIN, BB_SUID_DROP, sha256sum))
@@ -321,24 +291,16 @@ IF_SHOWKEY(APPLET(showkey, BB_DIR_USR_BIN, BB_SUID_DROP))
321IF_SLATTACH(APPLET(slattach, BB_DIR_SBIN, BB_SUID_DROP)) 291IF_SLATTACH(APPLET(slattach, BB_DIR_SBIN, BB_SUID_DROP))
322/* Do not make this applet NOFORK. It breaks ^C-ing of pauses in shells: */ 292/* Do not make this applet NOFORK. It breaks ^C-ing of pauses in shells: */
323IF_SLEEP(APPLET(sleep, BB_DIR_BIN, BB_SUID_DROP)) 293IF_SLEEP(APPLET(sleep, BB_DIR_BIN, BB_SUID_DROP))
324IF_SOFTLIMIT(APPLET_ODDNAME(softlimit, chpst, BB_DIR_USR_BIN, BB_SUID_DROP, softlimit))
325IF_SORT(APPLET_NOEXEC(sort, sort, BB_DIR_USR_BIN, BB_SUID_DROP, sort)) 294IF_SORT(APPLET_NOEXEC(sort, sort, BB_DIR_USR_BIN, BB_SUID_DROP, sort))
326IF_SPLIT(APPLET(split, BB_DIR_USR_BIN, BB_SUID_DROP)) 295IF_SPLIT(APPLET(split, BB_DIR_USR_BIN, BB_SUID_DROP))
327IF_START_STOP_DAEMON(APPLET_ODDNAME(start-stop-daemon, start_stop_daemon, BB_DIR_SBIN, BB_SUID_DROP, start_stop_daemon))
328IF_STAT(APPLET(stat, BB_DIR_BIN, BB_SUID_DROP)) 296IF_STAT(APPLET(stat, BB_DIR_BIN, BB_SUID_DROP))
329IF_STRINGS(APPLET(strings, BB_DIR_USR_BIN, BB_SUID_DROP)) 297IF_STRINGS(APPLET(strings, BB_DIR_USR_BIN, BB_SUID_DROP))
330IF_STTY(APPLET(stty, BB_DIR_BIN, BB_SUID_DROP)) 298IF_STTY(APPLET(stty, BB_DIR_BIN, BB_SUID_DROP))
331/* Needs to be run by root or be suid root - needs to change uid and gid: */
332IF_SU(APPLET(su, BB_DIR_BIN, BB_SUID_REQUIRE))
333IF_SULOGIN(APPLET(sulogin, BB_DIR_SBIN, BB_SUID_DROP))
334IF_SUM(APPLET(sum, BB_DIR_USR_BIN, BB_SUID_DROP)) 299IF_SUM(APPLET(sum, BB_DIR_USR_BIN, BB_SUID_DROP))
335IF_SV(APPLET(sv, BB_DIR_USR_BIN, BB_SUID_DROP))
336IF_SVLOGD(APPLET(svlogd, BB_DIR_USR_SBIN, BB_SUID_DROP))
337IF_SWAPONOFF(APPLET_ODDNAME(swapoff, swap_on_off, BB_DIR_SBIN, BB_SUID_DROP, swapoff)) 300IF_SWAPONOFF(APPLET_ODDNAME(swapoff, swap_on_off, BB_DIR_SBIN, BB_SUID_DROP, swapoff))
338IF_SWAPONOFF(APPLET_ODDNAME(swapon, swap_on_off, BB_DIR_SBIN, BB_SUID_DROP, swapon)) 301IF_SWAPONOFF(APPLET_ODDNAME(swapon, swap_on_off, BB_DIR_SBIN, BB_SUID_DROP, swapon))
339IF_SWITCH_ROOT(APPLET(switch_root, BB_DIR_SBIN, BB_SUID_DROP)) 302IF_SWITCH_ROOT(APPLET(switch_root, BB_DIR_SBIN, BB_SUID_DROP))
340IF_BB_SYSCTL(APPLET(sysctl, BB_DIR_SBIN, BB_SUID_DROP)) 303IF_BB_SYSCTL(APPLET(sysctl, BB_DIR_SBIN, BB_SUID_DROP))
341IF_SYSLOGD(APPLET(syslogd, BB_DIR_SBIN, BB_SUID_DROP))
342IF_TAC(APPLET_NOEXEC(tac, tac, BB_DIR_USR_BIN, BB_SUID_DROP, tac)) 304IF_TAC(APPLET_NOEXEC(tac, tac, BB_DIR_USR_BIN, BB_SUID_DROP, tac))
343IF_TAIL(APPLET(tail, BB_DIR_USR_BIN, BB_SUID_DROP)) 305IF_TAIL(APPLET(tail, BB_DIR_USR_BIN, BB_SUID_DROP))
344/* IF_TC(APPLET(tc, BB_DIR_SBIN, BB_SUID_DROP)) */ 306/* IF_TC(APPLET(tc, BB_DIR_SBIN, BB_SUID_DROP)) */
@@ -362,7 +324,6 @@ IF_TRUE(APPLET_NOFORK(true, true, BB_DIR_BIN, BB_SUID_DROP, true))
362IF_TTY(APPLET(tty, BB_DIR_USR_BIN, BB_SUID_DROP)) 324IF_TTY(APPLET(tty, BB_DIR_USR_BIN, BB_SUID_DROP))
363IF_TTYSIZE(APPLET(ttysize, BB_DIR_USR_BIN, BB_SUID_DROP)) 325IF_TTYSIZE(APPLET(ttysize, BB_DIR_USR_BIN, BB_SUID_DROP))
364IF_TUNCTL(APPLET(tunctl, BB_DIR_SBIN, BB_SUID_DROP)) 326IF_TUNCTL(APPLET(tunctl, BB_DIR_SBIN, BB_SUID_DROP))
365IF_TUNE2FS(APPLET(tune2fs, BB_DIR_SBIN, BB_SUID_DROP))
366IF_UDHCPC(APPLET(udhcpc, BB_DIR_SBIN, BB_SUID_DROP)) 327IF_UDHCPC(APPLET(udhcpc, BB_DIR_SBIN, BB_SUID_DROP))
367IF_UDHCPD(APPLET(udhcpd, BB_DIR_USR_SBIN, BB_SUID_DROP)) 328IF_UDHCPD(APPLET(udhcpd, BB_DIR_USR_SBIN, BB_SUID_DROP))
368IF_UDPSVD(APPLET_ODDNAME(udpsvd, tcpudpsvd, BB_DIR_USR_BIN, BB_SUID_DROP, udpsvd)) 329IF_UDPSVD(APPLET_ODDNAME(udpsvd, tcpudpsvd, BB_DIR_USR_BIN, BB_SUID_DROP, udpsvd))
@@ -376,13 +337,10 @@ IF_USLEEP(APPLET_NOFORK(usleep, usleep, BB_DIR_BIN, BB_SUID_DROP, usleep))
376IF_UUDECODE(APPLET(uudecode, BB_DIR_USR_BIN, BB_SUID_DROP)) 337IF_UUDECODE(APPLET(uudecode, BB_DIR_USR_BIN, BB_SUID_DROP))
377IF_UUENCODE(APPLET(uuencode, BB_DIR_USR_BIN, BB_SUID_DROP)) 338IF_UUENCODE(APPLET(uuencode, BB_DIR_USR_BIN, BB_SUID_DROP))
378IF_VCONFIG(APPLET(vconfig, BB_DIR_SBIN, BB_SUID_DROP)) 339IF_VCONFIG(APPLET(vconfig, BB_DIR_SBIN, BB_SUID_DROP))
379/* Needs to be run by root or be suid root - needs to change uid and gid: */
380IF_VLOCK(APPLET(vlock, BB_DIR_USR_BIN, BB_SUID_REQUIRE))
381IF_VOLNAME(APPLET(volname, BB_DIR_USR_BIN, BB_SUID_DROP)) 340IF_VOLNAME(APPLET(volname, BB_DIR_USR_BIN, BB_SUID_DROP))
382IF_WATCH(APPLET(watch, BB_DIR_BIN, BB_SUID_DROP)) 341IF_WATCH(APPLET(watch, BB_DIR_BIN, BB_SUID_DROP))
383IF_WATCHDOG(APPLET(watchdog, BB_DIR_SBIN, BB_SUID_DROP)) 342IF_WATCHDOG(APPLET(watchdog, BB_DIR_SBIN, BB_SUID_DROP))
384IF_WC(APPLET(wc, BB_DIR_USR_BIN, BB_SUID_DROP)) 343IF_WC(APPLET(wc, BB_DIR_USR_BIN, BB_SUID_DROP))
385IF_WHICH(APPLET(which, BB_DIR_USR_BIN, BB_SUID_DROP))
386IF_WHOAMI(APPLET_NOFORK(whoami, whoami, BB_DIR_USR_BIN, BB_SUID_DROP, whoami)) 344IF_WHOAMI(APPLET_NOFORK(whoami, whoami, BB_DIR_USR_BIN, BB_SUID_DROP, whoami))
387IF_YES(APPLET_NOFORK(yes, yes, BB_DIR_USR_BIN, BB_SUID_DROP, yes)) 345IF_YES(APPLET_NOFORK(yes, yes, BB_DIR_USR_BIN, BB_SUID_DROP, yes))
388IF_ZCIP(APPLET(zcip, BB_DIR_SBIN, BB_SUID_DROP)) 346IF_ZCIP(APPLET(zcip, BB_DIR_SBIN, BB_SUID_DROP))
diff --git a/include/bb_archive.h b/include/bb_archive.h
index d94169627..e2c8aede4 100644
--- a/include/bb_archive.h
+++ b/include/bb_archive.h
@@ -105,6 +105,7 @@ typedef struct archive_handle_t {
105#endif 105#endif
106#if ENABLE_CPIO || ENABLE_RPM2CPIO || ENABLE_RPM 106#if ENABLE_CPIO || ENABLE_RPM2CPIO || ENABLE_RPM
107 uoff_t cpio__blocks; 107 uoff_t cpio__blocks;
108 struct bb_uidgid_t cpio__owner;
108 struct hardlinks_t *cpio__hardlinks_to_create; 109 struct hardlinks_t *cpio__hardlinks_to_create;
109 struct hardlinks_t *cpio__created_hardlinks; 110 struct hardlinks_t *cpio__created_hardlinks;
110#endif 111#endif
@@ -169,6 +170,8 @@ struct BUG_tar_header {
169}; 170};
170 171
171 172
173extern const char cpio_TRAILER[];
174
172 175
173archive_handle_t *init_handle(void) FAST_FUNC; 176archive_handle_t *init_handle(void) FAST_FUNC;
174 177
diff --git a/include/libbb.h b/include/libbb.h
index 2f90b35f7..de00abe7f 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -934,14 +934,13 @@ long xuname2uid(const char *name) FAST_FUNC;
934long xgroup2gid(const char *name) FAST_FUNC; 934long xgroup2gid(const char *name) FAST_FUNC;
935/* wrapper: allows string to contain numeric uid or gid */ 935/* wrapper: allows string to contain numeric uid or gid */
936unsigned long get_ug_id(const char *s, long FAST_FUNC (*xname2id)(const char *)) FAST_FUNC; 936unsigned long get_ug_id(const char *s, long FAST_FUNC (*xname2id)(const char *)) FAST_FUNC;
937/* from chpst. Does not die, returns 0 on failure */
938struct bb_uidgid_t { 937struct bb_uidgid_t {
939 uid_t uid; 938 uid_t uid;
940 gid_t gid; 939 gid_t gid;
941}; 940};
942/* always sets uid and gid */ 941/* always sets uid and gid; returns 0 on failure */
943int get_uidgid(struct bb_uidgid_t*, const char*, int numeric_ok) FAST_FUNC; 942int get_uidgid(struct bb_uidgid_t*, const char*) FAST_FUNC;
944/* always sets uid and gid, allows numeric; exits on failure */ 943/* always sets uid and gid; exits on failure */
945void xget_uidgid(struct bb_uidgid_t*, const char*) FAST_FUNC; 944void xget_uidgid(struct bb_uidgid_t*, const char*) FAST_FUNC;
946/* chown-like handling of "user[:[group]" */ 945/* chown-like handling of "user[:[group]" */
947void parse_chown_usergroup_or_die(struct bb_uidgid_t *u, char *user_group) FAST_FUNC; 946void parse_chown_usergroup_or_die(struct bb_uidgid_t *u, char *user_group) FAST_FUNC;
@@ -1807,7 +1806,7 @@ extern const char bb_msg_can_not_create_raw_socket[] ALIGN1;
1807extern const char bb_msg_perm_denied_are_you_root[] ALIGN1; 1806extern const char bb_msg_perm_denied_are_you_root[] ALIGN1;
1808extern const char bb_msg_you_must_be_root[] ALIGN1; 1807extern const char bb_msg_you_must_be_root[] ALIGN1;
1809extern const char bb_msg_requires_arg[] ALIGN1; 1808extern const char bb_msg_requires_arg[] ALIGN1;
1810extern const char bb_msg_invalid_arg[] ALIGN1; 1809extern const char bb_msg_invalid_arg_to[] ALIGN1;
1811extern const char bb_msg_standard_input[] ALIGN1; 1810extern const char bb_msg_standard_input[] ALIGN1;
1812extern const char bb_msg_standard_output[] ALIGN1; 1811extern const char bb_msg_standard_output[] ALIGN1;
1813 1812
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index e75257a74..7da7cad1c 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -442,7 +442,7 @@ static void parse_config_file(void)
442 goto pe_label; 442 goto pe_label;
443 } 443 }
444 *e = ':'; /* get_uidgid needs USER:GROUP syntax */ 444 *e = ':'; /* get_uidgid needs USER:GROUP syntax */
445 if (get_uidgid(&sct->m_ugid, s, /*allow_numeric:*/ 1) == 0) { 445 if (get_uidgid(&sct->m_ugid, s) == 0) {
446 errmsg = "unknown user/group"; 446 errmsg = "unknown user/group";
447 goto pe_label; 447 goto pe_label;
448 } 448 }
diff --git a/libbb/human_readable.c b/libbb/human_readable.c
index 5c7fc076f..b4e0ef181 100644
--- a/libbb/human_readable.c
+++ b/libbb/human_readable.c
@@ -14,16 +14,11 @@
14 * representations (say, powers of 1024) and manipulating coefficients. 14 * representations (say, powers of 1024) and manipulating coefficients.
15 * The base ten "bytes" output could be handled similarly. 15 * The base ten "bytes" output could be handled similarly.
16 * 16 *
17 * 2) This routine always outputs a decimal point and a tenths digit when 17 * 2) This routine outputs a decimal point and a tenths digit when
18 * display_unit != 0. Hence, it isn't uncommon for the returned string 18 * display_unit == 0. Hence, it isn't uncommon for the returned string
19 * to have a length of 5 or 6. 19 * to have a length of 5 or 6.
20 * 20 *
21 * It might be nice to add a flag to indicate no decimal digits in 21 * If block_size is also 0, no decimal digits are printed.
22 * that case. This could be either an additional parameter, or a
23 * special value of display_unit. Such a flag would also be nice for du.
24 *
25 * Some code to omit the decimal point and tenths digit is sketched out
26 * and "#if 0"'d below.
27 * 22 *
28 * Licensed under GPLv2, see file LICENSE in this source tree. 23 * Licensed under GPLv2, see file LICENSE in this source tree.
29 */ 24 */
diff --git a/libbb/messages.c b/libbb/messages.c
index 108cb0285..2aa3f175d 100644
--- a/libbb/messages.c
+++ b/libbb/messages.c
@@ -29,7 +29,7 @@ const char bb_msg_can_not_create_raw_socket[] ALIGN1 = "can't create raw socket"
29const char bb_msg_perm_denied_are_you_root[] ALIGN1 = "permission denied (are you root?)"; 29const char bb_msg_perm_denied_are_you_root[] ALIGN1 = "permission denied (are you root?)";
30const char bb_msg_you_must_be_root[] ALIGN1 = "you must be root"; 30const char bb_msg_you_must_be_root[] ALIGN1 = "you must be root";
31const char bb_msg_requires_arg[] ALIGN1 = "%s requires an argument"; 31const char bb_msg_requires_arg[] ALIGN1 = "%s requires an argument";
32const char bb_msg_invalid_arg[] ALIGN1 = "invalid argument '%s' to '%s'"; 32const char bb_msg_invalid_arg_to[] ALIGN1 = "invalid argument '%s' to '%s'";
33const char bb_msg_standard_input[] ALIGN1 = "standard input"; 33const char bb_msg_standard_input[] ALIGN1 = "standard input";
34const char bb_msg_standard_output[] ALIGN1 = "standard output"; 34const char bb_msg_standard_output[] ALIGN1 = "standard output";
35 35
diff --git a/libpwdgrp/uidgid_get.c b/libpwdgrp/uidgid_get.c
index 8388be0da..1199f23f9 100644
--- a/libpwdgrp/uidgid_get.c
+++ b/libpwdgrp/uidgid_get.c
@@ -28,7 +28,7 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28#include "libbb.h" 28#include "libbb.h"
29 29
30/* Always sets uid and gid */ 30/* Always sets uid and gid */
31int FAST_FUNC get_uidgid(struct bb_uidgid_t *u, const char *ug, int numeric_ok) 31int FAST_FUNC get_uidgid(struct bb_uidgid_t *u, const char *ug)
32{ 32{
33 struct passwd *pwd; 33 struct passwd *pwd;
34 struct group *gr; 34 struct group *gr;
@@ -43,18 +43,16 @@ int FAST_FUNC get_uidgid(struct bb_uidgid_t *u, const char *ug, int numeric_ok)
43 /* copies sz-1 bytes, stores terminating '\0' */ 43 /* copies sz-1 bytes, stores terminating '\0' */
44 safe_strncpy(user, ug, sz); 44 safe_strncpy(user, ug, sz);
45 } 45 }
46 if (numeric_ok) { 46 n = bb_strtou(user, NULL, 10);
47 n = bb_strtou(user, NULL, 10); 47 if (!errno) {
48 if (!errno) { 48 u->uid = n;
49 u->uid = n; 49 pwd = getpwuid(n);
50 pwd = getpwuid(n); 50 /* If we have e.g. "500" string without user */
51 /* If we have e.g. "500" string without user */ 51 /* with uid 500 in /etc/passwd, we set gid == uid */
52 /* with uid 500 in /etc/passwd, we set gid == uid */ 52 u->gid = pwd ? pwd->pw_gid : n;
53 u->gid = pwd ? pwd->pw_gid : n; 53 goto skip;
54 goto skip;
55 }
56 } 54 }
57 /* Either it is not numeric, or caller disallows numeric username */ 55 /* it is not numeric */
58 pwd = getpwnam(user); 56 pwd = getpwnam(user);
59 if (!pwd) 57 if (!pwd)
60 return 0; 58 return 0;
@@ -63,12 +61,10 @@ int FAST_FUNC get_uidgid(struct bb_uidgid_t *u, const char *ug, int numeric_ok)
63 61
64 skip: 62 skip:
65 if (group) { 63 if (group) {
66 if (numeric_ok) { 64 n = bb_strtou(group, NULL, 10);
67 n = bb_strtou(group, NULL, 10); 65 if (!errno) {
68 if (!errno) { 66 u->gid = n;
69 u->gid = n; 67 return 1;
70 return 1;
71 }
72 } 68 }
73 gr = getgrnam(group); 69 gr = getgrnam(group);
74 if (!gr) 70 if (!gr)
@@ -79,7 +75,7 @@ int FAST_FUNC get_uidgid(struct bb_uidgid_t *u, const char *ug, int numeric_ok)
79} 75}
80void FAST_FUNC xget_uidgid(struct bb_uidgid_t *u, const char *ug) 76void FAST_FUNC xget_uidgid(struct bb_uidgid_t *u, const char *ug)
81{ 77{
82 if (!get_uidgid(u, ug, 1)) 78 if (!get_uidgid(u, ug))
83 bb_error_msg_and_die("unknown user/group %s", ug); 79 bb_error_msg_and_die("unknown user/group %s", ug);
84} 80}
85 81
@@ -94,6 +90,8 @@ void FAST_FUNC parse_chown_usergroup_or_die(struct bb_uidgid_t *u, char *user_gr
94{ 90{
95 char *group; 91 char *group;
96 92
93 u->uid = u->gid = (gid_t)-1L;
94
97 /* Check if there is a group name */ 95 /* Check if there is a group name */
98 group = strchr(user_group, '.'); /* deprecated? */ 96 group = strchr(user_group, '.'); /* deprecated? */
99 if (!group) 97 if (!group)
@@ -119,16 +117,16 @@ int main()
119{ 117{
120 unsigned u; 118 unsigned u;
121 struct bb_uidgid_t ug; 119 struct bb_uidgid_t ug;
122 u = get_uidgid(&ug, "apache", 0); 120 u = get_uidgid(&ug, "apache");
123 printf("%u = %u:%u\n", u, ug.uid, ug.gid); 121 printf("%u = %u:%u\n", u, ug.uid, ug.gid);
124 ug.uid = ug.gid = 1111; 122 ug.uid = ug.gid = 1111;
125 u = get_uidgid(&ug, "apache", 0); 123 u = get_uidgid(&ug, "apache");
126 printf("%u = %u:%u\n", u, ug.uid, ug.gid); 124 printf("%u = %u:%u\n", u, ug.uid, ug.gid);
127 ug.uid = ug.gid = 1111; 125 ug.uid = ug.gid = 1111;
128 u = get_uidgid(&ug, "apache:users", 0); 126 u = get_uidgid(&ug, "apache:users");
129 printf("%u = %u:%u\n", u, ug.uid, ug.gid); 127 printf("%u = %u:%u\n", u, ug.uid, ug.gid);
130 ug.uid = ug.gid = 1111; 128 ug.uid = ug.gid = 1111;
131 u = get_uidgid(&ug, "apache:users", 0); 129 u = get_uidgid(&ug, "apache:users");
132 printf("%u = %u:%u\n", u, ug.uid, ug.gid); 130 printf("%u = %u:%u\n", u, ug.uid, ug.gid);
133 return 0; 131 return 0;
134} 132}
diff --git a/loginutils/Config.src b/loginutils/Config.src
index fa2b4f8c0..efb954b6c 100644
--- a/loginutils/Config.src
+++ b/loginutils/Config.src
@@ -5,8 +5,6 @@
5 5
6menu "Login/Password Management Utilities" 6menu "Login/Password Management Utilities"
7 7
8INSERT
9
10config FEATURE_SHADOWPASSWDS 8config FEATURE_SHADOWPASSWDS
11 bool "Support for shadow passwords" 9 bool "Support for shadow passwords"
12 default y 10 default y
@@ -93,239 +91,6 @@ config USE_BB_CRYPT_SHA
93 With this option off, login will fail password check for any 91 With this option off, login will fail password check for any
94 user which has password encrypted with these algorithms. 92 user which has password encrypted with these algorithms.
95 93
96config ADDUSER 94INSERT
97 bool "adduser"
98 default y
99 help
100 Utility for creating a new user account.
101
102config FEATURE_ADDUSER_LONG_OPTIONS
103 bool "Enable long options"
104 default y
105 depends on ADDUSER && LONG_OPTS
106 help
107 Support long options for the adduser applet.
108
109config FEATURE_CHECK_NAMES
110 bool "Enable sanity check on user/group names in adduser and addgroup"
111 default n
112 depends on ADDUSER || ADDGROUP
113 help
114 Enable sanity check on user and group names in adduser and addgroup.
115 To avoid problems, the user or group name should consist only of
116 letters, digits, underscores, periods, at signs and dashes,
117 and not start with a dash (as defined by IEEE Std 1003.1-2001).
118 For compatibility with Samba machine accounts "$" is also supported
119 at the end of the user or group name.
120
121config LAST_ID
122 int "Last valid uid or gid for adduser and addgroup"
123 depends on ADDUSER || ADDGROUP
124 default 60000
125 help
126 Last valid uid or gid for adduser and addgroup
127
128config FIRST_SYSTEM_ID
129 int "First valid system uid or gid for adduser and addgroup"
130 depends on ADDUSER || ADDGROUP
131 range 0 LAST_ID
132 default 100
133 help
134 First valid system uid or gid for adduser and addgroup
135
136config LAST_SYSTEM_ID
137 int "Last valid system uid or gid for adduser and addgroup"
138 depends on ADDUSER || ADDGROUP
139 range FIRST_SYSTEM_ID LAST_ID
140 default 999
141 help
142 Last valid system uid or gid for adduser and addgroup
143
144config ADDGROUP
145 bool "addgroup"
146 default y
147 help
148 Utility for creating a new group account.
149
150config FEATURE_ADDGROUP_LONG_OPTIONS
151 bool "Enable long options"
152 default y
153 depends on ADDGROUP && LONG_OPTS
154 help
155 Support long options for the addgroup applet.
156
157config FEATURE_ADDUSER_TO_GROUP
158 bool "Support for adding users to groups"
159 default y
160 depends on ADDGROUP
161 help
162 If called with two non-option arguments,
163 addgroup will add an existing user to an
164 existing group.
165
166config DELUSER
167 bool "deluser"
168 default y
169 help
170 Utility for deleting a user account.
171
172config DELGROUP
173 bool "delgroup"
174 default y
175 help
176 Utility for deleting a group account.
177
178config FEATURE_DEL_USER_FROM_GROUP
179 bool "Support for removing users from groups"
180 default y
181 depends on DELGROUP
182 help
183 If called with two non-option arguments, deluser
184 or delgroup will remove an user from a specified group.
185
186config GETTY
187 bool "getty"
188 default y
189 select FEATURE_SYSLOG
190 help
191 getty lets you log in on a tty. It is normally invoked by init.
192
193 Note that you can save a few bytes by disabling it and
194 using login applet directly.
195 If you need to reset tty attributes before calling login,
196 this script approximates getty:
197
198 exec </dev/$1 >/dev/$1 2>&1 || exit 1
199 reset
200 stty sane; stty ispeed 38400; stty ospeed 38400
201 printf "%s login: " "`hostname`"
202 read -r login
203 exec /bin/login "$login"
204
205config LOGIN
206 bool "login"
207 default y
208 select FEATURE_SYSLOG
209 help
210 login is used when signing onto a system.
211
212 Note that Busybox binary must be setuid root for this applet to
213 work properly.
214
215config LOGIN_SESSION_AS_CHILD
216 bool "Run logged in session in a child process"
217 default y if PAM
218 depends on LOGIN
219 help
220 Run the logged in session in a child process. This allows
221 login to clean up things such as utmp entries or PAM sessions
222 when the login session is complete. If you use PAM, you
223 almost always would want this to be set to Y, else PAM session
224 will not be cleaned up.
225
226config LOGIN_SCRIPTS
227 bool "Support for login scripts"
228 depends on LOGIN
229 default y
230 help
231 Enable this if you want login to execute $LOGIN_PRE_SUID_SCRIPT
232 just prior to switching from root to logged-in user.
233
234config FEATURE_NOLOGIN
235 bool "Support for /etc/nologin"
236 default y
237 depends on LOGIN
238 help
239 The file /etc/nologin is used by (some versions of) login(1).
240 If it exists, non-root logins are prohibited.
241
242config FEATURE_SECURETTY
243 bool "Support for /etc/securetty"
244 default y
245 depends on LOGIN
246 help
247 The file /etc/securetty is used by (some versions of) login(1).
248 The file contains the device names of tty lines (one per line,
249 without leading /dev/) on which root is allowed to login.
250
251config PASSWD
252 bool "passwd"
253 default y
254 select FEATURE_SYSLOG
255 help
256 passwd changes passwords for user and group accounts. A normal user
257 may only change the password for his/her own account, the super user
258 may change the password for any account. The administrator of a group
259 may change the password for the group.
260
261 Note that Busybox binary must be setuid root for this applet to
262 work properly.
263
264config FEATURE_PASSWD_WEAK_CHECK
265 bool "Check new passwords for weakness"
266 default y
267 depends on PASSWD
268 help
269 With this option passwd will refuse new passwords which are "weak".
270
271config CRYPTPW
272 bool "cryptpw"
273 default y
274 help
275 Encrypts the given password with the crypt(3) libc function
276 using the given salt. Debian has this utility under mkpasswd
277 name. Busybox provides mkpasswd as an alias for cryptpw.
278
279config CHPASSWD
280 bool "chpasswd"
281 default y
282 help
283 Reads a file of user name and password pairs from standard input
284 and uses this information to update a group of existing users.
285
286config FEATURE_DEFAULT_PASSWD_ALGO
287 string "Default password encryption method (passwd -a, cryptpw -m parameter)"
288 default "des"
289 depends on PASSWD || CRYPTPW
290 help
291 Possible choices are "d[es]", "m[d5]", "s[ha256]" or "sha512".
292
293config SU
294 bool "su"
295 default y
296 select FEATURE_SYSLOG
297 help
298 su is used to become another user during a login session.
299 Invoked without a username, su defaults to becoming the super user.
300
301 Note that Busybox binary must be setuid root for this applet to
302 work properly.
303
304config FEATURE_SU_SYSLOG
305 bool "Enable su to write to syslog"
306 default y
307 depends on SU
308
309config FEATURE_SU_CHECKS_SHELLS
310 bool "Enable su to check user's shell to be listed in /etc/shells"
311 depends on SU
312 default y
313
314config SULOGIN
315 bool "sulogin"
316 default y
317 select FEATURE_SYSLOG
318 help
319 sulogin is invoked when the system goes into single user
320 mode (this is done through an entry in inittab).
321
322config VLOCK
323 bool "vlock"
324 default y
325 help
326 Build the "vlock" applet which allows you to lock (virtual) terminals.
327
328 Note that Busybox binary must be setuid root for this applet to
329 work properly.
330 95
331endmenu 96endmenu
diff --git a/loginutils/Kbuild.src b/loginutils/Kbuild.src
index ef416a76f..6b4fb7470 100644
--- a/loginutils/Kbuild.src
+++ b/loginutils/Kbuild.src
@@ -7,15 +7,3 @@
7lib-y:= 7lib-y:=
8 8
9INSERT 9INSERT
10lib-$(CONFIG_ADDGROUP) += addgroup.o
11lib-$(CONFIG_ADDUSER) += adduser.o
12lib-$(CONFIG_CRYPTPW) += cryptpw.o
13lib-$(CONFIG_CHPASSWD) += chpasswd.o
14lib-$(CONFIG_GETTY) += getty.o
15lib-$(CONFIG_LOGIN) += login.o
16lib-$(CONFIG_PASSWD) += passwd.o
17lib-$(CONFIG_SU) += su.o
18lib-$(CONFIG_SULOGIN) += sulogin.o
19lib-$(CONFIG_VLOCK) += vlock.o
20lib-$(CONFIG_DELUSER) += deluser.o
21lib-$(CONFIG_DELGROUP) += deluser.o
diff --git a/loginutils/add-remove-shell.c b/loginutils/add-remove-shell.c
index 9419ff5e7..ce4a7bbd2 100644
--- a/loginutils/add-remove-shell.c
+++ b/loginutils/add-remove-shell.c
@@ -7,13 +7,6 @@
7 * Licensed under GPLv2 or later, see the LICENSE file in this source tree 7 * Licensed under GPLv2 or later, see the LICENSE file in this source tree
8 * for details. 8 * for details.
9 */ 9 */
10
11//applet:IF_ADD_SHELL( APPLET_ODDNAME(add-shell , add_remove_shell, BB_DIR_USR_SBIN, BB_SUID_DROP, add_shell ))
12//applet:IF_REMOVE_SHELL(APPLET_ODDNAME(remove-shell, add_remove_shell, BB_DIR_USR_SBIN, BB_SUID_DROP, remove_shell))
13
14//kbuild:lib-$(CONFIG_ADD_SHELL) += add-remove-shell.o
15//kbuild:lib-$(CONFIG_REMOVE_SHELL) += add-remove-shell.o
16
17//config:config ADD_SHELL 10//config:config ADD_SHELL
18//config: bool "add-shell" 11//config: bool "add-shell"
19//config: default y if DESKTOP 12//config: default y if DESKTOP
@@ -26,6 +19,12 @@
26//config: help 19//config: help
27//config: Remove shells from /etc/shells. 20//config: Remove shells from /etc/shells.
28 21
22//applet:IF_ADD_SHELL( APPLET_ODDNAME(add-shell , add_remove_shell, BB_DIR_USR_SBIN, BB_SUID_DROP, add_shell ))
23//applet:IF_REMOVE_SHELL(APPLET_ODDNAME(remove-shell, add_remove_shell, BB_DIR_USR_SBIN, BB_SUID_DROP, remove_shell))
24
25//kbuild:lib-$(CONFIG_ADD_SHELL) += add-remove-shell.o
26//kbuild:lib-$(CONFIG_REMOVE_SHELL) += add-remove-shell.o
27
29//usage:#define add_shell_trivial_usage 28//usage:#define add_shell_trivial_usage
30//usage: "SHELL..." 29//usage: "SHELL..."
31//usage:#define add_shell_full_usage "\n\n" 30//usage:#define add_shell_full_usage "\n\n"
diff --git a/loginutils/addgroup.c b/loginutils/addgroup.c
index 260e337f3..4d4fc3f28 100644
--- a/loginutils/addgroup.c
+++ b/loginutils/addgroup.c
@@ -9,6 +9,31 @@
9 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 9 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
10 * 10 *
11 */ 11 */
12//config:config ADDGROUP
13//config: bool "addgroup"
14//config: default y
15//config: help
16//config: Utility for creating a new group account.
17//config:
18//config:config FEATURE_ADDGROUP_LONG_OPTIONS
19//config: bool "Enable long options"
20//config: default y
21//config: depends on ADDGROUP && LONG_OPTS
22//config: help
23//config: Support long options for the addgroup applet.
24//config:
25//config:config FEATURE_ADDUSER_TO_GROUP
26//config: bool "Support for adding users to groups"
27//config: default y
28//config: depends on ADDGROUP
29//config: help
30//config: If called with two non-option arguments,
31//config: addgroup will add an existing user to an
32//config: existing group.
33
34//applet:IF_ADDGROUP(APPLET(addgroup, BB_DIR_USR_SBIN, BB_SUID_DROP))
35
36//kbuild:lib-$(CONFIG_ADDGROUP) += addgroup.o
12 37
13//usage:#define addgroup_trivial_usage 38//usage:#define addgroup_trivial_usage
14//usage: "[-g GID] [-S] " IF_FEATURE_ADDUSER_TO_GROUP("[USER] ") "GROUP" 39//usage: "[-g GID] [-S] " IF_FEATURE_ADDUSER_TO_GROUP("[USER] ") "GROUP"
diff --git a/loginutils/adduser.c b/loginutils/adduser.c
index 605e3363f..608fb8437 100644
--- a/loginutils/adduser.c
+++ b/loginutils/adduser.c
@@ -7,6 +7,57 @@
7 * 7 *
8 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
9 */ 9 */
10//config:config ADDUSER
11//config: bool "adduser"
12//config: default y
13//config: help
14//config: Utility for creating a new user account.
15//config:
16//config:config FEATURE_ADDUSER_LONG_OPTIONS
17//config: bool "Enable long options"
18//config: default y
19//config: depends on ADDUSER && LONG_OPTS
20//config: help
21//config: Support long options for the adduser applet.
22//config:
23//config:config FEATURE_CHECK_NAMES
24//config: bool "Enable sanity check on user/group names in adduser and addgroup"
25//config: default n
26//config: depends on ADDUSER || ADDGROUP
27//config: help
28//config: Enable sanity check on user and group names in adduser and addgroup.
29//config: To avoid problems, the user or group name should consist only of
30//config: letters, digits, underscores, periods, at signs and dashes,
31//config: and not start with a dash (as defined by IEEE Std 1003.1-2001).
32//config: For compatibility with Samba machine accounts "$" is also supported
33//config: at the end of the user or group name.
34//config:
35//config:config LAST_ID
36//config: int "Last valid uid or gid for adduser and addgroup"
37//config: depends on ADDUSER || ADDGROUP
38//config: default 60000
39//config: help
40//config: Last valid uid or gid for adduser and addgroup
41//config:
42//config:config FIRST_SYSTEM_ID
43//config: int "First valid system uid or gid for adduser and addgroup"
44//config: depends on ADDUSER || ADDGROUP
45//config: range 0 LAST_ID
46//config: default 100
47//config: help
48//config: First valid system uid or gid for adduser and addgroup
49//config:
50//config:config LAST_SYSTEM_ID
51//config: int "Last valid system uid or gid for adduser and addgroup"
52//config: depends on ADDUSER || ADDGROUP
53//config: range FIRST_SYSTEM_ID LAST_ID
54//config: default 999
55//config: help
56//config: Last valid system uid or gid for adduser and addgroup
57
58//applet:IF_ADDUSER(APPLET(adduser, BB_DIR_USR_SBIN, BB_SUID_DROP))
59
60//kbuild:lib-$(CONFIG_ADDUSER) += adduser.o
10 61
11//usage:#define adduser_trivial_usage 62//usage:#define adduser_trivial_usage
12//usage: "[OPTIONS] USER [GROUP]" 63//usage: "[OPTIONS] USER [GROUP]"
diff --git a/loginutils/chpasswd.c b/loginutils/chpasswd.c
index 54ed73795..6c41d17be 100644
--- a/loginutils/chpasswd.c
+++ b/loginutils/chpasswd.c
@@ -5,7 +5,23 @@
5 * Written for SLIND (from passwd.c) by Alexander Shishkin <virtuoso@slind.org> 5 * Written for SLIND (from passwd.c) by Alexander Shishkin <virtuoso@slind.org>
6 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 6 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
7 */ 7 */
8#include "libbb.h" 8//config:config CHPASSWD
9//config: bool "chpasswd"
10//config: default y
11//config: help
12//config: Reads a file of user name and password pairs from standard input
13//config: and uses this information to update a group of existing users.
14//config:
15//config:config FEATURE_DEFAULT_PASSWD_ALGO
16//config: string "Default password encryption method (passwd -a, cryptpw -m parameter)"
17//config: default "des"
18//config: depends on PASSWD || CRYPTPW
19//config: help
20//config: Possible choices are "d[es]", "m[d5]", "s[ha256]" or "sha512".
21
22//applet:IF_CHPASSWD(APPLET(chpasswd, BB_DIR_USR_SBIN, BB_SUID_DROP))
23
24//kbuild:lib-$(CONFIG_CHPASSWD) += chpasswd.o
9 25
10//usage:#define chpasswd_trivial_usage 26//usage:#define chpasswd_trivial_usage
11//usage: IF_LONG_OPTS("[--md5|--encrypted]") IF_NOT_LONG_OPTS("[-m|-e]") 27//usage: IF_LONG_OPTS("[--md5|--encrypted]") IF_NOT_LONG_OPTS("[-m|-e]")
@@ -22,6 +38,8 @@
22 38
23//TODO: implement -c ALGO 39//TODO: implement -c ALGO
24 40
41#include "libbb.h"
42
25#if ENABLE_LONG_OPTS 43#if ENABLE_LONG_OPTS
26static const char chpasswd_longopts[] ALIGN1 = 44static const char chpasswd_longopts[] ALIGN1 =
27 "encrypted\0" No_argument "e" 45 "encrypted\0" No_argument "e"
diff --git a/loginutils/cryptpw.c b/loginutils/cryptpw.c
index 29f0fbe91..55dcc2914 100644
--- a/loginutils/cryptpw.c
+++ b/loginutils/cryptpw.c
@@ -9,6 +9,18 @@
9 * 9 *
10 * Licensed under GPLv2, see file LICENSE in this source tree. 10 * Licensed under GPLv2, see file LICENSE in this source tree.
11 */ 11 */
12//config:config CRYPTPW
13//config: bool "cryptpw"
14//config: default y
15//config: help
16//config: Encrypts the given password with the crypt(3) libc function
17//config: using the given salt. Debian has this utility under mkpasswd
18//config: name. Busybox provides mkpasswd as an alias for cryptpw.
19
20//applet:IF_CRYPTPW(APPLET(cryptpw, BB_DIR_USR_BIN, BB_SUID_DROP))
21//applet:IF_CRYPTPW(APPLET_ODDNAME(mkpasswd, cryptpw, BB_DIR_USR_BIN, BB_SUID_DROP, mkpasswd))
22
23//kbuild:lib-$(CONFIG_CRYPTPW) += cryptpw.o
12 24
13//usage:#define cryptpw_trivial_usage 25//usage:#define cryptpw_trivial_usage
14//usage: "[OPTIONS] [PASSWORD] [SALT]" 26//usage: "[OPTIONS] [PASSWORD] [SALT]"
diff --git a/loginutils/deluser.c b/loginutils/deluser.c
index 110cd6310..7c3caf9e3 100644
--- a/loginutils/deluser.c
+++ b/loginutils/deluser.c
@@ -7,8 +7,32 @@
7 * Copyright (C) 2007 by Tito Ragusa <farmatito@tiscali.it> 7 * Copyright (C) 2007 by Tito Ragusa <farmatito@tiscali.it>
8 * 8 *
9 * Licensed under GPLv2, see file LICENSE in this source tree. 9 * Licensed under GPLv2, see file LICENSE in this source tree.
10 *
11 */ 10 */
11//config:config DELUSER
12//config: bool "deluser"
13//config: default y
14//config: help
15//config: Utility for deleting a user account.
16//config:
17//config:config DELGROUP
18//config: bool "delgroup"
19//config: default y
20//config: help
21//config: Utility for deleting a group account.
22//config:
23//config:config FEATURE_DEL_USER_FROM_GROUP
24//config: bool "Support for removing users from groups"
25//config: default y
26//config: depends on DELGROUP
27//config: help
28//config: If called with two non-option arguments, deluser
29//config: or delgroup will remove an user from a specified group.
30
31//applet:IF_DELUSER(APPLET(deluser, BB_DIR_USR_SBIN, BB_SUID_DROP))
32//applet:IF_DELGROUP(APPLET_ODDNAME(delgroup, deluser, BB_DIR_USR_SBIN, BB_SUID_DROP, delgroup))
33
34//kbuild:lib-$(CONFIG_DELUSER) += deluser.o
35//kbuild:lib-$(CONFIG_DELGROUP) += deluser.o
12 36
13//usage:#define deluser_trivial_usage 37//usage:#define deluser_trivial_usage
14//usage: IF_LONG_OPTS("[--remove-home] ") "USER" 38//usage: IF_LONG_OPTS("[--remove-home] ") "USER"
diff --git a/loginutils/getty.c b/loginutils/getty.c
index 762d5c773..b10bdbdbf 100644
--- a/loginutils/getty.c
+++ b/loginutils/getty.c
@@ -21,6 +21,28 @@
21 * 21 *
22 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 22 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
23 */ 23 */
24//config:config GETTY
25//config: bool "getty"
26//config: default y
27//config: select FEATURE_SYSLOG
28//config: help
29//config: getty lets you log in on a tty. It is normally invoked by init.
30//config:
31//config: Note that you can save a few bytes by disabling it and
32//config: using login applet directly.
33//config: If you need to reset tty attributes before calling login,
34//config: this script approximates getty:
35//config:
36//config: exec </dev/$1 >/dev/$1 2>&1 || exit 1
37//config: reset
38//config: stty sane; stty ispeed 38400; stty ospeed 38400
39//config: printf "%s login: " "`hostname`"
40//config: read -r login
41//config: exec /bin/login "$login"
42
43//applet:IF_GETTY(APPLET(getty, BB_DIR_SBIN, BB_SUID_DROP))
44
45//kbuild:lib-$(CONFIG_GETTY) += getty.o
24 46
25#include "libbb.h" 47#include "libbb.h"
26#include <syslog.h> 48#include <syslog.h>
diff --git a/loginutils/login.c b/loginutils/login.c
index 1700cfcb5..f1f04da19 100644
--- a/loginutils/login.c
+++ b/loginutils/login.c
@@ -2,6 +2,56 @@
2/* 2/*
3 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 3 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
4 */ 4 */
5//config:config LOGIN
6//config: bool "login"
7//config: default y
8//config: select FEATURE_SYSLOG
9//config: help
10//config: login is used when signing onto a system.
11//config:
12//config: Note that Busybox binary must be setuid root for this applet to
13//config: work properly.
14//config:
15//config:config LOGIN_SESSION_AS_CHILD
16//config: bool "Run logged in session in a child process"
17//config: default y if PAM
18//config: depends on LOGIN
19//config: help
20//config: Run the logged in session in a child process. This allows
21//config: login to clean up things such as utmp entries or PAM sessions
22//config: when the login session is complete. If you use PAM, you
23//config: almost always would want this to be set to Y, else PAM session
24//config: will not be cleaned up.
25//config:
26//config:config LOGIN_SCRIPTS
27//config: bool "Support for login scripts"
28//config: depends on LOGIN
29//config: default y
30//config: help
31//config: Enable this if you want login to execute $LOGIN_PRE_SUID_SCRIPT
32//config: just prior to switching from root to logged-in user.
33//config:
34//config:config FEATURE_NOLOGIN
35//config: bool "Support for /etc/nologin"
36//config: default y
37//config: depends on LOGIN
38//config: help
39//config: The file /etc/nologin is used by (some versions of) login(1).
40//config: If it exists, non-root logins are prohibited.
41//config:
42//config:config FEATURE_SECURETTY
43//config: bool "Support for /etc/securetty"
44//config: default y
45//config: depends on LOGIN
46//config: help
47//config: The file /etc/securetty is used by (some versions of) login(1).
48//config: The file contains the device names of tty lines (one per line,
49//config: without leading /dev/) on which root is allowed to login.
50
51//applet:/* Needs to be run by root or be suid root - needs to change uid and gid: */
52//applet:IF_LOGIN(APPLET(login, BB_DIR_BIN, BB_SUID_REQUIRE))
53
54//kbuild:lib-$(CONFIG_LOGIN) += login.o
5 55
6//usage:#define login_trivial_usage 56//usage:#define login_trivial_usage
7//usage: "[-p] [-h HOST] [[-f] USER]" 57//usage: "[-p] [-h HOST] [[-f] USER]"
diff --git a/loginutils/passwd.c b/loginutils/passwd.c
index 150908932..73726d3e0 100644
--- a/loginutils/passwd.c
+++ b/loginutils/passwd.c
@@ -2,6 +2,30 @@
2/* 2/*
3 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 3 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
4 */ 4 */
5//config:config PASSWD
6//config: bool "passwd"
7//config: default y
8//config: select FEATURE_SYSLOG
9//config: help
10//config: passwd changes passwords for user and group accounts. A normal user
11//config: may only change the password for his/her own account, the super user
12//config: may change the password for any account. The administrator of a group
13//config: may change the password for the group.
14//config:
15//config: Note that Busybox binary must be setuid root for this applet to
16//config: work properly.
17//config:
18//config:config FEATURE_PASSWD_WEAK_CHECK
19//config: bool "Check new passwords for weakness"
20//config: default y
21//config: depends on PASSWD
22//config: help
23//config: With this option passwd will refuse new passwords which are "weak".
24
25//applet:/* Needs to be run by root or be suid root - needs to change /etc/{passwd,shadow}: */
26//applet:IF_PASSWD(APPLET(passwd, BB_DIR_USR_BIN, BB_SUID_REQUIRE))
27
28//kbuild:lib-$(CONFIG_PASSWD) += passwd.o
5 29
6//usage:#define passwd_trivial_usage 30//usage:#define passwd_trivial_usage
7//usage: "[OPTIONS] [USER]" 31//usage: "[OPTIONS] [USER]"
diff --git a/loginutils/su.c b/loginutils/su.c
index f8125054a..3c0e8c100 100644
--- a/loginutils/su.c
+++ b/loginutils/su.c
@@ -4,9 +4,31 @@
4 * 4 *
5 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 5 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
6 */ 6 */
7 7//config:config SU
8#include "libbb.h" 8//config: bool "su"
9#include <syslog.h> 9//config: default y
10//config: select FEATURE_SYSLOG
11//config: help
12//config: su is used to become another user during a login session.
13//config: Invoked without a username, su defaults to becoming the super user.
14//config:
15//config: Note that Busybox binary must be setuid root for this applet to
16//config: work properly.
17//config:
18//config:config FEATURE_SU_SYSLOG
19//config: bool "Enable su to write to syslog"
20//config: default y
21//config: depends on SU
22//config:
23//config:config FEATURE_SU_CHECKS_SHELLS
24//config: bool "Enable su to check user's shell to be listed in /etc/shells"
25//config: depends on SU
26//config: default y
27
28//applet:/* Needs to be run by root or be suid root - needs to change uid and gid: */
29//applet:IF_SU(APPLET(su, BB_DIR_BIN, BB_SUID_REQUIRE))
30
31//kbuild:lib-$(CONFIG_SU) += su.o
10 32
11//usage:#define su_trivial_usage 33//usage:#define su_trivial_usage
12//usage: "[OPTIONS] [-] [USER]" 34//usage: "[OPTIONS] [-] [USER]"
@@ -17,6 +39,9 @@
17//usage: "\n -c CMD Command to pass to 'sh -c'" 39//usage: "\n -c CMD Command to pass to 'sh -c'"
18//usage: "\n -s SH Shell to use instead of user's default" 40//usage: "\n -s SH Shell to use instead of user's default"
19 41
42#include "libbb.h"
43#include <syslog.h>
44
20#if ENABLE_FEATURE_SU_CHECKS_SHELLS 45#if ENABLE_FEATURE_SU_CHECKS_SHELLS
21/* Return 1 if SHELL is a restricted shell (one not returned by 46/* Return 1 if SHELL is a restricted shell (one not returned by
22 * getusershell), else 0, meaning it is a standard shell. */ 47 * getusershell), else 0, meaning it is a standard shell. */
diff --git a/loginutils/sulogin.c b/loginutils/sulogin.c
index 2a2909937..19b1e304c 100644
--- a/loginutils/sulogin.c
+++ b/loginutils/sulogin.c
@@ -4,6 +4,18 @@
4 * 4 *
5 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 5 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
6 */ 6 */
7//config:config SULOGIN
8//config: bool "sulogin"
9//config: default y
10//config: select FEATURE_SYSLOG
11//config: help
12//config: sulogin is invoked when the system goes into single user
13//config: mode (this is done through an entry in inittab).
14
15//applet:/* Needs to be run by root or be suid root - needs to change uid and gid: */
16//applet:IF_SULOGIN(APPLET(sulogin, BB_DIR_SBIN, BB_SUID_DROP))
17
18//kbuild:lib-$(CONFIG_SULOGIN) += sulogin.o
7 19
8//usage:#define sulogin_trivial_usage 20//usage:#define sulogin_trivial_usage
9//usage: "[-t N] [TTY]" 21//usage: "[-t N] [TTY]"
diff --git a/loginutils/vlock.c b/loginutils/vlock.c
index 44b14e6bc..52ae607c9 100644
--- a/loginutils/vlock.c
+++ b/loginutils/vlock.c
@@ -13,7 +13,21 @@
13 * minimalistic vlock. 13 * minimalistic vlock.
14 */ 14 */
15/* Fixed by Erik Andersen to do passwords the tinylogin way... 15/* Fixed by Erik Andersen to do passwords the tinylogin way...
16 * It now works with md5, sha1, etc passwords. */ 16 * It now works with md5, sha1, etc passwords.
17 */
18//config:config VLOCK
19//config: bool "vlock"
20//config: default y
21//config: help
22//config: Build the "vlock" applet which allows you to lock (virtual) terminals.
23//config:
24//config: Note that Busybox binary must be setuid root for this applet to
25//config: work properly.
26
27//applet:/* Needs to be run by root or be suid root - needs to change uid and gid: */
28//applet:IF_VLOCK(APPLET(vlock, BB_DIR_USR_BIN, BB_SUID_REQUIRE))
29
30//kbuild:lib-$(CONFIG_VLOCK) += vlock.o
17 31
18//usage:#define vlock_trivial_usage 32//usage:#define vlock_trivial_usage
19//usage: "[-a]" 33//usage: "[-a]"
diff --git a/miscutils/hdparm.c b/miscutils/hdparm.c
index 9c486e7aa..8e201ac35 100644
--- a/miscutils/hdparm.c
+++ b/miscutils/hdparm.c
@@ -368,9 +368,6 @@ struct globals {
368#endif 368#endif
369} FIX_ALIASING; 369} FIX_ALIASING;
370#define G (*(struct globals*)&bb_common_bufsiz1) 370#define G (*(struct globals*)&bb_common_bufsiz1)
371struct BUG_G_too_big {
372 char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1];
373};
374#define get_identity (G.get_identity ) 371#define get_identity (G.get_identity )
375#define get_geom (G.get_geom ) 372#define get_geom (G.get_geom )
376#define do_flush (G.do_flush ) 373#define do_flush (G.do_flush )
@@ -433,7 +430,9 @@ struct BUG_G_too_big {
433#define hwif_data (G.hwif_data ) 430#define hwif_data (G.hwif_data )
434#define hwif_ctrl (G.hwif_ctrl ) 431#define hwif_ctrl (G.hwif_ctrl )
435#define hwif_irq (G.hwif_irq ) 432#define hwif_irq (G.hwif_irq )
436#define INIT_G() do { } while (0) 433#define INIT_G() do { \
434 BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
435} while (0)
437 436
438 437
439/* Busybox messages and functions */ 438/* Busybox messages and functions */
diff --git a/miscutils/taskset.c b/miscutils/taskset.c
index 2646e1dab..100b1d926 100644
--- a/miscutils/taskset.c
+++ b/miscutils/taskset.c
@@ -75,12 +75,10 @@ static char *from_cpuset(cpu_set_t *mask)
75#define TASKSET_PRINTF_MASK "%llx" 75#define TASKSET_PRINTF_MASK "%llx"
76static unsigned long long from_cpuset(cpu_set_t *mask) 76static unsigned long long from_cpuset(cpu_set_t *mask)
77{ 77{
78 struct BUG_CPU_SETSIZE_is_too_small {
79 char BUG_CPU_SETSIZE_is_too_small[
80 CPU_SETSIZE < sizeof(int) ? -1 : 1];
81 };
82 char *p = (void*)mask; 78 char *p = (void*)mask;
83 79
80 BUILD_BUG_ON(CPU_SETSIZE < sizeof(int));
81
84 /* Take the least significant bits. Careful! 82 /* Take the least significant bits. Careful!
85 * Consider both CPU_SETSIZE=4 and CPU_SETSIZE=1024 cases 83 * Consider both CPU_SETSIZE=4 and CPU_SETSIZE=1024 cases
86 */ 84 */
diff --git a/networking/Config.src b/networking/Config.src
index 43ccbf385..8c7417f86 100644
--- a/networking/Config.src
+++ b/networking/Config.src
@@ -554,6 +554,13 @@ config FEATURE_IP_RULE
554 help 554 help
555 Add support for rule commands to "ip". 555 Add support for rule commands to "ip".
556 556
557config FEATURE_IP_NEIGH
558 bool "ip neighbor"
559 default y
560 depends on IP
561 help
562 Add support for neighbor commands to "ip".
563
557config FEATURE_IP_SHORT_FORMS 564config FEATURE_IP_SHORT_FORMS
558 bool "Support short forms of ip commands" 565 bool "Support short forms of ip commands"
559 default y 566 default y
@@ -565,6 +572,7 @@ config FEATURE_IP_SHORT_FORMS
565 ip route -> iproute 572 ip route -> iproute
566 ip tunnel -> iptunnel 573 ip tunnel -> iptunnel
567 ip rule -> iprule 574 ip rule -> iprule
575 ip neigh -> ipneigh
568 576
569 Say N unless you desparately need the short form of the ip 577 Say N unless you desparately need the short form of the ip
570 object commands. 578 object commands.
@@ -604,6 +612,11 @@ config IPRULE
604 default y 612 default y
605 depends on FEATURE_IP_SHORT_FORMS && FEATURE_IP_RULE 613 depends on FEATURE_IP_SHORT_FORMS && FEATURE_IP_RULE
606 614
615config IPNEIGH
616 bool
617 default y
618 depends on FEATURE_IP_SHORT_FORMS && FEATURE_IP_NEIGH
619
607config IPCALC 620config IPCALC
608 bool "ipcalc" 621 bool "ipcalc"
609 default y 622 default y
diff --git a/networking/brctl.c b/networking/brctl.c
index c01a86998..b7320966a 100644
--- a/networking/brctl.c
+++ b/networking/brctl.c
@@ -128,7 +128,7 @@ static ALWAYS_INLINE void bb_strtotimeval(struct timeval *tv,
128# else 128# else
129 if (sscanf(time_str, "%lf", &secs) != 1) 129 if (sscanf(time_str, "%lf", &secs) != 1)
130# endif 130# endif
131 bb_error_msg_and_die(bb_msg_invalid_arg, time_str, "timespec"); 131 bb_error_msg_and_die(bb_msg_invalid_arg_to, time_str, "timespec");
132 tv->tv_sec = secs; 132 tv->tv_sec = secs;
133 tv->tv_usec = 1000000 * (secs - tv->tv_sec); 133 tv->tv_usec = 1000000 * (secs - tv->tv_sec);
134} 134}
@@ -205,7 +205,7 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
205 205
206 key = index_in_strings(keywords, *argv); 206 key = index_in_strings(keywords, *argv);
207 if (key == -1) /* no match found in keywords array, bail out. */ 207 if (key == -1) /* no match found in keywords array, bail out. */
208 bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name); 208 bb_error_msg_and_die(bb_msg_invalid_arg_to, *argv, applet_name);
209 argv++; 209 argv++;
210 fd = xsocket(AF_INET, SOCK_STREAM, 0); 210 fd = xsocket(AF_INET, SOCK_STREAM, 0);
211 211
@@ -299,7 +299,7 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
299 "1\0" "on\0" "y\0" "yes\0"; /* 4 .. 7 */ 299 "1\0" "on\0" "y\0" "yes\0"; /* 4 .. 7 */
300 int onoff = index_in_strings(no_yes, *argv); 300 int onoff = index_in_strings(no_yes, *argv);
301 if (onoff < 0) 301 if (onoff < 0)
302 bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name); 302 bb_error_msg_and_die(bb_msg_invalid_arg_to, *argv, applet_name);
303 onoff = (unsigned)onoff / 4; 303 onoff = (unsigned)onoff / 4;
304 arm_ioctl(args, BRCTL_SET_BRIDGE_STP_STATE, onoff, 0); 304 arm_ioctl(args, BRCTL_SET_BRIDGE_STP_STATE, onoff, 0);
305 goto fire; 305 goto fire;
@@ -332,7 +332,7 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
332 332
333 port = if_nametoindex(*argv++); 333 port = if_nametoindex(*argv++);
334 if (!port) 334 if (!port)
335 bb_error_msg_and_die(bb_msg_invalid_arg, *argv, "port"); 335 bb_error_msg_and_die(bb_msg_invalid_arg_to, *argv, "port");
336 memset(ifidx, 0, sizeof ifidx); 336 memset(ifidx, 0, sizeof ifidx);
337 arm_ioctl(args, BRCTL_GET_PORT_LIST, (unsigned long)ifidx, 337 arm_ioctl(args, BRCTL_GET_PORT_LIST, (unsigned long)ifidx,
338 MAX_PORTS); 338 MAX_PORTS);
diff --git a/networking/inetd.c b/networking/inetd.c
index dce5a0885..243165a07 100644
--- a/networking/inetd.c
+++ b/networking/inetd.c
@@ -329,9 +329,6 @@ struct globals {
329} FIX_ALIASING; 329} FIX_ALIASING;
330#define G (*(struct globals*)&bb_common_bufsiz1) 330#define G (*(struct globals*)&bb_common_bufsiz1)
331enum { LINE_SIZE = COMMON_BUFSIZE - offsetof(struct globals, line) }; 331enum { LINE_SIZE = COMMON_BUFSIZE - offsetof(struct globals, line) };
332struct BUG_G_too_big {
333 char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1];
334};
335#define rlim_ofile_cur (G.rlim_ofile_cur ) 332#define rlim_ofile_cur (G.rlim_ofile_cur )
336#define rlim_ofile (G.rlim_ofile ) 333#define rlim_ofile (G.rlim_ofile )
337#define serv_list (G.serv_list ) 334#define serv_list (G.serv_list )
@@ -352,6 +349,7 @@ struct BUG_G_too_big {
352#define allsock (G.allsock ) 349#define allsock (G.allsock )
353#define line (G.line ) 350#define line (G.line )
354#define INIT_G() do { \ 351#define INIT_G() do { \
352 BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
355 rlim_ofile_cur = OPEN_MAX; \ 353 rlim_ofile_cur = OPEN_MAX; \
356 global_queuelen = 128; \ 354 global_queuelen = 128; \
357 config_filename = "/etc/inetd.conf"; \ 355 config_filename = "/etc/inetd.conf"; \
diff --git a/networking/ip.c b/networking/ip.c
index d35345c36..ddfe74e9c 100644
--- a/networking/ip.c
+++ b/networking/ip.c
@@ -16,6 +16,7 @@
16//usage: IF_FEATURE_IP_ROUTE("route | ") 16//usage: IF_FEATURE_IP_ROUTE("route | ")
17//usage: IF_FEATURE_IP_LINK("link | ") 17//usage: IF_FEATURE_IP_LINK("link | ")
18//usage: IF_FEATURE_IP_TUNNEL("tunnel | ") 18//usage: IF_FEATURE_IP_TUNNEL("tunnel | ")
19//usage: IF_FEATURE_IP_NEIGH("neigh | ")
19//usage: IF_FEATURE_IP_RULE("rule") 20//usage: IF_FEATURE_IP_RULE("rule")
20//usage: "} {COMMAND}" 21//usage: "} {COMMAND}"
21//usage:#define ip_full_usage "\n\n" 22//usage:#define ip_full_usage "\n\n"
@@ -25,6 +26,7 @@
25//usage: IF_FEATURE_IP_ROUTE("route | ") 26//usage: IF_FEATURE_IP_ROUTE("route | ")
26//usage: IF_FEATURE_IP_LINK("link | ") 27//usage: IF_FEATURE_IP_LINK("link | ")
27//usage: IF_FEATURE_IP_TUNNEL("tunnel | ") 28//usage: IF_FEATURE_IP_TUNNEL("tunnel | ")
29//usage: IF_FEATURE_IP_NEIGH("neigh | ")
28//usage: IF_FEATURE_IP_RULE("rule") 30//usage: IF_FEATURE_IP_RULE("rule")
29//usage: "}\n" 31//usage: "}\n"
30//usage: "OPTIONS := { -f[amily] { inet | inet6 | link } | -o[neline] }" 32//usage: "OPTIONS := { -f[amily] { inet | inet6 | link } | -o[neline] }"
@@ -80,6 +82,11 @@
80//usage: " [mode { ipip | gre | sit }] [remote ADDR] [local ADDR]\n" 82//usage: " [mode { ipip | gre | sit }] [remote ADDR] [local ADDR]\n"
81//usage: " [[i|o]seq] [[i|o]key KEY] [[i|o]csum]\n" 83//usage: " [[i|o]seq] [[i|o]key KEY] [[i|o]csum]\n"
82//usage: " [ttl TTL] [tos TOS] [[no]pmtudisc] [dev PHYS_DEV]" 84//usage: " [ttl TTL] [tos TOS] [[no]pmtudisc] [dev PHYS_DEV]"
85//usage:
86//usage:#define ipneigh_trivial_usage
87//usage: "{ show | flush} [ to PREFIX ] [ dev DEV ] [ nud STATE ]"
88//usage:#define ipneigh_full_usage "\n\n"
89//usage: "ipneigh { show | flush} [ to PREFIX ] [ dev DEV ] [ nud STATE ]"
83 90
84#include "libbb.h" 91#include "libbb.h"
85 92
@@ -90,7 +97,8 @@
90 || ENABLE_FEATURE_IP_ROUTE \ 97 || ENABLE_FEATURE_IP_ROUTE \
91 || ENABLE_FEATURE_IP_LINK \ 98 || ENABLE_FEATURE_IP_LINK \
92 || ENABLE_FEATURE_IP_TUNNEL \ 99 || ENABLE_FEATURE_IP_TUNNEL \
93 || ENABLE_FEATURE_IP_RULE 100 || ENABLE_FEATURE_IP_RULE \
101 || ENABLE_FEATURE_IP_NEIGH
94 102
95static int FAST_FUNC ip_print_help(char **argv UNUSED_PARAM) 103static int FAST_FUNC ip_print_help(char **argv UNUSED_PARAM)
96{ 104{
@@ -140,6 +148,13 @@ int iptunnel_main(int argc UNUSED_PARAM, char **argv)
140 return ip_do(do_iptunnel, argv); 148 return ip_do(do_iptunnel, argv);
141} 149}
142#endif 150#endif
151#if ENABLE_FEATURE_IP_NEIGH
152int ipneigh_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
153int ipneigh_main(int argc UNUSED_PARAM, char **argv)
154{
155 return ip_do(do_ipneigh, argv);
156}
157#endif
143 158
144 159
145int ip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 160int ip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
@@ -153,6 +168,7 @@ int ip_main(int argc UNUSED_PARAM, char **argv)
153 IF_FEATURE_IP_TUNNEL("tunnel\0") 168 IF_FEATURE_IP_TUNNEL("tunnel\0")
154 IF_FEATURE_IP_TUNNEL("tunl\0") 169 IF_FEATURE_IP_TUNNEL("tunl\0")
155 IF_FEATURE_IP_RULE("rule\0") 170 IF_FEATURE_IP_RULE("rule\0")
171 IF_FEATURE_IP_NEIGH("neigh\0")
156 ; 172 ;
157 static const ip_func_ptr_t ip_func_ptrs[] = { 173 static const ip_func_ptr_t ip_func_ptrs[] = {
158 ip_print_help, 174 ip_print_help,
@@ -163,6 +179,7 @@ int ip_main(int argc UNUSED_PARAM, char **argv)
163 IF_FEATURE_IP_TUNNEL(do_iptunnel,) 179 IF_FEATURE_IP_TUNNEL(do_iptunnel,)
164 IF_FEATURE_IP_TUNNEL(do_iptunnel,) 180 IF_FEATURE_IP_TUNNEL(do_iptunnel,)
165 IF_FEATURE_IP_RULE(do_iprule,) 181 IF_FEATURE_IP_RULE(do_iprule,)
182 IF_FEATURE_IP_NEIGH(do_ipneigh,)
166 }; 183 };
167 ip_func_ptr_t ip_func; 184 ip_func_ptr_t ip_func;
168 int key; 185 int key;
diff --git a/networking/libiproute/Kbuild.src b/networking/libiproute/Kbuild.src
index 7c78f3c6a..c20e2fee8 100644
--- a/networking/libiproute/Kbuild.src
+++ b/networking/libiproute/Kbuild.src
@@ -64,3 +64,11 @@ lib-$(CONFIG_FEATURE_IP_RULE) += \
64 iprule.o \ 64 iprule.o \
65 rt_names.o \ 65 rt_names.o \
66 utils.o 66 utils.o
67
68lib-$(CONFIG_FEATURE_IP_NEIGH) += \
69 ip_parse_common_args.o \
70 ipneigh.o \
71 libnetlink.o \
72 ll_map.o \
73 rt_names.o \
74 utils.o
diff --git a/networking/libiproute/ip_common.h b/networking/libiproute/ip_common.h
index 30c7e595b..40171bed9 100644
--- a/networking/libiproute/ip_common.h
+++ b/networking/libiproute/ip_common.h
@@ -24,7 +24,7 @@ int FAST_FUNC ipaddr_list_or_flush(char **argv, int flush);
24int FAST_FUNC do_ipaddr(char **argv); 24int FAST_FUNC do_ipaddr(char **argv);
25int FAST_FUNC do_iproute(char **argv); 25int FAST_FUNC do_iproute(char **argv);
26int FAST_FUNC do_iprule(char **argv); 26int FAST_FUNC do_iprule(char **argv);
27//int FAST_FUNC do_ipneigh(char **argv); 27int FAST_FUNC do_ipneigh(char **argv);
28int FAST_FUNC do_iptunnel(char **argv); 28int FAST_FUNC do_iptunnel(char **argv);
29int FAST_FUNC do_iplink(char **argv); 29int FAST_FUNC do_iplink(char **argv);
30//int FAST_FUNC do_ipmonitor(char **argv); 30//int FAST_FUNC do_ipmonitor(char **argv);
diff --git a/networking/libiproute/ip_parse_common_args.c b/networking/libiproute/ip_parse_common_args.c
index 59c759b23..1a298f738 100644
--- a/networking/libiproute/ip_parse_common_args.c
+++ b/networking/libiproute/ip_parse_common_args.c
@@ -67,7 +67,7 @@ char** FAST_FUNC ip_parse_common_args(char **argv)
67 bb_show_usage(); 67 bb_show_usage();
68 arg = index_in_strings(families, *argv); 68 arg = index_in_strings(families, *argv);
69 if (arg < 0) 69 if (arg < 0)
70 invarg(*argv, "protocol family"); 70 invarg_1_to_2(*argv, "family");
71 /* now arg == 0, 1 or 2 */ 71 /* now arg == 0, 1 or 2 */
72 } else { 72 } else {
73 arg -= ARG_IPv4; 73 arg -= ARG_IPv4;
diff --git a/networking/libiproute/ipaddress.c b/networking/libiproute/ipaddress.c
index 8845cab91..5c975d8c5 100644
--- a/networking/libiproute/ipaddress.c
+++ b/networking/libiproute/ipaddress.c
@@ -214,8 +214,7 @@ static int FAST_FUNC print_addrinfo(const struct sockaddr_nl *who UNUSED_PARAM,
214{ 214{
215 struct ifaddrmsg *ifa = NLMSG_DATA(n); 215 struct ifaddrmsg *ifa = NLMSG_DATA(n);
216 int len = n->nlmsg_len; 216 int len = n->nlmsg_len;
217 struct rtattr * rta_tb[IFA_MAX+1]; 217 struct rtattr *rta_tb[IFA_MAX+1];
218 char abuf[256];
219 218
220 if (n->nlmsg_type != RTM_NEWADDR && n->nlmsg_type != RTM_DELADDR) 219 if (n->nlmsg_type != RTM_NEWADDR && n->nlmsg_type != RTM_DELADDR)
221 return 0; 220 return 0;
@@ -291,9 +290,9 @@ static int FAST_FUNC print_addrinfo(const struct sockaddr_nl *who UNUSED_PARAM,
291 printf(" family %d ", ifa->ifa_family); 290 printf(" family %d ", ifa->ifa_family);
292 291
293 if (rta_tb[IFA_LOCAL]) { 292 if (rta_tb[IFA_LOCAL]) {
294 fputs(rt_addr_n2a(ifa->ifa_family, 293 fputs(rt_addr_n2a(ifa->ifa_family, RTA_DATA(rta_tb[IFA_LOCAL])),
295 RTA_DATA(rta_tb[IFA_LOCAL]), 294 stdout
296 abuf, sizeof(abuf)), stdout); 295 );
297 296
298 if (rta_tb[IFA_ADDRESS] == NULL 297 if (rta_tb[IFA_ADDRESS] == NULL
299 || memcmp(RTA_DATA(rta_tb[IFA_ADDRESS]), RTA_DATA(rta_tb[IFA_LOCAL]), 4) == 0 298 || memcmp(RTA_DATA(rta_tb[IFA_ADDRESS]), RTA_DATA(rta_tb[IFA_LOCAL]), 4) == 0
@@ -301,25 +300,22 @@ static int FAST_FUNC print_addrinfo(const struct sockaddr_nl *who UNUSED_PARAM,
301 printf("/%d ", ifa->ifa_prefixlen); 300 printf("/%d ", ifa->ifa_prefixlen);
302 } else { 301 } else {
303 printf(" peer %s/%d ", 302 printf(" peer %s/%d ",
304 rt_addr_n2a(ifa->ifa_family, 303 rt_addr_n2a(ifa->ifa_family, RTA_DATA(rta_tb[IFA_ADDRESS])),
305 RTA_DATA(rta_tb[IFA_ADDRESS]), 304 ifa->ifa_prefixlen
306 abuf, sizeof(abuf)), 305 );
307 ifa->ifa_prefixlen);
308 } 306 }
309 } 307 }
310 308
311 if (rta_tb[IFA_BROADCAST]) { 309 if (rta_tb[IFA_BROADCAST]) {
312 printf("brd %s ", 310 printf("brd %s ",
313 rt_addr_n2a(ifa->ifa_family, 311 rt_addr_n2a(ifa->ifa_family,
314 RTA_DATA(rta_tb[IFA_BROADCAST]), 312 RTA_DATA(rta_tb[IFA_BROADCAST]))
315 abuf, sizeof(abuf))
316 ); 313 );
317 } 314 }
318 if (rta_tb[IFA_ANYCAST]) { 315 if (rta_tb[IFA_ANYCAST]) {
319 printf("any %s ", 316 printf("any %s ",
320 rt_addr_n2a(ifa->ifa_family, 317 rt_addr_n2a(ifa->ifa_family,
321 RTA_DATA(rta_tb[IFA_ANYCAST]), 318 RTA_DATA(rta_tb[IFA_ANYCAST]))
322 abuf, sizeof(abuf))
323 ); 319 );
324 } 320 }
325 printf("scope %s ", rtnl_rtscope_n2a(ifa->ifa_scope)); 321 printf("scope %s ", rtnl_rtscope_n2a(ifa->ifa_scope));
@@ -455,7 +451,7 @@ int FAST_FUNC ipaddr_list_or_flush(char **argv, int flush)
455 G_filter.scopemask = -1; 451 G_filter.scopemask = -1;
456 if (rtnl_rtscope_a2n(&scope, *argv)) { 452 if (rtnl_rtscope_a2n(&scope, *argv)) {
457 if (strcmp(*argv, "all") != 0) { 453 if (strcmp(*argv, "all") != 0) {
458 invarg(*argv, "scope"); 454 invarg_1_to_2(*argv, "scope");
459 } 455 }
460 scope = RT_SCOPE_NOWHERE; 456 scope = RT_SCOPE_NOWHERE;
461 G_filter.scopemask = 0; 457 G_filter.scopemask = 0;
@@ -669,7 +665,7 @@ static int ipaddr_modify(int cmd, int flags, char **argv)
669 } else if (arg == 5) { /* scope */ 665 } else if (arg == 5) { /* scope */
670 uint32_t scope = 0; 666 uint32_t scope = 0;
671 if (rtnl_rtscope_a2n(&scope, *argv)) { 667 if (rtnl_rtscope_a2n(&scope, *argv)) {
672 invarg(*argv, "scope"); 668 invarg_1_to_2(*argv, "scope");
673 } 669 }
674 req.ifa.ifa_scope = scope; 670 req.ifa.ifa_scope = scope;
675 scoped = 1; 671 scoped = 1;
@@ -751,7 +747,7 @@ int FAST_FUNC do_ipaddr(char **argv)
751 if (*argv) { 747 if (*argv) {
752 cmd = index_in_substrings(commands, *argv); 748 cmd = index_in_substrings(commands, *argv);
753 if (cmd < 0) 749 if (cmd < 0)
754 invarg(*argv, applet_name); 750 invarg_1_to_2(*argv, applet_name);
755 argv++; 751 argv++;
756 if (cmd <= 4) { 752 if (cmd <= 4) {
757 return ipaddr_modify( 753 return ipaddr_modify(
diff --git a/networking/libiproute/iplink.c b/networking/libiproute/iplink.c
index 5c27c2de3..ae3ef0ceb 100644
--- a/networking/libiproute/iplink.c
+++ b/networking/libiproute/iplink.c
@@ -349,7 +349,7 @@ static void vlan_parse_opt(char **argv, struct nlmsghdr *n, unsigned int size)
349 while (*argv) { 349 while (*argv) {
350 arg = index_in_substrings(keywords, *argv); 350 arg = index_in_substrings(keywords, *argv);
351 if (arg < 0) 351 if (arg < 0)
352 invarg(*argv, "type vlan"); 352 invarg_1_to_2(*argv, "type vlan");
353 353
354 NEXT_ARG(); 354 NEXT_ARG();
355 if (arg == ARG_id) { 355 if (arg == ARG_id) {
@@ -512,7 +512,7 @@ static int do_add_or_delete(char **argv, const unsigned rtm)
512 if (name_str) { 512 if (name_str) {
513 const size_t name_len = strlen(name_str) + 1; 513 const size_t name_len = strlen(name_str) + 1;
514 if (name_len < 2 || name_len > IFNAMSIZ) 514 if (name_len < 2 || name_len > IFNAMSIZ)
515 invarg(name_str, "name"); 515 invarg_1_to_2(name_str, "name");
516 addattr_l(&req.n, sizeof(req), IFLA_IFNAME, name_str, name_len); 516 addattr_l(&req.n, sizeof(req), IFLA_IFNAME, name_str, name_len);
517 } 517 }
518 if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) 518 if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
@@ -536,14 +536,14 @@ static int do_add_or_delete(char **argv, const unsigned rtm)
536 if (qlen != -1) 536 if (qlen != -1)
537 duparg("txqueuelen", *argv); 537 duparg("txqueuelen", *argv);
538 if (get_integer(&qlen, *argv, 0)) 538 if (get_integer(&qlen, *argv, 0))
539 invarg("Invalid \"txqueuelen\" value\n", *argv); 539 invarg_1_to_2(*argv, "txqueuelen");
540 addattr_l(&req->n, sizeof(*req), IFLA_TXQLEN, &qlen, 4); 540 addattr_l(&req->n, sizeof(*req), IFLA_TXQLEN, &qlen, 4);
541 } else if (strcmp(*argv, "mtu") == 0) { 541 } else if (strcmp(*argv, "mtu") == 0) {
542 NEXT_ARG(); 542 NEXT_ARG();
543 if (mtu != -1) 543 if (mtu != -1)
544 duparg("mtu", *argv); 544 duparg("mtu", *argv);
545 if (get_integer(&mtu, *argv, 0)) 545 if (get_integer(&mtu, *argv, 0))
546 invarg("Invalid \"mtu\" value\n", *argv); 546 invarg_1_to_2(*argv, "mtu");
547 addattr_l(&req->n, sizeof(*req), IFLA_MTU, &mtu, 4); 547 addattr_l(&req->n, sizeof(*req), IFLA_MTU, &mtu, 4);
548 } else if (strcmp(*argv, "netns") == 0) { 548 } else if (strcmp(*argv, "netns") == 0) {
549 NEXT_ARG(); 549 NEXT_ARG();
@@ -554,7 +554,7 @@ static int do_add_or_delete(char **argv, const unsigned rtm)
554 else if (get_integer(&netns, *argv, 0) == 0) 554 else if (get_integer(&netns, *argv, 0) == 0)
555 addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_PID, &netns, 4); 555 addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_PID, &netns, 4);
556 else 556 else
557 invarg("Invalid \"netns\" value\n", *argv); 557 invarg_1_to_2(*argv, "netns");
558 } else if (strcmp(*argv, "multicast") == 0) { 558 } else if (strcmp(*argv, "multicast") == 0) {
559 NEXT_ARG(); 559 NEXT_ARG();
560 req->i.ifi_change |= IFF_MULTICAST; 560 req->i.ifi_change |= IFF_MULTICAST;
@@ -604,7 +604,7 @@ static int do_add_or_delete(char **argv, const unsigned rtm)
604 struct rtattr *vflist; 604 struct rtattr *vflist;
605 NEXT_ARG(); 605 NEXT_ARG();
606 if (get_integer(&vf, *argv, 0)) { 606 if (get_integer(&vf, *argv, 0)) {
607 invarg("Invalid \"vf\" value\n", *argv); 607 invarg_1_to_2(*argv, "vf");
608 } 608 }
609 vflist = addattr_nest(&req->n, sizeof(*req), 609 vflist = addattr_nest(&req->n, sizeof(*req),
610 IFLA_VFINFO_LIST); 610 IFLA_VFINFO_LIST);
@@ -617,7 +617,7 @@ static int do_add_or_delete(char **argv, const unsigned rtm)
617 NEXT_ARG(); 617 NEXT_ARG();
618 ifindex = ll_name_to_index(*argv); 618 ifindex = ll_name_to_index(*argv);
619 if (!ifindex) 619 if (!ifindex)
620 invarg("Device does not exist\n", *argv); 620 invarg_1_to_2(*argv, "master");
621 addattr_l(&req->n, sizeof(*req), IFLA_MASTER, 621 addattr_l(&req->n, sizeof(*req), IFLA_MASTER,
622 &ifindex, 4); 622 &ifindex, 4);
623 } else if (matches(*argv, "nomaster") == 0) { 623 } else if (matches(*argv, "nomaster") == 0) {
@@ -644,28 +644,27 @@ static int do_add_or_delete(char **argv, const unsigned rtm)
644 if (*group != -1) 644 if (*group != -1)
645 duparg("group", *argv); 645 duparg("group", *argv);
646 if (rtnl_group_a2n(group, *argv)) 646 if (rtnl_group_a2n(group, *argv))
647 invarg("Invalid \"group\" value\n", *argv); 647 invarg_1_to_2(*argv, "group");
648 } else if (strcmp(*argv, "mode") == 0) { 648 } else if (strcmp(*argv, "mode") == 0) {
649 int mode; 649 int mode;
650 NEXT_ARG(); 650 NEXT_ARG();
651 mode = get_link_mode(*argv); 651 mode = get_link_mode(*argv);
652 if (mode < 0) 652 if (mode < 0)
653 invarg("Invalid link mode\n", *argv); 653 invarg_1_to_2(*argv, "mode");
654 addattr8(&req->n, sizeof(*req), IFLA_LINKMODE, mode); 654 addattr8(&req->n, sizeof(*req), IFLA_LINKMODE, mode);
655 } else if (strcmp(*argv, "state") == 0) { 655 } else if (strcmp(*argv, "state") == 0) {
656 int state; 656 int state;
657 NEXT_ARG(); 657 NEXT_ARG();
658 state = get_operstate(*argv); 658 state = get_operstate(*argv);
659 if (state < 0) 659 if (state < 0)
660 invarg("Invalid operstate\n", *argv); 660 invarg_1_to_2(*argv, "state");
661
662 addattr8(&req->n, sizeof(*req), IFLA_OPERSTATE, state); 661 addattr8(&req->n, sizeof(*req), IFLA_OPERSTATE, state);
663 } else if (matches(*argv, "numtxqueues") == 0) { 662 } else if (matches(*argv, "numtxqueues") == 0) {
664 NEXT_ARG(); 663 NEXT_ARG();
665 if (numtxqueues != -1) 664 if (numtxqueues != -1)
666 duparg("numtxqueues", *argv); 665 duparg("numtxqueues", *argv);
667 if (get_integer(&numtxqueues, *argv, 0)) 666 if (get_integer(&numtxqueues, *argv, 0))
668 invarg("Invalid \"numtxqueues\" value\n", *argv); 667 invarg_1_to_2(*argv, "numtxqueues");
669 addattr_l(&req->n, sizeof(*req), IFLA_NUM_TX_QUEUES, 668 addattr_l(&req->n, sizeof(*req), IFLA_NUM_TX_QUEUES,
670 &numtxqueues, 4); 669 &numtxqueues, 4);
671 } else if (matches(*argv, "numrxqueues") == 0) { 670 } else if (matches(*argv, "numrxqueues") == 0) {
@@ -673,7 +672,7 @@ static int do_add_or_delete(char **argv, const unsigned rtm)
673 if (numrxqueues != -1) 672 if (numrxqueues != -1)
674 duparg("numrxqueues", *argv); 673 duparg("numrxqueues", *argv);
675 if (get_integer(&numrxqueues, *argv, 0)) 674 if (get_integer(&numrxqueues, *argv, 0))
676 invarg("Invalid \"numrxqueues\" value\n", *argv); 675 invarg_1_to_2(*argv, "numrxqueues");
677 addattr_l(&req->n, sizeof(*req), IFLA_NUM_RX_QUEUES, 676 addattr_l(&req->n, sizeof(*req), IFLA_NUM_RX_QUEUES,
678 &numrxqueues, 4); 677 &numrxqueues, 4);
679 } 678 }
@@ -687,7 +686,7 @@ int FAST_FUNC do_iplink(char **argv)
687 if (*argv) { 686 if (*argv) {
688 int key = index_in_substrings(keywords, *argv); 687 int key = index_in_substrings(keywords, *argv);
689 if (key < 0) /* invalid argument */ 688 if (key < 0) /* invalid argument */
690 invarg(*argv, applet_name); 689 invarg_1_to_2(*argv, applet_name);
691 argv++; 690 argv++;
692 if (key <= 1) /* add/delete */ 691 if (key <= 1) /* add/delete */
693 return do_add_or_delete(argv, key ? RTM_DELLINK : RTM_NEWLINK); 692 return do_add_or_delete(argv, key ? RTM_DELLINK : RTM_NEWLINK);
diff --git a/networking/libiproute/ipneigh.c b/networking/libiproute/ipneigh.c
new file mode 100644
index 000000000..179505c2d
--- /dev/null
+++ b/networking/libiproute/ipneigh.c
@@ -0,0 +1,353 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
4 *
5 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
6 *
7 * Ported to Busybox by: Curt Brune <curt@cumulusnetworks.com>
8 */
9
10#include "ip_common.h" /* #include "libbb.h" is inside */
11#include "rt_names.h"
12#include "utils.h"
13#include <linux/neighbour.h>
14#include <net/if_arp.h>
15
16//static int xshow_stats = 3;
17enum { xshow_stats = 3 };
18
19static inline uint32_t rta_getattr_u32(const struct rtattr *rta)
20{
21 return *(uint32_t *)RTA_DATA(rta);
22}
23
24#ifndef RTAX_RTTVAR
25#define RTAX_RTTVAR RTAX_HOPS
26#endif
27
28
29struct filter_t {
30 int family;
31 int index;
32 int state;
33 int unused_only;
34 inet_prefix pfx;
35 int flushed;
36 char *flushb;
37 int flushp;
38 int flushe;
39 struct rtnl_handle *rth;
40} FIX_ALIASING;
41typedef struct filter_t filter_t;
42
43#define G_filter (*(filter_t*)&bb_common_bufsiz1)
44
45static int flush_update(void)
46{
47 if (rtnl_send(G_filter.rth, G_filter.flushb, G_filter.flushp) < 0) {
48 bb_perror_msg("can't send flush request");
49 return -1;
50 }
51 G_filter.flushp = 0;
52 return 0;
53}
54
55static unsigned nud_state_a2n(char *arg)
56{
57 static const char keywords[] ALIGN1 =
58 /* "ip neigh show/flush" parameters: */
59 "permanent\0" "reachable\0" "noarp\0" "none\0"
60 "stale\0" "incomplete\0" "delay\0" "probe\0"
61 "failed\0"
62 ;
63 static uint8_t nuds[] = {
64 NUD_PERMANENT,NUD_REACHABLE, NUD_NOARP,NUD_NONE,
65 NUD_STALE, NUD_INCOMPLETE,NUD_DELAY,NUD_PROBE,
66 NUD_FAILED
67 };
68 int id;
69
70 BUILD_BUG_ON(
71 (NUD_PERMANENT|NUD_REACHABLE| NUD_NOARP|NUD_NONE|
72 NUD_STALE| NUD_INCOMPLETE|NUD_DELAY|NUD_PROBE|
73 NUD_FAILED) > 0xff
74 );
75
76 id = index_in_substrings(keywords, arg);
77 if (id < 0)
78 bb_error_msg_and_die(bb_msg_invalid_arg_to, arg, "nud state");
79 return nuds[id];
80}
81
82#ifndef NDA_RTA
83#define NDA_RTA(r) \
84 ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))
85#endif
86
87
88static int FAST_FUNC print_neigh(const struct sockaddr_nl *who UNUSED_PARAM,
89 struct nlmsghdr *n, void *arg UNUSED_PARAM)
90{
91 struct ndmsg *r = NLMSG_DATA(n);
92 int len = n->nlmsg_len;
93 struct rtattr *tb[NDA_MAX+1];
94
95 if (n->nlmsg_type != RTM_NEWNEIGH && n->nlmsg_type != RTM_DELNEIGH) {
96 bb_error_msg_and_die("not RTM_NEWNEIGH: %08x %08x %08x",
97 n->nlmsg_len, n->nlmsg_type,
98 n->nlmsg_flags);
99 }
100 len -= NLMSG_LENGTH(sizeof(*r));
101 if (len < 0) {
102 bb_error_msg_and_die("BUG: wrong nlmsg len %d", len);
103 }
104
105 if (G_filter.flushb && n->nlmsg_type != RTM_NEWNEIGH)
106 return 0;
107
108 if (G_filter.family && G_filter.family != r->ndm_family)
109 return 0;
110 if (G_filter.index && G_filter.index != r->ndm_ifindex)
111 return 0;
112 if (!(G_filter.state&r->ndm_state) &&
113 !(r->ndm_flags & NTF_PROXY) &&
114 (r->ndm_state || !(G_filter.state & 0x100)) &&
115 (r->ndm_family != AF_DECnet))
116 return 0;
117
118 parse_rtattr(tb, NDA_MAX, NDA_RTA(r), n->nlmsg_len - NLMSG_LENGTH(sizeof(*r)));
119
120 if (tb[NDA_DST]) {
121 if (G_filter.pfx.family) {
122 inet_prefix dst;
123 memset(&dst, 0, sizeof(dst));
124 dst.family = r->ndm_family;
125 memcpy(&dst.data, RTA_DATA(tb[NDA_DST]), RTA_PAYLOAD(tb[NDA_DST]));
126 if (inet_addr_match(&dst, &G_filter.pfx, G_filter.pfx.bitlen))
127 return 0;
128 }
129 }
130 if (G_filter.unused_only && tb[NDA_CACHEINFO]) {
131 struct nda_cacheinfo *ci = RTA_DATA(tb[NDA_CACHEINFO]);
132 if (ci->ndm_refcnt)
133 return 0;
134 }
135
136 if (G_filter.flushb) {
137 struct nlmsghdr *fn;
138 if (NLMSG_ALIGN(G_filter.flushp) + n->nlmsg_len > G_filter.flushe) {
139 if (flush_update())
140 return -1;
141 }
142 fn = (struct nlmsghdr*)(G_filter.flushb + NLMSG_ALIGN(G_filter.flushp));
143 memcpy(fn, n, n->nlmsg_len);
144 fn->nlmsg_type = RTM_DELNEIGH;
145 fn->nlmsg_flags = NLM_F_REQUEST;
146 fn->nlmsg_seq = ++(G_filter.rth->seq);
147 G_filter.flushp = (((char*)fn) + n->nlmsg_len) - G_filter.flushb;
148 G_filter.flushed++;
149 if (xshow_stats < 2)
150 return 0;
151 }
152
153 if (tb[NDA_DST]) {
154 printf("%s ",
155 format_host(r->ndm_family,
156 RTA_PAYLOAD(tb[NDA_DST]),
157 RTA_DATA(tb[NDA_DST]))
158 );
159 }
160 if (!G_filter.index && r->ndm_ifindex)
161 printf("dev %s ", ll_index_to_name(r->ndm_ifindex));
162 if (tb[NDA_LLADDR]) {
163 SPRINT_BUF(b1);
164 printf("lladdr %s", ll_addr_n2a(RTA_DATA(tb[NDA_LLADDR]),
165 RTA_PAYLOAD(tb[NDA_LLADDR]),
166 ARPHRD_ETHER,
167 b1, sizeof(b1)));
168 }
169 if (r->ndm_flags & NTF_ROUTER) {
170 printf(" router");
171 }
172 if (r->ndm_flags & NTF_PROXY) {
173 printf(" proxy");
174 }
175 if (tb[NDA_CACHEINFO] && xshow_stats) {
176 struct nda_cacheinfo *ci = RTA_DATA(tb[NDA_CACHEINFO]);
177 int hz = get_hz();
178
179 if (ci->ndm_refcnt)
180 printf(" ref %d", ci->ndm_refcnt);
181 printf(" used %d/%d/%d", ci->ndm_used/hz,
182 ci->ndm_confirmed/hz, ci->ndm_updated/hz);
183 }
184
185 if (tb[NDA_PROBES] && xshow_stats) {
186 uint32_t p = rta_getattr_u32(tb[NDA_PROBES]);
187 printf(" probes %u", p);
188 }
189
190 /*if (r->ndm_state)*/ {
191 int nud = r->ndm_state;
192 char c = ' ';
193#define PRINT_FLAG(f) \
194 if (nud & NUD_##f) { \
195 printf("%c"#f, c); \
196 c = ','; \
197 }
198 PRINT_FLAG(INCOMPLETE);
199 PRINT_FLAG(REACHABLE);
200 PRINT_FLAG(STALE);
201 PRINT_FLAG(DELAY);
202 PRINT_FLAG(PROBE);
203 PRINT_FLAG(FAILED);
204 PRINT_FLAG(NOARP);
205 PRINT_FLAG(PERMANENT);
206#undef PRINT_FLAG
207 }
208 bb_putchar('\n');
209
210 return 0;
211}
212
213static void ipneigh_reset_filter(void)
214{
215 memset(&G_filter, 0, sizeof(G_filter));
216 G_filter.state = ~0;
217}
218
219#define MAX_ROUNDS 10
220/* Return value becomes exitcode. It's okay to not return at all */
221static int FAST_FUNC ipneigh_list_or_flush(char **argv, int flush)
222{
223 static const char keywords[] ALIGN1 =
224 /* "ip neigh show/flush" parameters: */
225 "to\0" "dev\0" "nud\0";
226 enum {
227 KW_to, KW_dev, KW_nud,
228 };
229 struct rtnl_handle rth;
230 struct ndmsg ndm = { 0 };
231 char *filter_dev = NULL;
232 int state_given = 0;
233 int arg;
234
235 ipneigh_reset_filter();
236
237 if (flush && !*argv)
238 bb_error_msg_and_die(bb_msg_requires_arg, "\"ip neigh flush\"");
239
240 if (!G_filter.family)
241 G_filter.family = preferred_family;
242
243 G_filter.state = (flush) ?
244 ~(NUD_PERMANENT|NUD_NOARP) : 0xFF & ~NUD_NOARP;
245
246 while (*argv) {
247 arg = index_in_substrings(keywords, *argv);
248 if (arg == KW_dev) {
249 NEXT_ARG();
250 filter_dev = *argv;
251 } else if (arg == KW_nud) {
252 unsigned state;
253 NEXT_ARG();
254 if (!state_given) {
255 state_given = 1;
256 G_filter.state = 0;
257 }
258 if (strcmp(*argv, "all") == 0) {
259 state = ~0;
260 if (flush)
261 state &= ~NUD_NOARP;
262 } else {
263 state = nud_state_a2n(*argv);
264 }
265 if (state == 0)
266 state = 0x100;
267 G_filter.state |= state;
268 } else {
269 if (arg == KW_to) {
270 NEXT_ARG();
271 }
272 get_prefix(&G_filter.pfx, *argv, G_filter.family);
273 if (G_filter.family == AF_UNSPEC)
274 G_filter.family = G_filter.pfx.family;
275 }
276 argv++;
277 }
278
279 xrtnl_open(&rth);
280 ll_init_map(&rth);
281
282 if (filter_dev) {
283 G_filter.index = xll_name_to_index(filter_dev);
284 if (G_filter.index == 0) {
285 bb_error_msg_and_die("can't find device '%s'", filter_dev);
286 }
287 }
288
289 if (flush) {
290 int round = 0;
291 char flushb[4096-512];
292 G_filter.flushb = flushb;
293 G_filter.flushp = 0;
294 G_filter.flushe = sizeof(flushb);
295 G_filter.state &= ~NUD_FAILED;
296 G_filter.rth = &rth;
297
298 while (round < MAX_ROUNDS) {
299 if (xrtnl_wilddump_request(&rth, G_filter.family, RTM_GETNEIGH) < 0) {
300 bb_perror_msg_and_die("can't send dump request");
301 }
302 G_filter.flushed = 0;
303 if (xrtnl_dump_filter(&rth, print_neigh, NULL) < 0) {
304 bb_perror_msg_and_die("flush terminated");
305 }
306 if (G_filter.flushed == 0) {
307 if (round == 0)
308 puts("Nothing to flush");
309 else
310 printf("*** Flush is complete after %d round(s) ***\n", round);
311 return 0;
312 }
313 round++;
314 if (flush_update() < 0)
315 xfunc_die();
316 printf("\n*** Round %d, deleting %d entries ***\n", round, G_filter.flushed);
317 }
318 bb_error_msg_and_die("*** Flush not complete bailing out after %d rounds", MAX_ROUNDS);
319 }
320
321 ndm.ndm_family = G_filter.family;
322
323 if (rtnl_dump_request(&rth, RTM_GETNEIGH, &ndm, sizeof(struct ndmsg)) < 0) {
324 bb_perror_msg_and_die("can't send dump request");
325 }
326
327 if (xrtnl_dump_filter(&rth, print_neigh, NULL) < 0) {
328 bb_error_msg_and_die("dump terminated");
329 }
330
331 return 0;
332}
333
334/* Return value becomes exitcode. It's okay to not return at all */
335int FAST_FUNC do_ipneigh(char **argv)
336{
337 static const char ip_neigh_commands[] ALIGN1 =
338 /*0-1*/ "show\0" "flush\0";
339 int command_num;
340
341 if (!*argv)
342 return ipneigh_list_or_flush(argv, 0);
343
344 command_num = index_in_substrings(ip_neigh_commands, *argv);
345 switch (command_num) {
346 case 0: /* show */
347 return ipneigh_list_or_flush(argv + 1, 0);
348 case 1: /* flush */
349 return ipneigh_list_or_flush(argv + 1, 1);
350 }
351 invarg_1_to_2(*argv, applet_name);
352 return 1;
353}
diff --git a/networking/libiproute/iproute.c b/networking/libiproute/iproute.c
index 6ecd5f719..d232ee6fd 100644
--- a/networking/libiproute/iproute.c
+++ b/networking/libiproute/iproute.c
@@ -55,35 +55,12 @@ static int flush_update(void)
55 return 0; 55 return 0;
56} 56}
57 57
58static unsigned get_hz(void)
59{
60 static unsigned hz_internal;
61 FILE *fp;
62
63 if (hz_internal)
64 return hz_internal;
65
66 fp = fopen_for_read("/proc/net/psched");
67 if (fp) {
68 unsigned nom, denom;
69
70 if (fscanf(fp, "%*08x%*08x%08x%08x", &nom, &denom) == 2)
71 if (nom == 1000000)
72 hz_internal = denom;
73 fclose(fp);
74 }
75 if (!hz_internal)
76 hz_internal = bb_clk_tck();
77 return hz_internal;
78}
79
80static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM, 58static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
81 struct nlmsghdr *n, void *arg UNUSED_PARAM) 59 struct nlmsghdr *n, void *arg UNUSED_PARAM)
82{ 60{
83 struct rtmsg *r = NLMSG_DATA(n); 61 struct rtmsg *r = NLMSG_DATA(n);
84 int len = n->nlmsg_len; 62 int len = n->nlmsg_len;
85 struct rtattr *tb[RTA_MAX+1]; 63 struct rtattr *tb[RTA_MAX+1];
86 char abuf[256];
87 inet_prefix dst; 64 inet_prefix dst;
88 inet_prefix src; 65 inet_prefix src;
89 int host_len = -1; 66 int host_len = -1;
@@ -217,7 +194,7 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
217 194
218 if (NLMSG_ALIGN(G_filter.flushp) + n->nlmsg_len > G_filter.flushe) { 195 if (NLMSG_ALIGN(G_filter.flushp) + n->nlmsg_len > G_filter.flushe) {
219 if (flush_update()) 196 if (flush_update())
220 bb_error_msg_and_die("flush"); 197 xfunc_die();
221 } 198 }
222 fn = (void*)(G_filter.flushb + NLMSG_ALIGN(G_filter.flushp)); 199 fn = (void*)(G_filter.flushb + NLMSG_ALIGN(G_filter.flushp));
223 memcpy(fn, n, n->nlmsg_len); 200 memcpy(fn, n, n->nlmsg_len);
@@ -240,17 +217,15 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
240 217
241 if (tb[RTA_DST]) { 218 if (tb[RTA_DST]) {
242 if (r->rtm_dst_len != host_len) { 219 if (r->rtm_dst_len != host_len) {
243 printf("%s/%u ", rt_addr_n2a(r->rtm_family, 220 printf("%s/%u ",
244 RTA_DATA(tb[RTA_DST]), 221 rt_addr_n2a(r->rtm_family, RTA_DATA(tb[RTA_DST])),
245 abuf, sizeof(abuf)), 222 r->rtm_dst_len
246 r->rtm_dst_len 223 );
247 );
248 } else { 224 } else {
249 printf("%s ", format_host(r->rtm_family, 225 printf("%s ", format_host(r->rtm_family,
250 RTA_PAYLOAD(tb[RTA_DST]), 226 RTA_PAYLOAD(tb[RTA_DST]),
251 RTA_DATA(tb[RTA_DST]), 227 RTA_DATA(tb[RTA_DST]))
252 abuf, sizeof(abuf)) 228 );
253 );
254 } 229 }
255 } else if (r->rtm_dst_len) { 230 } else if (r->rtm_dst_len) {
256 printf("0/%d ", r->rtm_dst_len); 231 printf("0/%d ", r->rtm_dst_len);
@@ -259,17 +234,15 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
259 } 234 }
260 if (tb[RTA_SRC]) { 235 if (tb[RTA_SRC]) {
261 if (r->rtm_src_len != host_len) { 236 if (r->rtm_src_len != host_len) {
262 printf("from %s/%u ", rt_addr_n2a(r->rtm_family, 237 printf("from %s/%u ",
263 RTA_DATA(tb[RTA_SRC]), 238 rt_addr_n2a(r->rtm_family, RTA_DATA(tb[RTA_SRC])),
264 abuf, sizeof(abuf)), 239 r->rtm_src_len
265 r->rtm_src_len 240 );
266 );
267 } else { 241 } else {
268 printf("from %s ", format_host(r->rtm_family, 242 printf("from %s ", format_host(r->rtm_family,
269 RTA_PAYLOAD(tb[RTA_SRC]), 243 RTA_PAYLOAD(tb[RTA_SRC]),
270 RTA_DATA(tb[RTA_SRC]), 244 RTA_DATA(tb[RTA_SRC]))
271 abuf, sizeof(abuf)) 245 );
272 );
273 } 246 }
274 } else if (r->rtm_src_len) { 247 } else if (r->rtm_src_len) {
275 printf("from 0/%u ", r->rtm_src_len); 248 printf("from 0/%u ", r->rtm_src_len);
@@ -277,8 +250,8 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
277 if (tb[RTA_GATEWAY] && G_filter.rvia.bitlen != host_len) { 250 if (tb[RTA_GATEWAY] && G_filter.rvia.bitlen != host_len) {
278 printf("via %s ", format_host(r->rtm_family, 251 printf("via %s ", format_host(r->rtm_family,
279 RTA_PAYLOAD(tb[RTA_GATEWAY]), 252 RTA_PAYLOAD(tb[RTA_GATEWAY]),
280 RTA_DATA(tb[RTA_GATEWAY]), 253 RTA_DATA(tb[RTA_GATEWAY]))
281 abuf, sizeof(abuf))); 254 );
282 } 255 }
283 if (tb[RTA_OIF]) { 256 if (tb[RTA_OIF]) {
284 printf("dev %s ", ll_index_to_name(*(int*)RTA_DATA(tb[RTA_OIF]))); 257 printf("dev %s ", ll_index_to_name(*(int*)RTA_DATA(tb[RTA_OIF])));
@@ -291,8 +264,7 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
291 and symbolic name will not be useful. 264 and symbolic name will not be useful.
292 */ 265 */
293 printf(" src %s ", rt_addr_n2a(r->rtm_family, 266 printf(" src %s ", rt_addr_n2a(r->rtm_family,
294 RTA_DATA(tb[RTA_PREFSRC]), 267 RTA_DATA(tb[RTA_PREFSRC])));
295 abuf, sizeof(abuf)));
296 } 268 }
297 if (tb[RTA_PRIORITY]) { 269 if (tb[RTA_PRIORITY]) {
298 printf(" metric %d ", *(uint32_t*)RTA_DATA(tb[RTA_PRIORITY])); 270 printf(" metric %d ", *(uint32_t*)RTA_DATA(tb[RTA_PRIORITY]));
@@ -425,7 +397,7 @@ IF_FEATURE_IP_RULE(ARG_table,)
425 uint32_t prot; 397 uint32_t prot;
426 NEXT_ARG(); 398 NEXT_ARG();
427 if (rtnl_rtprot_a2n(&prot, *argv)) 399 if (rtnl_rtprot_a2n(&prot, *argv))
428 invarg(*argv, "protocol"); 400 invarg_1_to_2(*argv, "protocol");
429 req.r.rtm_protocol = prot; 401 req.r.rtm_protocol = prot;
430 ok |= proto_ok; 402 ok |= proto_ok;
431#if ENABLE_FEATURE_IP_RULE 403#if ENABLE_FEATURE_IP_RULE
@@ -433,7 +405,7 @@ IF_FEATURE_IP_RULE(ARG_table,)
433 uint32_t tid; 405 uint32_t tid;
434 NEXT_ARG(); 406 NEXT_ARG();
435 if (rtnl_rttable_a2n(&tid, *argv)) 407 if (rtnl_rttable_a2n(&tid, *argv))
436 invarg(*argv, "table"); 408 invarg_1_to_2(*argv, "table");
437 req.r.rtm_table = tid; 409 req.r.rtm_table = tid;
438#endif 410#endif
439 } else if (arg == ARG_dev || arg == ARG_oif) { 411 } else if (arg == ARG_dev || arg == ARG_oif) {
@@ -619,7 +591,7 @@ static int iproute_list_or_flush(char **argv, int flush)
619 //G_filter.protocolmask = -1; 591 //G_filter.protocolmask = -1;
620 if (rtnl_rtprot_a2n(&prot, *argv)) { 592 if (rtnl_rtprot_a2n(&prot, *argv)) {
621 if (index_in_strings(keywords, *argv) != KW_all) 593 if (index_in_strings(keywords, *argv) != KW_all)
622 invarg(*argv, "protocol"); 594 invarg_1_to_2(*argv, "protocol");
623 prot = 0; 595 prot = 0;
624 //G_filter.protocolmask = 0; 596 //G_filter.protocolmask = 0;
625 } 597 }
@@ -644,10 +616,10 @@ static int iproute_list_or_flush(char **argv, int flush)
644#if ENABLE_FEATURE_IP_RULE 616#if ENABLE_FEATURE_IP_RULE
645 uint32_t tid; 617 uint32_t tid;
646 if (rtnl_rttable_a2n(&tid, *argv)) 618 if (rtnl_rttable_a2n(&tid, *argv))
647 invarg(*argv, "table"); 619 invarg_1_to_2(*argv, "table");
648 G_filter.tb = tid; 620 G_filter.tb = tid;
649#else 621#else
650 invarg(*argv, "table"); 622 invarg_1_to_2(*argv, "table");
651#endif 623#endif
652 } 624 }
653 } else if (arg == KW_cache) { 625 } else if (arg == KW_cache) {
@@ -954,7 +926,7 @@ int FAST_FUNC do_iproute(char **argv)
954 case 11: /* flush */ 926 case 11: /* flush */
955 return iproute_list_or_flush(argv+1, 1); 927 return iproute_list_or_flush(argv+1, 1);
956 default: 928 default:
957 bb_error_msg_and_die("unknown command %s", *argv); 929 invarg_1_to_2(*argv, applet_name);
958 } 930 }
959 931
960 return iproute_modify(cmd, flags, argv+1); 932 return iproute_modify(cmd, flags, argv+1);
diff --git a/networking/libiproute/iprule.c b/networking/libiproute/iprule.c
index 774a3e220..dba64346f 100644
--- a/networking/libiproute/iprule.c
+++ b/networking/libiproute/iprule.c
@@ -44,7 +44,6 @@ static int FAST_FUNC print_rule(const struct sockaddr_nl *who UNUSED_PARAM,
44 int len = n->nlmsg_len; 44 int len = n->nlmsg_len;
45 int host_len = -1; 45 int host_len = -1;
46 struct rtattr * tb[RTA_MAX+1]; 46 struct rtattr * tb[RTA_MAX+1];
47 char abuf[256];
48 47
49 if (n->nlmsg_type != RTM_NEWRULE) 48 if (n->nlmsg_type != RTM_NEWRULE)
50 return 0; 49 return 0;
@@ -71,16 +70,14 @@ static int FAST_FUNC print_rule(const struct sockaddr_nl *who UNUSED_PARAM,
71 printf("from "); 70 printf("from ");
72 if (tb[RTA_SRC]) { 71 if (tb[RTA_SRC]) {
73 if (r->rtm_src_len != host_len) { 72 if (r->rtm_src_len != host_len) {
74 printf("%s/%u", rt_addr_n2a(r->rtm_family, 73 printf("%s/%u",
75 RTA_DATA(tb[RTA_SRC]), 74 rt_addr_n2a(r->rtm_family, RTA_DATA(tb[RTA_SRC])),
76 abuf, sizeof(abuf)),
77 r->rtm_src_len 75 r->rtm_src_len
78 ); 76 );
79 } else { 77 } else {
80 fputs(format_host(r->rtm_family, 78 fputs(format_host(r->rtm_family,
81 RTA_PAYLOAD(tb[RTA_SRC]), 79 RTA_PAYLOAD(tb[RTA_SRC]),
82 RTA_DATA(tb[RTA_SRC]), 80 RTA_DATA(tb[RTA_SRC])),
83 abuf, sizeof(abuf)),
84 stdout 81 stdout
85 ); 82 );
86 } 83 }
@@ -94,15 +91,13 @@ static int FAST_FUNC print_rule(const struct sockaddr_nl *who UNUSED_PARAM,
94 if (tb[RTA_DST]) { 91 if (tb[RTA_DST]) {
95 if (r->rtm_dst_len != host_len) { 92 if (r->rtm_dst_len != host_len) {
96 printf("to %s/%u ", rt_addr_n2a(r->rtm_family, 93 printf("to %s/%u ", rt_addr_n2a(r->rtm_family,
97 RTA_DATA(tb[RTA_DST]), 94 RTA_DATA(tb[RTA_DST])),
98 abuf, sizeof(abuf)),
99 r->rtm_dst_len 95 r->rtm_dst_len
100 ); 96 );
101 } else { 97 } else {
102 printf("to %s ", format_host(r->rtm_family, 98 printf("to %s ", format_host(r->rtm_family,
103 RTA_PAYLOAD(tb[RTA_DST]), 99 RTA_PAYLOAD(tb[RTA_DST]),
104 RTA_DATA(tb[RTA_DST]), 100 RTA_DATA(tb[RTA_DST])));
105 abuf, sizeof(abuf)));
106 } 101 }
107 } else if (r->rtm_dst_len) { 102 } else if (r->rtm_dst_len) {
108 printf("to 0/%d ", r->rtm_dst_len); 103 printf("to 0/%d ", r->rtm_dst_len);
@@ -139,8 +134,8 @@ static int FAST_FUNC print_rule(const struct sockaddr_nl *who UNUSED_PARAM,
139 printf("map-to %s ", 134 printf("map-to %s ",
140 format_host(r->rtm_family, 135 format_host(r->rtm_family,
141 RTA_PAYLOAD(tb[RTA_GATEWAY]), 136 RTA_PAYLOAD(tb[RTA_GATEWAY]),
142 RTA_DATA(tb[RTA_GATEWAY]), 137 RTA_DATA(tb[RTA_GATEWAY]))
143 abuf, sizeof(abuf))); 138 );
144 } else 139 } else
145 printf("masquerade"); 140 printf("masquerade");
146 } else if (r->rtm_type != RTN_UNICAST) 141 } else if (r->rtm_type != RTN_UNICAST)
@@ -214,7 +209,7 @@ static int iprule_modify(int cmd, char **argv)
214 while (*argv) { 209 while (*argv) {
215 key = index_in_substrings(keywords, *argv) + 1; 210 key = index_in_substrings(keywords, *argv) + 1;
216 if (key == 0) /* no match found in keywords array, bail out. */ 211 if (key == 0) /* no match found in keywords array, bail out. */
217 invarg(*argv, applet_name); 212 invarg_1_to_2(*argv, applet_name);
218 if (key == ARG_from) { 213 if (key == ARG_from) {
219 inet_prefix dst; 214 inet_prefix dst;
220 NEXT_ARG(); 215 NEXT_ARG();
@@ -239,7 +234,7 @@ static int iprule_modify(int cmd, char **argv)
239 uint32_t tos; 234 uint32_t tos;
240 NEXT_ARG(); 235 NEXT_ARG();
241 if (rtnl_dsfield_a2n(&tos, *argv)) 236 if (rtnl_dsfield_a2n(&tos, *argv))
242 invarg(*argv, "TOS"); 237 invarg_1_to_2(*argv, "TOS");
243 req.r.rtm_tos = tos; 238 req.r.rtm_tos = tos;
244 } else if (key == ARG_fwmark) { 239 } else if (key == ARG_fwmark) {
245 uint32_t fwmark; 240 uint32_t fwmark;
@@ -250,7 +245,7 @@ static int iprule_modify(int cmd, char **argv)
250 uint32_t realm; 245 uint32_t realm;
251 NEXT_ARG(); 246 NEXT_ARG();
252 if (get_rt_realms(&realm, *argv)) 247 if (get_rt_realms(&realm, *argv))
253 invarg(*argv, "realms"); 248 invarg_1_to_2(*argv, "realms");
254 addattr32(&req.n, sizeof(req), RTA_FLOW, realm); 249 addattr32(&req.n, sizeof(req), RTA_FLOW, realm);
255 } else if (key == ARG_table || 250 } else if (key == ARG_table ||
256 key == ARG_lookup 251 key == ARG_lookup
@@ -258,7 +253,7 @@ static int iprule_modify(int cmd, char **argv)
258 uint32_t tid; 253 uint32_t tid;
259 NEXT_ARG(); 254 NEXT_ARG();
260 if (rtnl_rttable_a2n(&tid, *argv)) 255 if (rtnl_rttable_a2n(&tid, *argv))
261 invarg(*argv, "table ID"); 256 invarg_1_to_2(*argv, "table ID");
262 req.r.rtm_table = tid; 257 req.r.rtm_table = tid;
263 table_ok = 1; 258 table_ok = 1;
264 } else if (key == ARG_dev || 259 } else if (key == ARG_dev ||
@@ -281,7 +276,7 @@ static int iprule_modify(int cmd, char **argv)
281 if (key == ARG_help) 276 if (key == ARG_help)
282 bb_show_usage(); 277 bb_show_usage();
283 if (rtnl_rtntype_a2n(&type, *argv)) 278 if (rtnl_rtntype_a2n(&type, *argv))
284 invarg(*argv, "type"); 279 invarg_1_to_2(*argv, "type");
285 req.r.rtm_type = type; 280 req.r.rtm_type = type;
286 } 281 }
287 argv++; 282 argv++;
@@ -309,7 +304,7 @@ int FAST_FUNC do_iprule(char **argv)
309 if (*argv) { 304 if (*argv) {
310 int cmd = index_in_substrings(ip_rule_commands, *argv); 305 int cmd = index_in_substrings(ip_rule_commands, *argv);
311 if (cmd < 0) 306 if (cmd < 0)
312 invarg(*argv, applet_name); 307 invarg_1_to_2(*argv, applet_name);
313 argv++; 308 argv++;
314 if (cmd < 2) 309 if (cmd < 2)
315 return iprule_modify((cmd == 0) ? RTM_NEWRULE : RTM_DELRULE, argv); 310 return iprule_modify((cmd == 0) ? RTM_NEWRULE : RTM_DELRULE, argv);
diff --git a/networking/libiproute/iptunnel.c b/networking/libiproute/iptunnel.c
index a65d5e579..eb136e435 100644
--- a/networking/libiproute/iptunnel.c
+++ b/networking/libiproute/iptunnel.c
@@ -294,7 +294,7 @@ static void parse_args(char **argv, int cmd, struct ip_tunnel_parm *p)
294 if (key != ARG_inherit) { 294 if (key != ARG_inherit) {
295 uval = get_unsigned(*argv, "TTL"); 295 uval = get_unsigned(*argv, "TTL");
296 if (uval > 255) 296 if (uval > 255)
297 invarg(*argv, "TTL must be <=255"); 297 invarg_1_to_2(*argv, "TTL");
298 p->iph.ttl = uval; 298 p->iph.ttl = uval;
299 } 299 }
300 } else if (key == ARG_tos || 300 } else if (key == ARG_tos ||
@@ -305,7 +305,7 @@ static void parse_args(char **argv, int cmd, struct ip_tunnel_parm *p)
305 key = index_in_strings(keywords, *argv); 305 key = index_in_strings(keywords, *argv);
306 if (key != ARG_inherit) { 306 if (key != ARG_inherit) {
307 if (rtnl_dsfield_a2n(&uval, *argv)) 307 if (rtnl_dsfield_a2n(&uval, *argv))
308 invarg(*argv, "TOS"); 308 invarg_1_to_2(*argv, "TOS");
309 p->iph.tos = uval; 309 p->iph.tos = uval;
310 } else 310 } else
311 p->iph.tos = 1; 311 p->iph.tos = 1;
@@ -404,22 +404,18 @@ static int do_del(char **argv)
404 404
405static void print_tunnel(struct ip_tunnel_parm *p) 405static void print_tunnel(struct ip_tunnel_parm *p)
406{ 406{
407 char s1[256]; 407 char s3[INET_ADDRSTRLEN];
408 char s2[256]; 408 char s4[INET_ADDRSTRLEN];
409 char s3[64];
410 char s4[64];
411
412 format_host(AF_INET, 4, &p->iph.daddr, s1, sizeof(s1));
413 format_host(AF_INET, 4, &p->iph.saddr, s2, sizeof(s2));
414 inet_ntop(AF_INET, &p->i_key, s3, sizeof(s3));
415 inet_ntop(AF_INET, &p->o_key, s4, sizeof(s4));
416 409
417 printf("%s: %s/ip remote %s local %s ", 410 printf("%s: %s/ip remote %s local %s ",
418 p->name, 411 p->name,
419 p->iph.protocol == IPPROTO_IPIP ? "ip" : 412 p->iph.protocol == IPPROTO_IPIP ? "ip" :
420 (p->iph.protocol == IPPROTO_GRE ? "gre" : 413 p->iph.protocol == IPPROTO_GRE ? "gre" :
421 (p->iph.protocol == IPPROTO_IPV6 ? "ipv6" : "unknown")), 414 p->iph.protocol == IPPROTO_IPV6 ? "ipv6" :
422 p->iph.daddr ? s1 : "any", p->iph.saddr ? s2 : "any"); 415 "unknown",
416 p->iph.daddr ? format_host(AF_INET, 4, &p->iph.daddr) : "any",
417 p->iph.saddr ? format_host(AF_INET, 4, &p->iph.saddr) : "any"
418 );
423 if (p->link) { 419 if (p->link) {
424 char *n = do_ioctl_get_ifname(p->link); 420 char *n = do_ioctl_get_ifname(p->link);
425 if (n) { 421 if (n) {
@@ -442,9 +438,11 @@ static void print_tunnel(struct ip_tunnel_parm *p)
442 if (!(p->iph.frag_off & htons(IP_DF))) 438 if (!(p->iph.frag_off & htons(IP_DF)))
443 printf(" nopmtudisc"); 439 printf(" nopmtudisc");
444 440
441 inet_ntop(AF_INET, &p->i_key, s3, sizeof(s3));
442 inet_ntop(AF_INET, &p->o_key, s4, sizeof(s4));
445 if ((p->i_flags & GRE_KEY) && (p->o_flags & GRE_KEY) && p->o_key == p->i_key) 443 if ((p->i_flags & GRE_KEY) && (p->o_flags & GRE_KEY) && p->o_key == p->i_key)
446 printf(" key %s", s3); 444 printf(" key %s", s3);
447 else if ((p->i_flags | p->o_flags) & GRE_KEY) { 445 else {
448 if (p->i_flags & GRE_KEY) 446 if (p->i_flags & GRE_KEY)
449 printf(" ikey %s ", s3); 447 printf(" ikey %s ", s3);
450 if (p->o_flags & GRE_KEY) 448 if (p->o_flags & GRE_KEY)
@@ -562,7 +560,7 @@ int FAST_FUNC do_iptunnel(char **argv)
562 if (*argv) { 560 if (*argv) {
563 int key = index_in_substrings(keywords, *argv); 561 int key = index_in_substrings(keywords, *argv);
564 if (key < 0) 562 if (key < 0)
565 invarg(*argv, applet_name); 563 invarg_1_to_2(*argv, applet_name);
566 argv++; 564 argv++;
567 if (key == ARG_add) 565 if (key == ARG_add)
568 return do_add(SIOCADDTUNNEL, argv); 566 return do_add(SIOCADDTUNNEL, argv);
diff --git a/networking/libiproute/utils.c b/networking/libiproute/utils.c
index d0fe30605..42025bc66 100644
--- a/networking/libiproute/utils.c
+++ b/networking/libiproute/utils.c
@@ -13,6 +13,28 @@
13#include "utils.h" 13#include "utils.h"
14#include "inet_common.h" 14#include "inet_common.h"
15 15
16unsigned get_hz(void)
17{
18 static unsigned hz_internal;
19 FILE *fp;
20
21 if (hz_internal)
22 return hz_internal;
23
24 fp = fopen_for_read("/proc/net/psched");
25 if (fp) {
26 unsigned nom, denom;
27
28 if (fscanf(fp, "%*08x%*08x%08x%08x", &nom, &denom) == 2)
29 if (nom == 1000000)
30 hz_internal = denom;
31 fclose(fp);
32 }
33 if (!hz_internal)
34 hz_internal = bb_clk_tck();
35 return hz_internal;
36}
37
16unsigned get_unsigned(char *arg, const char *errmsg) 38unsigned get_unsigned(char *arg, const char *errmsg)
17{ 39{
18 unsigned long res; 40 unsigned long res;
@@ -25,7 +47,7 @@ unsigned get_unsigned(char *arg, const char *errmsg)
25 return res; 47 return res;
26 } 48 }
27 } 49 }
28 invarg(arg, errmsg); /* does not return */ 50 invarg_1_to_2(arg, errmsg); /* does not return */
29} 51}
30 52
31uint32_t get_u32(char *arg, const char *errmsg) 53uint32_t get_u32(char *arg, const char *errmsg)
@@ -40,7 +62,7 @@ uint32_t get_u32(char *arg, const char *errmsg)
40 return res; 62 return res;
41 } 63 }
42 } 64 }
43 invarg(arg, errmsg); /* does not return */ 65 invarg_1_to_2(arg, errmsg); /* does not return */
44} 66}
45 67
46uint16_t get_u16(char *arg, const char *errmsg) 68uint16_t get_u16(char *arg, const char *errmsg)
@@ -55,7 +77,7 @@ uint16_t get_u16(char *arg, const char *errmsg)
55 return res; 77 return res;
56 } 78 }
57 } 79 }
58 invarg(arg, errmsg); /* does not return */ 80 invarg_1_to_2(arg, errmsg); /* does not return */
59} 81}
60 82
61int get_addr_1(inet_prefix *addr, char *name, int family) 83int get_addr_1(inet_prefix *addr, char *name, int family)
@@ -208,12 +230,12 @@ uint32_t get_addr32(char *name)
208 230
209void incomplete_command(void) 231void incomplete_command(void)
210{ 232{
211 bb_error_msg_and_die("command line is not complete, try option \"help\""); 233 bb_error_msg_and_die("command line is not complete, try \"help\"");
212} 234}
213 235
214void invarg(const char *arg, const char *opt) 236void invarg_1_to_2(const char *arg, const char *opt)
215{ 237{
216 bb_error_msg_and_die(bb_msg_invalid_arg, arg, opt); 238 bb_error_msg_and_die(bb_msg_invalid_arg_to, arg, opt);
217} 239}
218 240
219void duparg(const char *key, const char *arg) 241void duparg(const char *key, const char *arg)
@@ -254,20 +276,21 @@ int inet_addr_match(const inet_prefix *a, const inet_prefix *b, int bits)
254 return 0; 276 return 0;
255} 277}
256 278
257const char *rt_addr_n2a(int af, 279const char *rt_addr_n2a(int af, void *addr)
258 void *addr, char *buf, int buflen)
259{ 280{
260 switch (af) { 281 switch (af) {
261 case AF_INET: 282 case AF_INET:
262 case AF_INET6: 283 case AF_INET6:
263 return inet_ntop(af, addr, buf, buflen); 284 return inet_ntop(af, addr,
285 auto_string(xzalloc(INET6_ADDRSTRLEN)), INET6_ADDRSTRLEN
286 );
264 default: 287 default:
265 return "???"; 288 return "???";
266 } 289 }
267} 290}
268 291
269#ifdef RESOLVE_HOSTNAMES 292#ifdef RESOLVE_HOSTNAMES
270const char *format_host(int af, int len, void *addr, char *buf, int buflen) 293const char *format_host(int af, int len, void *addr)
271{ 294{
272 if (resolve_hosts) { 295 if (resolve_hosts) {
273 struct hostent *h_ent; 296 struct hostent *h_ent;
@@ -286,11 +309,10 @@ const char *format_host(int af, int len, void *addr, char *buf, int buflen)
286 if (len > 0) { 309 if (len > 0) {
287 h_ent = gethostbyaddr(addr, len, af); 310 h_ent = gethostbyaddr(addr, len, af);
288 if (h_ent != NULL) { 311 if (h_ent != NULL) {
289 safe_strncpy(buf, h_ent->h_name, buflen); 312 return auto_string(xstrdup(h_ent->h_name));
290 return buf;
291 } 313 }
292 } 314 }
293 } 315 }
294 return rt_addr_n2a(af, addr, buf, buflen); 316 return rt_addr_n2a(af, addr);
295} 317}
296#endif 318#endif
diff --git a/networking/libiproute/utils.h b/networking/libiproute/utils.h
index 5fb4a862c..408d5f65f 100644
--- a/networking/libiproute/utils.h
+++ b/networking/libiproute/utils.h
@@ -66,15 +66,15 @@ extern unsigned get_unsigned(char *arg, const char *errmsg);
66extern uint32_t get_u32(char *arg, const char *errmsg); 66extern uint32_t get_u32(char *arg, const char *errmsg);
67extern uint16_t get_u16(char *arg, const char *errmsg); 67extern uint16_t get_u16(char *arg, const char *errmsg);
68 68
69extern const char *rt_addr_n2a(int af, void *addr, char *buf, int buflen); 69extern const char *rt_addr_n2a(int af, void *addr);
70#ifdef RESOLVE_HOSTNAMES 70#ifdef RESOLVE_HOSTNAMES
71extern const char *format_host(int af, int len, void *addr, char *buf, int buflen); 71extern const char *format_host(int af, int len, void *addr);
72#else 72#else
73#define format_host(af, len, addr, buf, buflen) \ 73#define format_host(af, len, addr) \
74 rt_addr_n2a(af, addr, buf, buflen) 74 rt_addr_n2a(af, addr)
75#endif 75#endif
76 76
77void invarg(const char *, const char *) NORETURN; 77void invarg_1_to_2(const char *, const char *) NORETURN;
78void duparg(const char *, const char *) NORETURN; 78void duparg(const char *, const char *) NORETURN;
79void duparg2(const char *, const char *) NORETURN; 79void duparg2(const char *, const char *) NORETURN;
80int inet_addr_match(const inet_prefix *a, const inet_prefix *b, int bits); 80int inet_addr_match(const inet_prefix *a, const inet_prefix *b, int bits);
@@ -85,6 +85,8 @@ int dnet_pton(int af, const char *src, void *addr);
85const char *ipx_ntop(int af, const void *addr, char *str, size_t len); 85const char *ipx_ntop(int af, const void *addr, char *str, size_t len);
86int ipx_pton(int af, const char *src, void *addr); 86int ipx_pton(int af, const char *src, void *addr);
87 87
88unsigned get_hz(void);
89
88POP_SAVED_FUNCTION_VISIBILITY 90POP_SAVED_FUNCTION_VISIBILITY
89 91
90#endif 92#endif
diff --git a/networking/nbd-client.c b/networking/nbd-client.c
index a601430b6..70869d651 100644
--- a/networking/nbd-client.c
+++ b/networking/nbd-client.c
@@ -57,9 +57,8 @@ int nbdclient_main(int argc, char **argv)
57 uint32_t flags; 57 uint32_t flags;
58 char data[124]; 58 char data[124];
59 } nbd_header; 59 } nbd_header;
60 struct bug_check { 60
61 char c[offsetof(struct nbd_header_t, data) == 8+8+8+4 ? 1 : -1]; 61 BUILD_BUG_ON(offsetof(struct nbd_header_t, data) != 8+8+8+4);
62 };
63 62
64 // Parse command line stuff (just a stub now) 63 // Parse command line stuff (just a stub now)
65 if (argc != 4) 64 if (argc != 4)
diff --git a/networking/slattach.c b/networking/slattach.c
index a500da6d0..14e0c1941 100644
--- a/networking/slattach.c
+++ b/networking/slattach.c
@@ -27,7 +27,7 @@
27//usage: "\n -F Disable RTS/CTS flow control" 27//usage: "\n -F Disable RTS/CTS flow control"
28 28
29#include "libbb.h" 29#include "libbb.h"
30#include "libiproute/utils.h" /* invarg() */ 30#include "libiproute/utils.h" /* invarg_1_to_2() */
31 31
32struct globals { 32struct globals {
33 int handle; 33 int handle;
@@ -175,7 +175,7 @@ int slattach_main(int argc UNUSED_PARAM, char **argv)
175 encap = index_in_strings(proto_names, proto); 175 encap = index_in_strings(proto_names, proto);
176 176
177 if (encap < 0) 177 if (encap < 0)
178 invarg(proto, "protocol"); 178 invarg_1_to_2(proto, "protocol");
179 if (encap > 3) 179 if (encap > 3)
180 encap = 8; 180 encap = 8;
181 181
@@ -183,7 +183,7 @@ int slattach_main(int argc UNUSED_PARAM, char **argv)
183 if (opt & OPT_s_baud) { 183 if (opt & OPT_s_baud) {
184 baud_code = tty_value_to_baud(xatoi(baud_str)); 184 baud_code = tty_value_to_baud(xatoi(baud_str));
185 if (baud_code < 0) 185 if (baud_code < 0)
186 invarg(baud_str, "baud rate"); 186 invarg_1_to_2(baud_str, "baud rate");
187 } 187 }
188 188
189 /* Trap signals in order to restore tty states upon exit */ 189 /* Trap signals in order to restore tty states upon exit */
diff --git a/networking/tc.c b/networking/tc.c
index 6d1fef993..c84c18a67 100644
--- a/networking/tc.c
+++ b/networking/tc.c
@@ -459,14 +459,14 @@ int tc_main(int argc UNUSED_PARAM, char **argv)
459 459
460 obj = index_in_substrings(objects, *argv++); 460 obj = index_in_substrings(objects, *argv++);
461 461
462 if (obj < OBJ_qdisc) 462 if (obj < 0)
463 bb_show_usage(); 463 bb_show_usage();
464 if (!*argv) 464 if (!*argv)
465 cmd = CMD_show; /* list is the default */ 465 cmd = CMD_show; /* list is the default */
466 else { 466 else {
467 cmd = index_in_substrings(commands, *argv); 467 cmd = index_in_substrings(commands, *argv);
468 if (cmd < 0) 468 if (cmd < 0)
469 bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name); 469 invarg_1_to_2(*argv, argv[-1]);
470 argv++; 470 argv++;
471 } 471 }
472 memset(&msg, 0, sizeof(msg)); 472 memset(&msg, 0, sizeof(msg));
@@ -489,7 +489,7 @@ int tc_main(int argc UNUSED_PARAM, char **argv)
489 NEXT_ARG(); 489 NEXT_ARG();
490 /* We don't care about duparg2("qdisc handle",*argv) for now */ 490 /* We don't care about duparg2("qdisc handle",*argv) for now */
491 if (get_qdisc_handle(&filter_qdisc, *argv)) 491 if (get_qdisc_handle(&filter_qdisc, *argv))
492 invarg(*argv, "qdisc"); 492 invarg_1_to_2(*argv, "qdisc");
493 } else 493 } else
494 if (obj != OBJ_qdisc 494 if (obj != OBJ_qdisc
495 && (arg == ARG_root 495 && (arg == ARG_root
@@ -499,7 +499,7 @@ int tc_main(int argc UNUSED_PARAM, char **argv)
499 ) { 499 ) {
500 /* nothing */ 500 /* nothing */
501 } else { 501 } else {
502 invarg(*argv, "command"); 502 invarg_1_to_2(*argv, "command");
503 } 503 }
504 NEXT_ARG(); 504 NEXT_ARG();
505 if (arg == ARG_root) { 505 if (arg == ARG_root) {
@@ -513,7 +513,7 @@ int tc_main(int argc UNUSED_PARAM, char **argv)
513 if (msg.tcm_parent) 513 if (msg.tcm_parent)
514 duparg(*argv, "parent"); 514 duparg(*argv, "parent");
515 if (get_tc_classid(&handle, *argv)) 515 if (get_tc_classid(&handle, *argv))
516 invarg(*argv, "parent"); 516 invarg_1_to_2(*argv, "parent");
517 msg.tcm_parent = handle; 517 msg.tcm_parent = handle;
518 if (obj == OBJ_filter) 518 if (obj == OBJ_filter)
519 filter_parent = handle; 519 filter_parent = handle;
@@ -538,7 +538,7 @@ int tc_main(int argc UNUSED_PARAM, char **argv)
538 if (filter_proto) 538 if (filter_proto)
539 duparg(*argv, "protocol"); 539 duparg(*argv, "protocol");
540 if (ll_proto_a2n(&tmp, *argv)) 540 if (ll_proto_a2n(&tmp, *argv))
541 invarg(*argv, "protocol"); 541 invarg_1_to_2(*argv, "protocol");
542 filter_proto = tmp; 542 filter_proto = tmp;
543 } 543 }
544 } 544 }
diff --git a/networking/telnet.c b/networking/telnet.c
index 3bb6fb1ba..944cf1bd6 100644
--- a/networking/telnet.c
+++ b/networking/telnet.c
@@ -110,9 +110,7 @@ struct globals {
110} FIX_ALIASING; 110} FIX_ALIASING;
111#define G (*(struct globals*)&bb_common_bufsiz1) 111#define G (*(struct globals*)&bb_common_bufsiz1)
112#define INIT_G() do { \ 112#define INIT_G() do { \
113 struct G_sizecheck { \ 113 BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
114 char G_sizecheck[sizeof(G) > COMMON_BUFSIZE ? -1 : 1]; \
115 }; \
116} while (0) 114} while (0)
117 115
118 116
diff --git a/printutils/Config.src b/printutils/Config.src
index cc4ab8d28..e53b9d093 100644
--- a/printutils/Config.src
+++ b/printutils/Config.src
@@ -7,22 +7,4 @@ menu "Print Utilities"
7 7
8INSERT 8INSERT
9 9
10config LPD
11 bool "lpd"
12 default y
13 help
14 lpd is a print spooling daemon.
15
16config LPR
17 bool "lpr"
18 default y
19 help
20 lpr sends files (or standard input) to a print spooling daemon.
21
22config LPQ
23 bool "lpq"
24 default y
25 help
26 lpq is a print spool queue examination and manipulation program.
27
28endmenu 10endmenu
diff --git a/printutils/Kbuild.src b/printutils/Kbuild.src
index 194fe01d6..10c823063 100644
--- a/printutils/Kbuild.src
+++ b/printutils/Kbuild.src
@@ -4,6 +4,4 @@
4 4
5lib-y := 5lib-y :=
6 6
7lib-$(CONFIG_LPD) += lpd.o 7INSERT
8lib-$(CONFIG_LPR) += lpr.o
9lib-$(CONFIG_LPQ) += lpr.o
diff --git a/printutils/lpd.c b/printutils/lpd.c
index c98bbb347..882393436 100644
--- a/printutils/lpd.c
+++ b/printutils/lpd.c
@@ -69,6 +69,15 @@
69 * cat ./"$DATAFILE" >/dev/lp0 69 * cat ./"$DATAFILE" >/dev/lp0
70 * mv -f ./"$DATAFILE" save/ 70 * mv -f ./"$DATAFILE" save/
71 */ 71 */
72//config:config LPD
73//config: bool "lpd"
74//config: default y
75//config: help
76//config: lpd is a print spooling daemon.
77
78//applet:IF_LPD(APPLET(lpd, BB_DIR_USR_SBIN, BB_SUID_DROP))
79
80//kbuild:lib-$(CONFIG_LPD) += lpd.o
72 81
73//usage:#define lpd_trivial_usage 82//usage:#define lpd_trivial_usage
74//usage: "SPOOLDIR [HELPER [ARGS]]" 83//usage: "SPOOLDIR [HELPER [ARGS]]"
diff --git a/printutils/lpr.c b/printutils/lpr.c
index 70cda7717..ed6a84a93 100644
--- a/printutils/lpr.c
+++ b/printutils/lpr.c
@@ -11,6 +11,23 @@
11 * 11 *
12 * See RFC 1179 for protocol description. 12 * See RFC 1179 for protocol description.
13 */ 13 */
14//config:config LPR
15//config: bool "lpr"
16//config: default y
17//config: help
18//config: lpr sends files (or standard input) to a print spooling daemon.
19//config:
20//config:config LPQ
21//config: bool "lpq"
22//config: default y
23//config: help
24//config: lpq is a print spool queue examination and manipulation program.
25
26//applet:IF_LPQ(APPLET_ODDNAME(lpq, lpqr, BB_DIR_USR_BIN, BB_SUID_DROP, lpq))
27//applet:IF_LPR(APPLET_ODDNAME(lpr, lpqr, BB_DIR_USR_BIN, BB_SUID_DROP, lpr))
28
29//kbuild:lib-$(CONFIG_LPR) += lpr.o
30//kbuild:lib-$(CONFIG_LPQ) += lpr.o
14 31
15//usage:#define lpr_trivial_usage 32//usage:#define lpr_trivial_usage
16//usage: "-P queue[@host[:port]] -U USERNAME -J TITLE -Vmh [FILE]..." 33//usage: "-P queue[@host[:port]] -U USERNAME -J TITLE -Vmh [FILE]..."
diff --git a/procps/top.c b/procps/top.c
index 3d67c3cfd..ddf794d7d 100644
--- a/procps/top.c
+++ b/procps/top.c
@@ -184,10 +184,6 @@ struct globals {
184}; //FIX_ALIASING; - large code growth 184}; //FIX_ALIASING; - large code growth
185enum { LINE_BUF_SIZE = COMMON_BUFSIZE - offsetof(struct globals, line_buf) }; 185enum { LINE_BUF_SIZE = COMMON_BUFSIZE - offsetof(struct globals, line_buf) };
186#define G (*(struct globals*)&bb_common_bufsiz1) 186#define G (*(struct globals*)&bb_common_bufsiz1)
187struct BUG_bad_size {
188 char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1];
189 char BUG_line_buf_too_small[LINE_BUF_SIZE > 80 ? 1 : -1];
190};
191#define top (G.top ) 187#define top (G.top )
192#define ntop (G.ntop ) 188#define ntop (G.ntop )
193#define sort_field (G.sort_field ) 189#define sort_field (G.sort_field )
@@ -204,7 +200,10 @@ struct BUG_bad_size {
204#define num_cpus (G.num_cpus ) 200#define num_cpus (G.num_cpus )
205#define total_pcpu (G.total_pcpu ) 201#define total_pcpu (G.total_pcpu )
206#define line_buf (G.line_buf ) 202#define line_buf (G.line_buf )
207#define INIT_G() do { } while (0) 203#define INIT_G() do { \
204 BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
205 BUILD_BUG_ON(LINE_BUF_SIZE <= 80); \
206} while (0)
208 207
209enum { 208enum {
210 OPT_d = (1 << 0), 209 OPT_d = (1 << 0),
@@ -830,10 +829,17 @@ static NOINLINE void display_topmem_process_list(int lines_rem, int scr_width)
830#define HDR_STR " PID VSZ VSZRW RSS (SHR) DIRTY (SHR) STACK" 829#define HDR_STR " PID VSZ VSZRW RSS (SHR) DIRTY (SHR) STACK"
831#define MIN_WIDTH sizeof(HDR_STR) 830#define MIN_WIDTH sizeof(HDR_STR)
832 const topmem_status_t *s = topmem + G_scroll_ofs; 831 const topmem_status_t *s = topmem + G_scroll_ofs;
832 char *cp, ch;
833 833
834 display_topmem_header(scr_width, &lines_rem); 834 display_topmem_header(scr_width, &lines_rem);
835
835 strcpy(line_buf, HDR_STR " COMMAND"); 836 strcpy(line_buf, HDR_STR " COMMAND");
836 line_buf[11 + sort_field * 6] = "^_"[inverted]; 837 /* Mark the ^FIELD^ we sort by */
838 cp = &line_buf[5 + sort_field * 6];
839 ch = "^_"[inverted];
840 cp[6] = ch;
841 do *cp++ = ch; while (*cp == ' ');
842
837 printf(OPT_BATCH_MODE ? "%.*s" : "\e[7m%.*s\e[0m", scr_width, line_buf); 843 printf(OPT_BATCH_MODE ? "%.*s" : "\e[7m%.*s\e[0m", scr_width, line_buf);
838 lines_rem--; 844 lines_rem--;
839 845
@@ -1173,10 +1179,8 @@ int top_main(int argc UNUSED_PARAM, char **argv)
1173 ntop = 0; 1179 ntop = 0;
1174 while ((p = procps_scan(p, scan_mask)) != NULL) { 1180 while ((p = procps_scan(p, scan_mask)) != NULL) {
1175 int n; 1181 int n;
1176#if ENABLE_FEATURE_TOPMEM 1182
1177 if (scan_mask != TOPMEM_MASK) 1183 IF_FEATURE_TOPMEM(if (scan_mask != TOPMEM_MASK)) {
1178#endif
1179 {
1180 n = ntop; 1184 n = ntop;
1181 top = xrealloc_vector(top, 6, ntop++); 1185 top = xrealloc_vector(top, 6, ntop++);
1182 top[n].pid = p->pid; 1186 top[n].pid = p->pid;
@@ -1216,7 +1220,7 @@ int top_main(int argc UNUSED_PARAM, char **argv)
1216 break; 1220 break;
1217 } 1221 }
1218 1222
1219 if (scan_mask != TOPMEM_MASK) { 1223 IF_FEATURE_TOPMEM(if (scan_mask != TOPMEM_MASK)) {
1220#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE 1224#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
1221 if (!prev_hist_count) { 1225 if (!prev_hist_count) {
1222 do_stats(); 1226 do_stats();
@@ -1230,17 +1234,13 @@ int top_main(int argc UNUSED_PARAM, char **argv)
1230#else 1234#else
1231 qsort(top, ntop, sizeof(top_status_t), (void*)(sort_function[0])); 1235 qsort(top, ntop, sizeof(top_status_t), (void*)(sort_function[0]));
1232#endif 1236#endif
1237 display_process_list(G.lines, col);
1233 } 1238 }
1234#if ENABLE_FEATURE_TOPMEM 1239#if ENABLE_FEATURE_TOPMEM
1235 else { /* TOPMEM */ 1240 else { /* TOPMEM */
1236 qsort(topmem, ntop, sizeof(topmem_status_t), (void*)topmem_sort); 1241 qsort(topmem, ntop, sizeof(topmem_status_t), (void*)topmem_sort);
1237 }
1238#endif
1239 if (scan_mask != TOPMEM_MASK)
1240 display_process_list(G.lines, col);
1241#if ENABLE_FEATURE_TOPMEM
1242 else
1243 display_topmem_process_list(G.lines, col); 1242 display_topmem_process_list(G.lines, col);
1243 }
1244#endif 1244#endif
1245 clearmems(); 1245 clearmems();
1246 if (iterations >= 0 && !--iterations) 1246 if (iterations >= 0 && !--iterations)
@@ -1249,7 +1249,7 @@ int top_main(int argc UNUSED_PARAM, char **argv)
1249 sleep(interval); 1249 sleep(interval);
1250#else 1250#else
1251 scan_mask = handle_input(scan_mask, interval); 1251 scan_mask = handle_input(scan_mask, interval);
1252#endif /* FEATURE_USE_TERMIOS */ 1252#endif
1253 } /* end of "while (not Q)" */ 1253 } /* end of "while (not Q)" */
1254 1254
1255 bb_putchar('\n'); 1255 bb_putchar('\n');
diff --git a/runit/Config.src b/runit/Config.src
index 9db974002..8cde89680 100644
--- a/runit/Config.src
+++ b/runit/Config.src
@@ -7,83 +7,4 @@ menu "Runit Utilities"
7 7
8INSERT 8INSERT
9 9
10config RUNSV
11 bool "runsv"
12 default y
13 help
14 runsv starts and monitors a service and optionally an appendant log
15 service.
16
17config RUNSVDIR
18 bool "runsvdir"
19 default y
20 help
21 runsvdir starts a runsv process for each subdirectory, or symlink to
22 a directory, in the services directory dir, up to a limit of 1000
23 subdirectories, and restarts a runsv process if it terminates.
24
25config FEATURE_RUNSVDIR_LOG
26 bool "Enable scrolling argument log"
27 depends on RUNSVDIR
28 default n
29 help
30 Enable feature where second parameter of runsvdir holds last error
31 message (viewable via top/ps). Otherwise (feature is off
32 or no parameter), error messages go to stderr only.
33
34config SV
35 bool "sv"
36 default y
37 help
38 sv reports the current status and controls the state of services
39 monitored by the runsv supervisor.
40
41config SV_DEFAULT_SERVICE_DIR
42 string "Default directory for services"
43 default "/var/service"
44 depends on SV
45 help
46 Default directory for services.
47 Defaults to "/var/service"
48
49config SVLOGD
50 bool "svlogd"
51 default y
52 help
53 svlogd continuously reads log data from its standard input, optionally
54 filters log messages, and writes the data to one or more automatically
55 rotated logs.
56
57config CHPST
58 bool "chpst"
59 default y
60 help
61 chpst changes the process state according to the given options, and
62 execs specified program.
63
64config SETUIDGID
65 bool "setuidgid"
66 default y
67 help
68 Sets soft resource limits as specified by options
69
70config ENVUIDGID
71 bool "envuidgid"
72 default y
73 help
74 Sets $UID to account's uid and $GID to account's gid
75
76config ENVDIR
77 bool "envdir"
78 default y
79 help
80 Sets various environment variables as specified by files
81 in the given directory
82
83config SOFTLIMIT
84 bool "softlimit"
85 default y
86 help
87 Sets soft resource limits as specified by options
88
89endmenu 10endmenu
diff --git a/runit/Kbuild.src b/runit/Kbuild.src
index 0fce95507..6b4fb7470 100644
--- a/runit/Kbuild.src
+++ b/runit/Kbuild.src
@@ -7,14 +7,3 @@
7lib-y:= 7lib-y:=
8 8
9INSERT 9INSERT
10
11lib-$(CONFIG_RUNSV) += runsv.o
12lib-$(CONFIG_RUNSVDIR) += runsvdir.o
13lib-$(CONFIG_SV) += sv.o
14lib-$(CONFIG_SVLOGD) += svlogd.o
15lib-$(CONFIG_CHPST) += chpst.o
16
17lib-$(CONFIG_ENVDIR) += chpst.o
18lib-$(CONFIG_ENVUIDGID) += chpst.o
19lib-$(CONFIG_SETUIDGID) += chpst.o
20lib-$(CONFIG_SOFTLIMIT) += chpst.o
diff --git a/runit/chpst.c b/runit/chpst.c
index 71af29f66..301cdd08a 100644
--- a/runit/chpst.c
+++ b/runit/chpst.c
@@ -26,7 +26,50 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*/ 26*/
27 27
28/* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */ 28/* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */
29/* Dependencies on runit_lib.c removed */ 29
30//config:config CHPST
31//config: bool "chpst"
32//config: default y
33//config: help
34//config: chpst changes the process state according to the given options, and
35//config: execs specified program.
36//config:
37//config:config SETUIDGID
38//config: bool "setuidgid"
39//config: default y
40//config: help
41//config: Sets soft resource limits as specified by options
42//config:
43//config:config ENVUIDGID
44//config: bool "envuidgid"
45//config: default y
46//config: help
47//config: Sets $UID to account's uid and $GID to account's gid
48//config:
49//config:config ENVDIR
50//config: bool "envdir"
51//config: default y
52//config: help
53//config: Sets various environment variables as specified by files
54//config: in the given directory
55//config:
56//config:config SOFTLIMIT
57//config: bool "softlimit"
58//config: default y
59//config: help
60//config: Sets soft resource limits as specified by options
61
62//applet:IF_CHPST(APPLET(chpst, BB_DIR_USR_BIN, BB_SUID_DROP))
63//applet:IF_ENVDIR(APPLET_ODDNAME(envdir, chpst, BB_DIR_USR_BIN, BB_SUID_DROP, envdir))
64//applet:IF_ENVUIDGID(APPLET_ODDNAME(envuidgid, chpst, BB_DIR_USR_BIN, BB_SUID_DROP, envuidgid))
65//applet:IF_SETUIDGID(APPLET_ODDNAME(setuidgid, chpst, BB_DIR_USR_BIN, BB_SUID_DROP, setuidgid))
66//applet:IF_SOFTLIMIT(APPLET_ODDNAME(softlimit, chpst, BB_DIR_USR_BIN, BB_SUID_DROP, softlimit))
67
68//kbuild:lib-$(CONFIG_CHPST) += chpst.o
69//kbuild:lib-$(CONFIG_ENVDIR) += chpst.o
70//kbuild:lib-$(CONFIG_ENVUIDGID) += chpst.o
71//kbuild:lib-$(CONFIG_SETUIDGID) += chpst.o
72//kbuild:lib-$(CONFIG_SOFTLIMIT) += chpst.o
30 73
31//usage:#define chpst_trivial_usage 74//usage:#define chpst_trivial_usage
32//usage: "[-vP012] [-u USER[:GRP]] [-U USER[:GRP]] [-e DIR]\n" 75//usage: "[-vP012] [-u USER[:GRP]] [-U USER[:GRP]] [-e DIR]\n"
diff --git a/runit/runsv.c b/runit/runsv.c
index 6cf5bcc29..4b18d12d5 100644
--- a/runit/runsv.c
+++ b/runit/runsv.c
@@ -26,7 +26,17 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*/ 26*/
27 27
28/* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */ 28/* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */
29/* TODO: depends on runit_lib.c - review and reduce/eliminate */ 29
30//config:config RUNSV
31//config: bool "runsv"
32//config: default y
33//config: help
34//config: runsv starts and monitors a service and optionally an appendant log
35//config: service.
36
37//applet:IF_RUNSV(APPLET(runsv, BB_DIR_USR_BIN, BB_SUID_DROP))
38
39//kbuild:lib-$(CONFIG_RUNSV) += runsv.o
30 40
31//usage:#define runsv_trivial_usage 41//usage:#define runsv_trivial_usage
32//usage: "DIR" 42//usage: "DIR"
diff --git a/runit/runsvdir.c b/runit/runsvdir.c
index b4c0b2ef0..b3d9e7390 100644
--- a/runit/runsvdir.c
+++ b/runit/runsvdir.c
@@ -26,7 +26,27 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*/ 26*/
27 27
28/* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */ 28/* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */
29/* TODO: depends on runit_lib.c - review and reduce/eliminate */ 29
30//config:config RUNSVDIR
31//config: bool "runsvdir"
32//config: default y
33//config: help
34//config: runsvdir starts a runsv process for each subdirectory, or symlink to
35//config: a directory, in the services directory dir, up to a limit of 1000
36//config: subdirectories, and restarts a runsv process if it terminates.
37//config:
38//config:config FEATURE_RUNSVDIR_LOG
39//config: bool "Enable scrolling argument log"
40//config: depends on RUNSVDIR
41//config: default n
42//config: help
43//config: Enable feature where second parameter of runsvdir holds last error
44//config: message (viewable via top/ps). Otherwise (feature is off
45//config: or no parameter), error messages go to stderr only.
46
47//applet:IF_RUNSVDIR(APPLET(runsvdir, BB_DIR_USR_BIN, BB_SUID_DROP))
48
49//kbuild:lib-$(CONFIG_RUNSVDIR) += runsvdir.o
30 50
31//usage:#define runsvdir_trivial_usage 51//usage:#define runsvdir_trivial_usage
32//usage: "[-P] [-s SCRIPT] DIR" 52//usage: "[-P] [-s SCRIPT] DIR"
diff --git a/runit/sv.c b/runit/sv.c
index 825e9d45b..de8a0d8a4 100644
--- a/runit/sv.c
+++ b/runit/sv.c
@@ -151,7 +151,25 @@ Exit Codes
151*/ 151*/
152 152
153/* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */ 153/* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */
154/* TODO: depends on runit_lib.c - review and reduce/eliminate */ 154
155//config:config SV
156//config: bool "sv"
157//config: default y
158//config: help
159//config: sv reports the current status and controls the state of services
160//config: monitored by the runsv supervisor.
161//config:
162//config:config SV_DEFAULT_SERVICE_DIR
163//config: string "Default directory for services"
164//config: default "/var/service"
165//config: depends on SV
166//config: help
167//config: Default directory for services.
168//config: Defaults to "/var/service"
169
170//applet:IF_SV(APPLET(sv, BB_DIR_USR_BIN, BB_SUID_DROP))
171
172//kbuild:lib-$(CONFIG_SV) += sv.o
155 173
156//usage:#define sv_trivial_usage 174//usage:#define sv_trivial_usage
157//usage: "[-v] [-w SEC] CMD SERVICE_DIR..." 175//usage: "[-v] [-w SEC] CMD SERVICE_DIR..."
diff --git a/runit/svlogd.c b/runit/svlogd.c
index c080b9acc..dbe8df65c 100644
--- a/runit/svlogd.c
+++ b/runit/svlogd.c
@@ -26,7 +26,6 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*/ 26*/
27 27
28/* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */ 28/* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */
29/* TODO: depends on runit_lib.c - review and reduce/eliminate */
30 29
31/* 30/*
32Config files 31Config files
@@ -125,6 +124,18 @@ log message, you can use a pattern like this instead
125-*: *: pid * 124-*: *: pid *
126*/ 125*/
127 126
127//config:config SVLOGD
128//config: bool "svlogd"
129//config: default y
130//config: help
131//config: svlogd continuously reads log data from its standard input, optionally
132//config: filters log messages, and writes the data to one or more automatically
133//config: rotated logs.
134
135//applet:IF_SVLOGD(APPLET(svlogd, BB_DIR_USR_SBIN, BB_SUID_DROP))
136
137//kbuild:lib-$(CONFIG_SVLOGD) += svlogd.o
138
128//usage:#define svlogd_trivial_usage 139//usage:#define svlogd_trivial_usage
129//usage: "[-ttv] [-r C] [-R CHARS] [-l MATCHLEN] [-b BUFLEN] DIR..." 140//usage: "[-ttv] [-r C] [-R CHARS] [-l MATCHLEN] [-b BUFLEN] DIR..."
130//usage:#define svlogd_full_usage "\n\n" 141//usage:#define svlogd_full_usage "\n\n"
diff --git a/sysklogd/Config.src b/sysklogd/Config.src
index fcf993054..684e7d414 100644
--- a/sysklogd/Config.src
+++ b/sysklogd/Config.src
@@ -7,163 +7,4 @@ menu "System Logging Utilities"
7 7
8INSERT 8INSERT
9 9
10config SYSLOGD
11 bool "syslogd"
12 default y
13 help
14 The syslogd utility is used to record logs of all the
15 significant events that occur on a system. Every
16 message that is logged records the date and time of the
17 event, and will generally also record the name of the
18 application that generated the message. When used in
19 conjunction with klogd, messages from the Linux kernel
20 can also be recorded. This is terribly useful,
21 especially for finding what happened when something goes
22 wrong. And something almost always will go wrong if
23 you wait long enough....
24
25config FEATURE_ROTATE_LOGFILE
26 bool "Rotate message files"
27 default y
28 depends on SYSLOGD
29 help
30 This enables syslogd to rotate the message files
31 on his own. No need to use an external rotatescript.
32
33config FEATURE_REMOTE_LOG
34 bool "Remote Log support"
35 default y
36 depends on SYSLOGD
37 help
38 When you enable this feature, the syslogd utility can
39 be used to send system log messages to another system
40 connected via a network. This allows the remote
41 machine to log all the system messages, which can be
42 terribly useful for reducing the number of serial
43 cables you use. It can also be a very good security
44 measure to prevent system logs from being tampered with
45 by an intruder.
46
47config FEATURE_SYSLOGD_DUP
48 bool "Support -D (drop dups) option"
49 default y
50 depends on SYSLOGD
51 help
52 Option -D instructs syslogd to drop consecutive messages
53 which are totally the same.
54
55config FEATURE_SYSLOGD_CFG
56 bool "Support syslog.conf"
57 default y
58 depends on SYSLOGD
59 help
60 Supports restricted syslogd config. See docs/syslog.conf.txt
61
62config FEATURE_SYSLOGD_READ_BUFFER_SIZE
63 int "Read buffer size in bytes"
64 default 256
65 range 256 20000
66 depends on SYSLOGD
67 help
68 This option sets the size of the syslog read buffer.
69 Actual memory usage increases around five times the
70 change done here.
71
72config FEATURE_IPC_SYSLOG
73 bool "Circular Buffer support"
74 default y
75 depends on SYSLOGD
76 help
77 When you enable this feature, the syslogd utility will
78 use a circular buffer to record system log messages.
79 When the buffer is filled it will continue to overwrite
80 the oldest messages. This can be very useful for
81 systems with little or no permanent storage, since
82 otherwise system logs can eventually fill up your
83 entire filesystem, which may cause your system to
84 break badly.
85
86config FEATURE_IPC_SYSLOG_BUFFER_SIZE
87 int "Circular buffer size in Kbytes (minimum 4KB)"
88 default 16
89 range 4 2147483647
90 depends on FEATURE_IPC_SYSLOG
91 help
92 This option sets the size of the circular buffer
93 used to record system log messages.
94
95config LOGREAD
96 bool "logread"
97 default y
98 depends on FEATURE_IPC_SYSLOG
99 help
100 If you enabled Circular Buffer support, you almost
101 certainly want to enable this feature as well. This
102 utility will allow you to read the messages that are
103 stored in the syslogd circular buffer.
104
105config FEATURE_LOGREAD_REDUCED_LOCKING
106 bool "Double buffering"
107 default y
108 depends on LOGREAD
109 help
110 'logread' ouput to slow serial terminals can have
111 side effects on syslog because of the semaphore.
112 This option make logread to double buffer copy
113 from circular buffer, minimizing semaphore
114 contention at some minor memory expense.
115
116config FEATURE_KMSG_SYSLOG
117 bool "Linux kernel printk buffer support"
118 default y
119 depends on SYSLOGD
120 select PLATFORM_LINUX
121 help
122 When you enable this feature, the syslogd utility will
123 write system log message to the Linux kernel's printk buffer.
124 This can be used as a smaller alternative to the syslogd IPC
125 support, as klogd and logread aren't needed.
126
127 NOTICE: Syslog facilities in log entries needs kernel 3.5+.
128
129config KLOGD
130 bool "klogd"
131 default y
132 help
133 klogd is a utility which intercepts and logs all
134 messages from the Linux kernel and sends the messages
135 out to the 'syslogd' utility so they can be logged. If
136 you wish to record the messages produced by the kernel,
137 you should enable this option.
138
139comment "klogd should not be used together with syslog to kernel printk buffer"
140 depends on KLOGD && FEATURE_KMSG_SYSLOG
141
142config FEATURE_KLOGD_KLOGCTL
143 bool "Use the klogctl() interface"
144 default y
145 depends on KLOGD
146 select PLATFORM_LINUX
147 help
148 The klogd applet supports two interfaces for reading
149 kernel messages. Linux provides the klogctl() interface
150 which allows reading messages from the kernel ring buffer
151 independently from the file system.
152
153 If you answer 'N' here, klogd will use the more portable
154 approach of reading them from /proc or a device node.
155 However, this method requires the file to be available.
156
157 If in doubt, say 'Y'.
158
159config LOGGER
160 bool "logger"
161 default y
162 select FEATURE_SYSLOG
163 help
164 The logger utility allows you to send arbitrary text
165 messages to the system log (i.e. the 'syslogd' utility) so
166 they can be logged. This is generally used to help locate
167 problems that occur within programs and scripts.
168
169endmenu 10endmenu
diff --git a/sysklogd/Kbuild.src b/sysklogd/Kbuild.src
index d386cc291..6b4fb7470 100644
--- a/sysklogd/Kbuild.src
+++ b/sysklogd/Kbuild.src
@@ -7,7 +7,3 @@
7lib-y:= 7lib-y:=
8 8
9INSERT 9INSERT
10lib-$(CONFIG_KLOGD) += klogd.o
11lib-$(CONFIG_LOGGER) += syslogd_and_logger.o
12lib-$(CONFIG_LOGREAD) += logread.o
13lib-$(CONFIG_SYSLOGD) += syslogd_and_logger.o
diff --git a/sysklogd/klogd.c b/sysklogd/klogd.c
index 432ded153..ca8b848bd 100644
--- a/sysklogd/klogd.c
+++ b/sysklogd/klogd.c
@@ -16,6 +16,39 @@
16 * 16 *
17 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 17 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
18 */ 18 */
19//config:config KLOGD
20//config: bool "klogd"
21//config: default y
22//config: help
23//config: klogd is a utility which intercepts and logs all
24//config: messages from the Linux kernel and sends the messages
25//config: out to the 'syslogd' utility so they can be logged. If
26//config: you wish to record the messages produced by the kernel,
27//config: you should enable this option.
28//config:
29//config:comment "klogd should not be used together with syslog to kernel printk buffer"
30//config: depends on KLOGD && FEATURE_KMSG_SYSLOG
31//config:
32//config:config FEATURE_KLOGD_KLOGCTL
33//config: bool "Use the klogctl() interface"
34//config: default y
35//config: depends on KLOGD
36//config: select PLATFORM_LINUX
37//config: help
38//config: The klogd applet supports two interfaces for reading
39//config: kernel messages. Linux provides the klogctl() interface
40//config: which allows reading messages from the kernel ring buffer
41//config: independently from the file system.
42//config:
43//config: If you answer 'N' here, klogd will use the more portable
44//config: approach of reading them from /proc or a device node.
45//config: However, this method requires the file to be available.
46//config:
47//config: If in doubt, say 'Y'.
48
49//applet:IF_KLOGD(APPLET(klogd, BB_DIR_SBIN, BB_SUID_DROP))
50
51//kbuild:lib-$(CONFIG_KLOGD) += klogd.o
19 52
20//usage:#define klogd_trivial_usage 53//usage:#define klogd_trivial_usage
21//usage: "[-c N] [-n]" 54//usage: "[-c N] [-n]"
diff --git a/sysklogd/logger.c b/sysklogd/logger.c
index 5a7027731..b3ca85703 100644
--- a/sysklogd/logger.c
+++ b/sysklogd/logger.c
@@ -6,6 +6,19 @@
6 * 6 *
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config LOGGER
10//config: bool "logger"
11//config: default y
12//config: select FEATURE_SYSLOG
13//config: help
14//config: The logger utility allows you to send arbitrary text
15//config: messages to the system log (i.e. the 'syslogd' utility) so
16//config: they can be logged. This is generally used to help locate
17//config: problems that occur within programs and scripts.
18
19//applet:IF_LOGGER(APPLET(logger, BB_DIR_USR_BIN, BB_SUID_DROP))
20
21//kbuild:lib-$(CONFIG_LOGGER) += syslogd_and_logger.o
9 22
10//usage:#define logger_trivial_usage 23//usage:#define logger_trivial_usage
11//usage: "[OPTIONS] [MESSAGE]" 24//usage: "[OPTIONS] [MESSAGE]"
diff --git a/sysklogd/logread.c b/sysklogd/logread.c
index da4a4d4df..781a603b2 100644
--- a/sysklogd/logread.c
+++ b/sysklogd/logread.c
@@ -8,6 +8,31 @@
8 * 8 *
9 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 9 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
10 */ 10 */
11//config:config LOGREAD
12//config: bool "logread"
13//config: default y
14//config: depends on FEATURE_IPC_SYSLOG
15//config: help
16//config: If you enabled Circular Buffer support, you almost
17//config: certainly want to enable this feature as well. This
18//config: utility will allow you to read the messages that are
19//config: stored in the syslogd circular buffer.
20//config:
21//config:config FEATURE_LOGREAD_REDUCED_LOCKING
22//config: bool "Double buffering"
23//config: default y
24//config: depends on LOGREAD
25//config: help
26//config: 'logread' ouput to slow serial terminals can have
27//config: side effects on syslog because of the semaphore.
28//config: This option make logread to double buffer copy
29//config: from circular buffer, minimizing semaphore
30//config: contention at some minor memory expense.
31//config:
32
33//applet:IF_LOGREAD(APPLET(logread, BB_DIR_SBIN, BB_SUID_DROP))
34
35//kbuild:lib-$(CONFIG_LOGREAD) += logread.o
11 36
12//usage:#define logread_trivial_usage 37//usage:#define logread_trivial_usage
13//usage: "[-fF]" 38//usage: "[-fF]"
diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c
index 156f487e5..288b29cf7 100644
--- a/sysklogd/syslogd.c
+++ b/sysklogd/syslogd.c
@@ -12,6 +12,107 @@
12 * 12 *
13 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 13 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
14 */ 14 */
15//config:config SYSLOGD
16//config: bool "syslogd"
17//config: default y
18//config: help
19//config: The syslogd utility is used to record logs of all the
20//config: significant events that occur on a system. Every
21//config: message that is logged records the date and time of the
22//config: event, and will generally also record the name of the
23//config: application that generated the message. When used in
24//config: conjunction with klogd, messages from the Linux kernel
25//config: can also be recorded. This is terribly useful,
26//config: especially for finding what happened when something goes
27//config: wrong. And something almost always will go wrong if
28//config: you wait long enough....
29//config:
30//config:config FEATURE_ROTATE_LOGFILE
31//config: bool "Rotate message files"
32//config: default y
33//config: depends on SYSLOGD
34//config: help
35//config: This enables syslogd to rotate the message files
36//config: on his own. No need to use an external rotatescript.
37//config:
38//config:config FEATURE_REMOTE_LOG
39//config: bool "Remote Log support"
40//config: default y
41//config: depends on SYSLOGD
42//config: help
43//config: When you enable this feature, the syslogd utility can
44//config: be used to send system log messages to another system
45//config: connected via a network. This allows the remote
46//config: machine to log all the system messages, which can be
47//config: terribly useful for reducing the number of serial
48//config: cables you use. It can also be a very good security
49//config: measure to prevent system logs from being tampered with
50//config: by an intruder.
51//config:
52//config:config FEATURE_SYSLOGD_DUP
53//config: bool "Support -D (drop dups) option"
54//config: default y
55//config: depends on SYSLOGD
56//config: help
57//config: Option -D instructs syslogd to drop consecutive messages
58//config: which are totally the same.
59//config:
60//config:config FEATURE_SYSLOGD_CFG
61//config: bool "Support syslog.conf"
62//config: default y
63//config: depends on SYSLOGD
64//config: help
65//config: Supports restricted syslogd config. See docs/syslog.conf.txt
66//config:
67//config:config FEATURE_SYSLOGD_READ_BUFFER_SIZE
68//config: int "Read buffer size in bytes"
69//config: default 256
70//config: range 256 20000
71//config: depends on SYSLOGD
72//config: help
73//config: This option sets the size of the syslog read buffer.
74//config: Actual memory usage increases around five times the
75//config: change done here.
76//config:
77//config:config FEATURE_IPC_SYSLOG
78//config: bool "Circular Buffer support"
79//config: default y
80//config: depends on SYSLOGD
81//config: help
82//config: When you enable this feature, the syslogd utility will
83//config: use a circular buffer to record system log messages.
84//config: When the buffer is filled it will continue to overwrite
85//config: the oldest messages. This can be very useful for
86//config: systems with little or no permanent storage, since
87//config: otherwise system logs can eventually fill up your
88//config: entire filesystem, which may cause your system to
89//config: break badly.
90//config:
91//config:config FEATURE_IPC_SYSLOG_BUFFER_SIZE
92//config: int "Circular buffer size in Kbytes (minimum 4KB)"
93//config: default 16
94//config: range 4 2147483647
95//config: depends on FEATURE_IPC_SYSLOG
96//config: help
97//config: This option sets the size of the circular buffer
98//config: used to record system log messages.
99//config:
100//config:config FEATURE_KMSG_SYSLOG
101//config: bool "Linux kernel printk buffer support"
102//config: default y
103//config: depends on SYSLOGD
104//config: select PLATFORM_LINUX
105//config: help
106//config: When you enable this feature, the syslogd utility will
107//config: write system log message to the Linux kernel's printk buffer.
108//config: This can be used as a smaller alternative to the syslogd IPC
109//config: support, as klogd and logread aren't needed.
110//config:
111//config: NOTICE: Syslog facilities in log entries needs kernel 3.5+.
112
113//applet:IF_SYSLOGD(APPLET(syslogd, BB_DIR_SBIN, BB_SUID_DROP))
114
115//kbuild:lib-$(CONFIG_SYSLOGD) += syslogd_and_logger.o
15 116
16//usage:#define syslogd_trivial_usage 117//usage:#define syslogd_trivial_usage
17//usage: "[OPTIONS]" 118//usage: "[OPTIONS]"
diff --git a/util-linux/mdev.c b/util-linux/mdev.c
index 51781d597..37fa56827 100644
--- a/util-linux/mdev.c
+++ b/util-linux/mdev.c
@@ -400,7 +400,7 @@ static void parse_next_rule(void)
400 } 400 }
401 401
402 /* 2nd field: uid:gid - device ownership */ 402 /* 2nd field: uid:gid - device ownership */
403 if (get_uidgid(&G.cur_rule.ugid, tokens[1], /*allow_numeric:*/ 1) == 0) { 403 if (get_uidgid(&G.cur_rule.ugid, tokens[1]) == 0) {
404 bb_error_msg("unknown user/group '%s' on line %d", tokens[1], G.parser->lineno); 404 bb_error_msg("unknown user/group '%s' on line %d", tokens[1], G.parser->lineno);
405 goto next_rule; 405 goto next_rule;
406 } 406 }