aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2016-04-04 16:22:54 +0100
committerRon Yorston <rmy@pobox.com>2016-04-04 16:22:54 +0100
commit253dbd612b2d2f041f4263e15a3b94df70f41e36 (patch)
treef6c6e12a0541233058a7f7ccb1251afeb457da06
parent3cf56a021d7a62512b477640e930e1a78288075c (diff)
parentd7d4750e1e213e7448147186dddfe3bfbb47eea0 (diff)
downloadbusybox-w32-253dbd612b2d2f041f4263e15a3b94df70f41e36.tar.gz
busybox-w32-253dbd612b2d2f041f4263e15a3b94df70f41e36.tar.bz2
busybox-w32-253dbd612b2d2f041f4263e15a3b94df70f41e36.zip
Merge branch 'busybox' into merge
-rw-r--r--applets/applet_tables.c93
-rw-r--r--archival/libarchive/data_extract_to_command.c3
-rw-r--r--configs/TEST_nommu_defconfig2
-rw-r--r--configs/TEST_noprintf_defconfig2
-rw-r--r--configs/TEST_rh9_defconfig2
-rw-r--r--configs/android2_defconfig2
-rw-r--r--configs/android_502_defconfig1142
-rw-r--r--configs/android_defconfig2
-rw-r--r--configs/android_ndk_defconfig2
-rw-r--r--configs/cygwin_defconfig2
-rw-r--r--configs/freebsd_defconfig2
-rw-r--r--coreutils/ls.c6
-rw-r--r--coreutils/sort.c15
-rw-r--r--e2fsprogs/fsck.c8
-rwxr-xr-xexamples/undeb74
-rwxr-xr-xexamples/unrpm65
-rw-r--r--findutils/grep.c8
-rw-r--r--include/busybox.h15
-rw-r--r--include/libbb.h32
-rw-r--r--init/halt.c2
-rw-r--r--init/init.c41
-rw-r--r--libbb/Kbuild.src2
-rw-r--r--libbb/appletlib.c166
-rw-r--r--libbb/executable.c11
-rw-r--r--libbb/info_msg.c62
-rw-r--r--libbb/ubi.c43
-rw-r--r--libbb/verror_msg.c29
-rw-r--r--libbb/vfork_daemon_rexec.c3
-rw-r--r--libbb/xfuncs.c12
-rw-r--r--libbb/xfuncs_printf.c22
-rw-r--r--loginutils/chpasswd.c2
-rw-r--r--loginutils/cryptpw.c32
-rw-r--r--loginutils/passwd.c2
-rw-r--r--loginutils/sulogin.c29
-rw-r--r--mailutils/sendmail.c2
-rw-r--r--miscutils/beep.c2
-rw-r--r--miscutils/devfsd.c2
-rw-r--r--miscutils/eject.c26
-rw-r--r--miscutils/flash_eraseall.c2
-rw-r--r--miscutils/inotifyd.c4
-rw-r--r--miscutils/taskset.c37
-rw-r--r--miscutils/ubi_tools.c29
-rw-r--r--miscutils/ubirename.c94
-rw-r--r--modutils/modprobe.c22
-rw-r--r--networking/ifupdown.c17
-rw-r--r--networking/inetd.c8
-rw-r--r--networking/ntpd.c50
-rw-r--r--networking/ntpd.diff24
-rw-r--r--networking/traceroute.c2
-rw-r--r--networking/tunctl.c2
-rw-r--r--networking/udhcp/arpping.c2
-rw-r--r--networking/udhcp/common.c27
-rw-r--r--networking/udhcp/common.h6
-rw-r--r--networking/udhcp/d6_dhcpc.c60
-rw-r--r--networking/udhcp/d6_packet.c12
-rw-r--r--networking/udhcp/d6_socket.c2
-rw-r--r--networking/udhcp/dhcpc.c88
-rw-r--r--networking/udhcp/dhcpd.c34
-rw-r--r--networking/udhcp/domain_codec.c21
-rw-r--r--networking/udhcp/files.c8
-rw-r--r--networking/udhcp/leases.c6
-rw-r--r--networking/udhcp/packet.c12
-rw-r--r--networking/udhcp/socket.c4
-rw-r--r--networking/udhcp/static_leases.c2
-rw-r--r--networking/wget.c22
-rw-r--r--networking/zcip.c4
-rw-r--r--procps/nmeter.c200
-rw-r--r--procps/renice.c13
-rw-r--r--runit/chpst.c3
-rwxr-xr-x[-rw-r--r--]scripts/kconfig/lxdialog/check-lxdialog.sh17
-rwxr-xr-xscripts/trylink2
-rw-r--r--selinux/setfiles.c7
-rw-r--r--shell/ash.c2
-rw-r--r--shell/ash_test/.gitignore7
-rw-r--r--shell/ash_test/ash-vars/var-utf8-length.right1
-rwxr-xr-xshell/ash_test/ash-vars/var-utf8-length.tests2
-rw-r--r--shell/ash_test/printenv.c1
-rw-r--r--sysklogd/syslogd.c4
-rw-r--r--util-linux/fbset.c18
-rw-r--r--util-linux/minix.h5
-rw-r--r--util-linux/mkfs_ext2.c10
-rw-r--r--util-linux/mkfs_vfat.c4
-rw-r--r--util-linux/nsenter.c291
-rw-r--r--util-linux/umount.c3
-rw-r--r--util-linux/unshare.c380
85 files changed, 2897 insertions, 641 deletions
diff --git a/applets/applet_tables.c b/applets/applet_tables.c
index 92bf1e447..843f2ec08 100644
--- a/applets/applet_tables.c
+++ b/applets/applet_tables.c
@@ -41,8 +41,6 @@ struct bb_applet {
41 41
42enum { NUM_APPLETS = ARRAY_SIZE(applets) }; 42enum { NUM_APPLETS = ARRAY_SIZE(applets) };
43 43
44static int offset[NUM_APPLETS];
45
46static int cmp_name(const void *a, const void *b) 44static int cmp_name(const void *a, const void *b)
47{ 45{
48 const struct bb_applet *aa = a; 46 const struct bb_applet *aa = a;
@@ -62,24 +60,30 @@ static int str_isalnum_(const char *s)
62 60
63int main(int argc, char **argv) 61int main(int argc, char **argv)
64{ 62{
65 int i; 63 int i, j;
66 int ofs; 64
67// unsigned MAX_APPLET_NAME_LEN = 1; 65 // In find_applet_by_name(), before linear search, narrow it down
66 // by looking at N "equidistant" names. With ~350 applets:
67 // KNOWN_APPNAME_OFFSETS cycles
68 // 0 9057
69 // 2 4604 + ~100 bytes of code
70 // 4 2407 + 4 bytes
71 // 8 1342 + 8 bytes
72 // 16 908 + 16 bytes
73 // 32 884 + 32 bytes
74 // With 8, int16_t applet_nameofs[] table has 7 elements.
75 int KNOWN_APPNAME_OFFSETS = 8;
76 // With 128 applets we do two linear searches, with 1..7 strcmp's in the first one
77 // and 1..16 strcmp's in the second. With 256 apps, second search does 1..32 strcmp's.
78 if (NUM_APPLETS < 128)
79 KNOWN_APPNAME_OFFSETS = 4;
80 if (NUM_APPLETS < 32)
81 KNOWN_APPNAME_OFFSETS = 0;
68 82
69 qsort(applets, NUM_APPLETS, sizeof(applets[0]), cmp_name); 83 qsort(applets, NUM_APPLETS, sizeof(applets[0]), cmp_name);
70 84
71 ofs = 0;
72 for (i = 0; i < NUM_APPLETS; i++) {
73 offset[i] = ofs;
74 ofs += strlen(applets[i].name) + 1;
75 }
76 /* We reuse 4 high-order bits of offset array for other purposes,
77 * so if they are indeed needed, refuse to proceed */
78 if (ofs > 0xfff)
79 return 1;
80 if (!argv[1]) 85 if (!argv[1])
81 return 1; 86 return 1;
82
83 i = open(argv[1], O_WRONLY | O_TRUNC | O_CREAT, 0666); 87 i = open(argv[1], O_WRONLY | O_TRUNC | O_CREAT, 0666);
84 if (i < 0) 88 if (i < 0)
85 return 1; 89 return 1;
@@ -94,7 +98,27 @@ int main(int argc, char **argv)
94 printf("#define SINGLE_APPLET_STR \"%s\"\n", applets[0].name); 98 printf("#define SINGLE_APPLET_STR \"%s\"\n", applets[0].name);
95 printf("#define SINGLE_APPLET_MAIN %s_main\n", applets[0].main); 99 printf("#define SINGLE_APPLET_MAIN %s_main\n", applets[0].main);
96 } 100 }
97 printf("\n"); 101
102 printf("#define KNOWN_APPNAME_OFFSETS %u\n\n", KNOWN_APPNAME_OFFSETS);
103 if (KNOWN_APPNAME_OFFSETS > 0) {
104 int ofs, offset[KNOWN_APPNAME_OFFSETS], index[KNOWN_APPNAME_OFFSETS];
105 for (i = 0; i < KNOWN_APPNAME_OFFSETS; i++)
106 index[i] = i * NUM_APPLETS / KNOWN_APPNAME_OFFSETS;
107 ofs = 0;
108 for (i = 0; i < NUM_APPLETS; i++) {
109 for (j = 0; j < KNOWN_APPNAME_OFFSETS; j++)
110 if (i == index[j])
111 offset[j] = ofs;
112 ofs += strlen(applets[i].name) + 1;
113 }
114 /* If the list of names is too long refuse to proceed */
115 if (ofs > 0xffff)
116 return 1;
117 printf("const uint16_t applet_nameofs[] ALIGN2 = {\n");
118 for (i = 1; i < KNOWN_APPNAME_OFFSETS; i++)
119 printf("%d,\n", offset[i]);
120 printf("};\n\n");
121 }
98 122
99 //printf("#ifndef SKIP_definitions\n"); 123 //printf("#ifndef SKIP_definitions\n");
100 printf("const char applet_names[] ALIGN1 = \"\"\n"); 124 printf("const char applet_names[] ALIGN1 = \"\"\n");
@@ -119,20 +143,39 @@ int main(int argc, char **argv)
119 printf("};\n"); 143 printf("};\n");
120 printf("#endif\n\n"); 144 printf("#endif\n\n");
121 145
122 printf("const uint16_t applet_nameofs[] ALIGN2 = {\n");
123 for (i = 0; i < NUM_APPLETS; i++) {
124 printf("0x%04x,\n",
125 offset[i]
126#if ENABLE_FEATURE_PREFER_APPLETS 146#if ENABLE_FEATURE_PREFER_APPLETS
127 + (applets[i].nofork << 12) 147 printf("const uint8_t applet_flags[] ALIGN1 = {\n");
128 + (applets[i].noexec << 13) 148 i = 0;
149 while (i < NUM_APPLETS) {
150 int v = applets[i].nofork + (applets[i].noexec << 1);
151 if (++i < NUM_APPLETS)
152 v |= (applets[i].nofork + (applets[i].noexec << 1)) << 2;
153 if (++i < NUM_APPLETS)
154 v |= (applets[i].nofork + (applets[i].noexec << 1)) << 4;
155 if (++i < NUM_APPLETS)
156 v |= (applets[i].nofork + (applets[i].noexec << 1)) << 6;
157 printf("0x%02x,\n", v);
158 i++;
159 }
160 printf("};\n\n");
129#endif 161#endif
162
130#if ENABLE_FEATURE_SUID 163#if ENABLE_FEATURE_SUID
131 + (applets[i].need_suid << 14) /* 2 bits */ 164 printf("const uint8_t applet_suid[] ALIGN1 = {\n");
132#endif 165 i = 0;
133 ); 166 while (i < NUM_APPLETS) {
167 int v = applets[i].need_suid; /* 2 bits */
168 if (++i < NUM_APPLETS)
169 v |= applets[i].need_suid << 2;
170 if (++i < NUM_APPLETS)
171 v |= applets[i].need_suid << 4;
172 if (++i < NUM_APPLETS)
173 v |= applets[i].need_suid << 6;
174 printf("0x%02x,\n", v);
175 i++;
134 } 176 }
135 printf("};\n\n"); 177 printf("};\n\n");
178#endif
136 179
137#if ENABLE_FEATURE_INSTALLER 180#if ENABLE_FEATURE_INSTALLER
138 printf("const uint8_t applet_install_loc[] ALIGN1 = {\n"); 181 printf("const uint8_t applet_install_loc[] ALIGN1 = {\n");
diff --git a/archival/libarchive/data_extract_to_command.c b/archival/libarchive/data_extract_to_command.c
index 6f5317a0e..5d8769382 100644
--- a/archival/libarchive/data_extract_to_command.c
+++ b/archival/libarchive/data_extract_to_command.c
@@ -112,8 +112,7 @@ void FAST_FUNC data_extract_to_command(archive_handle_t *archive_handle)
112 bb_copyfd_exact_size(archive_handle->src_fd, p[1], -file_header->size); 112 bb_copyfd_exact_size(archive_handle->src_fd, p[1], -file_header->size);
113 close(p[1]); 113 close(p[1]);
114 114
115 if (safe_waitpid(pid, &status, 0) == -1) 115 status = wait_for_exitstatus(pid);
116 bb_perror_msg_and_die("waitpid");
117 if (WIFEXITED(status) && WEXITSTATUS(status)) 116 if (WIFEXITED(status) && WEXITSTATUS(status))
118 bb_error_msg_and_die("'%s' returned status %d", 117 bb_error_msg_and_die("'%s' returned status %d",
119 archive_handle->tar__to_command, WEXITSTATUS(status)); 118 archive_handle->tar__to_command, WEXITSTATUS(status));
diff --git a/configs/TEST_nommu_defconfig b/configs/TEST_nommu_defconfig
index b45afd956..5f822e598 100644
--- a/configs/TEST_nommu_defconfig
+++ b/configs/TEST_nommu_defconfig
@@ -390,7 +390,7 @@ CONFIG_FEATURE_INIT_SCTTY=y
390CONFIG_FEATURE_INIT_SYSLOG=y 390CONFIG_FEATURE_INIT_SYSLOG=y
391CONFIG_FEATURE_EXTRA_QUIET=y 391CONFIG_FEATURE_EXTRA_QUIET=y
392CONFIG_FEATURE_INIT_COREDUMPS=y 392CONFIG_FEATURE_INIT_COREDUMPS=y
393CONFIG_FEATURE_INITRD=y 393CONFIG_LINUXRC=y
394CONFIG_HALT=y 394CONFIG_HALT=y
395# CONFIG_FEATURE_CALL_TELINIT is not set 395# CONFIG_FEATURE_CALL_TELINIT is not set
396CONFIG_TELINIT_PATH="" 396CONFIG_TELINIT_PATH=""
diff --git a/configs/TEST_noprintf_defconfig b/configs/TEST_noprintf_defconfig
index 809b60cd8..c56781e32 100644
--- a/configs/TEST_noprintf_defconfig
+++ b/configs/TEST_noprintf_defconfig
@@ -395,7 +395,7 @@ CONFIG_FEATURE_KILL_DELAY=0
395# CONFIG_FEATURE_INIT_SYSLOG is not set 395# CONFIG_FEATURE_INIT_SYSLOG is not set
396# CONFIG_FEATURE_EXTRA_QUIET is not set 396# CONFIG_FEATURE_EXTRA_QUIET is not set
397# CONFIG_FEATURE_INIT_COREDUMPS is not set 397# CONFIG_FEATURE_INIT_COREDUMPS is not set
398# CONFIG_FEATURE_INITRD is not set 398# CONFIG_LINUXRC is not set
399# CONFIG_HALT is not set 399# CONFIG_HALT is not set
400# CONFIG_FEATURE_CALL_TELINIT is not set 400# CONFIG_FEATURE_CALL_TELINIT is not set
401CONFIG_TELINIT_PATH="" 401CONFIG_TELINIT_PATH=""
diff --git a/configs/TEST_rh9_defconfig b/configs/TEST_rh9_defconfig
index 565b826d0..28daa6273 100644
--- a/configs/TEST_rh9_defconfig
+++ b/configs/TEST_rh9_defconfig
@@ -407,7 +407,7 @@ CONFIG_FEATURE_INIT_SCTTY=y
407CONFIG_FEATURE_INIT_SYSLOG=y 407CONFIG_FEATURE_INIT_SYSLOG=y
408CONFIG_FEATURE_EXTRA_QUIET=y 408CONFIG_FEATURE_EXTRA_QUIET=y
409CONFIG_FEATURE_INIT_COREDUMPS=y 409CONFIG_FEATURE_INIT_COREDUMPS=y
410CONFIG_FEATURE_INITRD=y 410CONFIG_LINUXRC=y
411CONFIG_HALT=y 411CONFIG_HALT=y
412# CONFIG_FEATURE_CALL_TELINIT is not set 412# CONFIG_FEATURE_CALL_TELINIT is not set
413CONFIG_TELINIT_PATH="" 413CONFIG_TELINIT_PATH=""
diff --git a/configs/android2_defconfig b/configs/android2_defconfig
index 1095094fe..fbc0da091 100644
--- a/configs/android2_defconfig
+++ b/configs/android2_defconfig
@@ -425,7 +425,7 @@ CONFIG_FEATURE_INIT_SCTTY=y
425CONFIG_FEATURE_INIT_SYSLOG=y 425CONFIG_FEATURE_INIT_SYSLOG=y
426CONFIG_FEATURE_EXTRA_QUIET=y 426CONFIG_FEATURE_EXTRA_QUIET=y
427CONFIG_FEATURE_INIT_COREDUMPS=y 427CONFIG_FEATURE_INIT_COREDUMPS=y
428CONFIG_FEATURE_INITRD=y 428CONFIG_LINUXRC=y
429CONFIG_INIT_TERMINAL_TYPE="linux" 429CONFIG_INIT_TERMINAL_TYPE="linux"
430CONFIG_MESG=y 430CONFIG_MESG=y
431CONFIG_FEATURE_MESG_ENABLE_ONLY_GROUP=y 431CONFIG_FEATURE_MESG_ENABLE_ONLY_GROUP=y
diff --git a/configs/android_502_defconfig b/configs/android_502_defconfig
new file mode 100644
index 000000000..7ef1585fb
--- /dev/null
+++ b/configs/android_502_defconfig
@@ -0,0 +1,1142 @@
1## This config was successfully used to build busybox on
2## Samsung SM-T700 tablet
3## Android 5.0.2
4## gcc/toolchain from https://termux.com/
5## binutils 2.26.20160125
6## gcc 4.9.3
7## bionic ANDROID_API 21
8##
9## Static build did not work (static libraries not installed?):
10## # CONFIG_STATIC is not set
11## syslog() requires an additional library:
12## CONFIG_EXTRA_LDLIBS="log"
13## Bionic's botched off_t:
14## # CONFIG_LFS is not set
15##
16## Incompatible password database API:
17## # CONFIG_FEATURE_SHADOWPASSWDS is not set
18## # CONFIG_USE_BB_PWD_GRP is not set
19## # CONFIG_USE_BB_SHADOW is not set
20## # CONFIG_ADDUSER is not set
21## # CONFIG_ADDGROUP is not set
22## # CONFIG_DELUSER is not set
23## # CONFIG_DELGROUP is not set
24##
25## No utmp/wtmp:
26## # CONFIG_FEATURE_UTMP is not set
27## # CONFIG_FEATURE_WTMP is not set
28## # CONFIG_WHO is not set
29## # CONFIG_LAST is not set
30## # CONFIG_USERS is not set
31## # CONFIG_WALL is not set
32##
33## Assorted header problems:
34## # CONFIG_HOSTID is not set
35## # CONFIG_FEATURE_SYNC_FANCY is not set - syncfs()
36## # CONFIG_FEATURE_TOUCH_NODEREF is not set - lutimes()
37## # CONFIG_LOGNAME is not set - getlogin_r()
38## # CONFIG_LOADFONT is not set
39## # CONFIG_SETFONT is not set
40## # CONFIG_MDEV is not set
41## # CONFIG_FSCK_MINIX is not set
42## # CONFIG_MKFS_MINIX is not set
43## # CONFIG_IPCRM is not set
44## # CONFIG_IPCS is not set
45## # CONFIG_SWAPONOFF is not set
46## # CONFIG_CONSPY is not set
47## # CONFIG_NANDWRITE is not set
48## # CONFIG_NANDDUMP is not set
49## # CONFIG_RFKILL is not set
50## # CONFIG_UBIATTACH is not set
51## # CONFIG_UBIDETACH is not set
52## # CONFIG_UBIMKVOL is not set
53## # CONFIG_UBIRMVOL is not set
54## # CONFIG_UBIRSVOL is not set
55## # CONFIG_UBIUPDATEVOL is not set
56## # CONFIG_FEATURE_EJECT_SCSI is not set - scsi headers
57## # CONFIG_ARP is not set
58## # CONFIG_ARPING is not set
59## # CONFIG_ETHER_WAKE is not set
60## # CONFIG_IFCONFIG is not set
61## # CONFIG_IFENSLAVE is not set
62## # CONFIG_NSLOOKUP is not set
63## # CONFIG_ROUTE is not set
64## # CONFIG_ZCIP is not set
65## # CONFIG_HUSH is not set - glob.h
66## # CONFIG_KLOGD is not set
67## # CONFIG_LOGGER is not set
68## # CONFIG_LOGREAD is not set
69## # CONFIG_SYSLOGD is not set
70##-----------------------------------------------
71
72#
73# Automatically generated make config: don't edit
74# Busybox version: 1.25.0.git
75# Mon Mar 14 20:43:42 2016
76#
77CONFIG_HAVE_DOT_CONFIG=y
78
79#
80# Busybox Settings
81#
82
83#
84# General Configuration
85#
86CONFIG_DESKTOP=y
87# CONFIG_EXTRA_COMPAT is not set
88CONFIG_INCLUDE_SUSv2=y
89# CONFIG_USE_PORTABLE_CODE is not set
90CONFIG_PLATFORM_LINUX=y
91CONFIG_FEATURE_BUFFERS_USE_MALLOC=y
92# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set
93# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set
94CONFIG_SHOW_USAGE=y
95CONFIG_FEATURE_VERBOSE_USAGE=y
96CONFIG_FEATURE_COMPRESS_USAGE=y
97CONFIG_FEATURE_INSTALLER=y
98# CONFIG_INSTALL_NO_USR is not set
99# CONFIG_LOCALE_SUPPORT is not set
100CONFIG_UNICODE_SUPPORT=y
101# CONFIG_UNICODE_USING_LOCALE is not set
102# CONFIG_FEATURE_CHECK_UNICODE_IN_ENV is not set
103CONFIG_SUBST_WCHAR=63
104CONFIG_LAST_SUPPORTED_WCHAR=767
105# CONFIG_UNICODE_COMBINING_WCHARS is not set
106# CONFIG_UNICODE_WIDE_WCHARS is not set
107# CONFIG_UNICODE_BIDI_SUPPORT is not set
108# CONFIG_UNICODE_NEUTRAL_TABLE is not set
109# CONFIG_UNICODE_PRESERVE_BROKEN is not set
110# CONFIG_PAM is not set
111CONFIG_FEATURE_USE_SENDFILE=y
112CONFIG_LONG_OPTS=y
113CONFIG_FEATURE_DEVPTS=y
114# CONFIG_FEATURE_CLEAN_UP is not set
115# CONFIG_FEATURE_UTMP is not set
116# CONFIG_FEATURE_WTMP is not set
117CONFIG_FEATURE_PIDFILE=y
118CONFIG_PID_FILE_PATH="/var/run"
119CONFIG_FEATURE_SUID=y
120CONFIG_FEATURE_SUID_CONFIG=y
121CONFIG_FEATURE_SUID_CONFIG_QUIET=y
122# CONFIG_SELINUX is not set
123# CONFIG_FEATURE_PREFER_APPLETS is not set
124CONFIG_BUSYBOX_EXEC_PATH="/proc/self/exe"
125CONFIG_FEATURE_SYSLOG=y
126# CONFIG_FEATURE_HAVE_RPC is not set
127
128#
129# Build Options
130#
131# CONFIG_STATIC is not set
132# CONFIG_PIE is not set
133# CONFIG_NOMMU is not set
134# CONFIG_BUILD_LIBBUSYBOX is not set
135# CONFIG_FEATURE_INDIVIDUAL is not set
136# CONFIG_FEATURE_SHARED_BUSYBOX is not set
137# CONFIG_LFS is not set
138CONFIG_CROSS_COMPILER_PREFIX=""
139CONFIG_SYSROOT=""
140CONFIG_EXTRA_CFLAGS=""
141CONFIG_EXTRA_LDFLAGS=""
142CONFIG_EXTRA_LDLIBS="log"
143
144#
145# Debugging Options
146#
147# CONFIG_DEBUG is not set
148# CONFIG_DEBUG_PESSIMIZE is not set
149# CONFIG_DEBUG_SANITIZE is not set
150# CONFIG_UNIT_TEST is not set
151# CONFIG_WERROR is not set
152CONFIG_NO_DEBUG_LIB=y
153# CONFIG_DMALLOC is not set
154# CONFIG_EFENCE is not set
155
156#
157# Installation Options ("make install" behavior)
158#
159CONFIG_INSTALL_APPLET_SYMLINKS=y
160# CONFIG_INSTALL_APPLET_HARDLINKS is not set
161# CONFIG_INSTALL_APPLET_SCRIPT_WRAPPERS is not set
162# CONFIG_INSTALL_APPLET_DONT is not set
163# CONFIG_INSTALL_SH_APPLET_SYMLINK is not set
164# CONFIG_INSTALL_SH_APPLET_HARDLINK is not set
165# CONFIG_INSTALL_SH_APPLET_SCRIPT_WRAPPER is not set
166CONFIG_PREFIX="./_install"
167
168#
169# Busybox Library Tuning
170#
171CONFIG_FEATURE_RTMINMAX=y
172CONFIG_PASSWORD_MINLEN=6
173CONFIG_MD5_SMALL=1
174CONFIG_SHA3_SMALL=1
175# CONFIG_FEATURE_FAST_TOP is not set
176# CONFIG_FEATURE_ETC_NETWORKS is not set
177CONFIG_FEATURE_USE_TERMIOS=y
178CONFIG_FEATURE_EDITING=y
179CONFIG_FEATURE_EDITING_MAX_LEN=1024
180# CONFIG_FEATURE_EDITING_VI is not set
181CONFIG_FEATURE_EDITING_HISTORY=255
182CONFIG_FEATURE_EDITING_SAVEHISTORY=y
183# CONFIG_FEATURE_EDITING_SAVE_ON_EXIT is not set
184CONFIG_FEATURE_REVERSE_SEARCH=y
185CONFIG_FEATURE_TAB_COMPLETION=y
186# CONFIG_FEATURE_USERNAME_COMPLETION is not set
187CONFIG_FEATURE_EDITING_FANCY_PROMPT=y
188# CONFIG_FEATURE_EDITING_ASK_TERMINAL is not set
189CONFIG_FEATURE_NON_POSIX_CP=y
190# CONFIG_FEATURE_VERBOSE_CP_MESSAGE is not set
191CONFIG_FEATURE_COPYBUF_KB=4
192CONFIG_FEATURE_SKIP_ROOTFS=y
193CONFIG_MONOTONIC_SYSCALL=y
194CONFIG_IOCTL_HEX2STR_ERROR=y
195CONFIG_FEATURE_HWIB=y
196
197#
198# Applets
199#
200
201#
202# Archival Utilities
203#
204CONFIG_FEATURE_SEAMLESS_XZ=y
205CONFIG_FEATURE_SEAMLESS_LZMA=y
206CONFIG_FEATURE_SEAMLESS_BZ2=y
207CONFIG_FEATURE_SEAMLESS_GZ=y
208# CONFIG_FEATURE_SEAMLESS_Z is not set
209# CONFIG_AR is not set
210# CONFIG_FEATURE_AR_LONG_FILENAMES is not set
211# CONFIG_FEATURE_AR_CREATE is not set
212# CONFIG_UNCOMPRESS is not set
213CONFIG_GUNZIP=y
214CONFIG_FEATURE_GUNZIP_LONG_OPTIONS=y
215CONFIG_BUNZIP2=y
216CONFIG_UNLZMA=y
217# CONFIG_FEATURE_LZMA_FAST is not set
218CONFIG_LZMA=y
219CONFIG_UNXZ=y
220CONFIG_XZ=y
221CONFIG_BZIP2=y
222CONFIG_CPIO=y
223CONFIG_FEATURE_CPIO_O=y
224CONFIG_FEATURE_CPIO_P=y
225# CONFIG_DPKG is not set
226# CONFIG_DPKG_DEB is not set
227# CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY is not set
228CONFIG_GZIP=y
229CONFIG_FEATURE_GZIP_LONG_OPTIONS=y
230CONFIG_GZIP_FAST=0
231# CONFIG_FEATURE_GZIP_LEVELS is not set
232CONFIG_LZOP=y
233# CONFIG_LZOP_COMPR_HIGH is not set
234CONFIG_RPM=y
235CONFIG_RPM2CPIO=y
236CONFIG_TAR=y
237CONFIG_FEATURE_TAR_CREATE=y
238CONFIG_FEATURE_TAR_AUTODETECT=y
239CONFIG_FEATURE_TAR_FROM=y
240CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY=y
241CONFIG_FEATURE_TAR_OLDSUN_COMPATIBILITY=y
242CONFIG_FEATURE_TAR_GNU_EXTENSIONS=y
243CONFIG_FEATURE_TAR_LONG_OPTIONS=y
244CONFIG_FEATURE_TAR_TO_COMMAND=y
245CONFIG_FEATURE_TAR_UNAME_GNAME=y
246CONFIG_FEATURE_TAR_NOPRESERVE_TIME=y
247# CONFIG_FEATURE_TAR_SELINUX is not set
248CONFIG_UNZIP=y
249
250#
251# Coreutils
252#
253CONFIG_BASENAME=y
254CONFIG_CAT=y
255CONFIG_DATE=y
256CONFIG_FEATURE_DATE_ISOFMT=y
257# CONFIG_FEATURE_DATE_NANO is not set
258CONFIG_FEATURE_DATE_COMPAT=y
259CONFIG_DD=y
260CONFIG_FEATURE_DD_SIGNAL_HANDLING=y
261CONFIG_FEATURE_DD_THIRD_STATUS_LINE=y
262CONFIG_FEATURE_DD_IBS_OBS=y
263CONFIG_FEATURE_DD_STATUS=y
264# CONFIG_HOSTID is not set
265CONFIG_ID=y
266CONFIG_GROUPS=y
267CONFIG_SHUF=y
268CONFIG_STAT=y
269CONFIG_FEATURE_STAT_FORMAT=y
270CONFIG_FEATURE_STAT_FILESYSTEM=y
271CONFIG_SYNC=y
272# CONFIG_FEATURE_SYNC_FANCY is not set
273CONFIG_TEST=y
274CONFIG_FEATURE_TEST_64=y
275CONFIG_TOUCH=y
276# CONFIG_FEATURE_TOUCH_NODEREF is not set
277CONFIG_FEATURE_TOUCH_SUSV3=y
278CONFIG_TR=y
279CONFIG_FEATURE_TR_CLASSES=y
280CONFIG_FEATURE_TR_EQUIV=y
281CONFIG_TRUNCATE=y
282CONFIG_UNLINK=y
283CONFIG_BASE64=y
284# CONFIG_WHO is not set
285# CONFIG_USERS is not set
286CONFIG_CAL=y
287CONFIG_CATV=y
288CONFIG_CHGRP=y
289CONFIG_CHMOD=y
290CONFIG_CHOWN=y
291CONFIG_FEATURE_CHOWN_LONG_OPTIONS=y
292CONFIG_CHROOT=y
293CONFIG_CKSUM=y
294CONFIG_COMM=y
295CONFIG_CP=y
296CONFIG_FEATURE_CP_LONG_OPTIONS=y
297CONFIG_CUT=y
298CONFIG_DF=y
299CONFIG_FEATURE_DF_FANCY=y
300CONFIG_DIRNAME=y
301CONFIG_DOS2UNIX=y
302CONFIG_UNIX2DOS=y
303CONFIG_DU=y
304CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K=y
305CONFIG_ECHO=y
306CONFIG_FEATURE_FANCY_ECHO=y
307CONFIG_ENV=y
308CONFIG_FEATURE_ENV_LONG_OPTIONS=y
309CONFIG_EXPAND=y
310CONFIG_FEATURE_EXPAND_LONG_OPTIONS=y
311CONFIG_EXPR=y
312CONFIG_EXPR_MATH_SUPPORT_64=y
313CONFIG_FALSE=y
314CONFIG_FOLD=y
315CONFIG_FSYNC=y
316CONFIG_HEAD=y
317CONFIG_FEATURE_FANCY_HEAD=y
318CONFIG_INSTALL=y
319CONFIG_FEATURE_INSTALL_LONG_OPTIONS=y
320CONFIG_LN=y
321# CONFIG_LOGNAME is not set
322CONFIG_LS=y
323CONFIG_FEATURE_LS_FILETYPES=y
324CONFIG_FEATURE_LS_FOLLOWLINKS=y
325CONFIG_FEATURE_LS_RECURSIVE=y
326CONFIG_FEATURE_LS_SORTFILES=y
327CONFIG_FEATURE_LS_TIMESTAMPS=y
328CONFIG_FEATURE_LS_USERNAME=y
329CONFIG_FEATURE_LS_COLOR=y
330CONFIG_FEATURE_LS_COLOR_IS_DEFAULT=y
331CONFIG_MD5SUM=y
332CONFIG_MKDIR=y
333CONFIG_FEATURE_MKDIR_LONG_OPTIONS=y
334CONFIG_MKFIFO=y
335CONFIG_MKNOD=y
336CONFIG_MV=y
337CONFIG_FEATURE_MV_LONG_OPTIONS=y
338CONFIG_NICE=y
339CONFIG_NOHUP=y
340CONFIG_OD=y
341CONFIG_PRINTENV=y
342CONFIG_PRINTF=y
343CONFIG_PWD=y
344CONFIG_READLINK=y
345CONFIG_FEATURE_READLINK_FOLLOW=y
346CONFIG_REALPATH=y
347CONFIG_RM=y
348CONFIG_RMDIR=y
349CONFIG_FEATURE_RMDIR_LONG_OPTIONS=y
350CONFIG_SEQ=y
351CONFIG_SHA1SUM=y
352CONFIG_SHA256SUM=y
353CONFIG_SHA512SUM=y
354CONFIG_SHA3SUM=y
355CONFIG_SLEEP=y
356CONFIG_FEATURE_FANCY_SLEEP=y
357CONFIG_FEATURE_FLOAT_SLEEP=y
358CONFIG_SORT=y
359CONFIG_FEATURE_SORT_BIG=y
360CONFIG_SPLIT=y
361CONFIG_FEATURE_SPLIT_FANCY=y
362CONFIG_STTY=y
363CONFIG_SUM=y
364CONFIG_TAC=y
365CONFIG_TAIL=y
366CONFIG_FEATURE_FANCY_TAIL=y
367CONFIG_TEE=y
368CONFIG_FEATURE_TEE_USE_BLOCK_IO=y
369CONFIG_TRUE=y
370CONFIG_TTY=y
371CONFIG_UNAME=y
372CONFIG_UNAME_OSNAME="GNU/Linux"
373CONFIG_UNEXPAND=y
374CONFIG_FEATURE_UNEXPAND_LONG_OPTIONS=y
375CONFIG_UNIQ=y
376CONFIG_USLEEP=y
377CONFIG_UUDECODE=y
378CONFIG_UUENCODE=y
379CONFIG_WC=y
380CONFIG_FEATURE_WC_LARGE=y
381CONFIG_WHOAMI=y
382CONFIG_YES=y
383
384#
385# Common options
386#
387CONFIG_FEATURE_VERBOSE=y
388
389#
390# Common options for cp and mv
391#
392CONFIG_FEATURE_PRESERVE_HARDLINKS=y
393
394#
395# Common options for ls, more and telnet
396#
397CONFIG_FEATURE_AUTOWIDTH=y
398
399#
400# Common options for df, du, ls
401#
402CONFIG_FEATURE_HUMAN_READABLE=y
403
404#
405# Common options for md5sum, sha1sum, sha256sum, sha512sum, sha3sum
406#
407CONFIG_FEATURE_MD5_SHA1_SUM_CHECK=y
408
409#
410# Console Utilities
411#
412CONFIG_CHVT=y
413CONFIG_FGCONSOLE=y
414CONFIG_CLEAR=y
415CONFIG_DEALLOCVT=y
416CONFIG_DUMPKMAP=y
417CONFIG_KBD_MODE=y
418# CONFIG_LOADFONT is not set
419CONFIG_LOADKMAP=y
420CONFIG_OPENVT=y
421CONFIG_RESET=y
422CONFIG_RESIZE=y
423CONFIG_FEATURE_RESIZE_PRINT=y
424CONFIG_SETCONSOLE=y
425CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS=y
426# CONFIG_SETFONT is not set
427# CONFIG_FEATURE_SETFONT_TEXTUAL_MAP is not set
428CONFIG_DEFAULT_SETFONT_DIR=""
429CONFIG_SETKEYCODES=y
430CONFIG_SETLOGCONS=y
431CONFIG_SHOWKEY=y
432# CONFIG_FEATURE_LOADFONT_PSF2 is not set
433# CONFIG_FEATURE_LOADFONT_RAW is not set
434
435#
436# Debian Utilities
437#
438CONFIG_MKTEMP=y
439CONFIG_PIPE_PROGRESS=y
440CONFIG_RUN_PARTS=y
441CONFIG_FEATURE_RUN_PARTS_LONG_OPTIONS=y
442CONFIG_FEATURE_RUN_PARTS_FANCY=y
443CONFIG_START_STOP_DAEMON=y
444CONFIG_FEATURE_START_STOP_DAEMON_FANCY=y
445CONFIG_FEATURE_START_STOP_DAEMON_LONG_OPTIONS=y
446CONFIG_WHICH=y
447
448#
449# Editors
450#
451CONFIG_AWK=y
452CONFIG_FEATURE_AWK_LIBM=y
453CONFIG_FEATURE_AWK_GNU_EXTENSIONS=y
454CONFIG_CMP=y
455CONFIG_DIFF=y
456CONFIG_FEATURE_DIFF_LONG_OPTIONS=y
457CONFIG_FEATURE_DIFF_DIR=y
458CONFIG_ED=y
459CONFIG_PATCH=y
460CONFIG_SED=y
461CONFIG_VI=y
462CONFIG_FEATURE_VI_MAX_LEN=4096
463# CONFIG_FEATURE_VI_8BIT is not set
464CONFIG_FEATURE_VI_COLON=y
465CONFIG_FEATURE_VI_YANKMARK=y
466CONFIG_FEATURE_VI_SEARCH=y
467# CONFIG_FEATURE_VI_REGEX_SEARCH is not set
468CONFIG_FEATURE_VI_USE_SIGNALS=y
469CONFIG_FEATURE_VI_DOT_CMD=y
470CONFIG_FEATURE_VI_READONLY=y
471CONFIG_FEATURE_VI_SETOPTS=y
472CONFIG_FEATURE_VI_SET=y
473CONFIG_FEATURE_VI_WIN_RESIZE=y
474CONFIG_FEATURE_VI_ASK_TERMINAL=y
475CONFIG_FEATURE_VI_UNDO=y
476CONFIG_FEATURE_VI_UNDO_QUEUE=y
477CONFIG_FEATURE_VI_UNDO_QUEUE_MAX=256
478CONFIG_FEATURE_ALLOW_EXEC=y
479
480#
481# Finding Utilities
482#
483CONFIG_FIND=y
484CONFIG_FEATURE_FIND_PRINT0=y
485CONFIG_FEATURE_FIND_MTIME=y
486CONFIG_FEATURE_FIND_MMIN=y
487CONFIG_FEATURE_FIND_PERM=y
488CONFIG_FEATURE_FIND_TYPE=y
489CONFIG_FEATURE_FIND_XDEV=y
490CONFIG_FEATURE_FIND_MAXDEPTH=y
491CONFIG_FEATURE_FIND_NEWER=y
492CONFIG_FEATURE_FIND_INUM=y
493CONFIG_FEATURE_FIND_EXEC=y
494CONFIG_FEATURE_FIND_EXEC_PLUS=y
495CONFIG_FEATURE_FIND_USER=y
496CONFIG_FEATURE_FIND_GROUP=y
497CONFIG_FEATURE_FIND_NOT=y
498CONFIG_FEATURE_FIND_DEPTH=y
499CONFIG_FEATURE_FIND_PAREN=y
500CONFIG_FEATURE_FIND_SIZE=y
501CONFIG_FEATURE_FIND_PRUNE=y
502CONFIG_FEATURE_FIND_DELETE=y
503CONFIG_FEATURE_FIND_PATH=y
504CONFIG_FEATURE_FIND_REGEX=y
505# CONFIG_FEATURE_FIND_CONTEXT is not set
506CONFIG_FEATURE_FIND_LINKS=y
507CONFIG_GREP=y
508CONFIG_FEATURE_GREP_EGREP_ALIAS=y
509CONFIG_FEATURE_GREP_FGREP_ALIAS=y
510CONFIG_FEATURE_GREP_CONTEXT=y
511CONFIG_XARGS=y
512CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION=y
513CONFIG_FEATURE_XARGS_SUPPORT_QUOTES=y
514CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT=y
515CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM=y
516CONFIG_FEATURE_XARGS_SUPPORT_REPL_STR=y
517
518#
519# Init Utilities
520#
521CONFIG_BOOTCHARTD=y
522CONFIG_FEATURE_BOOTCHARTD_BLOATED_HEADER=y
523CONFIG_FEATURE_BOOTCHARTD_CONFIG_FILE=y
524CONFIG_HALT=y
525# CONFIG_FEATURE_CALL_TELINIT is not set
526CONFIG_TELINIT_PATH=""
527CONFIG_INIT=y
528CONFIG_FEATURE_USE_INITTAB=y
529# CONFIG_FEATURE_KILL_REMOVED is not set
530CONFIG_FEATURE_KILL_DELAY=0
531CONFIG_FEATURE_INIT_SCTTY=y
532CONFIG_FEATURE_INIT_SYSLOG=y
533CONFIG_FEATURE_EXTRA_QUIET=y
534CONFIG_FEATURE_INIT_COREDUMPS=y
535CONFIG_LINUXRC=y
536CONFIG_INIT_TERMINAL_TYPE="linux"
537CONFIG_FEATURE_INIT_MODIFY_CMDLINE=y
538CONFIG_MESG=y
539CONFIG_FEATURE_MESG_ENABLE_ONLY_GROUP=y
540
541#
542# Login/Password Management Utilities
543#
544# CONFIG_FEATURE_SHADOWPASSWDS is not set
545# CONFIG_USE_BB_PWD_GRP is not set
546# CONFIG_USE_BB_SHADOW is not set
547CONFIG_USE_BB_CRYPT=y
548CONFIG_USE_BB_CRYPT_SHA=y
549CONFIG_ADD_SHELL=y
550CONFIG_REMOVE_SHELL=y
551# CONFIG_ADDGROUP is not set
552# CONFIG_FEATURE_ADDGROUP_LONG_OPTIONS is not set
553# CONFIG_FEATURE_ADDUSER_TO_GROUP is not set
554# CONFIG_ADDUSER is not set
555# CONFIG_FEATURE_ADDUSER_LONG_OPTIONS is not set
556# CONFIG_FEATURE_CHECK_NAMES is not set
557CONFIG_LAST_ID=0
558CONFIG_FIRST_SYSTEM_ID=0
559CONFIG_LAST_SYSTEM_ID=0
560CONFIG_CHPASSWD=y
561CONFIG_FEATURE_DEFAULT_PASSWD_ALGO="des"
562CONFIG_CRYPTPW=y
563# CONFIG_DELUSER is not set
564# CONFIG_DELGROUP is not set
565# CONFIG_FEATURE_DEL_USER_FROM_GROUP is not set
566CONFIG_GETTY=y
567CONFIG_LOGIN=y
568# CONFIG_LOGIN_SESSION_AS_CHILD is not set
569CONFIG_LOGIN_SCRIPTS=y
570CONFIG_FEATURE_NOLOGIN=y
571CONFIG_FEATURE_SECURETTY=y
572CONFIG_PASSWD=y
573CONFIG_FEATURE_PASSWD_WEAK_CHECK=y
574CONFIG_SU=y
575CONFIG_FEATURE_SU_SYSLOG=y
576CONFIG_FEATURE_SU_CHECKS_SHELLS=y
577CONFIG_SULOGIN=y
578CONFIG_VLOCK=y
579
580#
581# Linux Ext2 FS Progs
582#
583CONFIG_CHATTR=y
584CONFIG_FSCK=y
585CONFIG_LSATTR=y
586# CONFIG_TUNE2FS is not set
587
588#
589# Linux Module Utilities
590#
591CONFIG_MODINFO=y
592CONFIG_MODPROBE_SMALL=y
593CONFIG_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE=y
594CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED=y
595# CONFIG_INSMOD is not set
596# CONFIG_RMMOD is not set
597# CONFIG_LSMOD is not set
598# CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT is not set
599# CONFIG_MODPROBE is not set
600# CONFIG_FEATURE_MODPROBE_BLACKLIST is not set
601# CONFIG_DEPMOD is not set
602
603#
604# Options common to multiple modutils
605#
606# CONFIG_FEATURE_2_4_MODULES is not set
607# CONFIG_FEATURE_INSMOD_TRY_MMAP is not set
608# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set
609# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set
610# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set
611# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set
612# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set
613# CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set
614# CONFIG_FEATURE_MODUTILS_ALIAS is not set
615# CONFIG_FEATURE_MODUTILS_SYMBOLS is not set
616CONFIG_DEFAULT_MODULES_DIR="/lib/modules"
617CONFIG_DEFAULT_DEPMOD_FILE="modules.dep"
618
619#
620# Linux System Utilities
621#
622CONFIG_BLKDISCARD=y
623CONFIG_BLOCKDEV=y
624CONFIG_FATATTR=y
625CONFIG_FSTRIM=y
626# CONFIG_MDEV is not set
627# CONFIG_FEATURE_MDEV_CONF is not set
628# CONFIG_FEATURE_MDEV_RENAME is not set
629# CONFIG_FEATURE_MDEV_RENAME_REGEXP is not set
630# CONFIG_FEATURE_MDEV_EXEC is not set
631# CONFIG_FEATURE_MDEV_LOAD_FIRMWARE is not set
632CONFIG_MOUNT=y
633CONFIG_FEATURE_MOUNT_FAKE=y
634CONFIG_FEATURE_MOUNT_VERBOSE=y
635# CONFIG_FEATURE_MOUNT_HELPERS is not set
636CONFIG_FEATURE_MOUNT_LABEL=y
637# CONFIG_FEATURE_MOUNT_NFS is not set
638CONFIG_FEATURE_MOUNT_CIFS=y
639CONFIG_FEATURE_MOUNT_FLAGS=y
640CONFIG_FEATURE_MOUNT_FSTAB=y
641CONFIG_FEATURE_MOUNT_OTHERTAB=y
642CONFIG_REV=y
643CONFIG_SETARCH=y
644CONFIG_UEVENT=y
645CONFIG_ACPID=y
646CONFIG_FEATURE_ACPID_COMPAT=y
647CONFIG_BLKID=y
648# CONFIG_FEATURE_BLKID_TYPE is not set
649CONFIG_DMESG=y
650CONFIG_FEATURE_DMESG_PRETTY=y
651CONFIG_FBSET=y
652CONFIG_FEATURE_FBSET_FANCY=y
653CONFIG_FEATURE_FBSET_READMODE=y
654CONFIG_FDFLUSH=y
655CONFIG_FDFORMAT=y
656CONFIG_FDISK=y
657CONFIG_FDISK_SUPPORT_LARGE_DISKS=y
658CONFIG_FEATURE_FDISK_WRITABLE=y
659# CONFIG_FEATURE_AIX_LABEL is not set
660# CONFIG_FEATURE_SGI_LABEL is not set
661# CONFIG_FEATURE_SUN_LABEL is not set
662# CONFIG_FEATURE_OSF_LABEL is not set
663# CONFIG_FEATURE_GPT_LABEL is not set
664CONFIG_FEATURE_FDISK_ADVANCED=y
665CONFIG_FINDFS=y
666CONFIG_FLOCK=y
667CONFIG_FREERAMDISK=y
668# CONFIG_FSCK_MINIX is not set
669CONFIG_MKFS_EXT2=y
670# CONFIG_MKFS_MINIX is not set
671# CONFIG_FEATURE_MINIX2 is not set
672# CONFIG_MKFS_REISER is not set
673CONFIG_MKFS_VFAT=y
674CONFIG_GETOPT=y
675CONFIG_FEATURE_GETOPT_LONG=y
676CONFIG_HEXDUMP=y
677CONFIG_FEATURE_HEXDUMP_REVERSE=y
678CONFIG_HD=y
679CONFIG_HWCLOCK=y
680CONFIG_FEATURE_HWCLOCK_LONG_OPTIONS=y
681# CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS is not set
682# CONFIG_IPCRM is not set
683# CONFIG_IPCS is not set
684CONFIG_LOSETUP=y
685CONFIG_LSPCI=y
686CONFIG_LSUSB=y
687CONFIG_MKSWAP=y
688CONFIG_FEATURE_MKSWAP_UUID=y
689CONFIG_MORE=y
690CONFIG_PIVOT_ROOT=y
691CONFIG_RDATE=y
692CONFIG_RDEV=y
693CONFIG_READPROFILE=y
694CONFIG_RTCWAKE=y
695CONFIG_SCRIPT=y
696CONFIG_SCRIPTREPLAY=y
697# CONFIG_SWAPONOFF is not set
698# CONFIG_FEATURE_SWAPON_DISCARD is not set
699# CONFIG_FEATURE_SWAPON_PRI is not set
700CONFIG_SWITCH_ROOT=y
701CONFIG_UMOUNT=y
702CONFIG_FEATURE_UMOUNT_ALL=y
703
704#
705# Common options for mount/umount
706#
707CONFIG_FEATURE_MOUNT_LOOP=y
708CONFIG_FEATURE_MOUNT_LOOP_CREATE=y
709# CONFIG_FEATURE_MTAB_SUPPORT is not set
710CONFIG_VOLUMEID=y
711
712#
713# Filesystem/Volume identification
714#
715CONFIG_FEATURE_VOLUMEID_BCACHE=y
716CONFIG_FEATURE_VOLUMEID_BTRFS=y
717CONFIG_FEATURE_VOLUMEID_CRAMFS=y
718CONFIG_FEATURE_VOLUMEID_EXFAT=y
719CONFIG_FEATURE_VOLUMEID_EXT=y
720CONFIG_FEATURE_VOLUMEID_F2FS=y
721CONFIG_FEATURE_VOLUMEID_FAT=y
722CONFIG_FEATURE_VOLUMEID_HFS=y
723CONFIG_FEATURE_VOLUMEID_ISO9660=y
724CONFIG_FEATURE_VOLUMEID_JFS=y
725CONFIG_FEATURE_VOLUMEID_LINUXRAID=y
726CONFIG_FEATURE_VOLUMEID_LINUXSWAP=y
727CONFIG_FEATURE_VOLUMEID_LUKS=y
728CONFIG_FEATURE_VOLUMEID_NILFS=y
729CONFIG_FEATURE_VOLUMEID_NTFS=y
730CONFIG_FEATURE_VOLUMEID_OCFS2=y
731CONFIG_FEATURE_VOLUMEID_REISERFS=y
732CONFIG_FEATURE_VOLUMEID_ROMFS=y
733# CONFIG_FEATURE_VOLUMEID_SQUASHFS is not set
734CONFIG_FEATURE_VOLUMEID_SYSV=y
735CONFIG_FEATURE_VOLUMEID_UDF=y
736CONFIG_FEATURE_VOLUMEID_XFS=y
737
738#
739# Miscellaneous Utilities
740#
741# CONFIG_CONSPY is not set
742CONFIG_CROND=y
743CONFIG_FEATURE_CROND_D=y
744CONFIG_FEATURE_CROND_CALL_SENDMAIL=y
745CONFIG_FEATURE_CROND_DIR="/var/spool/cron"
746CONFIG_I2CGET=y
747CONFIG_I2CSET=y
748CONFIG_I2CDUMP=y
749CONFIG_I2CDETECT=y
750CONFIG_LESS=y
751CONFIG_FEATURE_LESS_MAXLINES=9999999
752CONFIG_FEATURE_LESS_BRACKETS=y
753CONFIG_FEATURE_LESS_FLAGS=y
754CONFIG_FEATURE_LESS_TRUNCATE=y
755CONFIG_FEATURE_LESS_MARKS=y
756CONFIG_FEATURE_LESS_REGEXP=y
757CONFIG_FEATURE_LESS_WINCH=y
758CONFIG_FEATURE_LESS_ASK_TERMINAL=y
759CONFIG_FEATURE_LESS_DASHCMD=y
760CONFIG_FEATURE_LESS_LINENUMS=y
761# CONFIG_NANDWRITE is not set
762# CONFIG_NANDDUMP is not set
763# CONFIG_RFKILL is not set
764CONFIG_SETSERIAL=y
765CONFIG_TASKSET=y
766CONFIG_FEATURE_TASKSET_FANCY=y
767# CONFIG_UBIATTACH is not set
768# CONFIG_UBIDETACH is not set
769# CONFIG_UBIMKVOL is not set
770# CONFIG_UBIRMVOL is not set
771# CONFIG_UBIRSVOL is not set
772# CONFIG_UBIUPDATEVOL is not set
773# CONFIG_WALL is not set
774CONFIG_ADJTIMEX=y
775# CONFIG_BBCONFIG is not set
776# CONFIG_FEATURE_COMPRESS_BBCONFIG is not set
777CONFIG_BEEP=y
778CONFIG_FEATURE_BEEP_FREQ=4000
779CONFIG_FEATURE_BEEP_LENGTH_MS=30
780CONFIG_CHAT=y
781CONFIG_FEATURE_CHAT_NOFAIL=y
782# CONFIG_FEATURE_CHAT_TTY_HIFI is not set
783CONFIG_FEATURE_CHAT_IMPLICIT_CR=y
784CONFIG_FEATURE_CHAT_SWALLOW_OPTS=y
785CONFIG_FEATURE_CHAT_SEND_ESCAPES=y
786CONFIG_FEATURE_CHAT_VAR_ABORT_LEN=y
787CONFIG_FEATURE_CHAT_CLR_ABORT=y
788CONFIG_CHRT=y
789CONFIG_CRONTAB=y
790CONFIG_DC=y
791CONFIG_FEATURE_DC_LIBM=y
792# CONFIG_DEVFSD is not set
793# CONFIG_DEVFSD_MODLOAD is not set
794# CONFIG_DEVFSD_FG_NP is not set
795# CONFIG_DEVFSD_VERBOSE is not set
796# CONFIG_FEATURE_DEVFS is not set
797CONFIG_DEVMEM=y
798CONFIG_EJECT=y
799# CONFIG_FEATURE_EJECT_SCSI is not set
800CONFIG_FBSPLASH=y
801# CONFIG_FLASHCP is not set
802# CONFIG_FLASH_LOCK is not set
803# CONFIG_FLASH_UNLOCK is not set
804# CONFIG_FLASH_ERASEALL is not set
805CONFIG_IONICE=y
806# CONFIG_INOTIFYD is not set
807# CONFIG_LAST is not set
808# CONFIG_FEATURE_LAST_FANCY is not set
809CONFIG_HDPARM=y
810CONFIG_FEATURE_HDPARM_GET_IDENTITY=y
811CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF=y
812CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF=y
813CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET=y
814CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF=y
815CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA=y
816CONFIG_MAKEDEVS=y
817# CONFIG_FEATURE_MAKEDEVS_LEAF is not set
818CONFIG_FEATURE_MAKEDEVS_TABLE=y
819CONFIG_MAN=y
820CONFIG_MICROCOM=y
821CONFIG_MOUNTPOINT=y
822# CONFIG_MT is not set
823CONFIG_RAIDAUTORUN=y
824# CONFIG_READAHEAD is not set
825# CONFIG_RUNLEVEL is not set
826CONFIG_RX=y
827CONFIG_SETSID=y
828CONFIG_STRINGS=y
829CONFIG_TIME=y
830CONFIG_TIMEOUT=y
831CONFIG_TTYSIZE=y
832CONFIG_VOLNAME=y
833CONFIG_WATCHDOG=y
834
835#
836# Networking Utilities
837#
838CONFIG_NAMEIF=y
839CONFIG_FEATURE_NAMEIF_EXTENDED=y
840CONFIG_NBDCLIENT=y
841CONFIG_NC=y
842CONFIG_NC_SERVER=y
843CONFIG_NC_EXTRA=y
844# CONFIG_NC_110_COMPAT is not set
845CONFIG_PING=y
846CONFIG_PING6=y
847CONFIG_FEATURE_FANCY_PING=y
848CONFIG_WGET=y
849CONFIG_FEATURE_WGET_STATUSBAR=y
850CONFIG_FEATURE_WGET_AUTHENTICATION=y
851CONFIG_FEATURE_WGET_LONG_OPTIONS=y
852CONFIG_FEATURE_WGET_TIMEOUT=y
853CONFIG_FEATURE_WGET_OPENSSL=y
854CONFIG_FEATURE_WGET_SSL_HELPER=y
855CONFIG_WHOIS=y
856CONFIG_FEATURE_IPV6=y
857# CONFIG_FEATURE_UNIX_LOCAL is not set
858CONFIG_FEATURE_PREFER_IPV4_ADDRESS=y
859# CONFIG_VERBOSE_RESOLUTION_ERRORS is not set
860# CONFIG_ARP is not set
861# CONFIG_ARPING is not set
862CONFIG_BRCTL=y
863CONFIG_FEATURE_BRCTL_FANCY=y
864CONFIG_FEATURE_BRCTL_SHOW=y
865CONFIG_DNSD=y
866# CONFIG_ETHER_WAKE is not set
867CONFIG_FAKEIDENTD=y
868CONFIG_FTPD=y
869CONFIG_FEATURE_FTP_WRITE=y
870CONFIG_FEATURE_FTPD_ACCEPT_BROKEN_LIST=y
871CONFIG_FEATURE_FTP_AUTHENTICATION=y
872CONFIG_FTPGET=y
873CONFIG_FTPPUT=y
874CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS=y
875CONFIG_HOSTNAME=y
876CONFIG_HTTPD=y
877CONFIG_FEATURE_HTTPD_RANGES=y
878CONFIG_FEATURE_HTTPD_SETUID=y
879CONFIG_FEATURE_HTTPD_BASIC_AUTH=y
880CONFIG_FEATURE_HTTPD_AUTH_MD5=y
881CONFIG_FEATURE_HTTPD_CGI=y
882CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR=y
883CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV=y
884CONFIG_FEATURE_HTTPD_ENCODE_URL_STR=y
885CONFIG_FEATURE_HTTPD_ERROR_PAGES=y
886CONFIG_FEATURE_HTTPD_PROXY=y
887CONFIG_FEATURE_HTTPD_GZIP=y
888# CONFIG_IFCONFIG is not set
889# CONFIG_FEATURE_IFCONFIG_STATUS is not set
890# CONFIG_FEATURE_IFCONFIG_SLIP is not set
891# CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ is not set
892# CONFIG_FEATURE_IFCONFIG_HW is not set
893# CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS is not set
894# CONFIG_IFENSLAVE is not set
895CONFIG_IFPLUGD=y
896CONFIG_IFUPDOWN=y
897CONFIG_IFUPDOWN_IFSTATE_PATH="/var/run/ifstate"
898CONFIG_FEATURE_IFUPDOWN_IP=y
899CONFIG_FEATURE_IFUPDOWN_IP_BUILTIN=y
900# CONFIG_FEATURE_IFUPDOWN_IFCONFIG_BUILTIN is not set
901CONFIG_FEATURE_IFUPDOWN_IPV4=y
902CONFIG_FEATURE_IFUPDOWN_IPV6=y
903CONFIG_FEATURE_IFUPDOWN_MAPPING=y
904# CONFIG_FEATURE_IFUPDOWN_EXTERNAL_DHCP is not set
905CONFIG_INETD=y
906CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO=y
907CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD=y
908CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME=y
909CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME=y
910CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN=y
911# CONFIG_FEATURE_INETD_RPC is not set
912CONFIG_IP=y
913CONFIG_FEATURE_IP_ADDRESS=y
914CONFIG_FEATURE_IP_LINK=y
915CONFIG_FEATURE_IP_ROUTE=y
916CONFIG_FEATURE_IP_ROUTE_DIR="/etc/iproute2"
917CONFIG_FEATURE_IP_TUNNEL=y
918CONFIG_FEATURE_IP_RULE=y
919CONFIG_FEATURE_IP_NEIGH=y
920CONFIG_FEATURE_IP_SHORT_FORMS=y
921# CONFIG_FEATURE_IP_RARE_PROTOCOLS is not set
922CONFIG_IPADDR=y
923CONFIG_IPLINK=y
924CONFIG_IPROUTE=y
925CONFIG_IPTUNNEL=y
926CONFIG_IPRULE=y
927CONFIG_IPNEIGH=y
928CONFIG_IPCALC=y
929CONFIG_FEATURE_IPCALC_FANCY=y
930CONFIG_FEATURE_IPCALC_LONG_OPTIONS=y
931CONFIG_NETSTAT=y
932CONFIG_FEATURE_NETSTAT_WIDE=y
933CONFIG_FEATURE_NETSTAT_PRG=y
934# CONFIG_NSLOOKUP is not set
935CONFIG_NTPD=y
936CONFIG_FEATURE_NTPD_SERVER=y
937CONFIG_FEATURE_NTPD_CONF=y
938CONFIG_PSCAN=y
939# CONFIG_ROUTE is not set
940CONFIG_SLATTACH=y
941CONFIG_TCPSVD=y
942CONFIG_TELNET=y
943CONFIG_FEATURE_TELNET_TTYPE=y
944CONFIG_FEATURE_TELNET_AUTOLOGIN=y
945CONFIG_TELNETD=y
946CONFIG_FEATURE_TELNETD_STANDALONE=y
947CONFIG_FEATURE_TELNETD_INETD_WAIT=y
948CONFIG_TFTP=y
949CONFIG_TFTPD=y
950
951#
952# Common options for tftp/tftpd
953#
954CONFIG_FEATURE_TFTP_GET=y
955CONFIG_FEATURE_TFTP_PUT=y
956CONFIG_FEATURE_TFTP_BLOCKSIZE=y
957CONFIG_FEATURE_TFTP_PROGRESS_BAR=y
958# CONFIG_TFTP_DEBUG is not set
959CONFIG_TRACEROUTE=y
960CONFIG_TRACEROUTE6=y
961CONFIG_FEATURE_TRACEROUTE_VERBOSE=y
962# CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE is not set
963# CONFIG_FEATURE_TRACEROUTE_USE_ICMP is not set
964CONFIG_TUNCTL=y
965CONFIG_FEATURE_TUNCTL_UG=y
966# CONFIG_UDHCPC6 is not set
967CONFIG_UDHCPD=y
968CONFIG_DHCPRELAY=y
969CONFIG_DUMPLEASES=y
970CONFIG_FEATURE_UDHCPD_WRITE_LEASES_EARLY=y
971# CONFIG_FEATURE_UDHCPD_BASE_IP_ON_MAC is not set
972CONFIG_DHCPD_LEASES_FILE="/var/lib/misc/udhcpd.leases"
973CONFIG_UDHCPC=y
974CONFIG_FEATURE_UDHCPC_ARPING=y
975CONFIG_FEATURE_UDHCPC_SANITIZEOPT=y
976# CONFIG_FEATURE_UDHCP_PORT is not set
977CONFIG_UDHCP_DEBUG=9
978CONFIG_FEATURE_UDHCP_RFC3397=y
979CONFIG_FEATURE_UDHCP_8021Q=y
980CONFIG_UDHCPC_DEFAULT_SCRIPT="/usr/share/udhcpc/default.script"
981CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS=80
982CONFIG_IFUPDOWN_UDHCPC_CMD_OPTIONS="-R -n"
983CONFIG_UDPSVD=y
984CONFIG_VCONFIG=y
985# CONFIG_ZCIP is not set
986
987#
988# Print Utilities
989#
990CONFIG_LPD=y
991CONFIG_LPR=y
992CONFIG_LPQ=y
993
994#
995# Mail Utilities
996#
997CONFIG_MAKEMIME=y
998CONFIG_FEATURE_MIME_CHARSET="us-ascii"
999CONFIG_POPMAILDIR=y
1000CONFIG_FEATURE_POPMAILDIR_DELIVERY=y
1001CONFIG_REFORMIME=y
1002CONFIG_FEATURE_REFORMIME_COMPAT=y
1003CONFIG_SENDMAIL=y
1004
1005#
1006# Process Utilities
1007#
1008CONFIG_IOSTAT=y
1009CONFIG_LSOF=y
1010CONFIG_MPSTAT=y
1011CONFIG_NMETER=y
1012CONFIG_PMAP=y
1013CONFIG_POWERTOP=y
1014CONFIG_PSTREE=y
1015CONFIG_PWDX=y
1016CONFIG_SMEMCAP=y
1017CONFIG_TOP=y
1018CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE=y
1019CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS=y
1020CONFIG_FEATURE_TOP_SMP_CPU=y
1021CONFIG_FEATURE_TOP_DECIMALS=y
1022CONFIG_FEATURE_TOP_SMP_PROCESS=y
1023CONFIG_FEATURE_TOPMEM=y
1024CONFIG_UPTIME=y
1025# CONFIG_FEATURE_UPTIME_UTMP_SUPPORT is not set
1026CONFIG_FREE=y
1027CONFIG_FUSER=y
1028CONFIG_KILL=y
1029CONFIG_KILLALL=y
1030CONFIG_KILLALL5=y
1031CONFIG_PGREP=y
1032CONFIG_PIDOF=y
1033CONFIG_FEATURE_PIDOF_SINGLE=y
1034CONFIG_FEATURE_PIDOF_OMIT=y
1035CONFIG_PKILL=y
1036CONFIG_PS=y
1037# CONFIG_FEATURE_PS_WIDE is not set
1038# CONFIG_FEATURE_PS_LONG is not set
1039CONFIG_FEATURE_PS_TIME=y
1040CONFIG_FEATURE_PS_ADDITIONAL_COLUMNS=y
1041# CONFIG_FEATURE_PS_UNUSUAL_SYSTEMS is not set
1042CONFIG_RENICE=y
1043CONFIG_BB_SYSCTL=y
1044CONFIG_FEATURE_SHOW_THREADS=y
1045CONFIG_WATCH=y
1046
1047#
1048# Runit Utilities
1049#
1050CONFIG_CHPST=y
1051CONFIG_SETUIDGID=y
1052CONFIG_ENVUIDGID=y
1053CONFIG_ENVDIR=y
1054CONFIG_SOFTLIMIT=y
1055CONFIG_RUNSV=y
1056CONFIG_RUNSVDIR=y
1057# CONFIG_FEATURE_RUNSVDIR_LOG is not set
1058CONFIG_SV=y
1059CONFIG_SV_DEFAULT_SERVICE_DIR="/var/service"
1060CONFIG_SVLOGD=y
1061# CONFIG_CHCON is not set
1062# CONFIG_FEATURE_CHCON_LONG_OPTIONS is not set
1063# CONFIG_GETENFORCE is not set
1064# CONFIG_GETSEBOOL is not set
1065# CONFIG_LOAD_POLICY is not set
1066# CONFIG_MATCHPATHCON is not set
1067# CONFIG_RESTORECON is not set
1068# CONFIG_RUNCON is not set
1069# CONFIG_FEATURE_RUNCON_LONG_OPTIONS is not set
1070# CONFIG_SELINUXENABLED is not set
1071# CONFIG_SETENFORCE is not set
1072# CONFIG_SETFILES is not set
1073# CONFIG_FEATURE_SETFILES_CHECK_OPTION is not set
1074# CONFIG_SETSEBOOL is not set
1075# CONFIG_SESTATUS is not set
1076
1077#
1078# Shells
1079#
1080CONFIG_ASH=y
1081CONFIG_ASH_BASH_COMPAT=y
1082# CONFIG_ASH_IDLE_TIMEOUT is not set
1083CONFIG_ASH_JOB_CONTROL=y
1084CONFIG_ASH_ALIAS=y
1085CONFIG_ASH_GETOPTS=y
1086CONFIG_ASH_BUILTIN_ECHO=y
1087CONFIG_ASH_BUILTIN_PRINTF=y
1088CONFIG_ASH_BUILTIN_TEST=y
1089CONFIG_ASH_HELP=y
1090CONFIG_ASH_CMDCMD=y
1091# CONFIG_ASH_MAIL is not set
1092CONFIG_ASH_OPTIMIZE_FOR_SIZE=y
1093CONFIG_ASH_RANDOM_SUPPORT=y
1094CONFIG_ASH_EXPAND_PRMT=y
1095CONFIG_CTTYHACK=y
1096# CONFIG_HUSH is not set
1097# CONFIG_HUSH_BASH_COMPAT is not set
1098# CONFIG_HUSH_BRACE_EXPANSION is not set
1099# CONFIG_HUSH_HELP is not set
1100# CONFIG_HUSH_INTERACTIVE is not set
1101# CONFIG_HUSH_SAVEHISTORY is not set
1102# CONFIG_HUSH_JOB is not set
1103# CONFIG_HUSH_TICK is not set
1104# CONFIG_HUSH_IF is not set
1105# CONFIG_HUSH_LOOPS is not set
1106# CONFIG_HUSH_CASE is not set
1107# CONFIG_HUSH_FUNCTIONS is not set
1108# CONFIG_HUSH_LOCAL is not set
1109# CONFIG_HUSH_RANDOM_SUPPORT is not set
1110# CONFIG_HUSH_EXPORT_N is not set
1111# CONFIG_HUSH_MODE_X is not set
1112# CONFIG_MSH is not set
1113CONFIG_FEATURE_SH_IS_ASH=y
1114# CONFIG_FEATURE_SH_IS_HUSH is not set
1115# CONFIG_FEATURE_SH_IS_NONE is not set
1116# CONFIG_FEATURE_BASH_IS_ASH is not set
1117# CONFIG_FEATURE_BASH_IS_HUSH is not set
1118CONFIG_FEATURE_BASH_IS_NONE=y
1119CONFIG_SH_MATH_SUPPORT=y
1120CONFIG_SH_MATH_SUPPORT_64=y
1121CONFIG_FEATURE_SH_EXTRA_QUIET=y
1122# CONFIG_FEATURE_SH_STANDALONE is not set
1123# CONFIG_FEATURE_SH_NOFORK is not set
1124CONFIG_FEATURE_SH_HISTFILESIZE=y
1125
1126#
1127# System Logging Utilities
1128#
1129# CONFIG_KLOGD is not set
1130# CONFIG_FEATURE_KLOGD_KLOGCTL is not set
1131# CONFIG_LOGGER is not set
1132# CONFIG_LOGREAD is not set
1133# CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING is not set
1134# CONFIG_SYSLOGD is not set
1135# CONFIG_FEATURE_ROTATE_LOGFILE is not set
1136# CONFIG_FEATURE_REMOTE_LOG is not set
1137# CONFIG_FEATURE_SYSLOGD_DUP is not set
1138# CONFIG_FEATURE_SYSLOGD_CFG is not set
1139CONFIG_FEATURE_SYSLOGD_READ_BUFFER_SIZE=0
1140# CONFIG_FEATURE_IPC_SYSLOG is not set
1141CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE=0
1142# CONFIG_FEATURE_KMSG_SYSLOG is not set
diff --git a/configs/android_defconfig b/configs/android_defconfig
index 082994b6c..4e0224207 100644
--- a/configs/android_defconfig
+++ b/configs/android_defconfig
@@ -448,7 +448,7 @@ CONFIG_FEATURE_INIT_SCTTY=y
448CONFIG_FEATURE_INIT_SYSLOG=y 448CONFIG_FEATURE_INIT_SYSLOG=y
449CONFIG_FEATURE_EXTRA_QUIET=y 449CONFIG_FEATURE_EXTRA_QUIET=y
450CONFIG_FEATURE_INIT_COREDUMPS=y 450CONFIG_FEATURE_INIT_COREDUMPS=y
451CONFIG_FEATURE_INITRD=y 451CONFIG_LINUXRC=y
452CONFIG_INIT_TERMINAL_TYPE="linux" 452CONFIG_INIT_TERMINAL_TYPE="linux"
453CONFIG_MESG=y 453CONFIG_MESG=y
454CONFIG_FEATURE_MESG_ENABLE_ONLY_GROUP=y 454CONFIG_FEATURE_MESG_ENABLE_ONLY_GROUP=y
diff --git a/configs/android_ndk_defconfig b/configs/android_ndk_defconfig
index 63fafb468..d657d33e9 100644
--- a/configs/android_ndk_defconfig
+++ b/configs/android_ndk_defconfig
@@ -458,7 +458,7 @@ CONFIG_FEATURE_INIT_SCTTY=y
458CONFIG_FEATURE_INIT_SYSLOG=y 458CONFIG_FEATURE_INIT_SYSLOG=y
459CONFIG_FEATURE_EXTRA_QUIET=y 459CONFIG_FEATURE_EXTRA_QUIET=y
460CONFIG_FEATURE_INIT_COREDUMPS=y 460CONFIG_FEATURE_INIT_COREDUMPS=y
461CONFIG_FEATURE_INITRD=y 461CONFIG_LINUXRC=y
462CONFIG_INIT_TERMINAL_TYPE="linux" 462CONFIG_INIT_TERMINAL_TYPE="linux"
463CONFIG_MESG=y 463CONFIG_MESG=y
464CONFIG_FEATURE_MESG_ENABLE_ONLY_GROUP=y 464CONFIG_FEATURE_MESG_ENABLE_ONLY_GROUP=y
diff --git a/configs/cygwin_defconfig b/configs/cygwin_defconfig
index 2c02be743..38d580ad1 100644
--- a/configs/cygwin_defconfig
+++ b/configs/cygwin_defconfig
@@ -425,7 +425,7 @@ CONFIG_FEATURE_KILL_DELAY=0
425# CONFIG_FEATURE_INIT_SYSLOG is not set 425# CONFIG_FEATURE_INIT_SYSLOG is not set
426# CONFIG_FEATURE_EXTRA_QUIET is not set 426# CONFIG_FEATURE_EXTRA_QUIET is not set
427# CONFIG_FEATURE_INIT_COREDUMPS is not set 427# CONFIG_FEATURE_INIT_COREDUMPS is not set
428# CONFIG_FEATURE_INITRD is not set 428# CONFIG_LINUXRC is not set
429CONFIG_INIT_TERMINAL_TYPE="" 429CONFIG_INIT_TERMINAL_TYPE=""
430CONFIG_MESG=y 430CONFIG_MESG=y
431CONFIG_FEATURE_MESG_ENABLE_ONLY_GROUP=y 431CONFIG_FEATURE_MESG_ENABLE_ONLY_GROUP=y
diff --git a/configs/freebsd_defconfig b/configs/freebsd_defconfig
index ec3ed03c4..ae62f1389 100644
--- a/configs/freebsd_defconfig
+++ b/configs/freebsd_defconfig
@@ -422,7 +422,7 @@ CONFIG_FEATURE_KILL_DELAY=0
422# CONFIG_FEATURE_INIT_SYSLOG is not set 422# CONFIG_FEATURE_INIT_SYSLOG is not set
423# CONFIG_FEATURE_EXTRA_QUIET is not set 423# CONFIG_FEATURE_EXTRA_QUIET is not set
424# CONFIG_FEATURE_INIT_COREDUMPS is not set 424# CONFIG_FEATURE_INIT_COREDUMPS is not set
425# CONFIG_FEATURE_INITRD is not set 425# CONFIG_LINUXRC is not set
426CONFIG_INIT_TERMINAL_TYPE="" 426CONFIG_INIT_TERMINAL_TYPE=""
427# CONFIG_MESG is not set 427# CONFIG_MESG is not set
428 428
diff --git a/coreutils/ls.c b/coreutils/ls.c
index c48498858..20bd61860 100644
--- a/coreutils/ls.c
+++ b/coreutils/ls.c
@@ -668,7 +668,7 @@ static void display_files(struct dnode **dn, unsigned nfiles)
668 if (column_width < len) 668 if (column_width < len)
669 column_width = len; 669 column_width = len;
670 } 670 }
671 column_width += 1 + 671 column_width += 2 +
672 IF_SELINUX( ((G.all_fmt & LIST_CONTEXT) ? 33 : 0) + ) 672 IF_SELINUX( ((G.all_fmt & LIST_CONTEXT) ? 33 : 0) + )
673 ((G.all_fmt & LIST_INO) ? 8 : 0) + 673 ((G.all_fmt & LIST_INO) ? 8 : 0) +
674 ((G.all_fmt & LIST_BLOCKS) ? 5 : 0); 674 ((G.all_fmt & LIST_BLOCKS) ? 5 : 0);
@@ -696,8 +696,8 @@ static void display_files(struct dnode **dn, unsigned nfiles)
696 if (i < nfiles) { 696 if (i < nfiles) {
697 if (column > 0) { 697 if (column > 0) {
698 nexttab -= column; 698 nexttab -= column;
699 printf("%*s ", nexttab, ""); 699 printf("%*s", nexttab, "");
700 column += nexttab + 1; 700 column += nexttab;
701 } 701 }
702 nexttab = column + column_width; 702 nexttab = column + column_width;
703 column += display_single(dn[i]); 703 column += display_single(dn[i]);
diff --git a/coreutils/sort.c b/coreutils/sort.c
index 07d903388..9139d9f47 100644
--- a/coreutils/sort.c
+++ b/coreutils/sort.c
@@ -14,23 +14,23 @@
14 14
15//usage:#define sort_trivial_usage 15//usage:#define sort_trivial_usage
16//usage: "[-nru" 16//usage: "[-nru"
17//usage: IF_FEATURE_SORT_BIG("gMcszbdfimSTokt] [-o FILE] [-k start[.offset][opts][,end[.offset][opts]] [-t CHAR") 17//usage: IF_FEATURE_SORT_BIG("gMcszbdfiokt] [-o FILE] [-k start[.offset][opts][,end[.offset][opts]] [-t CHAR")
18//usage: "] [FILE]..." 18//usage: "] [FILE]..."
19//usage:#define sort_full_usage "\n\n" 19//usage:#define sort_full_usage "\n\n"
20//usage: "Sort lines of text\n" 20//usage: "Sort lines of text\n"
21//usage: IF_FEATURE_SORT_BIG( 21//usage: IF_FEATURE_SORT_BIG(
22//usage: "\n -b Ignore leading blanks" 22//usage: "\n -o FILE Output to FILE"
23//usage: "\n -c Check whether input is sorted" 23//usage: "\n -c Check whether input is sorted"
24//usage: "\n -d Dictionary order (blank or alphanumeric only)" 24//usage: "\n -b Ignore leading blanks"
25//usage: "\n -f Ignore case" 25//usage: "\n -f Ignore case"
26//usage: "\n -g General numerical sort"
27//usage: "\n -i Ignore unprintable characters" 26//usage: "\n -i Ignore unprintable characters"
27//usage: "\n -d Dictionary order (blank or alphanumeric only)"
28//usage: "\n -g General numerical sort"
28//usage: "\n -M Sort month" 29//usage: "\n -M Sort month"
29//usage: ) 30//usage: )
30//-h, --human-numeric-sort: compare human readable numbers (e.g., 2K 1G) 31//-h, --human-numeric-sort: compare human readable numbers (e.g., 2K 1G)
31//usage: "\n -n Sort numbers" 32//usage: "\n -n Sort numbers"
32//usage: IF_FEATURE_SORT_BIG( 33//usage: IF_FEATURE_SORT_BIG(
33//usage: "\n -o Output to file"
34//usage: "\n -t CHAR Field separator" 34//usage: "\n -t CHAR Field separator"
35//usage: "\n -k N[,M] Sort by Nth field" 35//usage: "\n -k N[,M] Sort by Nth field"
36//usage: ) 36//usage: )
@@ -41,7 +41,10 @@
41//usage: "\n -u Suppress duplicate lines" 41//usage: "\n -u Suppress duplicate lines"
42//usage: IF_FEATURE_SORT_BIG( 42//usage: IF_FEATURE_SORT_BIG(
43//usage: "\n -z Lines are terminated by NUL, not newline" 43//usage: "\n -z Lines are terminated by NUL, not newline"
44//usage: "\n -mST Ignored for GNU compatibility") 44////usage: "\n -m Ignored for GNU compatibility"
45////usage: "\n -S BUFSZ Ignored for GNU compatibility"
46////usage: "\n -T TMPDIR Ignored for GNU compatibility"
47//usage: )
45//usage: 48//usage:
46//usage:#define sort_example_usage 49//usage:#define sort_example_usage
47//usage: "$ echo -e \"e\\nf\\nb\\nd\\nc\\na\" | sort\n" 50//usage: "$ echo -e \"e\\nf\\nb\\nd\\nc\\na\" | sort\n"
diff --git a/e2fsprogs/fsck.c b/e2fsprogs/fsck.c
index 627d2be31..987d97528 100644
--- a/e2fsprogs/fsck.c
+++ b/e2fsprogs/fsck.c
@@ -345,7 +345,7 @@ static void load_fs_info(const char *filename)
345 345
346 // Loop through entries 346 // Loop through entries
347 while (getmntent_r(fstab, &mte, buf, sizeof(buf))) { 347 while (getmntent_r(fstab, &mte, buf, sizeof(buf))) {
348 //bb_info_msg("CREATE[%s][%s][%s][%s][%d]", mte.mnt_fsname, mte.mnt_dir, 348 //bb_error_msg("CREATE[%s][%s][%s][%s][%d]", mte.mnt_fsname, mte.mnt_dir,
349 // mte.mnt_type, mte.mnt_opts, 349 // mte.mnt_type, mte.mnt_opts,
350 // mte.mnt_passno); 350 // mte.mnt_passno);
351 create_fs_device(mte.mnt_fsname, mte.mnt_dir, 351 create_fs_device(mte.mnt_fsname, mte.mnt_dir,
@@ -602,7 +602,7 @@ static void fsck_device(struct fs_info *fs /*, int interactive */)
602 if (strcmp(fs->type, "auto") != 0) { 602 if (strcmp(fs->type, "auto") != 0) {
603 type = fs->type; 603 type = fs->type;
604 if (G.verbose > 2) 604 if (G.verbose > 2)
605 bb_info_msg("using filesystem type '%s' %s", 605 printf("using filesystem type '%s' %s\n",
606 type, "from fstab"); 606 type, "from fstab");
607 } else if (G.fstype 607 } else if (G.fstype
608 && (G.fstype[0] != 'n' || G.fstype[1] != 'o') /* != "no" */ 608 && (G.fstype[0] != 'n' || G.fstype[1] != 'o') /* != "no" */
@@ -612,12 +612,12 @@ static void fsck_device(struct fs_info *fs /*, int interactive */)
612 ) { 612 ) {
613 type = G.fstype; 613 type = G.fstype;
614 if (G.verbose > 2) 614 if (G.verbose > 2)
615 bb_info_msg("using filesystem type '%s' %s", 615 printf("using filesystem type '%s' %s\n",
616 type, "from -t"); 616 type, "from -t");
617 } else { 617 } else {
618 type = "auto"; 618 type = "auto";
619 if (G.verbose > 2) 619 if (G.verbose > 2)
620 bb_info_msg("using filesystem type '%s' %s", 620 printf("using filesystem type '%s' %s\n",
621 type, "(default)"); 621 type, "(default)");
622 } 622 }
623 623
diff --git a/examples/undeb b/examples/undeb
index 37104e9d8..c30baf31b 100755
--- a/examples/undeb
+++ b/examples/undeb
@@ -5,49 +5,55 @@
5# Requires the programs (ar, tar, gzip, and the pager more or less). 5# Requires the programs (ar, tar, gzip, and the pager more or less).
6# 6#
7usage() { 7usage() {
8echo "Usage: undeb -c package.deb <Print control file info>" 8 cat <<EOF
9echo " undeb -l package.deb <List contents of deb package>" 9Usage: undeb -c package.deb <Print control file info>
10echo " undeb -x package.deb /foo/boo <Extract deb package to this directory," 10 undeb -l package.deb <List contents of deb package>
11echo " put . for current directory>" 11 undeb -x package.deb /foo/boo <Extract deb package to this directory,
12exit 12 put . for current directory>
13EOF
14 exit
13} 15}
14 16
15deb=$2 17deb=$2
16 18
17exist() { 19exist() {
18if [ "$deb" = "" ]; then 20 if [ -z "${deb}" ]; then
19usage 21 usage
20elif [ ! -s "$deb" ]; then 22 elif [ ! -s "${deb}" ]; then
21echo "Can't find $deb!" 23 echo "Can't find ${deb}!"
22exit 24 exit 1
23fi 25 fi
24} 26}
25 27
26if [ "$1" = "" ]; then 28if [ -z "$1" ]; then
27usage 29 usage
28elif [ "$1" = "-l" ]; then 30elif [ "$1" = "-l" ]; then
29exist 31 exist
30type more >/dev/null 2>&1 && pager=more 32 type more >/dev/null 2>&1 && pager=more
31type less >/dev/null 2>&1 && pager=less 33 type less >/dev/null 2>&1 && pager=less
32[ "$pager" = "" ] && echo "No pager found!" && exit 34 [ -z "${pager}" ] && echo "No pager found!" && exit 1
33(ar -p $deb control.tar.gz | tar -xzO *control ; echo -e "\nPress enter to scroll, q to Quit!\n" ; ar -p $deb data.tar.gz | tar -tzv) | $pager 35 (
34exit 36 ar -p "${deb}" control.tar.gz | tar -xzO *control
37 printf "\nPress enter to scroll, q to Quit!\n\n"
38 ar -p "${deb}" data.tar.gz | tar -tzv
39 ) | ${pager}
40 exit
35elif [ "$1" = "-c" ]; then 41elif [ "$1" = "-c" ]; then
36exist 42 exist
37ar -p $deb control.tar.gz | tar -xzO *control 43 ar -p "${deb}" control.tar.gz | tar -xzO *control
38exit 44 exit
39elif [ "$1" = "-x" ]; then 45elif [ "$1" = "-x" ]; then
40exist 46 exist
41if [ "$3" = "" ]; then 47 if [ -z "$3" ]; then
42usage 48 usage
43elif [ ! -d "$3" ]; then 49 elif [ ! -d "$3" ]; then
44echo "No such directory $3!" 50 echo "No such directory $3!"
45exit 51 exit 1
46fi 52 fi
47ar -p $deb data.tar.gz | tar -xzvpf - -C $3 || exit 53 ar -p "${deb}" data.tar.gz | tar -xzvpf - -C "$3" || exit
48echo 54 echo
49echo "Extracted $deb to $3!" 55 echo "Extracted ${deb} to $3!"
50exit 56 exit
51else 57else
52usage 58 usage
53fi 59fi
diff --git a/examples/unrpm b/examples/unrpm
index 7fd3676f6..f48550b0a 100755
--- a/examples/unrpm
+++ b/examples/unrpm
@@ -5,44 +5,49 @@
5# Requires the programs (cpio, gzip, and the pager more or less). 5# Requires the programs (cpio, gzip, and the pager more or less).
6# 6#
7usage() { 7usage() {
8echo "Usage: unrpm -l package.rpm <List contents of rpm package>" 8 cat <<EOF
9echo " unrpm -x package.rpm /foo/boo <Extract rpm package to this directory," 9Usage: unrpm -l package.rpm <List contents of rpm package>
10echo " put . for current directory>" 10 unrpm -x package.rpm /foo/boo <Extract rpm package to this directory,
11exit 11 put . for current directory>
12EOF
13 exit
12} 14}
13 15
14rpm=$2 16rpm=$2
15 17
16exist() { 18exist() {
17if [ "$rpm" = "" ]; then 19 if [ -z "${rpm}" ]; then
18usage 20 usage
19elif [ ! -s "$rpm" ]; then 21 elif [ ! -s "${rpm}" ]; then
20echo "Can't find $rpm!" 22 echo "Can't find ${rpm}!"
21exit 23 exit 1
22fi 24 fi
23} 25}
24 26
25if [ "$1" = "" ]; then 27if [ -z "$1" ]; then
26usage 28 usage
27elif [ "$1" = "-l" ]; then 29elif [ "$1" = "-l" ]; then
28exist 30 exist
29type more >/dev/null 2>&1 && pager=more 31 type more >/dev/null 2>&1 && pager=more
30type less >/dev/null 2>&1 && pager=less 32 type less >/dev/null 2>&1 && pager=less
31[ "$pager" = "" ] && echo "No pager found!" && exit 33 [ "$pager" = "" ] && echo "No pager found!" && exit
32(echo -e "\nPress enter to scroll, q to Quit!\n" ; rpm2cpio $rpm | cpio -tv --quiet) | $pager 34 (
33exit 35 printf "\nPress enter to scroll, q to Quit!\n\n"
36 rpm2cpio "${rpm}" | cpio -tv --quiet
37 ) | ${pager}
38 exit
34elif [ "$1" = "-x" ]; then 39elif [ "$1" = "-x" ]; then
35exist 40 exist
36if [ "$3" = "" ]; then 41 if [ -z "$3" ]; then
37usage 42 usage
38elif [ ! -d "$3" ]; then 43 elif [ ! -d "$3" ]; then
39echo "No such directory $3!" 44 echo "No such directory $3!"
40exit 45 exit 1
41fi 46 fi
42rpm2cpio $rpm | (umask 0 ; cd $3 ; cpio -idmuv) || exit 47 rpm2cpio "${rpm}" | (umask 0 ; cd "$3" ; cpio -idmuv) || exit
43echo 48 echo
44echo "Extracted $rpm to $3!" 49 echo "Extracted ${rpm} to $3!"
45exit 50 exit
46else 51else
47usage 52 usage
48fi 53fi
diff --git a/findutils/grep.c b/findutils/grep.c
index e163e6562..5ed3faab2 100644
--- a/findutils/grep.c
+++ b/findutils/grep.c
@@ -689,11 +689,15 @@ int grep_main(int argc UNUSED_PARAM, char **argv)
689 FILE *file; 689 FILE *file;
690 int matched; 690 int matched;
691 llist_t *fopt = NULL; 691 llist_t *fopt = NULL;
692
693 /* do normal option parsing */
694#if ENABLE_FEATURE_GREP_CONTEXT 692#if ENABLE_FEATURE_GREP_CONTEXT
695 int Copt, opts; 693 int Copt, opts;
694#endif
696 695
696 /* For grep, exitcode of 1 is "not found". Other errors are 2: */
697 xfunc_error_retval = 2;
698
699 /* do normal option parsing */
700#if ENABLE_FEATURE_GREP_CONTEXT
697 /* -H unsets -h; -C unsets -A,-B; -e,-f are lists; 701 /* -H unsets -h; -C unsets -A,-B; -e,-f are lists;
698 * -m,-A,-B,-C have numeric param */ 702 * -m,-A,-B,-C have numeric param */
699 opt_complementary = "H-h:C-AB:e::f::m+:A+:B+:C+"; 703 opt_complementary = "H-h:C-AB:e::f::m+:A+:B+:C+";
diff --git a/include/busybox.h b/include/busybox.h
index b1e31e5ee..737627bd0 100644
--- a/include/busybox.h
+++ b/include/busybox.h
@@ -15,25 +15,20 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
15/* Keep in sync with applets/applet_tables.c! */ 15/* Keep in sync with applets/applet_tables.c! */
16extern const char applet_names[] ALIGN1; 16extern const char applet_names[] ALIGN1;
17extern int (*const applet_main[])(int argc, char **argv); 17extern int (*const applet_main[])(int argc, char **argv);
18extern const uint16_t applet_nameofs[]; 18extern const uint8_t applet_flags[] ALIGN1;
19extern const uint8_t applet_suid[] ALIGN1;
19extern const uint8_t applet_install_loc[] ALIGN1; 20extern const uint8_t applet_install_loc[] ALIGN1;
20 21
21#if ENABLE_FEATURE_SUID || ENABLE_FEATURE_PREFER_APPLETS
22# define APPLET_NAME(i) (applet_names + (applet_nameofs[i] & 0x0fff))
23#else
24# define APPLET_NAME(i) (applet_names + applet_nameofs[i])
25#endif
26
27#if ENABLE_FEATURE_PREFER_APPLETS 22#if ENABLE_FEATURE_PREFER_APPLETS
28# define APPLET_IS_NOFORK(i) (applet_nameofs[i] & (1 << 12)) 23# define APPLET_IS_NOFORK(i) (applet_flags[(i)/4] & (1 << (2 * ((i)%4))))
29# define APPLET_IS_NOEXEC(i) (applet_nameofs[i] & (1 << 13)) 24# define APPLET_IS_NOEXEC(i) (applet_flags[(i)/4] & (1 << ((2 * ((i)%4))+1)))
30#else 25#else
31# define APPLET_IS_NOFORK(i) 0 26# define APPLET_IS_NOFORK(i) 0
32# define APPLET_IS_NOEXEC(i) 0 27# define APPLET_IS_NOEXEC(i) 0
33#endif 28#endif
34 29
35#if ENABLE_FEATURE_SUID 30#if ENABLE_FEATURE_SUID
36# define APPLET_SUID(i) ((applet_nameofs[i] >> 14) & 0x3) 31# define APPLET_SUID(i) ((applet_suid[(i)/4] >> (2 * ((i)%4)) & 3))
37#endif 32#endif
38 33
39#if ENABLE_FEATURE_INSTALLER 34#if ENABLE_FEATURE_INSTALLER
diff --git a/include/libbb.h b/include/libbb.h
index cb61faad9..ffe1504e1 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -148,14 +148,18 @@
148# include <ws2tcpip.h> 148# include <ws2tcpip.h>
149#else 149#else
150# include <arpa/inet.h> 150# include <arpa/inet.h>
151# if !defined(__socklen_t_defined) && !defined(_SOCKLEN_T_DECLARED) 151//This breaks on bionic:
152/* We #define socklen_t *after* includes, otherwise we get 152//# if !defined(__socklen_t_defined) && !defined(_SOCKLEN_T_DECLARED)
153 * typedef redefinition errors from system headers 153///* We #define socklen_t *after* includes, otherwise we get
154 * (in case "is it defined already" detection above failed) 154// * typedef redefinition errors from system headers
155 */ 155// * (in case "is it defined already" detection above failed)
156# define socklen_t bb_socklen_t 156// */
157 typedef unsigned socklen_t; 157//# define socklen_t bb_socklen_t
158# endif 158// typedef unsigned socklen_t;
159//# endif
160//if this is still needed, add a fix along the lines of
161// ifdef SPECIFIC_BROKEN_LIBC_CHECK / typedef socklen_t / endif
162//in platform.h instead!
159#endif 163#endif
160#ifndef HAVE_CLEARENV 164#ifndef HAVE_CLEARENV
161# define clearenv() do { if (environ) environ[0] = NULL; } while (0) 165# define clearenv() do { if (environ) environ[0] = NULL; } while (0)
@@ -507,6 +511,7 @@ void xsetuid(uid_t uid) FAST_FUNC;
507void xsetegid(gid_t egid) FAST_FUNC; 511void xsetegid(gid_t egid) FAST_FUNC;
508void xseteuid(uid_t euid) FAST_FUNC; 512void xseteuid(uid_t euid) FAST_FUNC;
509void xchdir(const char *path) FAST_FUNC; 513void xchdir(const char *path) FAST_FUNC;
514void xfchdir(int fd) FAST_FUNC;
510void xchroot(const char *path) FAST_FUNC; 515void xchroot(const char *path) FAST_FUNC;
511void xsetenv(const char *key, const char *value) FAST_FUNC; 516void xsetenv(const char *key, const char *value) FAST_FUNC;
512void bb_unsetenv(const char *key) FAST_FUNC; 517void bb_unsetenv(const char *key) FAST_FUNC;
@@ -1001,9 +1006,10 @@ int BB_EXECVP(const char *file, char *const argv[]) FAST_FUNC;
1001#define BB_EXECVP(prog,cmd) execvp(prog,cmd) 1006#define BB_EXECVP(prog,cmd) execvp(prog,cmd)
1002#define BB_EXECLP(prog,cmd,...) execlp(prog,cmd,__VA_ARGS__) 1007#define BB_EXECLP(prog,cmd,...) execlp(prog,cmd,__VA_ARGS__)
1003#endif 1008#endif
1004int BB_EXECVP_or_die(char **argv) NORETURN FAST_FUNC; 1009void BB_EXECVP_or_die(char **argv) NORETURN FAST_FUNC;
1010void exec_prog_or_SHELL(char **argv) NORETURN FAST_FUNC;
1005 1011
1006/* xvfork() can't be a _function_, return after vfork mangles stack 1012/* xvfork() can't be a _function_, return after vfork in child mangles stack
1007 * in the parent. It must be a macro. */ 1013 * in the parent. It must be a macro. */
1008#define xvfork() \ 1014#define xvfork() \
1009({ \ 1015({ \
@@ -1015,6 +1021,7 @@ int BB_EXECVP_or_die(char **argv) NORETURN FAST_FUNC;
1015#if BB_MMU 1021#if BB_MMU
1016pid_t xfork(void) FAST_FUNC; 1022pid_t xfork(void) FAST_FUNC;
1017#endif 1023#endif
1024void xvfork_parent_waits_and_exits(void) FAST_FUNC;
1018 1025
1019/* NOMMU friendy fork+exec: */ 1026/* NOMMU friendy fork+exec: */
1020pid_t spawn(char **argv) FAST_FUNC; 1027pid_t spawn(char **argv) FAST_FUNC;
@@ -1031,6 +1038,7 @@ pid_t wait_any_nohang(int *wstat) FAST_FUNC;
1031 * if (rc > 0) bb_error_msg("exit code: %d", rc & 0xff); 1038 * if (rc > 0) bb_error_msg("exit code: %d", rc & 0xff);
1032 */ 1039 */
1033int wait4pid(pid_t pid) FAST_FUNC; 1040int wait4pid(pid_t pid) FAST_FUNC;
1041int wait_for_exitstatus(pid_t pid) FAST_FUNC;
1034/* Same as wait4pid(spawn(argv)), but with NOFORK/NOEXEC if configured: */ 1042/* Same as wait4pid(spawn(argv)), but with NOFORK/NOEXEC if configured: */
1035int spawn_and_wait(char **argv) FAST_FUNC; 1043int spawn_and_wait(char **argv) FAST_FUNC;
1036/* Does NOT check that applet is NOFORK, just blindly runs it */ 1044/* Does NOT check that applet is NOFORK, just blindly runs it */
@@ -1160,7 +1168,6 @@ extern void bb_herror_msg(const char *s, ...) __attribute__ ((format (printf, 1,
1160extern void bb_herror_msg_and_die(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2))) FAST_FUNC; 1168extern void bb_herror_msg_and_die(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2))) FAST_FUNC;
1161extern void bb_perror_nomsg_and_die(void) NORETURN FAST_FUNC; 1169extern void bb_perror_nomsg_and_die(void) NORETURN FAST_FUNC;
1162extern void bb_perror_nomsg(void) FAST_FUNC; 1170extern void bb_perror_nomsg(void) FAST_FUNC;
1163extern void bb_info_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2))) FAST_FUNC;
1164extern void bb_verror_msg(const char *s, va_list p, const char *strerr) FAST_FUNC; 1171extern void bb_verror_msg(const char *s, va_list p, const char *strerr) FAST_FUNC;
1165extern void bb_logenv_override(void) FAST_FUNC; 1172extern void bb_logenv_override(void) FAST_FUNC;
1166 1173
@@ -1784,6 +1791,9 @@ void bb_progress_update(bb_progress_t *p,
1784 uoff_t transferred, 1791 uoff_t transferred,
1785 uoff_t totalsize) FAST_FUNC; 1792 uoff_t totalsize) FAST_FUNC;
1786 1793
1794unsigned ubi_devnum_from_devname(const char *str) FAST_FUNC;
1795int ubi_get_volid_by_name(unsigned ubi_devnum, const char *vol_name) FAST_FUNC;
1796
1787 1797
1788extern const char *applet_name; 1798extern const char *applet_name;
1789 1799
diff --git a/init/halt.c b/init/halt.c
index ad12d9148..572d751b0 100644
--- a/init/halt.c
+++ b/init/halt.c
@@ -135,7 +135,7 @@ int halt_main(int argc UNUSED_PARAM, char **argv)
135 if (!(flags & 4)) { /* no -f */ 135 if (!(flags & 4)) { /* no -f */
136//TODO: I tend to think that signalling linuxrc is wrong 136//TODO: I tend to think that signalling linuxrc is wrong
137// pity original author didn't comment on it... 137// pity original author didn't comment on it...
138 if (ENABLE_FEATURE_INITRD) { 138 if (ENABLE_LINUXRC) {
139 /* talk to linuxrc */ 139 /* talk to linuxrc */
140 /* bbox init/linuxrc assumed */ 140 /* bbox init/linuxrc assumed */
141 pid_t *pidlist = find_pid_by_name("linuxrc"); 141 pid_t *pidlist = find_pid_by_name("linuxrc");
diff --git a/init/init.c b/init/init.c
index 25bfaec8c..6eb76b80e 100644
--- a/init/init.c
+++ b/init/init.c
@@ -16,10 +16,21 @@
16//config: help 16//config: help
17//config: init is the first program run when the system boots. 17//config: init is the first program run when the system boots.
18//config: 18//config:
19//config:config LINUXRC
20//config: bool "Support running init from within an initrd (not initramfs)"
21//config: default y
22//config: select FEATURE_SYSLOG
23//config: help
24//config: Legacy support for running init under the old-style initrd. Allows
25//config: the name linuxrc to act as init, and it doesn't assume init is PID 1.
26//config:
27//config: This does not apply to initramfs, which runs /init as PID 1 and
28//config: requires no special support.
29//config:
19//config:config FEATURE_USE_INITTAB 30//config:config FEATURE_USE_INITTAB
20//config: bool "Support reading an inittab file" 31//config: bool "Support reading an inittab file"
21//config: default y 32//config: default y
22//config: depends on INIT 33//config: depends on INIT || LINUXRC
23//config: help 34//config: help
24//config: Allow init to read an inittab file when the system boot. 35//config: Allow init to read an inittab file when the system boot.
25//config: 36//config:
@@ -46,7 +57,7 @@
46//config:config FEATURE_INIT_SCTTY 57//config:config FEATURE_INIT_SCTTY
47//config: bool "Run commands with leading dash with controlling tty" 58//config: bool "Run commands with leading dash with controlling tty"
48//config: default y 59//config: default y
49//config: depends on INIT 60//config: depends on INIT || LINUXRC
50//config: help 61//config: help
51//config: If this option is enabled, init will try to give a controlling 62//config: If this option is enabled, init will try to give a controlling
52//config: tty to any command which has leading hyphen (often it's "-/bin/sh"). 63//config: tty to any command which has leading hyphen (often it's "-/bin/sh").
@@ -61,40 +72,29 @@
61//config:config FEATURE_INIT_SYSLOG 72//config:config FEATURE_INIT_SYSLOG
62//config: bool "Enable init to write to syslog" 73//config: bool "Enable init to write to syslog"
63//config: default y 74//config: default y
64//config: depends on INIT 75//config: depends on INIT || LINUXRC
65//config: 76//config:
66//config:config FEATURE_EXTRA_QUIET 77//config:config FEATURE_EXTRA_QUIET
67//config: bool "Be _extra_ quiet on boot" 78//config: bool "Be _extra_ quiet on boot"
68//config: default y 79//config: default y
69//config: depends on INIT 80//config: depends on INIT || LINUXRC
70//config: help 81//config: help
71//config: Prevent init from logging some messages to the console during boot. 82//config: Prevent init from logging some messages to the console during boot.
72//config: 83//config:
73//config:config FEATURE_INIT_COREDUMPS 84//config:config FEATURE_INIT_COREDUMPS
74//config: bool "Support dumping core for child processes (debugging only)" 85//config: bool "Support dumping core for child processes (debugging only)"
75//config: default y 86//config: default y
76//config: depends on INIT 87//config: depends on INIT || LINUXRC
77//config: help 88//config: help
78//config: If this option is enabled and the file /.init_enable_core 89//config: If this option is enabled and the file /.init_enable_core
79//config: exists, then init will call setrlimit() to allow unlimited 90//config: exists, then init will call setrlimit() to allow unlimited
80//config: core file sizes. If this option is disabled, processes 91//config: core file sizes. If this option is disabled, processes
81//config: will not generate any core files. 92//config: will not generate any core files.
82//config: 93//config:
83//config:config FEATURE_INITRD
84//config: bool "Support running init from within an initrd (not initramfs)"
85//config: default y
86//config: depends on INIT
87//config: help
88//config: Legacy support for running init under the old-style initrd. Allows
89//config: the name linuxrc to act as init, and it doesn't assume init is PID 1.
90//config:
91//config: This does not apply to initramfs, which runs /init as PID 1 and
92//config: requires no special support.
93//config:
94//config:config INIT_TERMINAL_TYPE 94//config:config INIT_TERMINAL_TYPE
95//config: string "Initial terminal type" 95//config: string "Initial terminal type"
96//config: default "linux" 96//config: default "linux"
97//config: depends on INIT 97//config: depends on INIT || LINUXRC
98//config: help 98//config: help
99//config: This is the initial value set by init for the TERM environment 99//config: This is the initial value set by init for the TERM environment
100//config: variable. This variable is used by programs which make use of 100//config: variable. This variable is used by programs which make use of
@@ -106,7 +106,7 @@
106//config:config FEATURE_INIT_MODIFY_CMDLINE 106//config:config FEATURE_INIT_MODIFY_CMDLINE
107//config: bool "Modify the command-line to \"init\"" 107//config: bool "Modify the command-line to \"init\""
108//config: default y 108//config: default y
109//config: depends on INIT 109//config: depends on INIT || LINUXRC
110//config: help 110//config: help
111//config: When launched as PID 1 and after parsing its arguments, init 111//config: When launched as PID 1 and after parsing its arguments, init
112//config: wipes all the arguments but argv[0] and rewrites argv[0] to 112//config: wipes all the arguments but argv[0] and rewrites argv[0] to
@@ -119,9 +119,10 @@
119//config: retrieved in /proc/1/cmdline on Linux, for example. 119//config: retrieved in /proc/1/cmdline on Linux, for example.
120 120
121//applet:IF_INIT(APPLET(init, BB_DIR_SBIN, BB_SUID_DROP)) 121//applet:IF_INIT(APPLET(init, BB_DIR_SBIN, BB_SUID_DROP))
122//applet:IF_FEATURE_INITRD(APPLET_ODDNAME(linuxrc, init, BB_DIR_ROOT, BB_SUID_DROP, linuxrc)) 122//applet:IF_LINUXRC(APPLET_ODDNAME(linuxrc, init, BB_DIR_ROOT, BB_SUID_DROP, linuxrc))
123 123
124//kbuild:lib-$(CONFIG_INIT) += init.o 124//kbuild:lib-$(CONFIG_INIT) += init.o
125//kbuild:lib-$(CONFIG_LINUXRC) += init.o
125 126
126#define DEBUG_SEGV_HANDLER 0 127#define DEBUG_SEGV_HANDLER 0
127 128
@@ -1057,7 +1058,7 @@ int init_main(int argc UNUSED_PARAM, char **argv)
1057 if (!DEBUG_INIT) { 1058 if (!DEBUG_INIT) {
1058 /* Expect to be invoked as init with PID=1 or be invoked as linuxrc */ 1059 /* Expect to be invoked as init with PID=1 or be invoked as linuxrc */
1059 if (getpid() != 1 1060 if (getpid() != 1
1060 && (!ENABLE_FEATURE_INITRD || applet_name[0] != 'l') /* not linuxrc? */ 1061 && (!ENABLE_LINUXRC || applet_name[0] != 'l') /* not linuxrc? */
1061 ) { 1062 ) {
1062 bb_error_msg_and_die("must be run as PID 1"); 1063 bb_error_msg_and_die("must be run as PID 1");
1063 } 1064 }
diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src
index e0898565a..0e14e351e 100644
--- a/libbb/Kbuild.src
+++ b/libbb/Kbuild.src
@@ -43,7 +43,7 @@ lib-y += getopt32.o
43lib-y += get_volsize.o 43lib-y += get_volsize.o
44lib-y += herror_msg.o 44lib-y += herror_msg.o
45lib-y += human_readable.o 45lib-y += human_readable.o
46lib-y += info_msg.o 46lib-y += inet_common.o
47lib-y += inode_hash.o 47lib-y += inode_hash.o
48lib-y += isdirectory.o 48lib-y += isdirectory.o
49lib-y += last_char_is.o 49lib-y += last_char_is.o
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index 1d6a4b274..b71f2dd7e 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -140,32 +140,127 @@ void FAST_FUNC bb_show_usage(void)
140 xfunc_die(); 140 xfunc_die();
141} 141}
142 142
143#if NUM_APPLETS > 8
144static int applet_name_compare(const void *name, const void *idx)
145{
146 int i = (int)(ptrdiff_t)idx - 1;
147 return strcmp(name, APPLET_NAME(i));
148}
149#endif
150int FAST_FUNC find_applet_by_name(const char *name) 143int FAST_FUNC find_applet_by_name(const char *name)
151{ 144{
152#if NUM_APPLETS > 8 145 unsigned i, max;
153 /* Do a binary search to find the applet entry given the name. */ 146 int j;
154 const char *p; 147 const char *p;
155 p = bsearch(name, (void*)(ptrdiff_t)1, ARRAY_SIZE(applet_main), 1, applet_name_compare); 148
156 /* 149/* The commented-out word-at-a-time code is ~40% faster, but +160 bytes.
157 * if (!p) return -1; 150 * "Faster" here saves ~0.5 microsecond of real time - not worth it.
158 * ^^^^^^^^^^^^^^^^^^ the code below will do this if p == NULL :) 151 */
159 */ 152#if 0 /*BB_UNALIGNED_MEMACCESS_OK && BB_LITTLE_ENDIAN*/
160 return (int)(ptrdiff_t)p - 1; 153 uint32_t n32;
154
155 /* Handle all names < 2 chars long early */
156 if (name[0] == '\0')
157 return -1; /* "" is not a valid applet name */
158 if (name[1] == '\0') {
159 if (!ENABLE_TEST)
160 return -1; /* 1-char name is not valid */
161 if (name[0] != ']')
162 return -1; /* 1-char name which isn't "[" is not valid */
163 /* applet "[" is always applet #0: */
164 return 0;
165 }
166#endif
167
168 p = applet_names;
169 i = 0;
170#if KNOWN_APPNAME_OFFSETS <= 0
171 max = NUM_APPLETS;
161#else 172#else
162 /* A version which does not pull in bsearch */ 173 max = NUM_APPLETS * KNOWN_APPNAME_OFFSETS;
163 int i = 0; 174 for (j = ARRAY_SIZE(applet_nameofs)-1; j >= 0; j--) {
164 const char *p = applet_names; 175 const char *pp = applet_names + applet_nameofs[j];
165 while (i < NUM_APPLETS) { 176 if (strcmp(name, pp) >= 0) {
166 if (strcmp(name, p) == 0) 177 //bb_error_msg("name:'%s' >= pp:'%s'", name, pp);
178 p = pp;
179 i = max - NUM_APPLETS;
180 break;
181 }
182 max -= NUM_APPLETS;
183 }
184 max /= (unsigned)KNOWN_APPNAME_OFFSETS;
185 i /= (unsigned)KNOWN_APPNAME_OFFSETS;
186 //bb_error_msg("name:'%s' starting from:'%s' i:%u max:%u", name, p, i, max);
187#endif
188
189 /* Open-coded linear search without strcmp/strlen calls for speed */
190
191#if 0 /*BB_UNALIGNED_MEMACCESS_OK && BB_LITTLE_ENDIAN*/
192 /* skip "[\0" name, it's surely not it */
193 if (ENABLE_TEST && LONE_CHAR(p, '['))
194 i++, p += 2;
195 /* All remaining applet names in p[] are at least 2 chars long */
196 /* name[] is also at least 2 chars long */
197
198 n32 = (name[0] << 0) | (name[1] << 8) | (name[2] << 16);
199 while (i < max) {
200 uint32_t p32;
201 char ch;
202
203 /* Quickly check match of the first 3 bytes */
204 move_from_unaligned32(p32, p);
205 p += 3;
206 if ((p32 & 0x00ffffff) != n32) {
207 /* Most likely case: 3 first bytes do not match */
208 i++;
209 if ((p32 & 0x00ff0000) == '\0')
210 continue; // p[2] was NUL
211 p++;
212 if ((p32 & 0xff000000) == '\0')
213 continue; // p[3] was NUL
214 /* p[0..3] aren't matching and none is NUL, check the rest */
215 while (*p++ != '\0')
216 continue;
217 continue;
218 }
219
220 /* Unlikely branch: first 3 bytes ([0..2]) match */
221 if ((p32 & 0x00ff0000) == '\0') {
222 /* name is 2-byte long, it is full match */
223 //bb_error_msg("found:'%s' i:%u", name, i);
167 return i; 224 return i;
168 p += strlen(p) + 1; 225 }
226 /* Check remaining bytes [3..NUL] */
227 ch = (p32 >> 24);
228 j = 3;
229 while (ch == name[j]) {
230 if (ch == '\0') {
231 //bb_error_msg("found:'%s' i:%u", name, i);
232 return i;
233 }
234 ch = *++p;
235 j++;
236 }
237 /* Not a match. Skip it, including NUL */
238 while (ch != '\0')
239 ch = *++p;
240 p++;
241 i++;
242 }
243 return -1;
244#else
245 while (i < max) {
246 char ch;
247 j = 0;
248 /* Do we see "name\0" in applet_names[p] position? */
249 while ((ch = *p) == name[j]) {
250 if (ch == '\0') {
251 //bb_error_msg("found:'%s' i:%u", name, i);
252 return i; /* yes */
253 }
254 p++;
255 j++;
256 }
257 /* No.
258 * p => 1st non-matching char in applet_names[],
259 * skip to and including NUL.
260 */
261 while (ch != '\0')
262 ch = *++p;
263 p++;
169 i++; 264 i++;
170 } 265 }
171 return -1; 266 return -1;
@@ -588,6 +683,7 @@ static void install_links(const char *busybox, int use_symbolic_links,
588 * busybox.h::bb_install_loc_t, or else... */ 683 * busybox.h::bb_install_loc_t, or else... */
589 int (*lf)(const char *, const char *); 684 int (*lf)(const char *, const char *);
590 char *fpc; 685 char *fpc;
686 const char *appname = applet_names;
591 unsigned i; 687 unsigned i;
592 int rc; 688 int rc;
593 689
@@ -598,7 +694,7 @@ static void install_links(const char *busybox, int use_symbolic_links,
598 for (i = 0; i < ARRAY_SIZE(applet_main); i++) { 694 for (i = 0; i < ARRAY_SIZE(applet_main); i++) {
599 fpc = concat_path_file( 695 fpc = concat_path_file(
600 custom_install_dir ? custom_install_dir : install_dir[APPLET_INSTALL_LOC(i)], 696 custom_install_dir ? custom_install_dir : install_dir[APPLET_INSTALL_LOC(i)],
601 APPLET_NAME(i)); 697 appname);
602 // debug: bb_error_msg("%slinking %s to busybox", 698 // debug: bb_error_msg("%slinking %s to busybox",
603 // use_symbolic_links ? "sym" : "", fpc); 699 // use_symbolic_links ? "sym" : "", fpc);
604 rc = lf(busybox, fpc); 700 rc = lf(busybox, fpc);
@@ -606,6 +702,8 @@ static void install_links(const char *busybox, int use_symbolic_links,
606 bb_simple_perror_msg(fpc); 702 bb_simple_perror_msg(fpc);
607 } 703 }
608 free(fpc); 704 free(fpc);
705 while (*appname++ != '\0')
706 continue;
609 } 707 }
610} 708}
611# else 709# else
@@ -769,7 +867,7 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, char **argv)
769 867
770 /* Reinit some shared global data */ 868 /* Reinit some shared global data */
771 xfunc_error_retval = EXIT_FAILURE; 869 xfunc_error_retval = EXIT_FAILURE;
772 applet_name = APPLET_NAME(applet_no); 870 applet_name = bb_get_last_path_component_nostrip(argv[0]);
773 871
774 /* Special case. POSIX says "test --help" 872 /* Special case. POSIX says "test --help"
775 * should be no different from e.g. "test --foo". 873 * should be no different from e.g. "test --foo".
@@ -800,11 +898,14 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, char **argv)
800 898
801void FAST_FUNC run_applet_and_exit(const char *name, char **argv) 899void FAST_FUNC run_applet_and_exit(const char *name, char **argv)
802{ 900{
803 int applet = find_applet_by_name(name); 901 int applet;
804 if (applet >= 0) 902
805 run_applet_no_and_exit(applet, argv);
806 if (is_prefixed_with(name, "busybox")) 903 if (is_prefixed_with(name, "busybox"))
807 exit(busybox_main(argv)); 904 exit(busybox_main(argv));
905 /* find_applet_by_name() search is more expensive, so goes second */
906 applet = find_applet_by_name(name);
907 if (applet >= 0)
908 run_applet_no_and_exit(applet, argv);
808} 909}
809 910
810#endif /* !defined(SINGLE_APPLET_MAIN) */ 911#endif /* !defined(SINGLE_APPLET_MAIN) */
@@ -817,6 +918,19 @@ int lbb_main(char **argv)
817int main(int argc UNUSED_PARAM, char **argv) 918int main(int argc UNUSED_PARAM, char **argv)
818#endif 919#endif
819{ 920{
921#if 0
922 /* TODO: find a use for a block of memory between end of .bss
923 * and end of page. For example, I'm getting "_end:0x812e698 2408 bytes"
924 * - more than 2k of wasted memory (in this particular build)
925 * *per each running process*!
926 * (If your linker does not generate "_end" name, weak attribute
927 * makes &_end == NULL, end_len == 0 here.)
928 */
929 extern char _end[] __attribute__((weak));
930 unsigned end_len = (-(int)_end) & 0xfff;
931 printf("_end:%p %u bytes\n", &_end, end_len);
932#endif
933
820 /* Tweak malloc for reduced memory consumption */ 934 /* Tweak malloc for reduced memory consumption */
821#ifdef M_TRIM_THRESHOLD 935#ifdef M_TRIM_THRESHOLD
822 /* M_TRIM_THRESHOLD is the maximum amount of freed top-most memory 936 /* M_TRIM_THRESHOLD is the maximum amount of freed top-most memory
diff --git a/libbb/executable.c b/libbb/executable.c
index 12a48cea3..308c525a3 100644
--- a/libbb/executable.c
+++ b/libbb/executable.c
@@ -97,10 +97,19 @@ int FAST_FUNC BB_EXECVP(const char *file, char *const argv[])
97} 97}
98#endif 98#endif
99 99
100int FAST_FUNC BB_EXECVP_or_die(char **argv) 100void FAST_FUNC BB_EXECVP_or_die(char **argv)
101{ 101{
102 BB_EXECVP(argv[0], argv); 102 BB_EXECVP(argv[0], argv);
103 /* SUSv3-mandated exit codes */ 103 /* SUSv3-mandated exit codes */
104 xfunc_error_retval = (errno == ENOENT) ? 127 : 126; 104 xfunc_error_retval = (errno == ENOENT) ? 127 : 126;
105 bb_perror_msg_and_die("can't execute '%s'", argv[0]); 105 bb_perror_msg_and_die("can't execute '%s'", argv[0]);
106} 106}
107
108/* Typical idiom for applets which exec *optional* PROG [ARGS] */
109void FAST_FUNC exec_prog_or_SHELL(char **argv)
110{
111 if (argv[0]) {
112 BB_EXECVP_or_die(argv);
113 }
114 run_shell(getenv("SHELL"), /*login:*/ 1, NULL, NULL);
115}
diff --git a/libbb/info_msg.c b/libbb/info_msg.c
deleted file mode 100644
index 56ca2efd4..000000000
--- a/libbb/info_msg.c
+++ /dev/null
@@ -1,62 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Utility routines.
4 *
5 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
6 *
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */
9
10#include "libbb.h"
11#if ENABLE_FEATURE_SYSLOG
12# include <syslog.h>
13#endif
14
15void FAST_FUNC bb_info_msg(const char *s, ...)
16{
17#ifdef THIS_ONE_DOESNT_DO_SINGLE_WRITE
18 va_list p;
19 /* va_copy is used because it is not portable
20 * to use va_list p twice */
21 va_list p2;
22
23 va_start(p, s);
24 va_copy(p2, p);
25 if (logmode & LOGMODE_STDIO) {
26 vprintf(s, p);
27 fputs(msg_eol, stdout);
28 }
29# if ENABLE_FEATURE_SYSLOG
30 if (logmode & LOGMODE_SYSLOG)
31 vsyslog(LOG_INFO, s, p2);
32# endif
33 va_end(p2);
34 va_end(p);
35#else
36 int used;
37 char *msg;
38 va_list p;
39
40 if (logmode == 0)
41 return;
42
43 va_start(p, s);
44 used = vasprintf(&msg, s, p);
45 va_end(p);
46 if (used < 0)
47 return;
48
49# if ENABLE_FEATURE_SYSLOG
50 if (logmode & LOGMODE_SYSLOG)
51 syslog(LOG_INFO, "%s", msg);
52# endif
53 if (logmode & LOGMODE_STDIO) {
54 fflush_all();
55 /* used = strlen(msg); - must be true already */
56 msg[used++] = '\n';
57 full_write(STDOUT_FILENO, msg, used);
58 }
59
60 free(msg);
61#endif
62}
diff --git a/libbb/ubi.c b/libbb/ubi.c
new file mode 100644
index 000000000..34595d797
--- /dev/null
+++ b/libbb/ubi.c
@@ -0,0 +1,43 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Utility routines.
4 *
5 * Copyright (C) 2016 Denys Vlasenko
6 *
7 * Licensed under GPLv2, see file LICENSE in this source tree.
8 */
9//kbuild:lib-y += ubi.o
10
11#include "libbb.h"
12
13// from ubi-media.h
14#define UBI_MAX_VOLUME_NAME 127
15#define UBI_MAX_VOLUMES 128
16
17unsigned FAST_FUNC ubi_devnum_from_devname(const char *str)
18{
19 unsigned ubi_devnum;
20
21 if (sscanf(str, "/dev/ubi%u", &ubi_devnum) != 1)
22 bb_error_msg_and_die("not an UBI device: '%s'", str);
23 return ubi_devnum;
24}
25
26int FAST_FUNC ubi_get_volid_by_name(unsigned ubi_devnum, const char *vol_name)
27{
28 unsigned i;
29
30 for (i = 0; i < UBI_MAX_VOLUMES; i++) {
31 char buf[UBI_MAX_VOLUME_NAME + 1];
32 char fname[sizeof("/sys/class/ubi/ubi%u_%u/name") + 2 * sizeof(int)*3];
33
34 sprintf(fname, "/sys/class/ubi/ubi%u_%u/name", ubi_devnum, i);
35 if (open_read_close(fname, buf, sizeof(buf)) <= 0)
36 continue;
37
38 strchrnul(buf, '\n')[0] = '\0';
39 if (strcmp(vol_name, buf) == 0)
40 return i;
41 }
42 bb_error_msg_and_die("volume '%s' not found", vol_name);
43}
diff --git a/libbb/verror_msg.c b/libbb/verror_msg.c
index 0ef2a311f..22c30357b 100644
--- a/libbb/verror_msg.c
+++ b/libbb/verror_msg.c
@@ -20,6 +20,7 @@ const char *msg_eol = "\n";
20void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr) 20void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr)
21{ 21{
22 char *msg, *msg1; 22 char *msg, *msg1;
23 char stack_msg[80];
23 int applet_len, strerr_len, msgeol_len, used; 24 int applet_len, strerr_len, msgeol_len, used;
24 25
25 if (!logmode) 26 if (!logmode)
@@ -28,6 +29,27 @@ void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr)
28 if (!s) /* nomsg[_and_die] uses NULL fmt */ 29 if (!s) /* nomsg[_and_die] uses NULL fmt */
29 s = ""; /* some libc don't like printf(NULL) */ 30 s = ""; /* some libc don't like printf(NULL) */
30 31
32 applet_len = strlen(applet_name) + 2; /* "applet: " */
33 strerr_len = strerr ? strlen(strerr) : 0;
34 msgeol_len = strlen(msg_eol);
35
36 /* This costs ~90 bytes of code, but avoids costly
37 * malloc()[in vasprintf]+realloc()+memmove()+free() in 99% of cases.
38 * ~40% speedup.
39 */
40 if ((int)sizeof(stack_msg) - applet_len > 0) {
41 va_list p2;
42
43 /* It is not portable to use va_list twice, need to va_copy it */
44 va_copy(p2, p);
45 used = vsnprintf(stack_msg + applet_len, (int)sizeof(stack_msg) - applet_len, s, p2);
46 va_end(p2);
47 msg = stack_msg;
48 used += applet_len;
49 if (used < (int)sizeof(stack_msg) - 3 - msgeol_len - strerr_len)
50 goto add_pfx_and_sfx;
51 }
52
31 used = vasprintf(&msg, s, p); 53 used = vasprintf(&msg, s, p);
32 if (used < 0) 54 if (used < 0)
33 return; 55 return;
@@ -37,9 +59,6 @@ void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr)
37 * This is needed for e.g. httpd logging, when multiple 59 * This is needed for e.g. httpd logging, when multiple
38 * children can produce log messages simultaneously. */ 60 * children can produce log messages simultaneously. */
39 61
40 applet_len = strlen(applet_name) + 2; /* "applet: " */
41 strerr_len = strerr ? strlen(strerr) : 0;
42 msgeol_len = strlen(msg_eol);
43 /* can't use xrealloc: it calls error_msg on failure, 62 /* can't use xrealloc: it calls error_msg on failure,
44 * that may result in a recursion */ 63 * that may result in a recursion */
45 /* +3 is for ": " before strerr and for terminating NUL */ 64 /* +3 is for ": " before strerr and for terminating NUL */
@@ -52,6 +71,7 @@ void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr)
52 /* TODO: maybe use writev instead of memmoving? Need full_writev? */ 71 /* TODO: maybe use writev instead of memmoving? Need full_writev? */
53 memmove(msg + applet_len, msg, used); 72 memmove(msg + applet_len, msg, used);
54 used += applet_len; 73 used += applet_len;
74 add_pfx_and_sfx:
55 strcpy(msg, applet_name); 75 strcpy(msg, applet_name);
56 msg[applet_len - 2] = ':'; 76 msg[applet_len - 2] = ':';
57 msg[applet_len - 1] = ' '; 77 msg[applet_len - 1] = ' ';
@@ -76,7 +96,8 @@ void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr)
76 syslog(syslog_level, "%s", msg + applet_len); 96 syslog(syslog_level, "%s", msg + applet_len);
77 } 97 }
78#endif 98#endif
79 free(msg); 99 if (msg != stack_msg)
100 free(msg);
80} 101}
81 102
82#ifdef VERSION_WITH_WRITEV 103#ifdef VERSION_WITH_WRITEV
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c
index 2d3204507..f488f8e0c 100644
--- a/libbb/vfork_daemon_rexec.c
+++ b/libbb/vfork_daemon_rexec.c
@@ -118,8 +118,6 @@ int FAST_FUNC run_nofork_applet(int applet_no, char **argv)
118 118
119 save_nofork_data(&old); 119 save_nofork_data(&old);
120 120
121 applet_name = APPLET_NAME(applet_no);
122
123 xfunc_error_retval = EXIT_FAILURE; 121 xfunc_error_retval = EXIT_FAILURE;
124 122
125 /* In case getopt() or getopt32() was already called: 123 /* In case getopt() or getopt32() was already called:
@@ -159,6 +157,7 @@ int FAST_FUNC run_nofork_applet(int applet_no, char **argv)
159 * need argv untouched because they free argv[i]! */ 157 * need argv untouched because they free argv[i]! */
160 char *tmp_argv[argc+1]; 158 char *tmp_argv[argc+1];
161 memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0])); 159 memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0]));
160 applet_name = tmp_argv[0];
162 /* Finally we can call NOFORK applet's main() */ 161 /* Finally we can call NOFORK applet's main() */
163 rc = applet_main[applet_no](argc, tmp_argv); 162 rc = applet_main[applet_no](argc, tmp_argv);
164 } else { 163 } else {
diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c
index 206edb4a0..3f9a84ad4 100644
--- a/libbb/xfuncs.c
+++ b/libbb/xfuncs.c
@@ -315,3 +315,15 @@ int FAST_FUNC wait4pid(pid_t pid)
315 return WTERMSIG(status) + 0x180; 315 return WTERMSIG(status) + 0x180;
316 return 0; 316 return 0;
317} 317}
318
319// Useful when we do know that pid is valid, and we just want to wait
320// for it to exit. Not existing pid is fatal. waitpid() status is not returned.
321int FAST_FUNC wait_for_exitstatus(pid_t pid)
322{
323 int exit_status, n;
324
325 n = safe_waitpid(pid, &exit_status, 0);
326 if (n < 0)
327 bb_perror_msg_and_die("waitpid");
328 return exit_status;
329}
diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c
index 73488908d..e9222f690 100644
--- a/libbb/xfuncs_printf.c
+++ b/libbb/xfuncs_printf.c
@@ -390,6 +390,12 @@ void FAST_FUNC xchdir(const char *path)
390 bb_perror_msg_and_die("can't change directory to '%s'", path); 390 bb_perror_msg_and_die("can't change directory to '%s'", path);
391} 391}
392 392
393void FAST_FUNC xfchdir(int fd)
394{
395 if (fchdir(fd))
396 bb_perror_msg_and_die("fchdir");
397}
398
393void FAST_FUNC xchroot(const char *path) 399void FAST_FUNC xchroot(const char *path)
394{ 400{
395 if (chroot(path)) 401 if (chroot(path))
@@ -653,3 +659,19 @@ pid_t FAST_FUNC xfork(void)
653 return pid; 659 return pid;
654} 660}
655#endif 661#endif
662
663void FAST_FUNC xvfork_parent_waits_and_exits(void)
664{
665 pid_t pid;
666
667 fflush_all();
668 pid = xvfork();
669 if (pid > 0) {
670 /* Parent */
671 int exit_status = wait_for_exitstatus(pid);
672 if (WIFSIGNALED(exit_status))
673 kill_myself_with_sig(WTERMSIG(exit_status));
674 _exit(WEXITSTATUS(exit_status));
675 }
676 /* Child continues */
677}
diff --git a/loginutils/chpasswd.c b/loginutils/chpasswd.c
index a022a42d6..2d268be67 100644
--- a/loginutils/chpasswd.c
+++ b/loginutils/chpasswd.c
@@ -105,7 +105,7 @@ int chpasswd_main(int argc UNUSED_PARAM, char **argv)
105 if (rc < 0) 105 if (rc < 0)
106 bb_error_msg_and_die("an error occurred updating password for %s", name); 106 bb_error_msg_and_die("an error occurred updating password for %s", name);
107 if (rc) 107 if (rc)
108 bb_info_msg("Password for '%s' changed", name); 108 bb_error_msg("password for '%s' changed", name);
109 logmode = LOGMODE_STDIO; 109 logmode = LOGMODE_STDIO;
110 free(name); 110 free(name);
111 free(free_me); 111 free(free_me);
diff --git a/loginutils/cryptpw.c b/loginutils/cryptpw.c
index 55dcc2914..23a1884f4 100644
--- a/loginutils/cryptpw.c
+++ b/loginutils/cryptpw.c
@@ -14,13 +14,22 @@
14//config: default y 14//config: default y
15//config: help 15//config: help
16//config: Encrypts the given password with the crypt(3) libc function 16//config: Encrypts the given password with the crypt(3) libc function
17//config: using the given salt.
18//config:
19//config:config MKPASSWD
20//config: bool "mkpasswd"
21//config: default y
22//config: help
23//config: Encrypts the given password with the crypt(3) libc function
17//config: using the given salt. Debian has this utility under mkpasswd 24//config: using the given salt. Debian has this utility under mkpasswd
18//config: name. Busybox provides mkpasswd as an alias for cryptpw. 25//config: name. Busybox provides mkpasswd as an alias for cryptpw.
19 26
20//applet:IF_CRYPTPW(APPLET(cryptpw, BB_DIR_USR_BIN, BB_SUID_DROP)) 27//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)) 28// APPLET_ODDNAME:name main location suid_type help
29//applet:IF_MKPASSWD(APPLET_ODDNAME(mkpasswd, cryptpw, BB_DIR_USR_BIN, BB_SUID_DROP, cryptpw))
22 30
23//kbuild:lib-$(CONFIG_CRYPTPW) += cryptpw.o 31//kbuild:lib-$(CONFIG_CRYPTPW) += cryptpw.o
32//kbuild:lib-$(CONFIG_MKPASSWD) += cryptpw.o
24 33
25//usage:#define cryptpw_trivial_usage 34//usage:#define cryptpw_trivial_usage
26//usage: "[OPTIONS] [PASSWORD] [SALT]" 35//usage: "[OPTIONS] [PASSWORD] [SALT]"
@@ -40,25 +49,6 @@
40//usage: "\n -S SALT" 49//usage: "\n -S SALT"
41//usage: ) 50//usage: )
42 51
43/* mkpasswd is an alias to cryptpw */
44//usage:#define mkpasswd_trivial_usage
45//usage: "[OPTIONS] [PASSWORD] [SALT]"
46/* We do support -s, we just don't mention it */
47//usage:#define mkpasswd_full_usage "\n\n"
48//usage: "Crypt PASSWORD using crypt(3)\n"
49//usage: IF_LONG_OPTS(
50//usage: "\n -P,--password-fd=N Read password from fd N"
51/* //usage: "\n -s,--stdin Use stdin; like -P0" */
52//usage: "\n -m,--method=TYPE Encryption method"
53//usage: "\n -S,--salt=SALT"
54//usage: )
55//usage: IF_NOT_LONG_OPTS(
56//usage: "\n -P N Read password from fd N"
57/* //usage: "\n -s Use stdin; like -P0" */
58//usage: "\n -m TYPE Encryption method TYPE"
59//usage: "\n -S SALT"
60//usage: )
61
62#include "libbb.h" 52#include "libbb.h"
63 53
64/* Debian has 'mkpasswd' utility, manpage says: 54/* Debian has 'mkpasswd' utility, manpage says:
@@ -140,7 +130,7 @@ int cryptpw_main(int argc UNUSED_PARAM, char **argv)
140 if (!password) { 130 if (!password) {
141 /* Only mkpasswd, and only from tty, prompts. 131 /* Only mkpasswd, and only from tty, prompts.
142 * Otherwise it is a plain read. */ 132 * Otherwise it is a plain read. */
143 password = (isatty(STDIN_FILENO) && applet_name[0] == 'm') 133 password = (ENABLE_MKPASSWD && isatty(STDIN_FILENO) && applet_name[0] == 'm')
144 ? bb_ask_stdin("Password: ") 134 ? bb_ask_stdin("Password: ")
145 : xmalloc_fgetline(stdin) 135 : xmalloc_fgetline(stdin)
146 ; 136 ;
diff --git a/loginutils/passwd.c b/loginutils/passwd.c
index 73726d3e0..52b66ca50 100644
--- a/loginutils/passwd.c
+++ b/loginutils/passwd.c
@@ -230,7 +230,7 @@ int passwd_main(int argc UNUSED_PARAM, char **argv)
230 /* LOGMODE_BOTH */ 230 /* LOGMODE_BOTH */
231 if (rc < 0) 231 if (rc < 0)
232 bb_error_msg_and_die("can't update password file %s", filename); 232 bb_error_msg_and_die("can't update password file %s", filename);
233 bb_info_msg("Password for %s changed by %s", name, myname); 233 bb_error_msg("password for %s changed by %s", name, myname);
234 234
235 /*if (ENABLE_FEATURE_CLEAN_UP) free(newp); - can't, it may be non-malloced */ 235 /*if (ENABLE_FEATURE_CLEAN_UP) free(newp); - can't, it may be non-malloced */
236 skip: 236 skip:
diff --git a/loginutils/sulogin.c b/loginutils/sulogin.c
index 19b1e304c..f32469551 100644
--- a/loginutils/sulogin.c
+++ b/loginutils/sulogin.c
@@ -12,7 +12,6 @@
12//config: sulogin is invoked when the system goes into single user 12//config: sulogin is invoked when the system goes into single user
13//config: mode (this is done through an entry in inittab). 13//config: mode (this is done through an entry in inittab).
14 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)) 15//applet:IF_SULOGIN(APPLET(sulogin, BB_DIR_SBIN, BB_SUID_DROP))
17 16
18//kbuild:lib-$(CONFIG_SULOGIN) += sulogin.o 17//kbuild:lib-$(CONFIG_SULOGIN) += sulogin.o
@@ -33,6 +32,14 @@ int sulogin_main(int argc UNUSED_PARAM, char **argv)
33 struct passwd *pwd; 32 struct passwd *pwd;
34 const char *shell; 33 const char *shell;
35 34
35 /* Note: sulogin is not a suid app. It is meant to be run by init
36 * for single user / emergency mode. init starts it as root.
37 * Normal users (potentially malisious ones) can only run it under
38 * their UID, therefore no paranoia here is warranted:
39 * $LD_LIBRARY_PATH in env, TTY = /dev/sda
40 * are no more dangerous here than in e.g. cp applet.
41 */
42
36 logmode = LOGMODE_BOTH; 43 logmode = LOGMODE_BOTH;
37 openlog(applet_name, 0, LOG_AUTH); 44 openlog(applet_name, 0, LOG_AUTH);
38 45
@@ -48,18 +55,9 @@ int sulogin_main(int argc UNUSED_PARAM, char **argv)
48 dup(0); 55 dup(0);
49 } 56 }
50 57
51 /* Malicious use like "sulogin /dev/sda"? */
52 if (!isatty(0) || !isatty(1) || !isatty(2)) {
53 logmode = LOGMODE_SYSLOG;
54 bb_error_msg_and_die("not a tty");
55 }
56
57 /* Clear dangerous stuff, set PATH */
58 sanitize_env_if_suid();
59
60 pwd = getpwuid(0); 58 pwd = getpwuid(0);
61 if (!pwd) { 59 if (!pwd) {
62 goto auth_error; 60 bb_error_msg_and_die("no password entry for root");
63 } 61 }
64 62
65 while (1) { 63 while (1) {
@@ -71,17 +69,17 @@ int sulogin_main(int argc UNUSED_PARAM, char **argv)
71 ); 69 );
72 if (r < 0) { 70 if (r < 0) {
73 /* ^D, ^C, timeout, or read error */ 71 /* ^D, ^C, timeout, or read error */
74 bb_info_msg("Normal startup"); 72 bb_error_msg("normal startup");
75 return 0; 73 return 0;
76 } 74 }
77 if (r > 0) { 75 if (r > 0) {
78 break; 76 break;
79 } 77 }
80 bb_do_delay(LOGIN_FAIL_DELAY); 78 bb_do_delay(LOGIN_FAIL_DELAY);
81 bb_info_msg("Login incorrect"); 79 bb_error_msg("Login incorrect");
82 } 80 }
83 81
84 bb_info_msg("System Maintenance Mode"); 82 bb_error_msg("starting shell for system maintenance");
85 83
86 IF_SELINUX(renew_current_security_context()); 84 IF_SELINUX(renew_current_security_context());
87 85
@@ -93,7 +91,4 @@ int sulogin_main(int argc UNUSED_PARAM, char **argv)
93 91
94 /* Exec login shell with no additional parameters. Never returns. */ 92 /* Exec login shell with no additional parameters. Never returns. */
95 run_shell(shell, 1, NULL, NULL); 93 run_shell(shell, 1, NULL, NULL);
96
97 auth_error:
98 bb_error_msg_and_die("no password entry for root");
99} 94}
diff --git a/mailutils/sendmail.c b/mailutils/sendmail.c
index 4355e4dc5..5143fac8f 100644
--- a/mailutils/sendmail.c
+++ b/mailutils/sendmail.c
@@ -270,7 +270,7 @@ int sendmail_main(int argc UNUSED_PARAM, char **argv)
270 // G.method = xstrdup(a+1); 270 // G.method = xstrdup(a+1);
271 } 271 }
272 // N.B. list == NULL here 272 // N.B. list == NULL here
273 //bb_info_msg("OPT[%x] AU[%s], AP[%s], AM[%s], ARGV[%s]", opts, au, ap, am, *argv); 273 //bb_error_msg("OPT[%x] AU[%s], AP[%s], AM[%s], ARGV[%s]", opts, au, ap, am, *argv);
274 274
275 // connect to server 275 // connect to server
276 276
diff --git a/miscutils/beep.c b/miscutils/beep.c
index 910e03e1b..18b160cc4 100644
--- a/miscutils/beep.c
+++ b/miscutils/beep.c
@@ -88,7 +88,7 @@ int beep_main(int argc, char **argv)
88 bb_show_usage(); 88 bb_show_usage();
89 } 89 }
90 while (rep) { 90 while (rep) {
91//bb_info_msg("rep[%d] freq=%d, length=%d, delay=%d", rep, freq, length, delay); 91//bb_error_msg("rep[%d] freq=%d, length=%d, delay=%d", rep, freq, length, delay);
92 xioctl(speaker, KIOCSOUND, (void*)(uintptr_t)tickrate_div_freq); 92 xioctl(speaker, KIOCSOUND, (void*)(uintptr_t)tickrate_div_freq);
93 usleep(1000 * length); 93 usleep(1000 * length);
94 ioctl(speaker, KIOCSOUND, (void*)0); 94 ioctl(speaker, KIOCSOUND, (void*)0);
diff --git a/miscutils/devfsd.c b/miscutils/devfsd.c
index 9256567cc..6217918da 100644
--- a/miscutils/devfsd.c
+++ b/miscutils/devfsd.c
@@ -284,7 +284,7 @@ static const char bb_msg_variable_not_found[] ALIGN1 = "variable: %s not found";
284 284
285/* Busybox stuff */ 285/* Busybox stuff */
286#if ENABLE_DEVFSD_VERBOSE || ENABLE_DEBUG 286#if ENABLE_DEVFSD_VERBOSE || ENABLE_DEBUG
287#define info_logger(p, fmt, args...) bb_info_msg(fmt, ## args) 287#define info_logger(p, fmt, args...) bb_error_msg(fmt, ## args)
288#define msg_logger(p, fmt, args...) bb_error_msg(fmt, ## args) 288#define msg_logger(p, fmt, args...) bb_error_msg(fmt, ## args)
289#define msg_logger_and_die(p, fmt, args...) bb_error_msg_and_die(fmt, ## args) 289#define msg_logger_and_die(p, fmt, args...) bb_error_msg_and_die(fmt, ## args)
290#define error_logger(p, fmt, args...) bb_perror_msg(fmt, ## args) 290#define error_logger(p, fmt, args...) bb_perror_msg(fmt, ## args)
diff --git a/miscutils/eject.c b/miscutils/eject.c
index a20e04b7f..e33d79127 100644
--- a/miscutils/eject.c
+++ b/miscutils/eject.c
@@ -25,23 +25,19 @@
25 25
26#include <sys/mount.h> 26#include <sys/mount.h>
27#include "libbb.h" 27#include "libbb.h"
28#if ENABLE_FEATURE_EJECT_SCSI
28/* Must be after libbb.h: they need size_t */ 29/* Must be after libbb.h: they need size_t */
29#include "fix_u32.h" 30# include "fix_u32.h"
30#include <scsi/sg.h> 31# include <scsi/sg.h>
31#include <scsi/scsi.h> 32# include <scsi/scsi.h>
32 33#endif
33/* various defines swiped from linux/cdrom.h */
34#define CDROMCLOSETRAY 0x5319 /* pendant of CDROMEJECT */
35#define CDROMEJECT 0x5309 /* Ejects the cdrom media */
36#define CDROM_DRIVE_STATUS 0x5326 /* Get tray position, etc. */
37/* drive status possibilities returned by CDROM_DRIVE_STATUS ioctl */
38#define CDS_TRAY_OPEN 2
39 34
40#define dev_fd 3 35#define dev_fd 3
41 36
42/* Code taken from the original eject (http://eject.sourceforge.net/), 37/* Code taken from the original eject (http://eject.sourceforge.net/),
43 * refactored it a bit for busybox (ne-bb@nicoerfurth.de) */ 38 * refactored it a bit for busybox (ne-bb@nicoerfurth.de) */
44 39
40#if ENABLE_FEATURE_EJECT_SCSI
45static void eject_scsi(const char *dev) 41static void eject_scsi(const char *dev)
46{ 42{
47 static const char sg_commands[3][6] = { 43 static const char sg_commands[3][6] = {
@@ -76,6 +72,16 @@ static void eject_scsi(const char *dev)
76 /* force kernel to reread partition table when new disc is inserted */ 72 /* force kernel to reread partition table when new disc is inserted */
77 ioctl(dev_fd, BLKRRPART); 73 ioctl(dev_fd, BLKRRPART);
78} 74}
75#else
76# define eject_scsi(dev) ((void)0)
77#endif
78
79/* various defines swiped from linux/cdrom.h */
80#define CDROMCLOSETRAY 0x5319 /* pendant of CDROMEJECT */
81#define CDROMEJECT 0x5309 /* Ejects the cdrom media */
82#define CDROM_DRIVE_STATUS 0x5326 /* Get tray position, etc. */
83/* drive status possibilities returned by CDROM_DRIVE_STATUS ioctl */
84#define CDS_TRAY_OPEN 2
79 85
80#define FLAG_CLOSE 1 86#define FLAG_CLOSE 1
81#define FLAG_SMART 2 87#define FLAG_SMART 2
diff --git a/miscutils/flash_eraseall.c b/miscutils/flash_eraseall.c
index bf9b739a1..d95d214d9 100644
--- a/miscutils/flash_eraseall.c
+++ b/miscutils/flash_eraseall.c
@@ -147,7 +147,7 @@ int flash_eraseall_main(int argc UNUSED_PARAM, char **argv)
147 ret = ioctl(fd, MEMGETBADBLOCK, &offset); 147 ret = ioctl(fd, MEMGETBADBLOCK, &offset);
148 if (ret > 0) { 148 if (ret > 0) {
149 if (!(flags & OPTION_Q)) 149 if (!(flags & OPTION_Q))
150 bb_info_msg("\nSkipping bad block at 0x%08x", erase.start); 150 printf("\nSkipping bad block at 0x%08x\n", erase.start);
151 continue; 151 continue;
152 } 152 }
153 if (ret < 0) { 153 if (ret < 0) {
diff --git a/miscutils/inotifyd.c b/miscutils/inotifyd.c
index 7a1a6a2e5..908d657fd 100644
--- a/miscutils/inotifyd.c
+++ b/miscutils/inotifyd.c
@@ -47,8 +47,8 @@
47//usage: "\n o Event queue overflowed" 47//usage: "\n o Event queue overflowed"
48//usage: "\n x File can't be watched anymore" 48//usage: "\n x File can't be watched anymore"
49//usage: "\nIf watching a directory:" 49//usage: "\nIf watching a directory:"
50//usage: "\n m Subfile is moved into dir" 50//usage: "\n y Subfile is moved into dir"
51//usage: "\n y Subfile is moved out of dir" 51//usage: "\n m Subfile is moved out of dir"
52//usage: "\n n Subfile is created" 52//usage: "\n n Subfile is created"
53//usage: "\n d Subfile is deleted" 53//usage: "\n d Subfile is deleted"
54//usage: "\n" 54//usage: "\n"
diff --git a/miscutils/taskset.c b/miscutils/taskset.c
index 100b1d926..fb352ab8d 100644
--- a/miscutils/taskset.c
+++ b/miscutils/taskset.c
@@ -75,27 +75,26 @@ 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 char *p = (void*)mask; 78 BUILD_BUG_ON(CPU_SETSIZE < 8*sizeof(int));
79 79
80 BUILD_BUG_ON(CPU_SETSIZE < sizeof(int)); 80 /* Take the least significant bits. Assume cpu_set_t is
81 81 * implemented as an array of unsigned long or unsigned
82 /* Take the least significant bits. Careful! 82 * int.
83 * Consider both CPU_SETSIZE=4 and CPU_SETSIZE=1024 cases
84 */ 83 */
85#if BB_BIG_ENDIAN 84 if (CPU_SETSIZE < 8*sizeof(long))
86 /* For big endian, it means LAST bits */ 85 return *(unsigned*)mask;
87 if (CPU_SETSIZE < sizeof(long)) 86 if (CPU_SETSIZE < 8*sizeof(long long))
88 p += CPU_SETSIZE - sizeof(int); 87 return *(unsigned long*)mask;
89 else if (CPU_SETSIZE < sizeof(long long)) 88# if BB_BIG_ENDIAN
90 p += CPU_SETSIZE - sizeof(long); 89 if (sizeof(long long) > sizeof(long)) {
91 else 90 /* We can put two long in the long long, but they have to
92 p += CPU_SETSIZE - sizeof(long long); 91 * be swapped: the least significant word comes first in the
93#endif 92 * array */
94 if (CPU_SETSIZE < sizeof(long)) 93 unsigned long *p = (void*)mask;
95 return *(unsigned*)p; 94 return p[0] + ((unsigned long long)p[1] << (8*sizeof(long)));
96 if (CPU_SETSIZE < sizeof(long long)) 95 }
97 return *(unsigned long*)p; 96# endif
98 return *(unsigned long long*)p; 97 return *(unsigned long long*)mask;
99} 98}
100#endif 99#endif
101 100
diff --git a/miscutils/ubi_tools.c b/miscutils/ubi_tools.c
index dd1bda300..4364bc807 100644
--- a/miscutils/ubi_tools.c
+++ b/miscutils/ubi_tools.c
@@ -195,7 +195,7 @@ int ubi_tools_main(int argc UNUSED_PARAM, char **argv)
195 } else 195 } else
196 196
197//usage:#define ubimkvol_trivial_usage 197//usage:#define ubimkvol_trivial_usage
198//usage: "UBI_DEVICE -N NAME [-s SIZE | -m]" 198//usage: "-N NAME [-s SIZE | -m] UBI_DEVICE"
199//usage:#define ubimkvol_full_usage "\n\n" 199//usage:#define ubimkvol_full_usage "\n\n"
200//usage: "Create UBI volume\n" 200//usage: "Create UBI volume\n"
201//usage: "\n -a ALIGNMENT Volume alignment (default 1)" 201//usage: "\n -a ALIGNMENT Volume alignment (default 1)"
@@ -212,9 +212,7 @@ int ubi_tools_main(int argc UNUSED_PARAM, char **argv)
212 unsigned num; 212 unsigned num;
213 char *p; 213 char *p;
214 214
215 if (sscanf(ubi_ctrl, "/dev/ubi%u", &num) != 1) 215 num = ubi_devnum_from_devname(ubi_ctrl);
216 bb_error_msg_and_die("wrong format of UBI device name");
217
218 p = path_sys_class_ubi_ubi + sprintf(path_sys_class_ubi_ubi, "%u/", num); 216 p = path_sys_class_ubi_ubi + sprintf(path_sys_class_ubi_ubi, "%u/", num);
219 217
220 strcpy(p, "avail_eraseblocks"); 218 strcpy(p, "avail_eraseblocks");
@@ -248,20 +246,31 @@ int ubi_tools_main(int argc UNUSED_PARAM, char **argv)
248 } else 246 } else
249 247
250//usage:#define ubirmvol_trivial_usage 248//usage:#define ubirmvol_trivial_usage
251//usage: "UBI_DEVICE -n VOLID" 249//usage: "-n VOLID / -N VOLNAME UBI_DEVICE"
252//usage:#define ubirmvol_full_usage "\n\n" 250//usage:#define ubirmvol_full_usage "\n\n"
253//usage: "Remove UBI volume\n" 251//usage: "Remove UBI volume\n"
254//usage: "\n -n VOLID Volume ID" 252//usage: "\n -n VOLID Volume ID"
253//usage: "\n -N VOLNAME Volume name"
255 if (do_rmvol) { 254 if (do_rmvol) {
256 if (!(opts & OPTION_n)) 255 if (!(opts & (OPTION_n|OPTION_N)))
257 bb_error_msg_and_die("volume id not specified"); 256 bb_error_msg_and_die("volume id not specified");
258 257
259 /* FIXME? kernel expects int32_t* here: */ 258 if (opts & OPTION_N) {
260 xioctl(fd, UBI_IOCRMVOL, &vol_id); 259 unsigned num = ubi_devnum_from_devname(ubi_ctrl);
260 vol_id = ubi_get_volid_by_name(num, vol_name);
261 }
262
263 if (sizeof(vol_id) != 4) {
264 /* kernel expects int32_t* in this ioctl */
265 int32_t t = vol_id;
266 xioctl(fd, UBI_IOCRMVOL, &t);
267 } else {
268 xioctl(fd, UBI_IOCRMVOL, &vol_id);
269 }
261 } else 270 } else
262 271
263//usage:#define ubirsvol_trivial_usage 272//usage:#define ubirsvol_trivial_usage
264//usage: "UBI_DEVICE -n VOLID -s SIZE" 273//usage: "-n VOLID -s SIZE UBI_DEVICE"
265//usage:#define ubirsvol_full_usage "\n\n" 274//usage:#define ubirsvol_full_usage "\n\n"
266//usage: "Resize UBI volume\n" 275//usage: "Resize UBI volume\n"
267//usage: "\n -n VOLID Volume ID" 276//usage: "\n -n VOLID Volume ID"
@@ -279,7 +288,7 @@ int ubi_tools_main(int argc UNUSED_PARAM, char **argv)
279 } else 288 } else
280 289
281//usage:#define ubiupdatevol_trivial_usage 290//usage:#define ubiupdatevol_trivial_usage
282//usage: "UBI_DEVICE [-t | [-s SIZE] IMG_FILE]" 291//usage: "[-t | [-s SIZE] IMG_FILE] UBI_DEVICE"
283//usage:#define ubiupdatevol_full_usage "\n\n" 292//usage:#define ubiupdatevol_full_usage "\n\n"
284//usage: "Update UBI volume\n" 293//usage: "Update UBI volume\n"
285//usage: "\n -t Truncate to zero size" 294//usage: "\n -t Truncate to zero size"
diff --git a/miscutils/ubirename.c b/miscutils/ubirename.c
new file mode 100644
index 000000000..8b1c3785a
--- /dev/null
+++ b/miscutils/ubirename.c
@@ -0,0 +1,94 @@
1/* ubirename - port of the ubirename from the mtd-utils package
2 *
3 * A utility to rename one UBI volume.
4 *
5 * 2016-03-01 Sven Eisenberg <sven.eisenberg@novero.com>
6 *
7 * Licensed under GPLv2, see file LICENSE in this source tree.
8 */
9//config:config UBIRENAME
10//config: bool "ubirename"
11//config: default y
12//config: select PLATFORM_LINUX
13//config: help
14//config: Utility to rename UBI volumes
15
16//applet:IF_UBIRENAME(APPLET(ubirename, BB_DIR_USR_SBIN, BB_SUID_DROP))
17
18//kbuild:lib-$(CONFIG_UBIRENAME) += ubirename.o
19
20//usage:#define ubirename_trivial_usage
21//usage: "UBI_DEVICE OLD_VOLNAME NEW_VOLNAME [OLD2 NEW2]..."
22//usage:#define ubirename_full_usage "\n\n"
23//usage: "Rename UBI volumes on UBI_DEVICE"
24
25#include "libbb.h"
26#include <mtd/mtd-user.h>
27
28#ifndef __packed
29# define __packed __attribute__((packed))
30#endif
31
32// from ubi-media.h
33#define UBI_MAX_VOLUME_NAME 127
34#define UBI_MAX_VOLUMES 128
35// end ubi-media.h
36
37// from ubi-user.h
38/* ioctl commands of UBI character devices */
39#define UBI_IOC_MAGIC 'o'
40
41/* Re-name volumes */
42#define UBI_IOCRNVOL _IOW(UBI_IOC_MAGIC, 3, struct ubi_rnvol_req)
43
44/* Maximum amount of UBI volumes that can be re-named at one go */
45#define UBI_MAX_RNVOL 32
46
47struct ubi_rnvol_req {
48 int32_t count;
49 int8_t padding1[12];
50 struct {
51 int32_t vol_id;
52 int16_t name_len;
53 int8_t padding2[2];
54 char name[UBI_MAX_VOLUME_NAME + 1];
55 } ents[UBI_MAX_RNVOL];
56} __packed;
57// end ubi-user.h
58
59int ubirename_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
60int ubirename_main(int argc, char **argv)
61{
62 struct ubi_rnvol_req *rnvol;
63 const char *ubi_devname;
64 unsigned ubi_devnum;
65 unsigned n;
66
67 /* argc can be 4, 6, 8, ... */
68 if ((argc & 1) || (argc >>= 1) < 2)
69 bb_show_usage();
70
71 rnvol = xzalloc(sizeof(*rnvol));
72 rnvol->count = --argc;
73 if (argc > ARRAY_SIZE(rnvol->ents))
74 bb_error_msg_and_die("too many renames requested");
75
76 ubi_devname = argv[1];
77 ubi_devnum = ubi_devnum_from_devname(ubi_devname);
78
79 n = 0;
80 argv += 2;
81 while (argv[0]) {
82 rnvol->ents[n].vol_id = ubi_get_volid_by_name(ubi_devnum, argv[0]);
83 rnvol->ents[n].name_len = strlen(argv[1]);
84 if (rnvol->ents[n].name_len >= sizeof(rnvol->ents[n].name))
85 bb_error_msg_and_die("new name '%s' is too long", argv[1]);
86 strcpy(rnvol->ents[n].name, argv[1]);
87 n++;
88 argv += 2;
89 }
90
91 xioctl(xopen(ubi_devname, O_RDONLY), UBI_IOCRNVOL, rnvol);
92
93 return 0;
94}
diff --git a/modutils/modprobe.c b/modutils/modprobe.c
index 997ee3c67..8130c40b7 100644
--- a/modutils/modprobe.c
+++ b/modutils/modprobe.c
@@ -214,7 +214,7 @@ static void add_probe(const char *name)
214static int FAST_FUNC config_file_action(const char *filename, 214static int FAST_FUNC config_file_action(const char *filename,
215 struct stat *statbuf UNUSED_PARAM, 215 struct stat *statbuf UNUSED_PARAM,
216 void *userdata UNUSED_PARAM, 216 void *userdata UNUSED_PARAM,
217 int depth UNUSED_PARAM) 217 int depth)
218{ 218{
219 char *tokens[3]; 219 char *tokens[3];
220 parser_t *p; 220 parser_t *p;
@@ -222,15 +222,20 @@ static int FAST_FUNC config_file_action(const char *filename,
222 int rc = TRUE; 222 int rc = TRUE;
223 const char *base, *ext; 223 const char *base, *ext;
224 224
225 /* Skip files that begin with a ".". */ 225 /* Skip files that begin with a "." */
226 base = bb_basename(filename); 226 base = bb_basename(filename);
227 if (base[0] == '.') 227 if (base[0] == '.')
228 goto error; 228 goto error;
229 229
230 /* Skip files that do not end with a ".conf". */ 230 /* In dir recursion, skip files that do not end with a ".conf"
231 ext = strrchr(base, '.'); 231 * depth==0: read_config("modules.{symbols,alias}") must work,
232 if (ext == NULL || strcmp(ext + 1, "conf")) 232 * "include FILE_NOT_ENDING_IN_CONF" must work too.
233 goto error; 233 */
234 if (depth != 0) {
235 ext = strrchr(base, '.');
236 if (ext == NULL || strcmp(ext + 1, "conf"))
237 goto error;
238 }
234 239
235 p = config_open2(filename, fopen_for_read); 240 p = config_open2(filename, fopen_for_read);
236 if (p == NULL) { 241 if (p == NULL) {
@@ -275,7 +280,7 @@ static int FAST_FUNC config_file_action(const char *filename,
275 m = get_or_add_modentry(tokens[1]); 280 m = get_or_add_modentry(tokens[1]);
276 m->options = gather_options_str(m->options, tokens[2]); 281 m->options = gather_options_str(m->options, tokens[2]);
277 } else if (strcmp(tokens[0], "include") == 0) { 282 } else if (strcmp(tokens[0], "include") == 0) {
278 /* include <filename> */ 283 /* include <filename>/<dirname> (yes, directories also must work) */
279 read_config(tokens[1]); 284 read_config(tokens[1]);
280 } else if (ENABLE_FEATURE_MODPROBE_BLACKLIST 285 } else if (ENABLE_FEATURE_MODPROBE_BLACKLIST
281 && strcmp(tokens[0], "blacklist") == 0 286 && strcmp(tokens[0], "blacklist") == 0
@@ -292,7 +297,8 @@ static int FAST_FUNC config_file_action(const char *filename,
292static int read_config(const char *path) 297static int read_config(const char *path)
293{ 298{
294 return recursive_action(path, ACTION_RECURSE | ACTION_QUIET, 299 return recursive_action(path, ACTION_RECURSE | ACTION_QUIET,
295 config_file_action, NULL, NULL, 1); 300 config_file_action, NULL, NULL,
301 /*depth:*/ 0);
296} 302}
297 303
298static const char *humanly_readable_name(struct module_entry *m) 304static const char *humanly_readable_name(struct module_entry *m)
diff --git a/networking/ifupdown.c b/networking/ifupdown.c
index 766dfabbd..2c6db926f 100644
--- a/networking/ifupdown.c
+++ b/networking/ifupdown.c
@@ -850,7 +850,6 @@ static struct interfaces_file_t *read_interfaces(const char *filename, struct in
850 char *iface_name; 850 char *iface_name;
851 char *address_family_name; 851 char *address_family_name;
852 char *method_name; 852 char *method_name;
853 llist_t *iface_list;
854 853
855 currif = xzalloc(sizeof(*currif)); 854 currif = xzalloc(sizeof(*currif));
856 iface_name = next_word(&rest_of_line); 855 iface_name = next_word(&rest_of_line);
@@ -875,7 +874,20 @@ static struct interfaces_file_t *read_interfaces(const char *filename, struct in
875 currif->method = get_method(currif->address_family, method_name); 874 currif->method = get_method(currif->address_family, method_name);
876 if (!currif->method) 875 if (!currif->method)
877 bb_error_msg_and_die("unknown method \"%s\"", method_name); 876 bb_error_msg_and_die("unknown method \"%s\"", method_name);
878 877#if 0
878// Allegedly, Debian allows a duplicate definition:
879// iface eth0 inet static
880// address 192.168.0.15
881// netmask 255.255.0.0
882// gateway 192.168.0.1
883//
884// iface eth0 inet static
885// address 10.0.0.1
886// netmask 255.255.255.0
887//
888// This adds *two* addresses to eth0 (probably requires use of "ip", not "ifconfig"
889//
890 llist_t *iface_list;
879 for (iface_list = defn->ifaces; iface_list; iface_list = iface_list->link) { 891 for (iface_list = defn->ifaces; iface_list; iface_list = iface_list->link) {
880 struct interface_defn_t *tmp = (struct interface_defn_t *) iface_list->data; 892 struct interface_defn_t *tmp = (struct interface_defn_t *) iface_list->data;
881 if ((strcmp(tmp->iface, currif->iface) == 0) 893 if ((strcmp(tmp->iface, currif->iface) == 0)
@@ -884,6 +896,7 @@ static struct interfaces_file_t *read_interfaces(const char *filename, struct in
884 bb_error_msg_and_die("duplicate interface \"%s\"", tmp->iface); 896 bb_error_msg_and_die("duplicate interface \"%s\"", tmp->iface);
885 } 897 }
886 } 898 }
899#endif
887 llist_add_to_end(&(defn->ifaces), (char*)currif); 900 llist_add_to_end(&(defn->ifaces), (char*)currif);
888 901
889 debug_noise("iface %s %s %s\n", currif->iface, address_family_name, method_name); 902 debug_noise("iface %s %s %s\n", currif->iface, address_family_name, method_name);
diff --git a/networking/inetd.c b/networking/inetd.c
index 243165a07..4f6673b12 100644
--- a/networking/inetd.c
+++ b/networking/inetd.c
@@ -834,10 +834,10 @@ static NOINLINE servtab_t *parse_one_line(void)
834 goto parse_err; 834 goto parse_err;
835 } 835 }
836 836
837// bb_info_msg( 837 //bb_error_msg(
838// "ENTRY[%s][%s][%s][%d][%d][%d][%d][%d][%s][%s][%s]", 838 // "ENTRY[%s][%s][%s][%d][%d][%d][%d][%d][%s][%s][%s]",
839// sep->se_local_hostname, sep->se_service, sep->se_proto, sep->se_wait, sep->se_proto_no, 839 // sep->se_local_hostname, sep->se_service, sep->se_proto, sep->se_wait, sep->se_proto_no,
840// sep->se_max, sep->se_count, sep->se_time, sep->se_user, sep->se_group, sep->se_program); 840 // sep->se_max, sep->se_count, sep->se_time, sep->se_user, sep->se_group, sep->se_program);
841 841
842 /* check if the hostname specifier is a comma separated list 842 /* check if the hostname specifier is a comma separated list
843 * of hostnames. we'll make new entries for each address. */ 843 * of hostnames. we'll make new entries for each address. */
diff --git a/networking/ntpd.c b/networking/ntpd.c
index 1651670d9..410318979 100644
--- a/networking/ntpd.c
+++ b/networking/ntpd.c
@@ -267,6 +267,7 @@ typedef struct {
267 267
268typedef struct { 268typedef struct {
269 len_and_sockaddr *p_lsa; 269 len_and_sockaddr *p_lsa;
270 char *p_hostname;
270 char *p_dotted; 271 char *p_dotted;
271 int p_fd; 272 int p_fd;
272 int datapoint_idx; 273 int datapoint_idx;
@@ -727,7 +728,7 @@ reset_peer_stats(peer_t *p, double offset)
727 728
728 /* Used to set p->filter_datapoint[i].d_dispersion = MAXDISP 729 /* Used to set p->filter_datapoint[i].d_dispersion = MAXDISP
729 * and clear reachable bits, but this proved to be too agressive: 730 * and clear reachable bits, but this proved to be too agressive:
730 * after step (tested with suspinding laptop for ~30 secs), 731 * after step (tested with suspending laptop for ~30 secs),
731 * this caused all previous data to be considered invalid, 732 * this caused all previous data to be considered invalid,
732 * making us needing to collect full ~8 datapoins per peer 733 * making us needing to collect full ~8 datapoins per peer
733 * after step in order to start trusting them. 734 * after step in order to start trusting them.
@@ -766,11 +767,29 @@ reset_peer_stats(peer_t *p, double offset)
766static void 767static void
767add_peers(const char *s) 768add_peers(const char *s)
768{ 769{
770 llist_t *item;
769 peer_t *p; 771 peer_t *p;
770 772
771 p = xzalloc(sizeof(*p)); 773 p = xzalloc(sizeof(*p));
772 p->p_lsa = xhost2sockaddr(s, 123); 774 p->p_lsa = xhost2sockaddr(s, 123);
773 p->p_dotted = xmalloc_sockaddr2dotted_noport(&p->p_lsa->u.sa); 775 p->p_dotted = xmalloc_sockaddr2dotted_noport(&p->p_lsa->u.sa);
776
777 /* Names like N.<country2chars>.pool.ntp.org are randomly resolved
778 * to a pool of machines. Sometimes different N's resolve to the same IP.
779 * It is not useful to have two peers with same IP. We skip duplicates.
780 */
781 for (item = G.ntp_peers; item != NULL; item = item->link) {
782 peer_t *pp = (peer_t *) item->data;
783 if (strcmp(p->p_dotted, pp->p_dotted) == 0) {
784 bb_error_msg("duplicate peer %s (%s)", s, p->p_dotted);
785 free(p->p_lsa);
786 free(p->p_dotted);
787 free(p);
788 return;
789 }
790 }
791
792 p->p_hostname = xstrdup(s);
774 p->p_fd = -1; 793 p->p_fd = -1;
775 p->p_xmt_msg.m_status = MODE_CLIENT | (NTP_VERSION << 3); 794 p->p_xmt_msg.m_status = MODE_CLIENT | (NTP_VERSION << 3);
776 p->next_action_time = G.cur_time; /* = set_next(p, 0); */ 795 p->next_action_time = G.cur_time; /* = set_next(p, 0); */
@@ -1685,8 +1704,14 @@ update_local_clock(peer_t *p)
1685 VERB4 bb_error_msg("adjtimex:%d freq:%ld offset:%+ld status:0x%x", 1704 VERB4 bb_error_msg("adjtimex:%d freq:%ld offset:%+ld status:0x%x",
1686 rc, tmx.freq, tmx.offset, tmx.status); 1705 rc, tmx.freq, tmx.offset, tmx.status);
1687 G.kernel_freq_drift = tmx.freq / 65536; 1706 G.kernel_freq_drift = tmx.freq / 65536;
1688 VERB2 bb_error_msg("update from:%s offset:%+f jitter:%f clock drift:%+.3fppm tc:%d", 1707 VERB2 bb_error_msg("update from:%s offset:%+f delay:%f jitter:%f clock drift:%+.3fppm tc:%d",
1689 p->p_dotted, offset, G.discipline_jitter, (double)tmx.freq / 65536, (int)tmx.constant); 1708 p->p_dotted,
1709 offset,
1710 p->lastpkt_delay,
1711 G.discipline_jitter,
1712 (double)tmx.freq / 65536,
1713 (int)tmx.constant
1714 );
1690 1715
1691 return 1; /* "ok to increase poll interval" */ 1716 return 1; /* "ok to increase poll interval" */
1692} 1717}
@@ -1947,8 +1972,8 @@ recv_and_process_peer_pkt(peer_t *p)
1947 adjust_poll(MINPOLL); 1972 adjust_poll(MINPOLL);
1948 } else { 1973 } else {
1949 VERB3 if (rc > 0) 1974 VERB3 if (rc > 0)
1950 bb_error_msg("want smaller poll interval: offset/jitter > %u", 1975 bb_error_msg("want smaller interval: offset/jitter = %u",
1951 POLLADJ_GATE); 1976 G.offset_to_jitter_ratio);
1952 adjust_poll(-G.poll_exp * 2); 1977 adjust_poll(-G.poll_exp * 2);
1953 } 1978 }
1954 } 1979 }
@@ -2311,6 +2336,21 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv)
2311 timeout = poll_interval(NOREPLY_INTERVAL); 2336 timeout = poll_interval(NOREPLY_INTERVAL);
2312 bb_error_msg("timed out waiting for %s, reach 0x%02x, next query in %us", 2337 bb_error_msg("timed out waiting for %s, reach 0x%02x, next query in %us",
2313 p->p_dotted, p->reachable_bits, timeout); 2338 p->p_dotted, p->reachable_bits, timeout);
2339
2340 /* What if don't see it because it changed its IP? */
2341 if (p->reachable_bits == 0) {
2342 len_and_sockaddr *lsa = host2sockaddr(p->p_hostname, 123);
2343 if (lsa) {
2344 char *dotted = xmalloc_sockaddr2dotted_noport(&lsa->u.sa);
2345 //if (strcmp(dotted, p->p_dotted) != 0)
2346 // bb_error_msg("peer IP changed");
2347 free(p->p_lsa);
2348 free(p->p_dotted);
2349 p->p_lsa = lsa;
2350 p->p_dotted = dotted;
2351 }
2352 }
2353
2314 set_next(p, timeout); 2354 set_next(p, timeout);
2315 } 2355 }
2316 } 2356 }
diff --git a/networking/ntpd.diff b/networking/ntpd.diff
new file mode 100644
index 000000000..4afd7e134
--- /dev/null
+++ b/networking/ntpd.diff
@@ -0,0 +1,24 @@
1This patch scales down small offsets quadratically. Reduces sensitivity to jitter
2
3diff --git a/networking/ntpd.c b/networking/ntpd.c
4index 4695c33..ac05815 100644
5--- a/networking/ntpd.c
6+++ b/networking/ntpd.c
7@@ -1654,6 +1654,17 @@ update_local_clock(peer_t *p)
8 */
9 if (G.offset_to_jitter_ratio >= TIMECONST_HACK_GATE)
10 tmx.constant--;
11+
12+{
13+ double d = p->lastpkt_delay;
14+ if (d > SLEW_THRESHOLD)
15+ d = SLEW_THRESHOLD;
16+ d /= 2;
17+ if ((abs_offset / d) < 1) {
18+ offset *= (abs_offset / d);
19+ }
20+}
21+
22 tmx.offset = (long)(offset * 1000000); /* usec */
23 if (SLEW_THRESHOLD < STEP_THRESHOLD) {
24 if (tmx.offset > (long)(SLEW_THRESHOLD * 1000000)) {
diff --git a/networking/traceroute.c b/networking/traceroute.c
index 642110c54..eee4f8873 100644
--- a/networking/traceroute.c
+++ b/networking/traceroute.c
@@ -497,7 +497,7 @@ send_probe(int seq, int ttl)
497 497
498 res = xsendto(sndsock, out, len, &dest_lsa->u.sa, dest_lsa->len); 498 res = xsendto(sndsock, out, len, &dest_lsa->u.sa, dest_lsa->len);
499 if (res != len) 499 if (res != len)
500 bb_info_msg("sent %d octets, ret=%d", len, res); 500 bb_error_msg("sent %d octets, ret=%d", len, res);
501} 501}
502 502
503#if ENABLE_FEATURE_TRACEROUTE_VERBOSE 503#if ENABLE_FEATURE_TRACEROUTE_VERBOSE
diff --git a/networking/tunctl.c b/networking/tunctl.c
index 3a0870eb5..941e8bbd3 100644
--- a/networking/tunctl.c
+++ b/networking/tunctl.c
@@ -82,7 +82,7 @@ int tunctl_main(int argc UNUSED_PARAM, char **argv)
82 // delete? 82 // delete?
83 if (opts & OPT_d) { 83 if (opts & OPT_d) {
84 IOCTL(fd, TUNSETPERSIST, (void *)(uintptr_t)0); 84 IOCTL(fd, TUNSETPERSIST, (void *)(uintptr_t)0);
85 bb_info_msg("Set '%s' %spersistent", ifr.ifr_name, "non"); 85 printf("Set '%s' nonpersistent\n", ifr.ifr_name);
86 return EXIT_SUCCESS; 86 return EXIT_SUCCESS;
87 } 87 }
88 88
diff --git a/networking/udhcp/arpping.c b/networking/udhcp/arpping.c
index fad2283c3..c98027316 100644
--- a/networking/udhcp/arpping.c
+++ b/networking/udhcp/arpping.c
@@ -132,6 +132,6 @@ int FAST_FUNC arpping(uint32_t test_nip,
132 132
133 ret: 133 ret:
134 close(s); 134 close(s);
135 log1("%srp reply received for this address", rv ? "No a" : "A"); 135 log1("%srp reply received for this address", rv ? "no a" : "A");
136 return rv; 136 return rv;
137} 137}
diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c
index bc41c8d4d..0cf4dab63 100644
--- a/networking/udhcp/common.c
+++ b/networking/udhcp/common.c
@@ -142,7 +142,7 @@ const char dhcp_option_strings[] ALIGN1 =
142 * udhcp_str2optset: to determine how many bytes to allocate. 142 * udhcp_str2optset: to determine how many bytes to allocate.
143 * xmalloc_optname_optval: to estimate string length 143 * xmalloc_optname_optval: to estimate string length
144 * from binary option length: (option[LEN] / dhcp_option_lengths[opt_type]) 144 * from binary option length: (option[LEN] / dhcp_option_lengths[opt_type])
145 * is the number of elements, multiply in by one element's string width 145 * is the number of elements, multiply it by one element's string width
146 * (len_of_option_as_string[opt_type]) and you know how wide string you need. 146 * (len_of_option_as_string[opt_type]) and you know how wide string you need.
147 */ 147 */
148const uint8_t dhcp_option_lengths[] ALIGN1 = { 148const uint8_t dhcp_option_lengths[] ALIGN1 = {
@@ -162,7 +162,18 @@ const uint8_t dhcp_option_lengths[] ALIGN1 = {
162 [OPTION_S32] = 4, 162 [OPTION_S32] = 4,
163 /* Just like OPTION_STRING, we use minimum length here */ 163 /* Just like OPTION_STRING, we use minimum length here */
164 [OPTION_STATIC_ROUTES] = 5, 164 [OPTION_STATIC_ROUTES] = 5,
165 [OPTION_6RD] = 22, /* ignored by udhcp_str2optset */ 165 [OPTION_6RD] = 12, /* ignored by udhcp_str2optset */
166 /* The above value was chosen as follows:
167 * len_of_option_as_string[] for this option is >60: it's a string of the form
168 * "32 128 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 255.255.255.255 ".
169 * Each additional ipv4 address takes 4 bytes in binary option and appends
170 * another "255.255.255.255 " 16-byte string. We can set [OPTION_6RD] = 4
171 * but this severely overestimates string length: instead of 16 bytes,
172 * it adds >60 for every 4 bytes in binary option.
173 * We cheat and declare here that option is in units of 12 bytes.
174 * This adds more than 60 bytes for every three ipv4 addresses - more than enough.
175 * (Even 16 instead of 12 should work, but let's be paranoid).
176 */
166}; 177};
167 178
168 179
@@ -172,7 +183,7 @@ static void log_option(const char *pfx, const uint8_t *opt)
172 if (dhcp_verbose >= 2) { 183 if (dhcp_verbose >= 2) {
173 char buf[256 * 2 + 2]; 184 char buf[256 * 2 + 2];
174 *bin2hex(buf, (void*) (opt + OPT_DATA), opt[OPT_LEN]) = '\0'; 185 *bin2hex(buf, (void*) (opt + OPT_DATA), opt[OPT_LEN]) = '\0';
175 bb_info_msg("%s: 0x%02x %s", pfx, opt[OPT_CODE], buf); 186 bb_error_msg("%s: 0x%02x %s", pfx, opt[OPT_CODE], buf);
176 } 187 }
177} 188}
178#else 189#else
@@ -246,7 +257,7 @@ uint8_t* FAST_FUNC udhcp_get_option(struct dhcp_packet *packet, int code)
246 continue; /* complain and return NULL */ 257 continue; /* complain and return NULL */
247 258
248 if (optionptr[OPT_CODE] == code) { 259 if (optionptr[OPT_CODE] == code) {
249 log_option("Option found", optionptr); 260 log_option("option found", optionptr);
250 return optionptr + OPT_DATA; 261 return optionptr + OPT_DATA;
251 } 262 }
252 263
@@ -258,7 +269,7 @@ uint8_t* FAST_FUNC udhcp_get_option(struct dhcp_packet *packet, int code)
258 } 269 }
259 270
260 /* log3 because udhcpc uses it a lot - very noisy */ 271 /* log3 because udhcpc uses it a lot - very noisy */
261 log3("Option 0x%02x not found", code); 272 log3("option 0x%02x not found", code);
262 return NULL; 273 return NULL;
263} 274}
264 275
@@ -292,7 +303,7 @@ void FAST_FUNC udhcp_add_binary_option(struct dhcp_packet *packet, uint8_t *addo
292 addopt[OPT_CODE]); 303 addopt[OPT_CODE]);
293 return; 304 return;
294 } 305 }
295 log_option("Adding option", addopt); 306 log_option("adding option", addopt);
296 memcpy(optionptr + end, addopt, len); 307 memcpy(optionptr + end, addopt, len);
297 optionptr[end + len] = DHCP_END; 308 optionptr[end + len] = DHCP_END;
298} 309}
@@ -391,7 +402,7 @@ static NOINLINE void attach_option(
391 struct option_set *new, **curr; 402 struct option_set *new, **curr;
392 403
393 /* make a new option */ 404 /* make a new option */
394 log2("Attaching option %02x to list", optflag->code); 405 log2("attaching option %02x to list", optflag->code);
395 new = xmalloc(sizeof(*new)); 406 new = xmalloc(sizeof(*new));
396 new->data = xmalloc(length + OPT_DATA); 407 new->data = xmalloc(length + OPT_DATA);
397 new->data[OPT_CODE] = optflag->code; 408 new->data[OPT_CODE] = optflag->code;
@@ -411,7 +422,7 @@ static NOINLINE void attach_option(
411 unsigned old_len; 422 unsigned old_len;
412 423
413 /* add it to an existing option */ 424 /* add it to an existing option */
414 log2("Attaching option %02x to existing member of list", optflag->code); 425 log2("attaching option %02x to existing member of list", optflag->code);
415 old_len = existing->data[OPT_LEN]; 426 old_len = existing->data[OPT_LEN];
416 if (old_len + length < 255) { 427 if (old_len + length < 255) {
417 /* actually 255 is ok too, but adding a space can overlow it */ 428 /* actually 255 is ok too, but adding a space can overlow it */
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h
index d20659e2f..496ab11a1 100644
--- a/networking/udhcp/common.h
+++ b/networking/udhcp/common.h
@@ -256,16 +256,16 @@ struct option_set *udhcp_find_option(struct option_set *opt_list, uint8_t code)
256#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1 256#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
257# define IF_UDHCP_VERBOSE(...) __VA_ARGS__ 257# define IF_UDHCP_VERBOSE(...) __VA_ARGS__
258extern unsigned dhcp_verbose; 258extern unsigned dhcp_verbose;
259# define log1(...) do { if (dhcp_verbose >= 1) bb_info_msg(__VA_ARGS__); } while (0) 259# define log1(...) do { if (dhcp_verbose >= 1) bb_error_msg(__VA_ARGS__); } while (0)
260# if CONFIG_UDHCP_DEBUG >= 2 260# if CONFIG_UDHCP_DEBUG >= 2
261void udhcp_dump_packet(struct dhcp_packet *packet) FAST_FUNC; 261void udhcp_dump_packet(struct dhcp_packet *packet) FAST_FUNC;
262# define log2(...) do { if (dhcp_verbose >= 2) bb_info_msg(__VA_ARGS__); } while (0) 262# define log2(...) do { if (dhcp_verbose >= 2) bb_error_msg(__VA_ARGS__); } while (0)
263# else 263# else
264# define udhcp_dump_packet(...) ((void)0) 264# define udhcp_dump_packet(...) ((void)0)
265# define log2(...) ((void)0) 265# define log2(...) ((void)0)
266# endif 266# endif
267# if CONFIG_UDHCP_DEBUG >= 3 267# if CONFIG_UDHCP_DEBUG >= 3
268# define log3(...) do { if (dhcp_verbose >= 3) bb_info_msg(__VA_ARGS__); } while (0) 268# define log3(...) do { if (dhcp_verbose >= 3) bb_error_msg(__VA_ARGS__); } while (0)
269# else 269# else
270# define log3(...) ((void)0) 270# define log3(...) ((void)0)
271# endif 271# endif
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c
index 4e9b705b9..422254d62 100644
--- a/networking/udhcp/d6_dhcpc.c
+++ b/networking/udhcp/d6_dhcpc.c
@@ -251,7 +251,7 @@ static void d6_run_script(struct d6_packet *packet, const char *name)
251 envp = fill_envp(packet); 251 envp = fill_envp(packet);
252 252
253 /* call script */ 253 /* call script */
254 log1("Executing %s %s", client_config.script, name); 254 log1("executing %s %s", client_config.script, name);
255 argv[0] = (char*) client_config.script; 255 argv[0] = (char*) client_config.script;
256 argv[1] = (char*) name; 256 argv[1] = (char*) name;
257 argv[2] = NULL; 257 argv[2] = NULL;
@@ -428,7 +428,7 @@ static NOINLINE int send_d6_discover(uint32_t xid, struct in6_addr *requested_ip
428 */ 428 */
429 opt_ptr = add_d6_client_options(opt_ptr); 429 opt_ptr = add_d6_client_options(opt_ptr);
430 430
431 bb_info_msg("Sending discover..."); 431 bb_error_msg("sending %s", "discover");
432 return d6_mcast_from_client_config_ifindex(&packet, opt_ptr); 432 return d6_mcast_from_client_config_ifindex(&packet, opt_ptr);
433} 433}
434 434
@@ -481,7 +481,7 @@ static NOINLINE int send_d6_select(uint32_t xid)
481 */ 481 */
482 opt_ptr = add_d6_client_options(opt_ptr); 482 opt_ptr = add_d6_client_options(opt_ptr);
483 483
484 bb_info_msg("Sending select..."); 484 bb_error_msg("sending %s", "select");
485 return d6_mcast_from_client_config_ifindex(&packet, opt_ptr); 485 return d6_mcast_from_client_config_ifindex(&packet, opt_ptr);
486} 486}
487 487
@@ -550,7 +550,7 @@ static NOINLINE int send_d6_renew(uint32_t xid, struct in6_addr *server_ipv6, st
550 */ 550 */
551 opt_ptr = add_d6_client_options(opt_ptr); 551 opt_ptr = add_d6_client_options(opt_ptr);
552 552
553 bb_info_msg("Sending renew..."); 553 bb_error_msg("sending %s", "renew");
554 if (server_ipv6) 554 if (server_ipv6)
555 return d6_send_kernel_packet( 555 return d6_send_kernel_packet(
556 &packet, (opt_ptr - (uint8_t*) &packet), 556 &packet, (opt_ptr - (uint8_t*) &packet),
@@ -573,7 +573,7 @@ static int send_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cu
573 /* IA NA (contains our current IP) */ 573 /* IA NA (contains our current IP) */
574 opt_ptr = d6_store_blob(opt_ptr, client6_data.ia_na, client6_data.ia_na->len + 2+2); 574 opt_ptr = d6_store_blob(opt_ptr, client6_data.ia_na, client6_data.ia_na->len + 2+2);
575 575
576 bb_info_msg("Sending release..."); 576 bb_error_msg("sending %s", "release");
577 return d6_send_kernel_packet( 577 return d6_send_kernel_packet(
578 &packet, (opt_ptr - (uint8_t*) &packet), 578 &packet, (opt_ptr - (uint8_t*) &packet),
579 our_cur_ipv6, CLIENT_PORT6, 579 our_cur_ipv6, CLIENT_PORT6,
@@ -592,19 +592,19 @@ static NOINLINE int d6_recv_raw_packet(struct in6_addr *peer_ipv6
592 592
593 bytes = safe_read(fd, &packet, sizeof(packet)); 593 bytes = safe_read(fd, &packet, sizeof(packet));
594 if (bytes < 0) { 594 if (bytes < 0) {
595 log1("Packet read error, ignoring"); 595 log1("packet read error, ignoring");
596 /* NB: possible down interface, etc. Caller should pause. */ 596 /* NB: possible down interface, etc. Caller should pause. */
597 return bytes; /* returns -1 */ 597 return bytes; /* returns -1 */
598 } 598 }
599 599
600 if (bytes < (int) (sizeof(packet.ip6) + sizeof(packet.udp))) { 600 if (bytes < (int) (sizeof(packet.ip6) + sizeof(packet.udp))) {
601 log1("Packet is too short, ignoring"); 601 log1("packet is too short, ignoring");
602 return -2; 602 return -2;
603 } 603 }
604 604
605 if (bytes < sizeof(packet.ip6) + ntohs(packet.ip6.ip6_plen)) { 605 if (bytes < sizeof(packet.ip6) + ntohs(packet.ip6.ip6_plen)) {
606 /* packet is bigger than sizeof(packet), we did partial read */ 606 /* packet is bigger than sizeof(packet), we did partial read */
607 log1("Oversized packet, ignoring"); 607 log1("oversized packet, ignoring");
608 return -2; 608 return -2;
609 } 609 }
610 610
@@ -618,7 +618,7 @@ static NOINLINE int d6_recv_raw_packet(struct in6_addr *peer_ipv6
618 /* || bytes > (int) sizeof(packet) - can't happen */ 618 /* || bytes > (int) sizeof(packet) - can't happen */
619 || packet.udp.len != packet.ip6.ip6_plen 619 || packet.udp.len != packet.ip6.ip6_plen
620 ) { 620 ) {
621 log1("Unrelated/bogus packet, ignoring"); 621 log1("unrelated/bogus packet, ignoring");
622 return -2; 622 return -2;
623 } 623 }
624 624
@@ -630,11 +630,11 @@ static NOINLINE int d6_recv_raw_packet(struct in6_addr *peer_ipv6
630// check = packet.udp.check; 630// check = packet.udp.check;
631// packet.udp.check = 0; 631// packet.udp.check = 0;
632// if (check && check != inet_cksum((uint16_t *)&packet, bytes)) { 632// if (check && check != inet_cksum((uint16_t *)&packet, bytes)) {
633// log1("Packet with bad UDP checksum received, ignoring"); 633// log1("packet with bad UDP checksum received, ignoring");
634// return -2; 634// return -2;
635// } 635// }
636 636
637 log1("Received a packet"); 637 log1("received %s", "a packet");
638 d6_dump_packet(&packet.data); 638 d6_dump_packet(&packet.data);
639 639
640 bytes -= sizeof(packet.ip6) + sizeof(packet.udp); 640 bytes -= sizeof(packet.ip6) + sizeof(packet.udp);
@@ -722,10 +722,10 @@ static int d6_raw_socket(int ifindex)
722 }; 722 };
723#endif 723#endif
724 724
725 log1("Opening raw socket on ifindex %d", ifindex); //log2? 725 log1("opening raw socket on ifindex %d", ifindex); //log2?
726 726
727 fd = xsocket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6)); 727 fd = xsocket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6));
728 log1("Got raw socket fd %d", fd); //log2? 728 log1("got raw socket fd %d", fd); //log2?
729 729
730 sock.sll_family = AF_PACKET; 730 sock.sll_family = AF_PACKET;
731 sock.sll_protocol = htons(ETH_P_IPV6); 731 sock.sll_protocol = htons(ETH_P_IPV6);
@@ -738,18 +738,18 @@ static int d6_raw_socket(int ifindex)
738 /* Ignoring error (kernel may lack support for this) */ 738 /* Ignoring error (kernel may lack support for this) */
739 if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter_prog, 739 if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter_prog,
740 sizeof(filter_prog)) >= 0) 740 sizeof(filter_prog)) >= 0)
741 log1("Attached filter to raw socket fd %d", fd); // log? 741 log1("attached filter to raw socket fd %d", fd); // log?
742 } 742 }
743#endif 743#endif
744 744
745 log1("Created raw socket"); 745 log1("created raw socket");
746 746
747 return fd; 747 return fd;
748} 748}
749 749
750static void change_listen_mode(int new_mode) 750static void change_listen_mode(int new_mode)
751{ 751{
752 log1("Entering listen mode: %s", 752 log1("entering listen mode: %s",
753 new_mode != LISTEN_NONE 753 new_mode != LISTEN_NONE
754 ? (new_mode == LISTEN_KERNEL ? "kernel" : "raw") 754 ? (new_mode == LISTEN_KERNEL ? "kernel" : "raw")
755 : "none" 755 : "none"
@@ -770,7 +770,7 @@ static void change_listen_mode(int new_mode)
770/* Called only on SIGUSR1 */ 770/* Called only on SIGUSR1 */
771static void perform_renew(void) 771static void perform_renew(void)
772{ 772{
773 bb_info_msg("Performing a DHCP renew"); 773 bb_error_msg("performing DHCP renew");
774 switch (state) { 774 switch (state) {
775 case BOUND: 775 case BOUND:
776 change_listen_mode(LISTEN_KERNEL); 776 change_listen_mode(LISTEN_KERNEL);
@@ -794,11 +794,11 @@ static void perform_d6_release(struct in6_addr *server_ipv6, struct in6_addr *ou
794{ 794{
795 /* send release packet */ 795 /* send release packet */
796 if (state == BOUND || state == RENEWING || state == REBINDING) { 796 if (state == BOUND || state == RENEWING || state == REBINDING) {
797 bb_info_msg("Unicasting a release"); 797 bb_error_msg("unicasting a release");
798 send_d6_release(server_ipv6, our_cur_ipv6); /* unicast */ 798 send_d6_release(server_ipv6, our_cur_ipv6); /* unicast */
799 d6_run_script(NULL, "deconfig"); 799 d6_run_script(NULL, "deconfig");
800 } 800 }
801 bb_info_msg("Entering released state"); 801 bb_error_msg("entering released state");
802 802
803 change_listen_mode(LISTEN_NONE); 803 change_listen_mode(LISTEN_NONE);
804 state = RELEASED; 804 state = RELEASED;
@@ -1034,7 +1034,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1034 /* Create pidfile */ 1034 /* Create pidfile */
1035 write_pidfile(client_config.pidfile); 1035 write_pidfile(client_config.pidfile);
1036 /* Goes to stdout (unless NOMMU) and possibly syslog */ 1036 /* Goes to stdout (unless NOMMU) and possibly syslog */
1037 bb_info_msg("%s (v"BB_VER") started", applet_name); 1037 bb_error_msg("started, v"BB_VER);
1038 /* Set up the signal pipe */ 1038 /* Set up the signal pipe */
1039 udhcp_sp_setup(); 1039 udhcp_sp_setup();
1040 /* We want random_xid to be random... */ 1040 /* We want random_xid to be random... */
@@ -1074,7 +1074,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1074 retval = 0; 1074 retval = 0;
1075 /* If we already timed out, fall through with retval = 0, else... */ 1075 /* If we already timed out, fall through with retval = 0, else... */
1076 if ((int)tv.tv_sec > 0) { 1076 if ((int)tv.tv_sec > 0) {
1077 log1("Waiting on select %u seconds", (int)tv.tv_sec); 1077 log1("waiting on select %u seconds", (int)tv.tv_sec);
1078 timestamp_before_wait = (unsigned)monotonic_sec(); 1078 timestamp_before_wait = (unsigned)monotonic_sec();
1079 retval = select(max_fd + 1, &rfds, NULL, NULL, &tv); 1079 retval = select(max_fd + 1, &rfds, NULL, NULL, &tv);
1080 if (retval < 0) { 1080 if (retval < 0) {
@@ -1124,14 +1124,14 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1124 d6_run_script(NULL, "leasefail"); 1124 d6_run_script(NULL, "leasefail");
1125#if BB_MMU /* -b is not supported on NOMMU */ 1125#if BB_MMU /* -b is not supported on NOMMU */
1126 if (opt & OPT_b) { /* background if no lease */ 1126 if (opt & OPT_b) { /* background if no lease */
1127 bb_info_msg("No lease, forking to background"); 1127 bb_error_msg("no lease, forking to background");
1128 client_background(); 1128 client_background();
1129 /* do not background again! */ 1129 /* do not background again! */
1130 opt = ((opt & ~OPT_b) | OPT_f); 1130 opt = ((opt & ~OPT_b) | OPT_f);
1131 } else 1131 } else
1132#endif 1132#endif
1133 if (opt & OPT_n) { /* abort if no lease */ 1133 if (opt & OPT_n) { /* abort if no lease */
1134 bb_info_msg("No lease, failing"); 1134 bb_error_msg("no lease, failing");
1135 retval = 1; 1135 retval = 1;
1136 goto ret; 1136 goto ret;
1137 } 1137 }
@@ -1159,7 +1159,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1159 state = RENEWING; 1159 state = RENEWING;
1160 client_config.first_secs = 0; /* make secs field count from 0 */ 1160 client_config.first_secs = 0; /* make secs field count from 0 */
1161 change_listen_mode(LISTEN_KERNEL); 1161 change_listen_mode(LISTEN_KERNEL);
1162 log1("Entering renew state"); 1162 log1("entering renew state");
1163 /* fall right through */ 1163 /* fall right through */
1164 case RENEW_REQUESTED: /* manual (SIGUSR1) renew */ 1164 case RENEW_REQUESTED: /* manual (SIGUSR1) renew */
1165 case_RENEW_REQUESTED: 1165 case_RENEW_REQUESTED:
@@ -1179,7 +1179,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1179 continue; 1179 continue;
1180 } 1180 }
1181 /* Timed out, enter rebinding state */ 1181 /* Timed out, enter rebinding state */
1182 log1("Entering rebinding state"); 1182 log1("entering rebinding state");
1183 state = REBINDING; 1183 state = REBINDING;
1184 /* fall right through */ 1184 /* fall right through */
1185 case REBINDING: 1185 case REBINDING:
@@ -1194,7 +1194,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1194 continue; 1194 continue;
1195 } 1195 }
1196 /* Timed out, enter init state */ 1196 /* Timed out, enter init state */
1197 bb_info_msg("Lease lost, entering init state"); 1197 bb_error_msg("lease lost, entering init state");
1198 d6_run_script(NULL, "deconfig"); 1198 d6_run_script(NULL, "deconfig");
1199 state = INIT_SELECTING; 1199 state = INIT_SELECTING;
1200 client_config.first_secs = 0; /* make secs field count from 0 */ 1200 client_config.first_secs = 0; /* make secs field count from 0 */
@@ -1242,7 +1242,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1242 timeout = INT_MAX; 1242 timeout = INT_MAX;
1243 continue; 1243 continue;
1244 case SIGTERM: 1244 case SIGTERM:
1245 bb_info_msg("Received SIGTERM"); 1245 bb_error_msg("received %s", "SIGTERM");
1246 goto ret0; 1246 goto ret0;
1247 } 1247 }
1248 1248
@@ -1260,7 +1260,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1260 len = d6_recv_raw_packet(&srv6_buf, &packet, sockfd); 1260 len = d6_recv_raw_packet(&srv6_buf, &packet, sockfd);
1261 if (len == -1) { 1261 if (len == -1) {
1262 /* Error is severe, reopen socket */ 1262 /* Error is severe, reopen socket */
1263 bb_info_msg("Read error: %s, reopening socket", strerror(errno)); 1263 bb_error_msg("read error: %s, reopening socket", strerror(errno));
1264 sleep(discover_timeout); /* 3 seconds by default */ 1264 sleep(discover_timeout); /* 3 seconds by default */
1265 change_listen_mode(listen_mode); /* just close and reopen */ 1265 change_listen_mode(listen_mode); /* just close and reopen */
1266 } 1266 }
@@ -1298,7 +1298,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1298 option = d6_find_option(packet.d6_options, packet_end, D6_OPT_STATUS_CODE); 1298 option = d6_find_option(packet.d6_options, packet_end, D6_OPT_STATUS_CODE);
1299 if (option && option->data[4] != 0) { 1299 if (option && option->data[4] != 0) {
1300 /* return to init state */ 1300 /* return to init state */
1301 bb_info_msg("Received DHCP NAK (%u)", option->data[4]); 1301 bb_error_msg("received DHCP NAK (%u)", option->data[4]);
1302 d6_run_script(&packet, "nak"); 1302 d6_run_script(&packet, "nak");
1303 if (state != REQUESTING) 1303 if (state != REQUESTING)
1304 d6_run_script(NULL, "deconfig"); 1304 d6_run_script(NULL, "deconfig");
@@ -1453,7 +1453,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1453 lease_seconds = 0x0fffffff; 1453 lease_seconds = 0x0fffffff;
1454 /* enter bound state */ 1454 /* enter bound state */
1455 timeout = lease_seconds / 2; 1455 timeout = lease_seconds / 2;
1456 bb_info_msg("Lease obtained, lease time %u", 1456 bb_error_msg("lease obtained, lease time %u",
1457 /*inet_ntoa(temp_addr),*/ (unsigned)lease_seconds); 1457 /*inet_ntoa(temp_addr),*/ (unsigned)lease_seconds);
1458 d6_run_script(&packet, state == REQUESTING ? "bound" : "renew"); 1458 d6_run_script(&packet, state == REQUESTING ? "bound" : "renew");
1459 1459
diff --git a/networking/udhcp/d6_packet.c b/networking/udhcp/d6_packet.c
index 79b2946ef..e166f520d 100644
--- a/networking/udhcp/d6_packet.c
+++ b/networking/udhcp/d6_packet.c
@@ -17,12 +17,12 @@ void FAST_FUNC d6_dump_packet(struct d6_packet *packet)
17 if (dhcp_verbose < 2) 17 if (dhcp_verbose < 2)
18 return; 18 return;
19 19
20 bb_info_msg( 20 bb_error_msg(
21 " xid %x" 21 "xid %x"
22 , packet->d6_xid32 22 , packet->d6_xid32
23 ); 23 );
24 //*bin2hex(buf, (void *) packet->chaddr, sizeof(packet->chaddr)) = '\0'; 24 //*bin2hex(buf, (void *) packet->chaddr, sizeof(packet->chaddr)) = '\0';
25 //bb_info_msg(" chaddr %s", buf); 25 //bb_error_msg(" chaddr %s", buf);
26} 26}
27#endif 27#endif
28 28
@@ -35,15 +35,15 @@ int FAST_FUNC d6_recv_kernel_packet(struct in6_addr *peer_ipv6
35 memset(packet, 0, sizeof(*packet)); 35 memset(packet, 0, sizeof(*packet));
36 bytes = safe_read(fd, packet, sizeof(*packet)); 36 bytes = safe_read(fd, packet, sizeof(*packet));
37 if (bytes < 0) { 37 if (bytes < 0) {
38 log1("Packet read error, ignoring"); 38 log1("packet read error, ignoring");
39 return bytes; /* returns -1 */ 39 return bytes; /* returns -1 */
40 } 40 }
41 41
42 if (bytes < offsetof(struct d6_packet, d6_options)) { 42 if (bytes < offsetof(struct d6_packet, d6_options)) {
43 bb_info_msg("Packet with bad magic, ignoring"); 43 bb_error_msg("packet with bad magic, ignoring");
44 return -2; 44 return -2;
45 } 45 }
46 log1("Received a packet"); 46 log1("received %s", "a packet");
47 d6_dump_packet(packet); 47 d6_dump_packet(packet);
48 48
49 return bytes; 49 return bytes;
diff --git a/networking/udhcp/d6_socket.c b/networking/udhcp/d6_socket.c
index 56f69f6a1..910f296a3 100644
--- a/networking/udhcp/d6_socket.c
+++ b/networking/udhcp/d6_socket.c
@@ -13,7 +13,7 @@ int FAST_FUNC d6_listen_socket(int port, const char *inf)
13 int fd; 13 int fd;
14 struct sockaddr_in6 addr; 14 struct sockaddr_in6 addr;
15 15
16 log1("Opening listen socket on *:%d %s", port, inf); 16 log1("opening listen socket on *:%d %s", port, inf);
17 fd = xsocket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); 17 fd = xsocket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
18 18
19 setsockopt_reuseaddr(fd); 19 setsockopt_reuseaddr(fd);
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index 48097bc24..660b943ce 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -113,7 +113,7 @@ static const uint8_t len_of_option_as_string[] = {
113 [OPTION_IP ] = sizeof("255.255.255.255 "), 113 [OPTION_IP ] = sizeof("255.255.255.255 "),
114 [OPTION_IP_PAIR ] = sizeof("255.255.255.255 ") * 2, 114 [OPTION_IP_PAIR ] = sizeof("255.255.255.255 ") * 2,
115 [OPTION_STATIC_ROUTES ] = sizeof("255.255.255.255/32 255.255.255.255 "), 115 [OPTION_STATIC_ROUTES ] = sizeof("255.255.255.255/32 255.255.255.255 "),
116 [OPTION_6RD ] = sizeof("32 128 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 255.255.255.255 "), 116 [OPTION_6RD ] = sizeof("132 128 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 255.255.255.255 "),
117 [OPTION_STRING ] = 1, 117 [OPTION_STRING ] = 1,
118 [OPTION_STRING_HOST ] = 1, 118 [OPTION_STRING_HOST ] = 1,
119#if ENABLE_FEATURE_UDHCP_RFC3397 119#if ENABLE_FEATURE_UDHCP_RFC3397
@@ -222,7 +222,7 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_
222 type = optflag->flags & OPTION_TYPE_MASK; 222 type = optflag->flags & OPTION_TYPE_MASK;
223 optlen = dhcp_option_lengths[type]; 223 optlen = dhcp_option_lengths[type];
224 upper_length = len_of_option_as_string[type] 224 upper_length = len_of_option_as_string[type]
225 * ((unsigned)(len + optlen - 1) / (unsigned)optlen); 225 * ((unsigned)(len + optlen) / (unsigned)optlen);
226 226
227 dest = ret = xmalloc(upper_length + strlen(opt_name) + 2); 227 dest = ret = xmalloc(upper_length + strlen(opt_name) + 2);
228 dest += sprintf(ret, "%s=", opt_name); 228 dest += sprintf(ret, "%s=", opt_name);
@@ -561,7 +561,7 @@ static void udhcp_run_script(struct dhcp_packet *packet, const char *name)
561 envp = fill_envp(packet); 561 envp = fill_envp(packet);
562 562
563 /* call script */ 563 /* call script */
564 log1("Executing %s %s", client_config.script, name); 564 log1("executing %s %s", client_config.script, name);
565 argv[0] = (char*) client_config.script; 565 argv[0] = (char*) client_config.script;
566 argv[1] = (char*) name; 566 argv[1] = (char*) name;
567 argv[2] = NULL; 567 argv[2] = NULL;
@@ -675,10 +675,10 @@ static void add_client_options(struct dhcp_packet *packet)
675 * client reverts to using the IP broadcast address. 675 * client reverts to using the IP broadcast address.
676 */ 676 */
677 677
678static int raw_bcast_from_client_config_ifindex(struct dhcp_packet *packet) 678static int raw_bcast_from_client_config_ifindex(struct dhcp_packet *packet, uint32_t src_nip)
679{ 679{
680 return udhcp_send_raw_packet(packet, 680 return udhcp_send_raw_packet(packet,
681 /*src*/ INADDR_ANY, CLIENT_PORT, 681 /*src*/ src_nip, CLIENT_PORT,
682 /*dst*/ INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR, 682 /*dst*/ INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR,
683 client_config.ifindex); 683 client_config.ifindex);
684} 684}
@@ -689,7 +689,7 @@ static int bcast_or_ucast(struct dhcp_packet *packet, uint32_t ciaddr, uint32_t
689 return udhcp_send_kernel_packet(packet, 689 return udhcp_send_kernel_packet(packet,
690 ciaddr, CLIENT_PORT, 690 ciaddr, CLIENT_PORT,
691 server, SERVER_PORT); 691 server, SERVER_PORT);
692 return raw_bcast_from_client_config_ifindex(packet); 692 return raw_bcast_from_client_config_ifindex(packet, ciaddr);
693} 693}
694 694
695/* Broadcast a DHCP discover packet to the network, with an optionally requested IP */ 695/* Broadcast a DHCP discover packet to the network, with an optionally requested IP */
@@ -714,8 +714,8 @@ static NOINLINE int send_discover(uint32_t xid, uint32_t requested)
714 */ 714 */
715 add_client_options(&packet); 715 add_client_options(&packet);
716 716
717 bb_info_msg("Sending discover..."); 717 bb_error_msg("sending %s", "discover");
718 return raw_bcast_from_client_config_ifindex(&packet); 718 return raw_bcast_from_client_config_ifindex(&packet, INADDR_ANY);
719} 719}
720 720
721/* Broadcast a DHCP request message */ 721/* Broadcast a DHCP request message */
@@ -758,8 +758,8 @@ static NOINLINE int send_select(uint32_t xid, uint32_t server, uint32_t requeste
758 add_client_options(&packet); 758 add_client_options(&packet);
759 759
760 addr.s_addr = requested; 760 addr.s_addr = requested;
761 bb_info_msg("Sending select for %s...", inet_ntoa(addr)); 761 bb_error_msg("sending select for %s", inet_ntoa(addr));
762 return raw_bcast_from_client_config_ifindex(&packet); 762 return raw_bcast_from_client_config_ifindex(&packet, INADDR_ANY);
763} 763}
764 764
765/* Unicast or broadcast a DHCP renew message */ 765/* Unicast or broadcast a DHCP renew message */
@@ -797,7 +797,7 @@ static NOINLINE int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr)
797 */ 797 */
798 add_client_options(&packet); 798 add_client_options(&packet);
799 799
800 bb_info_msg("Sending renew..."); 800 bb_error_msg("sending %s", "renew");
801 return bcast_or_ucast(&packet, ciaddr, server); 801 return bcast_or_ucast(&packet, ciaddr, server);
802} 802}
803 803
@@ -826,8 +826,8 @@ static NOINLINE int send_decline(/*uint32_t xid,*/ uint32_t server, uint32_t req
826 826
827 udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); 827 udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server);
828 828
829 bb_info_msg("Sending decline..."); 829 bb_error_msg("sending %s", "decline");
830 return raw_bcast_from_client_config_ifindex(&packet); 830 return raw_bcast_from_client_config_ifindex(&packet, INADDR_ANY);
831} 831}
832#endif 832#endif
833 833
@@ -846,7 +846,7 @@ static int send_release(uint32_t server, uint32_t ciaddr)
846 846
847 udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); 847 udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server);
848 848
849 bb_info_msg("Sending release..."); 849 bb_error_msg("sending %s", "release");
850 /* Note: normally we unicast here since "server" is not zero. 850 /* Note: normally we unicast here since "server" is not zero.
851 * However, there _are_ people who run "address-less" DHCP servers, 851 * However, there _are_ people who run "address-less" DHCP servers,
852 * and reportedly ISC dhcp client and Windows allow that. 852 * and reportedly ISC dhcp client and Windows allow that.
@@ -881,7 +881,7 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd)
881 if (bytes < 0) { 881 if (bytes < 0) {
882 if (errno == EINTR) 882 if (errno == EINTR)
883 continue; 883 continue;
884 log1("Packet read error, ignoring"); 884 log1("packet read error, ignoring");
885 /* NB: possible down interface, etc. Caller should pause. */ 885 /* NB: possible down interface, etc. Caller should pause. */
886 return bytes; /* returns -1 */ 886 return bytes; /* returns -1 */
887 } 887 }
@@ -889,13 +889,13 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd)
889 } 889 }
890 890
891 if (bytes < (int) (sizeof(packet.ip) + sizeof(packet.udp))) { 891 if (bytes < (int) (sizeof(packet.ip) + sizeof(packet.udp))) {
892 log1("Packet is too short, ignoring"); 892 log1("packet is too short, ignoring");
893 return -2; 893 return -2;
894 } 894 }
895 895
896 if (bytes < ntohs(packet.ip.tot_len)) { 896 if (bytes < ntohs(packet.ip.tot_len)) {
897 /* packet is bigger than sizeof(packet), we did partial read */ 897 /* packet is bigger than sizeof(packet), we did partial read */
898 log1("Oversized packet, ignoring"); 898 log1("oversized packet, ignoring");
899 return -2; 899 return -2;
900 } 900 }
901 901
@@ -910,7 +910,7 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd)
910 /* || bytes > (int) sizeof(packet) - can't happen */ 910 /* || bytes > (int) sizeof(packet) - can't happen */
911 || ntohs(packet.udp.len) != (uint16_t)(bytes - sizeof(packet.ip)) 911 || ntohs(packet.udp.len) != (uint16_t)(bytes - sizeof(packet.ip))
912 ) { 912 ) {
913 log1("Unrelated/bogus packet, ignoring"); 913 log1("unrelated/bogus packet, ignoring");
914 return -2; 914 return -2;
915 } 915 }
916 916
@@ -918,7 +918,7 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd)
918 check = packet.ip.check; 918 check = packet.ip.check;
919 packet.ip.check = 0; 919 packet.ip.check = 0;
920 if (check != inet_cksum((uint16_t *)&packet.ip, sizeof(packet.ip))) { 920 if (check != inet_cksum((uint16_t *)&packet.ip, sizeof(packet.ip))) {
921 log1("Bad IP header checksum, ignoring"); 921 log1("bad IP header checksum, ignoring");
922 return -2; 922 return -2;
923 } 923 }
924 924
@@ -943,17 +943,17 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd)
943 check = packet.udp.check; 943 check = packet.udp.check;
944 packet.udp.check = 0; 944 packet.udp.check = 0;
945 if (check && check != inet_cksum((uint16_t *)&packet, bytes)) { 945 if (check && check != inet_cksum((uint16_t *)&packet, bytes)) {
946 log1("Packet with bad UDP checksum received, ignoring"); 946 log1("packet with bad UDP checksum received, ignoring");
947 return -2; 947 return -2;
948 } 948 }
949 skip_udp_sum_check: 949 skip_udp_sum_check:
950 950
951 if (packet.data.cookie != htonl(DHCP_MAGIC)) { 951 if (packet.data.cookie != htonl(DHCP_MAGIC)) {
952 bb_info_msg("Packet with bad magic, ignoring"); 952 bb_error_msg("packet with bad magic, ignoring");
953 return -2; 953 return -2;
954 } 954 }
955 955
956 log1("Received a packet"); 956 log1("received %s", "a packet");
957 udhcp_dump_packet(&packet.data); 957 udhcp_dump_packet(&packet.data);
958 958
959 bytes -= sizeof(packet.ip) + sizeof(packet.udp); 959 bytes -= sizeof(packet.ip) + sizeof(packet.udp);
@@ -992,14 +992,14 @@ static int udhcp_raw_socket(int ifindex)
992 int fd; 992 int fd;
993 struct sockaddr_ll sock; 993 struct sockaddr_ll sock;
994 994
995 log1("Opening raw socket on ifindex %d", ifindex); //log2? 995 log1("opening raw socket on ifindex %d", ifindex); //log2?
996 996
997 fd = xsocket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP)); 997 fd = xsocket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
998 /* ^^^^^ 998 /* ^^^^^
999 * SOCK_DGRAM: remove link-layer headers on input (SOCK_RAW keeps them) 999 * SOCK_DGRAM: remove link-layer headers on input (SOCK_RAW keeps them)
1000 * ETH_P_IP: want to receive only packets with IPv4 eth type 1000 * ETH_P_IP: want to receive only packets with IPv4 eth type
1001 */ 1001 */
1002 log1("Got raw socket fd"); //log2? 1002 log1("got raw socket fd"); //log2?
1003 1003
1004 sock.sll_family = AF_PACKET; 1004 sock.sll_family = AF_PACKET;
1005 sock.sll_protocol = htons(ETH_P_IP); 1005 sock.sll_protocol = htons(ETH_P_IP);
@@ -1055,23 +1055,23 @@ static int udhcp_raw_socket(int ifindex)
1055 /* Ignoring error (kernel may lack support for this) */ 1055 /* Ignoring error (kernel may lack support for this) */
1056 if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter_prog, 1056 if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter_prog,
1057 sizeof(filter_prog)) >= 0) 1057 sizeof(filter_prog)) >= 0)
1058 log1("Attached filter to raw socket fd"); // log? 1058 log1("attached filter to raw socket fd"); // log?
1059 } 1059 }
1060#endif 1060#endif
1061 1061
1062 if (setsockopt_1(fd, SOL_PACKET, PACKET_AUXDATA) != 0) { 1062 if (setsockopt_1(fd, SOL_PACKET, PACKET_AUXDATA) != 0) {
1063 if (errno != ENOPROTOOPT) 1063 if (errno != ENOPROTOOPT)
1064 log1("Can't set PACKET_AUXDATA on raw socket"); 1064 log1("can't set PACKET_AUXDATA on raw socket");
1065 } 1065 }
1066 1066
1067 log1("Created raw socket"); 1067 log1("created raw socket");
1068 1068
1069 return fd; 1069 return fd;
1070} 1070}
1071 1071
1072static void change_listen_mode(int new_mode) 1072static void change_listen_mode(int new_mode)
1073{ 1073{
1074 log1("Entering listen mode: %s", 1074 log1("entering listen mode: %s",
1075 new_mode != LISTEN_NONE 1075 new_mode != LISTEN_NONE
1076 ? (new_mode == LISTEN_KERNEL ? "kernel" : "raw") 1076 ? (new_mode == LISTEN_KERNEL ? "kernel" : "raw")
1077 : "none" 1077 : "none"
@@ -1092,7 +1092,7 @@ static void change_listen_mode(int new_mode)
1092/* Called only on SIGUSR1 */ 1092/* Called only on SIGUSR1 */
1093static void perform_renew(void) 1093static void perform_renew(void)
1094{ 1094{
1095 bb_info_msg("Performing a DHCP renew"); 1095 bb_error_msg("performing DHCP renew");
1096 switch (state) { 1096 switch (state) {
1097 case BOUND: 1097 case BOUND:
1098 change_listen_mode(LISTEN_KERNEL); 1098 change_listen_mode(LISTEN_KERNEL);
@@ -1122,12 +1122,12 @@ static void perform_release(uint32_t server_addr, uint32_t requested_ip)
1122 temp_addr.s_addr = server_addr; 1122 temp_addr.s_addr = server_addr;
1123 strcpy(buffer, inet_ntoa(temp_addr)); 1123 strcpy(buffer, inet_ntoa(temp_addr));
1124 temp_addr.s_addr = requested_ip; 1124 temp_addr.s_addr = requested_ip;
1125 bb_info_msg("Unicasting a release of %s to %s", 1125 bb_error_msg("unicasting a release of %s to %s",
1126 inet_ntoa(temp_addr), buffer); 1126 inet_ntoa(temp_addr), buffer);
1127 send_release(server_addr, requested_ip); /* unicast */ 1127 send_release(server_addr, requested_ip); /* unicast */
1128 udhcp_run_script(NULL, "deconfig"); 1128 udhcp_run_script(NULL, "deconfig");
1129 } 1129 }
1130 bb_info_msg("Entering released state"); 1130 bb_error_msg("entering released state");
1131 1131
1132 change_listen_mode(LISTEN_NONE); 1132 change_listen_mode(LISTEN_NONE);
1133 state = RELEASED; 1133 state = RELEASED;
@@ -1395,7 +1395,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1395 /* Create pidfile */ 1395 /* Create pidfile */
1396 write_pidfile(client_config.pidfile); 1396 write_pidfile(client_config.pidfile);
1397 /* Goes to stdout (unless NOMMU) and possibly syslog */ 1397 /* Goes to stdout (unless NOMMU) and possibly syslog */
1398 bb_info_msg("%s (v"BB_VER") started", applet_name); 1398 bb_error_msg("started, v"BB_VER);
1399 /* Set up the signal pipe */ 1399 /* Set up the signal pipe */
1400 udhcp_sp_setup(); 1400 udhcp_sp_setup();
1401 /* We want random_xid to be random... */ 1401 /* We want random_xid to be random... */
@@ -1434,7 +1434,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1434 retval = 0; 1434 retval = 0;
1435 /* If we already timed out, fall through with retval = 0, else... */ 1435 /* If we already timed out, fall through with retval = 0, else... */
1436 if ((int)tv.tv_sec > 0) { 1436 if ((int)tv.tv_sec > 0) {
1437 log1("Waiting on select %u seconds", (int)tv.tv_sec); 1437 log1("waiting on select %u seconds", (int)tv.tv_sec);
1438 timestamp_before_wait = (unsigned)monotonic_sec(); 1438 timestamp_before_wait = (unsigned)monotonic_sec();
1439 retval = select(max_fd + 1, &rfds, NULL, NULL, &tv); 1439 retval = select(max_fd + 1, &rfds, NULL, NULL, &tv);
1440 if (retval < 0) { 1440 if (retval < 0) {
@@ -1485,14 +1485,14 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1485 udhcp_run_script(NULL, "leasefail"); 1485 udhcp_run_script(NULL, "leasefail");
1486#if BB_MMU /* -b is not supported on NOMMU */ 1486#if BB_MMU /* -b is not supported on NOMMU */
1487 if (opt & OPT_b) { /* background if no lease */ 1487 if (opt & OPT_b) { /* background if no lease */
1488 bb_info_msg("No lease, forking to background"); 1488 bb_error_msg("no lease, forking to background");
1489 client_background(); 1489 client_background();
1490 /* do not background again! */ 1490 /* do not background again! */
1491 opt = ((opt & ~OPT_b) | OPT_f); 1491 opt = ((opt & ~OPT_b) | OPT_f);
1492 } else 1492 } else
1493#endif 1493#endif
1494 if (opt & OPT_n) { /* abort if no lease */ 1494 if (opt & OPT_n) { /* abort if no lease */
1495 bb_info_msg("No lease, failing"); 1495 bb_error_msg("no lease, failing");
1496 retval = 1; 1496 retval = 1;
1497 goto ret; 1497 goto ret;
1498 } 1498 }
@@ -1501,7 +1501,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1501 packet_num = 0; 1501 packet_num = 0;
1502 continue; 1502 continue;
1503 case REQUESTING: 1503 case REQUESTING:
1504 if (!discover_retries || packet_num < discover_retries) { 1504 if (packet_num < 3) {
1505 /* send broadcast select packet */ 1505 /* send broadcast select packet */
1506 send_select(xid, server_addr, requested_ip); 1506 send_select(xid, server_addr, requested_ip);
1507 timeout = discover_timeout; 1507 timeout = discover_timeout;
@@ -1520,7 +1520,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1520 state = RENEWING; 1520 state = RENEWING;
1521 client_config.first_secs = 0; /* make secs field count from 0 */ 1521 client_config.first_secs = 0; /* make secs field count from 0 */
1522 change_listen_mode(LISTEN_KERNEL); 1522 change_listen_mode(LISTEN_KERNEL);
1523 log1("Entering renew state"); 1523 log1("entering renew state");
1524 /* fall right through */ 1524 /* fall right through */
1525 case RENEW_REQUESTED: /* manual (SIGUSR1) renew */ 1525 case RENEW_REQUESTED: /* manual (SIGUSR1) renew */
1526 case_RENEW_REQUESTED: 1526 case_RENEW_REQUESTED:
@@ -1540,7 +1540,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1540 continue; 1540 continue;
1541 } 1541 }
1542 /* Timed out, enter rebinding state */ 1542 /* Timed out, enter rebinding state */
1543 log1("Entering rebinding state"); 1543 log1("entering rebinding state");
1544 state = REBINDING; 1544 state = REBINDING;
1545 /* fall right through */ 1545 /* fall right through */
1546 case REBINDING: 1546 case REBINDING:
@@ -1555,7 +1555,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1555 continue; 1555 continue;
1556 } 1556 }
1557 /* Timed out, enter init state */ 1557 /* Timed out, enter init state */
1558 bb_info_msg("Lease lost, entering init state"); 1558 bb_error_msg("lease lost, entering init state");
1559 udhcp_run_script(NULL, "deconfig"); 1559 udhcp_run_script(NULL, "deconfig");
1560 state = INIT_SELECTING; 1560 state = INIT_SELECTING;
1561 client_config.first_secs = 0; /* make secs field count from 0 */ 1561 client_config.first_secs = 0; /* make secs field count from 0 */
@@ -1603,7 +1603,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1603 timeout = INT_MAX; 1603 timeout = INT_MAX;
1604 continue; 1604 continue;
1605 case SIGTERM: 1605 case SIGTERM:
1606 bb_info_msg("Received SIGTERM"); 1606 bb_error_msg("received %s", "SIGTERM");
1607 goto ret0; 1607 goto ret0;
1608 } 1608 }
1609 1609
@@ -1621,7 +1621,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1621 len = udhcp_recv_raw_packet(&packet, sockfd); 1621 len = udhcp_recv_raw_packet(&packet, sockfd);
1622 if (len == -1) { 1622 if (len == -1) {
1623 /* Error is severe, reopen socket */ 1623 /* Error is severe, reopen socket */
1624 bb_info_msg("Read error: %s, reopening socket", strerror(errno)); 1624 bb_error_msg("read error: %s, reopening socket", strerror(errno));
1625 sleep(discover_timeout); /* 3 seconds by default */ 1625 sleep(discover_timeout); /* 3 seconds by default */
1626 change_listen_mode(listen_mode); /* just close and reopen */ 1626 change_listen_mode(listen_mode); /* just close and reopen */
1627 } 1627 }
@@ -1744,7 +1744,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1744 client_config.interface, 1744 client_config.interface,
1745 arpping_ms) 1745 arpping_ms)
1746 ) { 1746 ) {
1747 bb_info_msg("Offered address is in use " 1747 bb_error_msg("offered address is in use "
1748 "(got ARP reply), declining"); 1748 "(got ARP reply), declining");
1749 send_decline(/*xid,*/ server_addr, packet.yiaddr); 1749 send_decline(/*xid,*/ server_addr, packet.yiaddr);
1750 1750
@@ -1763,7 +1763,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1763#endif 1763#endif
1764 /* enter bound state */ 1764 /* enter bound state */
1765 temp_addr.s_addr = packet.yiaddr; 1765 temp_addr.s_addr = packet.yiaddr;
1766 bb_info_msg("Lease of %s obtained, lease time %u", 1766 bb_error_msg("lease of %s obtained, lease time %u",
1767 inet_ntoa(temp_addr), (unsigned)lease_seconds); 1767 inet_ntoa(temp_addr), (unsigned)lease_seconds);
1768 requested_ip = packet.yiaddr; 1768 requested_ip = packet.yiaddr;
1769 1769
@@ -1817,7 +1817,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1817 goto non_matching_svid; 1817 goto non_matching_svid;
1818 } 1818 }
1819 /* return to init state */ 1819 /* return to init state */
1820 bb_info_msg("Received DHCP NAK"); 1820 bb_error_msg("received %s", "DHCP NAK");
1821 udhcp_run_script(&packet, "nak"); 1821 udhcp_run_script(&packet, "nak");
1822 if (state != REQUESTING) 1822 if (state != REQUESTING)
1823 udhcp_run_script(NULL, "deconfig"); 1823 udhcp_run_script(NULL, "deconfig");
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c
index 2de074f9b..2671ea3e2 100644
--- a/networking/udhcp/dhcpd.c
+++ b/networking/udhcp/dhcpd.c
@@ -61,11 +61,11 @@ static void send_packet_to_client(struct dhcp_packet *dhcp_pkt, int force_broadc
61 || (dhcp_pkt->flags & htons(BROADCAST_FLAG)) 61 || (dhcp_pkt->flags & htons(BROADCAST_FLAG))
62 || dhcp_pkt->ciaddr == 0 62 || dhcp_pkt->ciaddr == 0
63 ) { 63 ) {
64 log1("Broadcasting packet to client"); 64 log1("broadcasting packet to client");
65 ciaddr = INADDR_BROADCAST; 65 ciaddr = INADDR_BROADCAST;
66 chaddr = MAC_BCAST_ADDR; 66 chaddr = MAC_BCAST_ADDR;
67 } else { 67 } else {
68 log1("Unicasting packet to client ciaddr"); 68 log1("unicasting packet to client ciaddr");
69 ciaddr = dhcp_pkt->ciaddr; 69 ciaddr = dhcp_pkt->ciaddr;
70 chaddr = dhcp_pkt->chaddr; 70 chaddr = dhcp_pkt->chaddr;
71 } 71 }
@@ -79,7 +79,7 @@ static void send_packet_to_client(struct dhcp_packet *dhcp_pkt, int force_broadc
79/* Send a packet to gateway_nip using the kernel ip stack */ 79/* Send a packet to gateway_nip using the kernel ip stack */
80static void send_packet_to_relay(struct dhcp_packet *dhcp_pkt) 80static void send_packet_to_relay(struct dhcp_packet *dhcp_pkt)
81{ 81{
82 log1("Forwarding packet to relay"); 82 log1("forwarding packet to relay");
83 83
84 udhcp_send_kernel_packet(dhcp_pkt, 84 udhcp_send_kernel_packet(dhcp_pkt,
85 server_config.server_nip, SERVER_PORT, 85 server_config.server_nip, SERVER_PORT,
@@ -214,7 +214,7 @@ static NOINLINE void send_offer(struct dhcp_packet *oldpacket,
214 add_server_options(&packet); 214 add_server_options(&packet);
215 215
216 addr.s_addr = packet.yiaddr; 216 addr.s_addr = packet.yiaddr;
217 bb_info_msg("Sending OFFER of %s", inet_ntoa(addr)); 217 bb_error_msg("sending OFFER of %s", inet_ntoa(addr));
218 /* send_packet emits error message itself if it detects failure */ 218 /* send_packet emits error message itself if it detects failure */
219 send_packet(&packet, /*force_bcast:*/ 0); 219 send_packet(&packet, /*force_bcast:*/ 0);
220} 220}
@@ -226,7 +226,7 @@ static NOINLINE void send_NAK(struct dhcp_packet *oldpacket)
226 226
227 init_packet(&packet, oldpacket, DHCPNAK); 227 init_packet(&packet, oldpacket, DHCPNAK);
228 228
229 log1("Sending NAK"); 229 log1("sending %s", "NAK");
230 send_packet(&packet, /*force_bcast:*/ 1); 230 send_packet(&packet, /*force_bcast:*/ 1);
231} 231}
232 232
@@ -247,7 +247,7 @@ static NOINLINE void send_ACK(struct dhcp_packet *oldpacket, uint32_t yiaddr)
247 add_server_options(&packet); 247 add_server_options(&packet);
248 248
249 addr.s_addr = yiaddr; 249 addr.s_addr = yiaddr;
250 bb_info_msg("Sending ACK to %s", inet_ntoa(addr)); 250 bb_error_msg("sending ACK to %s", inet_ntoa(addr));
251 send_packet(&packet, /*force_bcast:*/ 0); 251 send_packet(&packet, /*force_bcast:*/ 0);
252 252
253 p_host_name = (const char*) udhcp_get_option(oldpacket, DHCP_HOST_NAME); 253 p_host_name = (const char*) udhcp_get_option(oldpacket, DHCP_HOST_NAME);
@@ -361,7 +361,7 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv)
361 write_pidfile(server_config.pidfile); 361 write_pidfile(server_config.pidfile);
362 /* if (!..) bb_perror_msg("can't create pidfile %s", pidfile); */ 362 /* if (!..) bb_perror_msg("can't create pidfile %s", pidfile); */
363 363
364 bb_info_msg("%s (v"BB_VER") started", applet_name); 364 bb_error_msg("started, v"BB_VER);
365 365
366 option = udhcp_find_option(server_config.options, DHCP_LEASE_TIME); 366 option = udhcp_find_option(server_config.options, DHCP_LEASE_TIME);
367 server_config.max_lease_sec = DEFAULT_LEASE_TIME; 367 server_config.max_lease_sec = DEFAULT_LEASE_TIME;
@@ -427,18 +427,18 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv)
427 goto continue_with_autotime; 427 goto continue_with_autotime;
428 } 428 }
429 if (retval < 0 && errno != EINTR) { 429 if (retval < 0 && errno != EINTR) {
430 log1("Error on select"); 430 log1("error on select");
431 continue; 431 continue;
432 } 432 }
433 433
434 switch (udhcp_sp_read(&rfds)) { 434 switch (udhcp_sp_read(&rfds)) {
435 case SIGUSR1: 435 case SIGUSR1:
436 bb_info_msg("Received SIGUSR1"); 436 bb_error_msg("received %s", "SIGUSR1");
437 write_leases(); 437 write_leases();
438 /* why not just reset the timeout, eh */ 438 /* why not just reset the timeout, eh */
439 goto continue_with_autotime; 439 goto continue_with_autotime;
440 case SIGTERM: 440 case SIGTERM:
441 bb_info_msg("Received SIGTERM"); 441 bb_error_msg("received %s", "SIGTERM");
442 write_leases(); 442 write_leases();
443 goto ret0; 443 goto ret0;
444 case 0: /* no signal: read a packet */ 444 case 0: /* no signal: read a packet */
@@ -451,7 +451,7 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv)
451 if (bytes < 0) { 451 if (bytes < 0) {
452 /* bytes can also be -2 ("bad packet data") */ 452 /* bytes can also be -2 ("bad packet data") */
453 if (bytes == -1 && errno != EINTR) { 453 if (bytes == -1 && errno != EINTR) {
454 log1("Read error: %s, reopening socket", strerror(errno)); 454 log1("read error: %s, reopening socket", strerror(errno));
455 close(server_socket); 455 close(server_socket);
456 server_socket = -1; 456 server_socket = -1;
457 } 457 }
@@ -486,7 +486,7 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv)
486 /* Look for a static/dynamic lease */ 486 /* Look for a static/dynamic lease */
487 static_lease_nip = get_static_nip_by_mac(server_config.static_leases, &packet.chaddr); 487 static_lease_nip = get_static_nip_by_mac(server_config.static_leases, &packet.chaddr);
488 if (static_lease_nip) { 488 if (static_lease_nip) {
489 bb_info_msg("Found static lease: %x", static_lease_nip); 489 bb_error_msg("found static lease: %x", static_lease_nip);
490 memcpy(&fake_lease.lease_mac, &packet.chaddr, 6); 490 memcpy(&fake_lease.lease_mac, &packet.chaddr, 6);
491 fake_lease.lease_nip = static_lease_nip; 491 fake_lease.lease_nip = static_lease_nip;
492 fake_lease.expires = 0; 492 fake_lease.expires = 0;
@@ -504,13 +504,13 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv)
504 switch (state[0]) { 504 switch (state[0]) {
505 505
506 case DHCPDISCOVER: 506 case DHCPDISCOVER:
507 log1("Received DISCOVER"); 507 log1("received %s", "DISCOVER");
508 508
509 send_offer(&packet, static_lease_nip, lease, requested_ip_opt, arpping_ms); 509 send_offer(&packet, static_lease_nip, lease, requested_ip_opt, arpping_ms);
510 break; 510 break;
511 511
512 case DHCPREQUEST: 512 case DHCPREQUEST:
513 log1("Received REQUEST"); 513 log1("received %s", "REQUEST");
514/* RFC 2131: 514/* RFC 2131:
515 515
516o DHCPREQUEST generated during SELECTING state: 516o DHCPREQUEST generated during SELECTING state:
@@ -635,7 +635,7 @@ o DHCPREQUEST generated during REBINDING state:
635 * chaddr must be filled in, 635 * chaddr must be filled in,
636 * ciaddr must be 0 (we do not check this) 636 * ciaddr must be 0 (we do not check this)
637 */ 637 */
638 log1("Received DECLINE"); 638 log1("received %s", "DECLINE");
639 if (server_id_opt 639 if (server_id_opt
640 && requested_ip_opt 640 && requested_ip_opt
641 && lease /* chaddr matches this lease */ 641 && lease /* chaddr matches this lease */
@@ -655,7 +655,7 @@ o DHCPREQUEST generated during REBINDING state:
655 * chaddr must be filled in, 655 * chaddr must be filled in,
656 * ciaddr must be filled in 656 * ciaddr must be filled in
657 */ 657 */
658 log1("Received RELEASE"); 658 log1("received %s", "RELEASE");
659 if (server_id_opt 659 if (server_id_opt
660 && lease /* chaddr matches this lease */ 660 && lease /* chaddr matches this lease */
661 && packet.ciaddr == lease->lease_nip 661 && packet.ciaddr == lease->lease_nip
@@ -665,7 +665,7 @@ o DHCPREQUEST generated during REBINDING state:
665 break; 665 break;
666 666
667 case DHCPINFORM: 667 case DHCPINFORM:
668 log1("Received INFORM"); 668 log1("received %s", "INFORM");
669 send_inform(&packet); 669 send_inform(&packet);
670 break; 670 break;
671 } 671 }
diff --git a/networking/udhcp/domain_codec.c b/networking/udhcp/domain_codec.c
index c1325d8be..5a923cc2c 100644
--- a/networking/udhcp/domain_codec.c
+++ b/networking/udhcp/domain_codec.c
@@ -7,6 +7,7 @@
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#ifdef DNS_COMPR_TESTING 9#ifdef DNS_COMPR_TESTING
10# define _GNU_SOURCE
10# define FAST_FUNC /* nothing */ 11# define FAST_FUNC /* nothing */
11# define xmalloc malloc 12# define xmalloc malloc
12# include <stdlib.h> 13# include <stdlib.h>
@@ -42,7 +43,7 @@ char* FAST_FUNC dname_dec(const uint8_t *cstr, int clen, const char *pre)
42 */ 43 */
43 while (1) { 44 while (1) {
44 /* note: "return NULL" below are leak-safe since 45 /* note: "return NULL" below are leak-safe since
45 * dst isn't yet allocated */ 46 * dst isn't allocated yet */
46 const uint8_t *c; 47 const uint8_t *c;
47 unsigned crtpos, retpos, depth, len; 48 unsigned crtpos, retpos, depth, len;
48 49
@@ -63,11 +64,10 @@ char* FAST_FUNC dname_dec(const uint8_t *cstr, int clen, const char *pre)
63 if (crtpos + *c + 1 > clen) /* label too long? abort */ 64 if (crtpos + *c + 1 > clen) /* label too long? abort */
64 return NULL; 65 return NULL;
65 if (dst) 66 if (dst)
66 memcpy(dst + len, c + 1, *c); 67 /* \3com ---> "com." */
68 ((char*)mempcpy(dst + len, c + 1, *c))[0] = '.';
67 len += *c + 1; 69 len += *c + 1;
68 crtpos += *c + 1; 70 crtpos += *c + 1;
69 if (dst)
70 dst[len - 1] = '.';
71 } else { 71 } else {
72 /* NUL: end of current domain name */ 72 /* NUL: end of current domain name */
73 if (retpos == 0) { 73 if (retpos == 0) {
@@ -78,7 +78,10 @@ char* FAST_FUNC dname_dec(const uint8_t *cstr, int clen, const char *pre)
78 crtpos = retpos; 78 crtpos = retpos;
79 retpos = depth = 0; 79 retpos = depth = 0;
80 } 80 }
81 if (dst) 81 if (dst && len != 0)
82 /* \4host\3com\0\4host and we are at \0:
83 * \3com was converted to "com.", change dot to space.
84 */
82 dst[len - 1] = ' '; 85 dst[len - 1] = ' ';
83 } 86 }
84 87
@@ -95,9 +98,8 @@ char* FAST_FUNC dname_dec(const uint8_t *cstr, int clen, const char *pre)
95 if (!dst) { /* first pass? */ 98 if (!dst) { /* first pass? */
96 /* allocate dst buffer and copy pre */ 99 /* allocate dst buffer and copy pre */
97 unsigned plen = strlen(pre); 100 unsigned plen = strlen(pre);
98 ret = dst = xmalloc(plen + len); 101 ret = xmalloc(plen + len);
99 memcpy(dst, pre, plen); 102 dst = stpcpy(ret, pre);
100 dst += plen;
101 } else { 103 } else {
102 dst[len - 1] = '\0'; 104 dst[len - 1] = '\0';
103 break; 105 break;
@@ -228,6 +230,9 @@ int main(int argc, char **argv)
228 int len; 230 int len;
229 uint8_t *encoded; 231 uint8_t *encoded;
230 232
233 uint8_t str[6] = { 0x00, 0x00, 0x02, 0x65, 0x65, 0x00 };
234 printf("NUL:'%s'\n", dname_dec(str, 6, ""));
235
231#define DNAME_DEC(encoded,pre) dname_dec((uint8_t*)(encoded), sizeof(encoded), (pre)) 236#define DNAME_DEC(encoded,pre) dname_dec((uint8_t*)(encoded), sizeof(encoded), (pre))
232 printf("'%s'\n", DNAME_DEC("\4host\3com\0", "test1:")); 237 printf("'%s'\n", DNAME_DEC("\4host\3com\0", "test1:"));
233 printf("test2:'%s'\n", DNAME_DEC("\4host\3com\0\4host\3com\0", "")); 238 printf("test2:'%s'\n", DNAME_DEC("\4host\3com\0\4host\3com\0", ""));
diff --git a/networking/udhcp/files.c b/networking/udhcp/files.c
index 1c8808c0f..7b57c6258 100644
--- a/networking/udhcp/files.c
+++ b/networking/udhcp/files.c
@@ -195,7 +195,11 @@ void FAST_FUNC read_leases(const char *file)
195 uint32_t static_nip; 195 uint32_t static_nip;
196 196
197 if (expires <= 0) 197 if (expires <= 0)
198 continue; 198 /* We keep expired leases: add_lease() will add
199 * a lease with 0 seconds remaining.
200 * Fewer IP address changes this way for mass reboot scenario.
201 */
202 expires = 0;
199 203
200 /* Check if there is a different static lease for this IP or MAC */ 204 /* Check if there is a different static lease for this IP or MAC */
201 static_nip = get_static_nip_by_mac(server_config.static_leases, lease.lease_mac); 205 static_nip = get_static_nip_by_mac(server_config.static_leases, lease.lease_mac);
@@ -222,7 +226,7 @@ void FAST_FUNC read_leases(const char *file)
222#endif 226#endif
223 } 227 }
224 } 228 }
225 log1("Read %d leases", i); 229 log1("read %d leases", i);
226 ret: 230 ret:
227 close(fd); 231 close(fd);
228} 232}
diff --git a/networking/udhcp/leases.c b/networking/udhcp/leases.c
index 844bb60b1..6642e396d 100644
--- a/networking/udhcp/leases.c
+++ b/networking/udhcp/leases.c
@@ -17,7 +17,9 @@ static struct dyn_lease *oldest_expired_lease(void)
17 /* Unexpired leases have g_leases[i].expires >= current time 17 /* Unexpired leases have g_leases[i].expires >= current time
18 * and therefore can't ever match */ 18 * and therefore can't ever match */
19 for (i = 0; i < server_config.max_leases; i++) { 19 for (i = 0; i < server_config.max_leases; i++) {
20 if (g_leases[i].expires < oldest_time) { 20 if (g_leases[i].expires == 0 /* empty entry */
21 || g_leases[i].expires < oldest_time
22 ) {
21 oldest_time = g_leases[i].expires; 23 oldest_time = g_leases[i].expires;
22 oldest_lease = &g_leases[i]; 24 oldest_lease = &g_leases[i];
23 } 25 }
@@ -131,7 +133,7 @@ static int nobody_responds_to_arp(uint32_t nip, const uint8_t *safe_mac, unsigne
131 return r; 133 return r;
132 134
133 temp.s_addr = nip; 135 temp.s_addr = nip;
134 bb_info_msg("%s belongs to someone, reserving it for %u seconds", 136 bb_error_msg("%s belongs to someone, reserving it for %u seconds",
135 inet_ntoa(temp), (unsigned)server_config.conflict_time); 137 inet_ntoa(temp), (unsigned)server_config.conflict_time);
136 add_lease(NULL, nip, server_config.conflict_time, NULL, 0); 138 add_lease(NULL, nip, server_config.conflict_time, NULL, 0);
137 return 0; 139 return 0;
diff --git a/networking/udhcp/packet.c b/networking/udhcp/packet.c
index 148f52551..0a31f2643 100644
--- a/networking/udhcp/packet.c
+++ b/networking/udhcp/packet.c
@@ -38,8 +38,8 @@ void FAST_FUNC udhcp_dump_packet(struct dhcp_packet *packet)
38 if (dhcp_verbose < 2) 38 if (dhcp_verbose < 2)
39 return; 39 return;
40 40
41 bb_info_msg( 41 bb_error_msg(
42 //" op %x" 42 //"op %x"
43 //" htype %x" 43 //" htype %x"
44 " hlen %x" 44 " hlen %x"
45 //" hops %x" 45 //" hops %x"
@@ -73,7 +73,7 @@ void FAST_FUNC udhcp_dump_packet(struct dhcp_packet *packet)
73 //, packet->options[] 73 //, packet->options[]
74 ); 74 );
75 *bin2hex(buf, (void *) packet->chaddr, sizeof(packet->chaddr)) = '\0'; 75 *bin2hex(buf, (void *) packet->chaddr, sizeof(packet->chaddr)) = '\0';
76 bb_info_msg(" chaddr %s", buf); 76 bb_error_msg("chaddr %s", buf);
77} 77}
78#endif 78#endif
79 79
@@ -85,17 +85,17 @@ int FAST_FUNC udhcp_recv_kernel_packet(struct dhcp_packet *packet, int fd)
85 memset(packet, 0, sizeof(*packet)); 85 memset(packet, 0, sizeof(*packet));
86 bytes = safe_read(fd, packet, sizeof(*packet)); 86 bytes = safe_read(fd, packet, sizeof(*packet));
87 if (bytes < 0) { 87 if (bytes < 0) {
88 log1("Packet read error, ignoring"); 88 log1("packet read error, ignoring");
89 return bytes; /* returns -1 */ 89 return bytes; /* returns -1 */
90 } 90 }
91 91
92 if (bytes < offsetof(struct dhcp_packet, options) 92 if (bytes < offsetof(struct dhcp_packet, options)
93 || packet->cookie != htonl(DHCP_MAGIC) 93 || packet->cookie != htonl(DHCP_MAGIC)
94 ) { 94 ) {
95 bb_info_msg("Packet with bad magic, ignoring"); 95 bb_error_msg("packet with bad magic, ignoring");
96 return -2; 96 return -2;
97 } 97 }
98 log1("Received a packet"); 98 log1("received %s", "a packet");
99 udhcp_dump_packet(packet); 99 udhcp_dump_packet(packet);
100 100
101 return bytes; 101 return bytes;
diff --git a/networking/udhcp/socket.c b/networking/udhcp/socket.c
index a42106960..4fd79f423 100644
--- a/networking/udhcp/socket.c
+++ b/networking/udhcp/socket.c
@@ -56,7 +56,7 @@ int FAST_FUNC udhcp_read_interface(const char *interface, int *ifindex, uint32_t
56 close(fd); 56 close(fd);
57 return -1; 57 return -1;
58 } 58 }
59 log1("Adapter index %d", ifr->ifr_ifindex); 59 log1("adapter index %d", ifr->ifr_ifindex);
60 *ifindex = ifr->ifr_ifindex; 60 *ifindex = ifr->ifr_ifindex;
61 } 61 }
62 62
@@ -82,7 +82,7 @@ int FAST_FUNC udhcp_listen_socket(/*uint32_t ip,*/ int port, const char *inf)
82 struct sockaddr_in addr; 82 struct sockaddr_in addr;
83 char *colon; 83 char *colon;
84 84
85 log1("Opening listen socket on *:%d %s", port, inf); 85 log1("opening listen socket on *:%d %s", port, inf);
86 fd = xsocket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); 86 fd = xsocket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
87 87
88 setsockopt_reuseaddr(fd); 88 setsockopt_reuseaddr(fd);
diff --git a/networking/udhcp/static_leases.c b/networking/udhcp/static_leases.c
index f4a24ab62..b7f9e5c59 100644
--- a/networking/udhcp/static_leases.c
+++ b/networking/udhcp/static_leases.c
@@ -66,7 +66,7 @@ void FAST_FUNC log_static_leases(struct static_lease **st_lease_pp)
66 66
67 cur = *st_lease_pp; 67 cur = *st_lease_pp;
68 while (cur) { 68 while (cur) {
69 bb_info_msg("static lease: mac:%02x:%02x:%02x:%02x:%02x:%02x nip:%x", 69 bb_error_msg("static lease: mac:%02x:%02x:%02x:%02x:%02x:%02x nip:%x",
70 cur->mac[0], cur->mac[1], cur->mac[2], 70 cur->mac[0], cur->mac[1], cur->mac[2],
71 cur->mac[3], cur->mac[4], cur->mac[5], 71 cur->mac[3], cur->mac[4], cur->mac[5],
72 cur->nip 72 cur->nip
diff --git a/networking/wget.c b/networking/wget.c
index edf8fd8af..87d3bbd13 100644
--- a/networking/wget.c
+++ b/networking/wget.c
@@ -203,7 +203,7 @@ struct globals {
203 const char *user_agent; /* "User-Agent" header field */ 203 const char *user_agent; /* "User-Agent" header field */
204#if ENABLE_FEATURE_WGET_TIMEOUT 204#if ENABLE_FEATURE_WGET_TIMEOUT
205 unsigned timeout_seconds; 205 unsigned timeout_seconds;
206 bool connecting; 206 bool die_if_timed_out;
207#endif 207#endif
208 int output_fd; 208 int output_fd;
209 int o_flags; 209 int o_flags;
@@ -333,9 +333,20 @@ static char* sanitize_string(char *s)
333static void alarm_handler(int sig UNUSED_PARAM) 333static void alarm_handler(int sig UNUSED_PARAM)
334{ 334{
335 /* This is theoretically unsafe (uses stdio and malloc in signal handler) */ 335 /* This is theoretically unsafe (uses stdio and malloc in signal handler) */
336 if (G.connecting) 336 if (G.die_if_timed_out)
337 bb_error_msg_and_die("download timed out"); 337 bb_error_msg_and_die("download timed out");
338} 338}
339static void set_alarm(void)
340{
341 if (G.timeout_seconds) {
342 alarm(G.timeout_seconds);
343 G.die_if_timed_out = 1;
344 }
345}
346# define clear_alarm() ((void)(G.die_if_timed_out = 0))
347#else
348# define set_alarm() ((void)0)
349# define clear_alarm() ((void)0)
339#endif 350#endif
340 351
341static FILE *open_socket(len_and_sockaddr *lsa) 352static FILE *open_socket(len_and_sockaddr *lsa)
@@ -343,9 +354,9 @@ static FILE *open_socket(len_and_sockaddr *lsa)
343 int fd; 354 int fd;
344 FILE *fp; 355 FILE *fp;
345 356
346 IF_FEATURE_WGET_TIMEOUT(alarm(G.timeout_seconds); G.connecting = 1;) 357 set_alarm();
347 fd = xconnect_stream(lsa); 358 fd = xconnect_stream(lsa);
348 IF_FEATURE_WGET_TIMEOUT(G.connecting = 0;) 359 clear_alarm();
349 360
350 /* glibc 2.4 seems to try seeking on it - ??! */ 361 /* glibc 2.4 seems to try seeking on it - ??! */
351 /* hopefully it understands what ESPIPE means... */ 362 /* hopefully it understands what ESPIPE means... */
@@ -357,14 +368,15 @@ static FILE *open_socket(len_and_sockaddr *lsa)
357} 368}
358 369
359/* Returns '\n' if it was seen, else '\0'. Trims at first '\r' or '\n' */ 370/* Returns '\n' if it was seen, else '\0'. Trims at first '\r' or '\n' */
360/* FIXME: does not respect FEATURE_WGET_TIMEOUT and -T N: */
361static char fgets_and_trim(FILE *fp) 371static char fgets_and_trim(FILE *fp)
362{ 372{
363 char c; 373 char c;
364 char *buf_ptr; 374 char *buf_ptr;
365 375
376 set_alarm();
366 if (fgets(G.wget_buf, sizeof(G.wget_buf) - 1, fp) == NULL) 377 if (fgets(G.wget_buf, sizeof(G.wget_buf) - 1, fp) == NULL)
367 bb_perror_msg_and_die("error getting response"); 378 bb_perror_msg_and_die("error getting response");
379 clear_alarm();
368 380
369 buf_ptr = strchrnul(G.wget_buf, '\n'); 381 buf_ptr = strchrnul(G.wget_buf, '\n');
370 c = *buf_ptr; 382 c = *buf_ptr;
diff --git a/networking/zcip.c b/networking/zcip.c
index 1d6910555..c93082619 100644
--- a/networking/zcip.c
+++ b/networking/zcip.c
@@ -176,7 +176,7 @@ static int run(char *argv[3], const char *param, uint32_t nip)
176 xsetenv("ip", addr); 176 xsetenv("ip", addr);
177 fmt -= 3; 177 fmt -= 3;
178 } 178 }
179 bb_info_msg(fmt, argv[2], argv[0], addr); 179 bb_error_msg(fmt, argv[2], argv[0], addr);
180 180
181 status = spawn_and_wait(argv + 1); 181 status = spawn_and_wait(argv + 1);
182 if (status < 0) { 182 if (status < 0) {
@@ -317,7 +317,7 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
317#if BB_MMU 317#if BB_MMU
318 bb_daemonize(0 /*was: DAEMON_CHDIR_ROOT*/); 318 bb_daemonize(0 /*was: DAEMON_CHDIR_ROOT*/);
319#endif 319#endif
320 bb_info_msg("start, interface %s", argv_intf); 320 bb_error_msg("start, interface %s", argv_intf);
321 } 321 }
322 322
323 // Run the dynamic address negotiation protocol, 323 // Run the dynamic address negotiation protocol,
diff --git a/procps/nmeter.c b/procps/nmeter.c
index 5d5b83b8d..33de3790f 100644
--- a/procps/nmeter.c
+++ b/procps/nmeter.c
@@ -21,7 +21,7 @@
21//usage:#define nmeter_full_usage "\n\n" 21//usage:#define nmeter_full_usage "\n\n"
22//usage: "Monitor system in real time" 22//usage: "Monitor system in real time"
23//usage: "\n" 23//usage: "\n"
24//usage: "\n -d MSEC Milliseconds between updates (default:1000)" 24//usage: "\n -d MSEC Milliseconds between updates, default:1000, none:-1"
25//usage: "\n" 25//usage: "\n"
26//usage: "\nFormat specifiers:" 26//usage: "\nFormat specifiers:"
27//usage: "\n %Nc or %[cN] CPU. N - bar size (default:10)" 27//usage: "\n %Nc or %[cN] CPU. N - bar size (default:10)"
@@ -83,10 +83,10 @@ struct globals {
83 smallint is26; 83 smallint is26;
84 // 1 if sample delay is not an integer fraction of a second 84 // 1 if sample delay is not an integer fraction of a second
85 smallint need_seconds; 85 smallint need_seconds;
86 char final_char;
86 char *cur_outbuf; 87 char *cur_outbuf;
87 const char *final_str;
88 int delta; 88 int delta;
89 int deltanz; 89 unsigned deltanz;
90 struct timeval tv; 90 struct timeval tv;
91#define first_proc_file proc_stat 91#define first_proc_file proc_stat
92 proc_file proc_stat; // Must match the order of proc_name's! 92 proc_file proc_stat; // Must match the order of proc_name's!
@@ -101,9 +101,6 @@ struct globals {
101#define is26 (G.is26 ) 101#define is26 (G.is26 )
102#define need_seconds (G.need_seconds ) 102#define need_seconds (G.need_seconds )
103#define cur_outbuf (G.cur_outbuf ) 103#define cur_outbuf (G.cur_outbuf )
104#define final_str (G.final_str )
105#define delta (G.delta )
106#define deltanz (G.deltanz )
107#define tv (G.tv ) 104#define tv (G.tv )
108#define proc_stat (G.proc_stat ) 105#define proc_stat (G.proc_stat )
109#define proc_loadavg (G.proc_loadavg ) 106#define proc_loadavg (G.proc_loadavg )
@@ -114,8 +111,8 @@ struct globals {
114#define INIT_G() do { \ 111#define INIT_G() do { \
115 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ 112 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
116 cur_outbuf = outbuf; \ 113 cur_outbuf = outbuf; \
117 final_str = "\n"; \ 114 G.final_char = '\n'; \
118 deltanz = delta = 1000000; \ 115 G.deltanz = G.delta = 1000000; \
119} while (0) 116} while (0)
120 117
121// We depend on this being a char[], not char* - we take sizeof() of it 118// We depend on this being a char[], not char* - we take sizeof() of it
@@ -142,11 +139,11 @@ static void print_outbuf(void)
142 139
143static void put(const char *s) 140static void put(const char *s)
144{ 141{
145 int sz = strlen(s); 142 char *p = cur_outbuf;
146 if (sz > outbuf + sizeof(outbuf) - cur_outbuf) 143 int sz = outbuf + sizeof(outbuf) - p;
147 sz = outbuf + sizeof(outbuf) - cur_outbuf; 144 while (*s && --sz >= 0)
148 memcpy(cur_outbuf, s, sz); 145 *p++ = *s++;
149 cur_outbuf += sz; 146 cur_outbuf = p;
150} 147}
151 148
152static void put_c(char c) 149static void put_c(char c)
@@ -208,65 +205,50 @@ static ullong read_after_slash(const char *p)
208 return strtoull(p+1, NULL, 10); 205 return strtoull(p+1, NULL, 10);
209} 206}
210 207
211enum conv_type { conv_decimal, conv_slash }; 208enum conv_type {
209 conv_decimal = 0,
210 conv_slash = 1
211};
212 212
213// Reads decimal values from line. Values start after key, for example: 213// Reads decimal values from line. Values start after key, for example:
214// "cpu 649369 0 341297 4336769..." - key is "cpu" here. 214// "cpu 649369 0 341297 4336769..." - key is "cpu" here.
215// Values are stored in vec[]. arg_ptr has list of positions 215// Values are stored in vec[].
216// we are interested in: for example: 1,2,5 - we want 1st, 2nd and 5th value. 216// posbits is a bit lit of positions we are interested in.
217static int vrdval(const char* p, const char* key, 217// for example: 00100110 - we want 1st, 2nd and 5th value.
218 enum conv_type conv, ullong *vec, va_list arg_ptr) 218// posbits.bit0 encodes conversion type.
219static int rdval(const char* p, const char* key, ullong *vec, long posbits)
219{ 220{
220 int indexline; 221 unsigned curpos;
221 int indexnext;
222 222
223 p = strstr(p, key); 223 p = strstr(p, key);
224 if (!p) return 1; 224 if (!p) return 1;
225 225
226 p += strlen(key); 226 p += strlen(key);
227 indexline = 1; 227 curpos = 1 << 1;
228 indexnext = va_arg(arg_ptr, int);
229 while (1) { 228 while (1) {
230 while (*p == ' ' || *p == '\t') p++; 229 while (*p == ' ' || *p == '\t') p++;
231 if (*p == '\n' || *p == '\0') break; 230 if (*p == '\n' || *p == '\0') break;
232 231
233 if (indexline == indexnext) { // read this value 232 if (curpos & posbits) { // read this value
234 *vec++ = conv==conv_decimal ? 233 *vec++ = (posbits & 1) == conv_decimal ?
235 strtoull(p, NULL, 10) : 234 strtoull(p, NULL, 10) :
236 read_after_slash(p); 235 read_after_slash(p);
237 indexnext = va_arg(arg_ptr, int); 236 posbits -= curpos;
237 if (posbits <= 1)
238 return 0;
238 } 239 }
239 while (*p > ' ') p++; // skip over value 240 while (*p > ' ') // skip over the value
240 indexline++; 241 p++;
242 curpos <<= 1;
241 } 243 }
242 return 0; 244 return 0;
243} 245}
244 246
245// Parses files with lines like "cpu0 21727 0 15718 1813856 9461 10485 0 0":
246// rdval(file_contents, "string_to_find", result_vector, value#, value#...)
247// value# start with 1
248static int rdval(const char* p, const char* key, ullong *vec, ...)
249{
250 va_list arg_ptr;
251 int result;
252
253 va_start(arg_ptr, vec);
254 result = vrdval(p, key, conv_decimal, vec, arg_ptr);
255 va_end(arg_ptr);
256
257 return result;
258}
259
260// Parses files with lines like "... ... ... 3/148 ...." 247// Parses files with lines like "... ... ... 3/148 ...."
261static int rdval_loadavg(const char* p, ullong *vec, ...) 248static int rdval_loadavg(const char* p, ullong *vec, long posbits)
262{ 249{
263 va_list arg_ptr;
264 int result; 250 int result;
265 251 result = rdval(p, "", vec, posbits | conv_slash);
266 va_start(arg_ptr, vec);
267 result = vrdval(p, "", conv_slash, vec, arg_ptr);
268 va_end(arg_ptr);
269
270 return result; 252 return result;
271} 253}
272 254
@@ -337,7 +319,6 @@ static void scale(ullong ul)
337 put(buf); 319 put(buf);
338} 320}
339 321
340
341#define S_STAT(a) \ 322#define S_STAT(a) \
342typedef struct a { \ 323typedef struct a { \
343 struct s_stat *next; \ 324 struct s_stat *next; \
@@ -359,21 +340,12 @@ static s_stat* init_literal(void)
359 return (s_stat*)s; 340 return (s_stat*)s;
360} 341}
361 342
362static s_stat* init_delay(const char *param)
363{
364 delta = strtoul(param, NULL, 0) * 1000; /* param can be "" */
365 deltanz = delta > 0 ? delta : 1;
366 need_seconds = (1000000%deltanz) != 0;
367 return NULL;
368}
369
370static s_stat* init_cr(const char *param UNUSED_PARAM) 343static s_stat* init_cr(const char *param UNUSED_PARAM)
371{ 344{
372 final_str = "\r"; 345 G.final_char = '\r';
373 return (s_stat*)0; 346 return NULL;
374} 347}
375 348
376
377// user nice system idle iowait irq softirq (last 3 only in 2.6) 349// user nice system idle iowait irq softirq (last 3 only in 2.6)
378//cpu 649369 0 341297 4336769 11640 7122 1183 350//cpu 649369 0 341297 4336769 11640 7122 1183
379//cpuN 649369 0 341297 4336769 11640 7122 1183 351//cpuN 649369 0 341297 4336769 11640 7122 1183
@@ -381,10 +353,9 @@ enum { CPU_FIELDCNT = 7 };
381S_STAT(cpu_stat) 353S_STAT(cpu_stat)
382 ullong old[CPU_FIELDCNT]; 354 ullong old[CPU_FIELDCNT];
383 int bar_sz; 355 int bar_sz;
384 char *bar; 356 char bar[1];
385S_STAT_END(cpu_stat) 357S_STAT_END(cpu_stat)
386 358
387
388static void FAST_FUNC collect_cpu(cpu_stat *s) 359static void FAST_FUNC collect_cpu(cpu_stat *s)
389{ 360{
390 ullong data[CPU_FIELDCNT] = { 0, 0, 0, 0, 0, 0, 0 }; 361 ullong data[CPU_FIELDCNT] = { 0, 0, 0, 0, 0, 0, 0 };
@@ -395,7 +366,15 @@ static void FAST_FUNC collect_cpu(cpu_stat *s)
395 char *bar = s->bar; 366 char *bar = s->bar;
396 int i; 367 int i;
397 368
398 if (rdval(get_file(&proc_stat), "cpu ", data, 1, 2, 3, 4, 5, 6, 7)) { 369 if (rdval(get_file(&proc_stat), "cpu ", data, 0
370 | (1 << 1)
371 | (1 << 2)
372 | (1 << 3)
373 | (1 << 4)
374 | (1 << 5)
375 | (1 << 6)
376 | (1 << 7))
377 ) {
399 put_question_marks(bar_sz); 378 put_question_marks(bar_sz);
400 return; 379 return;
401 } 380 }
@@ -438,22 +417,20 @@ static void FAST_FUNC collect_cpu(cpu_stat *s)
438 put(s->bar); 417 put(s->bar);
439} 418}
440 419
441
442static s_stat* init_cpu(const char *param) 420static s_stat* init_cpu(const char *param)
443{ 421{
444 int sz; 422 int sz;
445 cpu_stat *s = xzalloc(sizeof(*s)); 423 cpu_stat *s;
446 s->collect = collect_cpu;
447 sz = strtoul(param, NULL, 0); /* param can be "" */ 424 sz = strtoul(param, NULL, 0); /* param can be "" */
448 if (sz < 10) sz = 10; 425 if (sz < 10) sz = 10;
449 if (sz > 1000) sz = 1000; 426 if (sz > 1000) sz = 1000;
450 s->bar = xzalloc(sz+1); 427 s = xzalloc(sizeof(*s) + sz);
451 /*s->bar[sz] = '\0'; - xzalloc did it */ 428 /*s->bar[sz] = '\0'; - xzalloc did it */
452 s->bar_sz = sz; 429 s->bar_sz = sz;
430 s->collect = collect_cpu;
453 return (s_stat*)s; 431 return (s_stat*)s;
454} 432}
455 433
456
457S_STAT(int_stat) 434S_STAT(int_stat)
458 ullong old; 435 ullong old;
459 int no; 436 int no;
@@ -464,7 +441,7 @@ static void FAST_FUNC collect_int(int_stat *s)
464 ullong data[1]; 441 ullong data[1];
465 ullong old; 442 ullong old;
466 443
467 if (rdval(get_file(&proc_stat), "intr", data, s->no)) { 444 if (rdval(get_file(&proc_stat), "intr", data, 1 << s->no)) {
468 put_question_marks(4); 445 put_question_marks(4);
469 return; 446 return;
470 } 447 }
@@ -488,7 +465,6 @@ static s_stat* init_int(const char *param)
488 return (s_stat*)s; 465 return (s_stat*)s;
489} 466}
490 467
491
492S_STAT(ctx_stat) 468S_STAT(ctx_stat)
493 ullong old; 469 ullong old;
494S_STAT_END(ctx_stat) 470S_STAT_END(ctx_stat)
@@ -498,7 +474,7 @@ static void FAST_FUNC collect_ctx(ctx_stat *s)
498 ullong data[1]; 474 ullong data[1];
499 ullong old; 475 ullong old;
500 476
501 if (rdval(get_file(&proc_stat), "ctxt", data, 1)) { 477 if (rdval(get_file(&proc_stat), "ctxt", data, 1 << 1)) {
502 put_question_marks(4); 478 put_question_marks(4);
503 return; 479 return;
504 } 480 }
@@ -516,7 +492,6 @@ static s_stat* init_ctx(const char *param UNUSED_PARAM)
516 return (s_stat*)s; 492 return (s_stat*)s;
517} 493}
518 494
519
520S_STAT(blk_stat) 495S_STAT(blk_stat)
521 const char* lookfor; 496 const char* lookfor;
522 ullong old[2]; 497 ullong old[2];
@@ -530,7 +505,10 @@ static void FAST_FUNC collect_blk(blk_stat *s)
530 if (is26) { 505 if (is26) {
531 i = rdval_diskstats(get_file(&proc_diskstats), data); 506 i = rdval_diskstats(get_file(&proc_diskstats), data);
532 } else { 507 } else {
533 i = rdval(get_file(&proc_stat), s->lookfor, data, 1, 2); 508 i = rdval(get_file(&proc_stat), s->lookfor, data, 0
509 | (1 << 1)
510 | (1 << 2)
511 );
534 // Linux 2.4 reports bio in Kbytes, convert to sectors: 512 // Linux 2.4 reports bio in Kbytes, convert to sectors:
535 data[0] *= 2; 513 data[0] *= 2;
536 data[1] *= 2; 514 data[1] *= 2;
@@ -559,7 +537,6 @@ static s_stat* init_blk(const char *param UNUSED_PARAM)
559 return (s_stat*)s; 537 return (s_stat*)s;
560} 538}
561 539
562
563S_STAT(fork_stat) 540S_STAT(fork_stat)
564 ullong old; 541 ullong old;
565S_STAT_END(fork_stat) 542S_STAT_END(fork_stat)
@@ -568,7 +545,7 @@ static void FAST_FUNC collect_thread_nr(fork_stat *s UNUSED_PARAM)
568{ 545{
569 ullong data[1]; 546 ullong data[1];
570 547
571 if (rdval_loadavg(get_file(&proc_loadavg), data, 4)) { 548 if (rdval_loadavg(get_file(&proc_loadavg), data, 1 << 4)) {
572 put_question_marks(4); 549 put_question_marks(4);
573 return; 550 return;
574 } 551 }
@@ -580,7 +557,7 @@ static void FAST_FUNC collect_fork(fork_stat *s)
580 ullong data[1]; 557 ullong data[1];
581 ullong old; 558 ullong old;
582 559
583 if (rdval(get_file(&proc_stat), "processes", data, 1)) { 560 if (rdval(get_file(&proc_stat), "processes", data, 1 << 1)) {
584 put_question_marks(4); 561 put_question_marks(4);
585 return; 562 return;
586 } 563 }
@@ -602,7 +579,6 @@ static s_stat* init_fork(const char *param)
602 return (s_stat*)s; 579 return (s_stat*)s;
603} 580}
604 581
605
606S_STAT(if_stat) 582S_STAT(if_stat)
607 ullong old[4]; 583 ullong old[4];
608 const char *device; 584 const char *device;
@@ -614,7 +590,12 @@ static void FAST_FUNC collect_if(if_stat *s)
614 ullong data[4]; 590 ullong data[4];
615 int i; 591 int i;
616 592
617 if (rdval(get_file(&proc_net_dev), s->device_colon, data, 1, 3, 9, 11)) { 593 if (rdval(get_file(&proc_net_dev), s->device_colon, data, 0
594 | (1 << 1)
595 | (1 << 3)
596 | (1 << 9)
597 | (1 << 11))
598 ) {
618 put_question_marks(10); 599 put_question_marks(10);
619 return; 600 return;
620 } 601 }
@@ -644,7 +625,6 @@ static s_stat* init_if(const char *device)
644 return (s_stat*)s; 625 return (s_stat*)s;
645} 626}
646 627
647
648S_STAT(mem_stat) 628S_STAT(mem_stat)
649 char opt; 629 char opt;
650S_STAT_END(mem_stat) 630S_STAT_END(mem_stat)
@@ -692,7 +672,7 @@ static void FAST_FUNC collect_mem(mem_stat *s)
692 ullong m_cached = 0; 672 ullong m_cached = 0;
693 ullong m_slab = 0; 673 ullong m_slab = 0;
694 674
695 if (rdval(get_file(&proc_meminfo), "MemTotal:", &m_total, 1)) { 675 if (rdval(get_file(&proc_meminfo), "MemTotal:", &m_total, 1 << 1)) {
696 put_question_marks(4); 676 put_question_marks(4);
697 return; 677 return;
698 } 678 }
@@ -701,10 +681,10 @@ static void FAST_FUNC collect_mem(mem_stat *s)
701 return; 681 return;
702 } 682 }
703 683
704 if (rdval(proc_meminfo.file, "MemFree:", &m_free , 1) 684 if (rdval(proc_meminfo.file, "MemFree:", &m_free , 1 << 1)
705 || rdval(proc_meminfo.file, "Buffers:", &m_bufs , 1) 685 || rdval(proc_meminfo.file, "Buffers:", &m_bufs , 1 << 1)
706 || rdval(proc_meminfo.file, "Cached:", &m_cached, 1) 686 || rdval(proc_meminfo.file, "Cached:", &m_cached, 1 << 1)
707 || rdval(proc_meminfo.file, "Slab:", &m_slab , 1) 687 || rdval(proc_meminfo.file, "Slab:", &m_slab , 1 << 1)
708 ) { 688 ) {
709 put_question_marks(4); 689 put_question_marks(4);
710 return; 690 return;
@@ -727,7 +707,6 @@ static s_stat* init_mem(const char *param)
727 return (s_stat*)s; 707 return (s_stat*)s;
728} 708}
729 709
730
731S_STAT(swp_stat) 710S_STAT(swp_stat)
732S_STAT_END(swp_stat) 711S_STAT_END(swp_stat)
733 712
@@ -735,8 +714,8 @@ static void FAST_FUNC collect_swp(swp_stat *s UNUSED_PARAM)
735{ 714{
736 ullong s_total[1]; 715 ullong s_total[1];
737 ullong s_free[1]; 716 ullong s_free[1];
738 if (rdval(get_file(&proc_meminfo), "SwapTotal:", s_total, 1) 717 if (rdval(get_file(&proc_meminfo), "SwapTotal:", s_total, 1 << 1)
739 || rdval(proc_meminfo.file, "SwapFree:" , s_free, 1) 718 || rdval(proc_meminfo.file, "SwapFree:" , s_free, 1 << 1)
740 ) { 719 ) {
741 put_question_marks(4); 720 put_question_marks(4);
742 return; 721 return;
@@ -751,7 +730,6 @@ static s_stat* init_swp(const char *param UNUSED_PARAM)
751 return (s_stat*)s; 730 return (s_stat*)s;
752} 731}
753 732
754
755S_STAT(fd_stat) 733S_STAT(fd_stat)
756S_STAT_END(fd_stat) 734S_STAT_END(fd_stat)
757 735
@@ -759,7 +737,10 @@ static void FAST_FUNC collect_fd(fd_stat *s UNUSED_PARAM)
759{ 737{
760 ullong data[2]; 738 ullong data[2];
761 739
762 if (rdval(get_file(&proc_sys_fs_filenr), "", data, 1, 2)) { 740 if (rdval(get_file(&proc_sys_fs_filenr), "", data, 0
741 | (1 << 1)
742 | (1 << 2))
743 ) {
763 put_question_marks(4); 744 put_question_marks(4);
764 return; 745 return;
765 } 746 }
@@ -774,17 +755,16 @@ static s_stat* init_fd(const char *param UNUSED_PARAM)
774 return (s_stat*)s; 755 return (s_stat*)s;
775} 756}
776 757
777
778S_STAT(time_stat) 758S_STAT(time_stat)
779 int prec; 759 unsigned prec;
780 int scale; 760 unsigned scale;
781S_STAT_END(time_stat) 761S_STAT_END(time_stat)
782 762
783static void FAST_FUNC collect_time(time_stat *s) 763static void FAST_FUNC collect_time(time_stat *s)
784{ 764{
785 char buf[sizeof("12:34:56.123456")]; 765 char buf[sizeof("12:34:56.123456")];
786 struct tm* tm; 766 struct tm* tm;
787 int us = tv.tv_usec + s->scale/2; 767 unsigned us = tv.tv_usec + s->scale/2;
788 time_t t = tv.tv_sec; 768 time_t t = tv.tv_sec;
789 769
790 if (us >= 1000000) { 770 if (us >= 1000000) {
@@ -825,11 +805,9 @@ static void FAST_FUNC collect_info(s_stat *s)
825 } 805 }
826} 806}
827 807
828
829typedef s_stat* init_func(const char *param); 808typedef s_stat* init_func(const char *param);
830 809
831// Deprecated %NNNd is to be removed, -d MSEC supersedes it 810static const char options[] ALIGN1 = "ncmsfixptbr";
832static const char options[] ALIGN1 = "ncmsfixptbdr";
833static init_func *const init_functions[] = { 811static init_func *const init_functions[] = {
834 init_if, 812 init_if,
835 init_cpu, 813 init_cpu,
@@ -841,7 +819,6 @@ static init_func *const init_functions[] = {
841 init_fork, 819 init_fork,
842 init_time, 820 init_time,
843 init_blk, 821 init_blk,
844 init_delay,
845 init_cr 822 init_cr
846}; 823};
847 824
@@ -864,8 +841,11 @@ int nmeter_main(int argc UNUSED_PARAM, char **argv)
864 is26 = (strstr(buf, " 2.4.") == NULL); 841 is26 = (strstr(buf, " 2.4.") == NULL);
865 } 842 }
866 843
867 if (getopt32(argv, "d:", &opt_d)) 844 if (getopt32(argv, "d:", &opt_d)) {
868 init_delay(opt_d); 845 G.delta = xatoi(opt_d) * 1000;
846 G.deltanz = G.delta > 0 ? G.delta : 1;
847 need_seconds = (1000000 % G.deltanz) != 0;
848 }
869 argv += optind; 849 argv += optind;
870 850
871 if (!argv[0]) 851 if (!argv[0])
@@ -920,8 +900,8 @@ int nmeter_main(int argc UNUSED_PARAM, char **argv)
920 last->next = s; 900 last->next = s;
921 last = s; 901 last = s;
922 } else { 902 } else {
923 // %NNNNd or %r option. remove it from string 903 // %r option. remove it from string
924 strcpy(prev + strlen(prev), cur); 904 overlapping_strcpy(prev + strlen(prev), cur);
925 cur = prev; 905 cur = prev;
926 } 906 }
927 } 907 }
@@ -939,15 +919,15 @@ int nmeter_main(int argc UNUSED_PARAM, char **argv)
939 // Generate first samples but do not print them, they're bogus 919 // Generate first samples but do not print them, they're bogus
940 collect_info(first); 920 collect_info(first);
941 reset_outbuf(); 921 reset_outbuf();
942 if (delta >= 0) { 922 if (G.delta >= 0) {
943 gettimeofday(&tv, NULL); 923 gettimeofday(&tv, NULL);
944 usleep(delta > 1000000 ? 1000000 : delta - tv.tv_usec%deltanz); 924 usleep(G.delta > 1000000 ? 1000000 : G.delta - tv.tv_usec % G.deltanz);
945 } 925 }
946 926
947 while (1) { 927 while (1) {
948 gettimeofday(&tv, NULL); 928 gettimeofday(&tv, NULL);
949 collect_info(first); 929 collect_info(first);
950 put(final_str); 930 put_c(G.final_char);
951 print_outbuf(); 931 print_outbuf();
952 932
953 // Negative delta -> no usleep at all 933 // Negative delta -> no usleep at all
@@ -955,18 +935,18 @@ int nmeter_main(int argc UNUSED_PARAM, char **argv)
955 // time resolution ;) 935 // time resolution ;)
956 // TODO: detect and avoid useless updates 936 // TODO: detect and avoid useless updates
957 // (like: nothing happens except time) 937 // (like: nothing happens except time)
958 if (delta >= 0) { 938 if (G.delta >= 0) {
959 int rem; 939 int rem;
960 // can be commented out, will sacrifice sleep time precision a bit 940 // can be commented out, will sacrifice sleep time precision a bit
961 gettimeofday(&tv, NULL); 941 gettimeofday(&tv, NULL);
962 if (need_seconds) 942 if (need_seconds)
963 rem = delta - ((ullong)tv.tv_sec*1000000 + tv.tv_usec) % deltanz; 943 rem = G.delta - ((ullong)tv.tv_sec*1000000 + tv.tv_usec) % G.deltanz;
964 else 944 else
965 rem = delta - tv.tv_usec%deltanz; 945 rem = G.delta - (unsigned)tv.tv_usec % G.deltanz;
966 // Sometimes kernel wakes us up just a tiny bit earlier than asked 946 // Sometimes kernel wakes us up just a tiny bit earlier than asked
967 // Do not go to very short sleep in this case 947 // Do not go to very short sleep in this case
968 if (rem < delta/128) { 948 if (rem < (unsigned)G.delta / 128) {
969 rem += delta; 949 rem += G.delta;
970 } 950 }
971 usleep(rem); 951 usleep(rem);
972 } 952 }
diff --git a/procps/renice.c b/procps/renice.c
index 77f400a1d..2b690e0ed 100644
--- a/procps/renice.c
+++ b/procps/renice.c
@@ -20,13 +20,14 @@
20 */ 20 */
21 21
22//usage:#define renice_trivial_usage 22//usage:#define renice_trivial_usage
23//usage: "{{-n INCREMENT} | PRIORITY} [[-p | -g | -u] ID...]" 23//usage: "[-n] PRIORITY [[-p | -g | -u] ID...]..."
24//usage:#define renice_full_usage "\n\n" 24//usage:#define renice_full_usage "\n\n"
25//usage: "Change scheduling priority for a running process\n" 25//usage: "Change scheduling priority of a running process\n"
26//usage: "\n -n Adjust current nice value (smaller is faster)" 26//usage: "\n -n Add PRIORITY to current nice value"
27//usage: "\n -p Process id(s) (default)" 27//usage: "\n Without -n, nice value is set to PRIORITY"
28//usage: "\n -g Process group id(s)" 28//usage: "\n -p Process ids (default)"
29//usage: "\n -u Process user name(s) and/or id(s)" 29//usage: "\n -g Process group ids"
30//usage: "\n -u Process user names"
30 31
31#include "libbb.h" 32#include "libbb.h"
32#include <sys/resource.h> 33#include <sys/resource.h>
diff --git a/runit/chpst.c b/runit/chpst.c
index 301cdd08a..7fe5151db 100644
--- a/runit/chpst.c
+++ b/runit/chpst.c
@@ -255,8 +255,7 @@ static NOINLINE void edir(const char *directory_name)
255 xsetenv(d->d_name, buf); 255 xsetenv(d->d_name, buf);
256 } 256 }
257 closedir(dir); 257 closedir(dir);
258 if (fchdir(wdir) == -1) 258 xfchdir(wdir);
259 bb_perror_msg_and_die("fchdir");
260 close(wdir); 259 close(wdir);
261} 260}
262 261
diff --git a/scripts/kconfig/lxdialog/check-lxdialog.sh b/scripts/kconfig/lxdialog/check-lxdialog.sh
index d34dfd46d..5075ebf2d 100644..100755
--- a/scripts/kconfig/lxdialog/check-lxdialog.sh
+++ b/scripts/kconfig/lxdialog/check-lxdialog.sh
@@ -4,7 +4,9 @@
4# What library to link 4# What library to link
5ldflags() 5ldflags()
6{ 6{
7 for ext in so a dylib ; do 7 pkg-config --libs ncursesw 2>/dev/null && exit
8 pkg-config --libs ncurses 2>/dev/null && exit
9 for ext in so a dll.a dylib ; do
8 for lib in ncursesw ncurses curses ; do 10 for lib in ncursesw ncurses curses ; do
9 $cc -print-file-name=lib${lib}.${ext} | grep -q / 11 $cc -print-file-name=lib${lib}.${ext} | grep -q /
10 if [ $? -eq 0 ]; then 12 if [ $? -eq 0 ]; then
@@ -19,14 +21,17 @@ ldflags()
19# Where is ncurses.h? 21# Where is ncurses.h?
20ccflags() 22ccflags()
21{ 23{
22 if [ -f /usr/include/ncursesw/ncurses.h ]; then 24 if pkg-config --cflags ncursesw 2>/dev/null; then
23 echo '-I/usr/include/ncursesw -DCURSES_LOC="<ncurses.h>"' 25 echo '-DCURSES_LOC="<ncurses.h>" -DNCURSES_WIDECHAR=1'
26 elif pkg-config --cflags ncurses 2>/dev/null; then
27 echo '-DCURSES_LOC="<ncurses.h>"'
24 elif [ -f /usr/include/ncursesw/curses.h ]; then 28 elif [ -f /usr/include/ncursesw/curses.h ]; then
25 echo '-I/usr/include/ncursesw -DCURSES_LOC="<ncursesw/curses.h>"' 29 echo '-I/usr/include/ncursesw -DCURSES_LOC="<curses.h>"'
30 echo ' -DNCURSES_WIDECHAR=1'
26 elif [ -f /usr/include/ncurses/ncurses.h ]; then 31 elif [ -f /usr/include/ncurses/ncurses.h ]; then
27 echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"' 32 echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"'
28 elif [ -f /usr/include/ncurses/curses.h ]; then 33 elif [ -f /usr/include/ncurses/curses.h ]; then
29 echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"' 34 echo '-I/usr/include/ncurses -DCURSES_LOC="<curses.h>"'
30 elif [ -f /usr/include/ncurses.h ]; then 35 elif [ -f /usr/include/ncurses.h ]; then
31 echo '-DCURSES_LOC="<ncurses.h>"' 36 echo '-DCURSES_LOC="<ncurses.h>"'
32 else 37 else
@@ -40,7 +45,7 @@ trap "rm -f $tmp" 0 1 2 3 15
40 45
41# Check if we can link to ncurses 46# Check if we can link to ncurses
42check() { 47check() {
43 $cc -xc - -o $tmp 2>/dev/null <<'EOF' 48 $cc -x c - -o $tmp 2>/dev/null <<'EOF'
44#include CURSES_LOC 49#include CURSES_LOC
45main() {} 50main() {}
46EOF 51EOF
diff --git a/scripts/trylink b/scripts/trylink
index 3c431edc3..15435f009 100755
--- a/scripts/trylink
+++ b/scripts/trylink
@@ -140,6 +140,8 @@ try $CC $CFLAGS $LDFLAGS \
140|| { 140|| {
141 echo "Failed: $l_list" 141 echo "Failed: $l_list"
142 cat $EXE.out 142 cat $EXE.out
143 echo 'Note: if build needs additional libraries, put them in CONFIG_EXTRA_LDLIBS.'
144 echo 'Example: CONFIG_EXTRA_LDLIBS="pthread dl tirpc audit pam"'
143 exit 1 145 exit 1
144} 146}
145 147
diff --git a/selinux/setfiles.c b/selinux/setfiles.c
index c974c4a9d..de99dfe44 100644
--- a/selinux/setfiles.c
+++ b/selinux/setfiles.c
@@ -17,6 +17,7 @@
17//usage: ) 17//usage: )
18//usage: "\n -d Show which specification matched each file" 18//usage: "\n -d Show which specification matched each file"
19//usage: "\n -l Log changes in file labels to syslog" 19//usage: "\n -l Log changes in file labels to syslog"
20//TODO: log to syslog is not yet implemented, it goes to stdout only now
20//usage: "\n -n Don't change any file labels" 21//usage: "\n -n Don't change any file labels"
21//usage: "\n -q Suppress warnings" 22//usage: "\n -q Suppress warnings"
22//usage: "\n -r DIR Use an alternate root path" 23//usage: "\n -r DIR Use an alternate root path"
@@ -383,16 +384,16 @@ static int restore(const char *file)
383 * the user has changed but the role and type are the 384 * the user has changed but the role and type are the
384 * same. For "-vv", emit everything. */ 385 * same. For "-vv", emit everything. */
385 if (verbose > 1 || !user_only_changed) { 386 if (verbose > 1 || !user_only_changed) {
386 bb_info_msg("%s: reset %s context %s->%s", 387 printf("%s: reset %s context %s->%s\n",
387 applet_name, my_file, context ? context : "", newcon); 388 applet_name, my_file, context ? context : "", newcon);
388 } 389 }
389 } 390 }
390 391
391 if (FLAG_l_take_log && !user_only_changed) { 392 if (FLAG_l_take_log && !user_only_changed) {
392 if (context) 393 if (context)
393 bb_info_msg("relabeling %s from %s to %s", my_file, context, newcon); 394 printf("relabeling %s from %s to %s\n", my_file, context, newcon);
394 else 395 else
395 bb_info_msg("labeling %s to %s", my_file, newcon); 396 printf("labeling %s to %s\n", my_file, newcon);
396 } 397 }
397 398
398 if (outfile && !user_only_changed) 399 if (outfile && !user_only_changed)
diff --git a/shell/ash.c b/shell/ash.c
index 57d192822..7cad34511 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -7026,6 +7026,8 @@ varvalue(char *name, int varflags, int flags, struct strlist *var_str_list)
7026 if (subtype == VSLENGTH && len > 0) { 7026 if (subtype == VSLENGTH && len > 0) {
7027 reinit_unicode_for_ash(); 7027 reinit_unicode_for_ash();
7028 if (unicode_status == UNICODE_ON) { 7028 if (unicode_status == UNICODE_ON) {
7029 STADJUST(-len, expdest);
7030 discard = 0;
7029 len = unicode_strlen(p); 7031 len = unicode_strlen(p);
7030 } 7032 }
7031 } 7033 }
diff --git a/shell/ash_test/.gitignore b/shell/ash_test/.gitignore
new file mode 100644
index 000000000..a1f937cdd
--- /dev/null
+++ b/shell/ash_test/.gitignore
@@ -0,0 +1,7 @@
1/ash
2/printenv
3/recho
4/zecho
5
6/*.fail
7*.xx
diff --git a/shell/ash_test/ash-vars/var-utf8-length.right b/shell/ash_test/ash-vars/var-utf8-length.right
new file mode 100644
index 000000000..6f4247a62
--- /dev/null
+++ b/shell/ash_test/ash-vars/var-utf8-length.right
@@ -0,0 +1 @@
26
diff --git a/shell/ash_test/ash-vars/var-utf8-length.tests b/shell/ash_test/ash-vars/var-utf8-length.tests
new file mode 100755
index 000000000..d04b2cbb6
--- /dev/null
+++ b/shell/ash_test/ash-vars/var-utf8-length.tests
@@ -0,0 +1,2 @@
1X=abcdÉfghÍjklmnÓpqrstÚvwcyz
2echo ${#X}
diff --git a/shell/ash_test/printenv.c b/shell/ash_test/printenv.c
index c4ccda8a6..c0c5e197c 100644
--- a/shell/ash_test/printenv.c
+++ b/shell/ash_test/printenv.c
@@ -24,6 +24,7 @@
24 with Bash; see the file COPYING. If not, write to the Free Software 24 with Bash; see the file COPYING. If not, write to the Free Software
25 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ 25 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
26 26
27#include <stdio.h>
27#include <stdlib.h> 28#include <stdlib.h>
28#include <string.h> 29#include <string.h>
29 30
diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c
index 0ea557a6c..a119bdeae 100644
--- a/sysklogd/syslogd.c
+++ b/sysklogd/syslogd.c
@@ -33,7 +33,7 @@
33//config: depends on SYSLOGD 33//config: depends on SYSLOGD
34//config: help 34//config: help
35//config: This enables syslogd to rotate the message files 35//config: This enables syslogd to rotate the message files
36//config: on his own. No need to use an external rotatescript. 36//config: on his own. No need to use an external rotate script.
37//config: 37//config:
38//config:config FEATURE_REMOTE_LOG 38//config:config FEATURE_REMOTE_LOG
39//config: bool "Remote Log support" 39//config: bool "Remote Log support"
@@ -133,7 +133,7 @@
133//usage: IF_FEATURE_KMSG_SYSLOG( 133//usage: IF_FEATURE_KMSG_SYSLOG(
134//usage: "\n -K Log to kernel printk buffer (use dmesg to read it)" 134//usage: "\n -K Log to kernel printk buffer (use dmesg to read it)"
135//usage: ) 135//usage: )
136//usage: "\n -O FILE Log to FILE (default:/var/log/messages, stdout if -)" 136//usage: "\n -O FILE Log to FILE (default: /var/log/messages, stdout if -)"
137//usage: IF_FEATURE_ROTATE_LOGFILE( 137//usage: IF_FEATURE_ROTATE_LOGFILE(
138//usage: "\n -s SIZE Max size (KB) before rotation (default:200KB, 0=off)" 138//usage: "\n -s SIZE Max size (KB) before rotation (default:200KB, 0=off)"
139//usage: "\n -b N N rotated logs to keep (default:1, max=99, 0=purge)" 139//usage: "\n -b N N rotated logs to keep (default:1, max=99, 0=purge)"
diff --git a/util-linux/fbset.c b/util-linux/fbset.c
index ac0082f70..09e96b763 100644
--- a/util-linux/fbset.c
+++ b/util-linux/fbset.c
@@ -248,12 +248,12 @@ static int read_mode_db(struct fb_var_screeninfo *base, const char *fn,
248 if (!p) 248 if (!p)
249 continue; 249 continue;
250 s = p + strlen(mode); 250 s = p + strlen(mode);
251 //bb_info_msg("CHECK[%s][%s][%d]", mode, p-1, *s); 251 //bb_error_msg("CHECK[%s][%s][%d]", mode, p-1, *s);
252 /* exact match? */ 252 /* exact match? */
253 if (((!*s || isspace(*s)) && '"' != s[-1]) /* end-of-token */ 253 if (((!*s || isspace(*s)) && '"' != s[-1]) /* end-of-token */
254 || ('"' == *s && '"' == p[-1]) /* ends with " but starts with " too! */ 254 || ('"' == *s && '"' == p[-1]) /* ends with " but starts with " too! */
255 ) { 255 ) {
256 //bb_info_msg("FOUND[%s][%s][%s][%d]", token[1], p, mode, isspace(*s)); 256 //bb_error_msg("FOUND[%s][%s][%s][%d]", token[1], p, mode, isspace(*s));
257 break; 257 break;
258 } 258 }
259 } 259 }
@@ -264,9 +264,9 @@ static int read_mode_db(struct fb_var_screeninfo *base, const char *fn,
264 while (config_read(parser, token, 2, 1, "# \t", PARSE_NORMAL)) { 264 while (config_read(parser, token, 2, 1, "# \t", PARSE_NORMAL)) {
265 int i; 265 int i;
266 266
267//bb_info_msg("???[%s][%s]", token[0], token[1]); 267//bb_error_msg("???[%s][%s]", token[0], token[1]);
268 if (strcmp(token[0], "endmode") == 0) { 268 if (strcmp(token[0], "endmode") == 0) {
269//bb_info_msg("OK[%s]", mode); 269//bb_error_msg("OK[%s]", mode);
270 return 1; 270 return 1;
271 } 271 }
272 p = token[1]; 272 p = token[1];
@@ -294,7 +294,7 @@ static int read_mode_db(struct fb_var_screeninfo *base, const char *fn,
294 base->yres_virtual = base_yres_virtual; 294 base->yres_virtual = base_yres_virtual;
295 base->bits_per_pixel = base_bits_per_pixel; 295 base->bits_per_pixel = base_bits_per_pixel;
296 } 296 }
297//bb_info_msg("GEO[%s]", p); 297//bb_error_msg("GEO[%s]", p);
298 break; 298 break;
299 case 1: 299 case 1:
300 if (sizeof(int) == sizeof(base->xres)) { 300 if (sizeof(int) == sizeof(base->xres)) {
@@ -321,13 +321,13 @@ static int read_mode_db(struct fb_var_screeninfo *base, const char *fn,
321 base->hsync_len = base_hsync_len; 321 base->hsync_len = base_hsync_len;
322 base->vsync_len = base_vsync_len; 322 base->vsync_len = base_vsync_len;
323 } 323 }
324//bb_info_msg("TIM[%s]", p); 324//bb_error_msg("TIM[%s]", p);
325 break; 325 break;
326 case 2: 326 case 2:
327 case 3: { 327 case 3: {
328 static const uint32_t syncs[] = {FB_VMODE_INTERLACED, FB_VMODE_DOUBLE}; 328 static const uint32_t syncs[] = {FB_VMODE_INTERLACED, FB_VMODE_DOUBLE};
329 ss(&base->vmode, syncs[i-2], p, "false"); 329 ss(&base->vmode, syncs[i-2], p, "false");
330//bb_info_msg("VMODE[%s]", p); 330//bb_error_msg("VMODE[%s]", p);
331 break; 331 break;
332 } 332 }
333 case 4: 333 case 4:
@@ -335,12 +335,12 @@ static int read_mode_db(struct fb_var_screeninfo *base, const char *fn,
335 case 6: { 335 case 6: {
336 static const uint32_t syncs[] = {FB_SYNC_VERT_HIGH_ACT, FB_SYNC_HOR_HIGH_ACT, FB_SYNC_COMP_HIGH_ACT}; 336 static const uint32_t syncs[] = {FB_SYNC_VERT_HIGH_ACT, FB_SYNC_HOR_HIGH_ACT, FB_SYNC_COMP_HIGH_ACT};
337 ss(&base->sync, syncs[i-4], p, "low"); 337 ss(&base->sync, syncs[i-4], p, "low");
338//bb_info_msg("SYNC[%s]", p); 338//bb_error_msg("SYNC[%s]", p);
339 break; 339 break;
340 } 340 }
341 case 7: 341 case 7:
342 ss(&base->sync, FB_SYNC_EXT, p, "false"); 342 ss(&base->sync, FB_SYNC_EXT, p, "false");
343//bb_info_msg("EXTSYNC[%s]", p); 343//bb_error_msg("EXTSYNC[%s]", p);
344 break; 344 break;
345 case 8: { 345 case 8: {
346 int red_offset, red_length; 346 int red_offset, red_length;
diff --git a/util-linux/minix.h b/util-linux/minix.h
index e0fbcf761..83ffe6da5 100644
--- a/util-linux/minix.h
+++ b/util-linux/minix.h
@@ -61,9 +61,14 @@ enum {
61 MINIX_ROOT_INO = 1, 61 MINIX_ROOT_INO = 1,
62 MINIX_BAD_INO = 2, 62 MINIX_BAD_INO = 2,
63 63
64#undef MINIX1_SUPER_MAGIC
64 MINIX1_SUPER_MAGIC = 0x137F, /* original minix fs */ 65 MINIX1_SUPER_MAGIC = 0x137F, /* original minix fs */
66#undef MINIX1_SUPER_MAGIC2
65 MINIX1_SUPER_MAGIC2 = 0x138F, /* minix fs, 30 char names */ 67 MINIX1_SUPER_MAGIC2 = 0x138F, /* minix fs, 30 char names */
68/* bionic has this define */
69#undef MINIX2_SUPER_MAGIC
66 MINIX2_SUPER_MAGIC = 0x2468, /* minix V2 fs */ 70 MINIX2_SUPER_MAGIC = 0x2468, /* minix V2 fs */
71#undef MINIX2_SUPER_MAGIC2
67 MINIX2_SUPER_MAGIC2 = 0x2478, /* minix V2 fs, 30 char names */ 72 MINIX2_SUPER_MAGIC2 = 0x2478, /* minix V2 fs, 30 char names */
68 MINIX_VALID_FS = 0x0001, /* clean fs */ 73 MINIX_VALID_FS = 0x0001, /* clean fs */
69 MINIX_ERROR_FS = 0x0002, /* fs has errors */ 74 MINIX_ERROR_FS = 0x0002, /* fs has errors */
diff --git a/util-linux/mkfs_ext2.c b/util-linux/mkfs_ext2.c
index 3258d7eee..f91a0b4bf 100644
--- a/util-linux/mkfs_ext2.c
+++ b/util-linux/mkfs_ext2.c
@@ -116,7 +116,7 @@ static void allocate(uint8_t *bitmap, uint32_t blocksize, uint32_t start, uint32
116{ 116{
117 uint32_t i; 117 uint32_t i;
118 118
119//bb_info_msg("ALLOC: [%u][%u][%u]: [%u-%u]:=[%x],[%x]", blocksize, start, end, start/8, blocksize - end/8 - 1, (1 << (start & 7)) - 1, (uint8_t)(0xFF00 >> (end & 7))); 119//bb_error_msg("ALLOC: [%u][%u][%u]: [%u-%u]:=[%x],[%x]", blocksize, start, end, start/8, blocksize - end/8 - 1, (1 << (start & 7)) - 1, (uint8_t)(0xFF00 >> (end & 7)));
120 memset(bitmap, 0, blocksize); 120 memset(bitmap, 0, blocksize);
121 i = start / 8; 121 i = start / 8;
122 memset(bitmap, 0xFF, i); 122 memset(bitmap, 0xFF, i);
@@ -151,7 +151,7 @@ static uint32_t has_super(uint32_t x)
151 151
152static void PUT(uint64_t off, void *buf, uint32_t size) 152static void PUT(uint64_t off, void *buf, uint32_t size)
153{ 153{
154// bb_info_msg("PUT[%llu]:[%u]", off, size); 154 //bb_error_msg("PUT[%llu]:[%u]", off, size);
155 xlseek(fd, off, SEEK_SET); 155 xlseek(fd, off, SEEK_SET);
156 xwrite(fd, buf, size); 156 xwrite(fd, buf, size);
157} 157}
@@ -412,7 +412,7 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
412 // (a bit after 8M image size), but it works for two->three groups 412 // (a bit after 8M image size), but it works for two->three groups
413 // transition (at 16M). 413 // transition (at 16M).
414 if (remainder && (remainder < overhead + 50)) { 414 if (remainder && (remainder < overhead + 50)) {
415//bb_info_msg("CHOP[%u]", remainder); 415//bb_error_msg("CHOP[%u]", remainder);
416 nblocks -= remainder; 416 nblocks -= remainder;
417 goto retry; 417 goto retry;
418 } 418 }
@@ -568,7 +568,7 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
568 free_blocks = (n < blocks_per_group ? n : blocks_per_group) - overhead; 568 free_blocks = (n < blocks_per_group ? n : blocks_per_group) - overhead;
569 569
570 // mark preallocated blocks as allocated 570 // mark preallocated blocks as allocated
571//bb_info_msg("ALLOC: [%u][%u][%u]", blocksize, overhead, blocks_per_group - (free_blocks + overhead)); 571//bb_error_msg("ALLOC: [%u][%u][%u]", blocksize, overhead, blocks_per_group - (free_blocks + overhead));
572 allocate(buf, blocksize, 572 allocate(buf, blocksize,
573 // reserve "overhead" blocks 573 // reserve "overhead" blocks
574 overhead, 574 overhead,
@@ -647,7 +647,7 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
647 n = FETCH_LE32(inode->i_block[0]) + 1; 647 n = FETCH_LE32(inode->i_block[0]) + 1;
648 for (i = 0; i < lost_and_found_blocks; ++i) 648 for (i = 0; i < lost_and_found_blocks; ++i)
649 STORE_LE(inode->i_block[i], i + n); // use next block 649 STORE_LE(inode->i_block[i], i + n); // use next block
650//bb_info_msg("LAST BLOCK USED[%u]", i + n); 650//bb_error_msg("LAST BLOCK USED[%u]", i + n);
651 PUT(((uint64_t)FETCH_LE32(gd[0].bg_inode_table) * blocksize) + (EXT2_GOOD_OLD_FIRST_INO-1) * inodesize, 651 PUT(((uint64_t)FETCH_LE32(gd[0].bg_inode_table) * blocksize) + (EXT2_GOOD_OLD_FIRST_INO-1) * inodesize,
652 buf, inodesize); 652 buf, inodesize);
653 653
diff --git a/util-linux/mkfs_vfat.c b/util-linux/mkfs_vfat.c
index 7d81ed06d..d53c751eb 100644
--- a/util-linux/mkfs_vfat.c
+++ b/util-linux/mkfs_vfat.c
@@ -578,7 +578,7 @@ int mkfs_vfat_main(int argc UNUSED_PARAM, char **argv)
578 start_data_sector = (reserved_sect + NUM_FATS * sect_per_fat) * (bytes_per_sect / SECTOR_SIZE); 578 start_data_sector = (reserved_sect + NUM_FATS * sect_per_fat) * (bytes_per_sect / SECTOR_SIZE);
579 start_data_block = (start_data_sector + SECTORS_PER_BLOCK - 1) / SECTORS_PER_BLOCK; 579 start_data_block = (start_data_sector + SECTORS_PER_BLOCK - 1) / SECTORS_PER_BLOCK;
580 580
581 bb_info_msg("searching for bad blocks "); 581 bb_error_msg("searching for bad blocks");
582 currently_testing = 0; 582 currently_testing = 0;
583 try = TEST_BUFFER_BLOCKS; 583 try = TEST_BUFFER_BLOCKS;
584 while (currently_testing < volume_size_blocks) { 584 while (currently_testing < volume_size_blocks) {
@@ -616,7 +616,7 @@ int mkfs_vfat_main(int argc UNUSED_PARAM, char **argv)
616 } 616 }
617 free(blkbuf); 617 free(blkbuf);
618 if (badblocks) 618 if (badblocks)
619 bb_info_msg("%d bad block(s)", badblocks); 619 bb_error_msg("%d bad block(s)", badblocks);
620 } 620 }
621#endif 621#endif
622 622
diff --git a/util-linux/nsenter.c b/util-linux/nsenter.c
new file mode 100644
index 000000000..b08b3dae7
--- /dev/null
+++ b/util-linux/nsenter.c
@@ -0,0 +1,291 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Mini nsenter implementation for busybox.
4 *
5 * Copyright (C) 2016 by Bartosz Golaszewski <bartekgola@gmail.com>
6 *
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */
9
10//config:config NSENTER
11//config: bool "nsenter"
12//config: default y
13//config: select PLATFORM_LINUX
14//config: help
15//config: Run program with namespaces of other processes.
16//config:
17//config:config FEATURE_NSENTER_LONG_OPTS
18//config: bool "Enable long options"
19//config: default y
20//config: depends on NSENTER && LONG_OPTS
21//config: help
22//config: Support long options for the nsenter applet. This makes
23//config: the busybox implementation more compatible with upstream.
24
25//applet:IF_NSENTER(APPLET(nsenter, BB_DIR_USR_BIN, BB_SUID_DROP))
26
27//kbuild:lib-$(CONFIG_NSENTER) += nsenter.o
28
29//usage:#define nsenter_trivial_usage
30//usage: "[OPTIONS] [PROG [ARGS]]"
31//usage:#if ENABLE_FEATURE_NSENTER_LONG_OPTS
32//usage:#define nsenter_full_usage "\n"
33//usage: "\n -t, --target=PID Target process to get namespaces from"
34//usage: "\n -m, --mount[=FILE] Enter mount namespace"
35//usage: "\n -u, --uts[=FILE] Enter UTS namespace (hostname etc)"
36//usage: "\n -i, --ipc[=FILE] Enter System V IPC namespace"
37//usage: "\n -n, --net[=FILE] Enter network namespace"
38//usage: "\n -p, --pid[=FILE] Enter pid namespace"
39//usage: "\n -U, --user[=FILE] Enter user namespace"
40//usage: "\n -S, --setuid=UID Set uid in entered namespace"
41//usage: "\n -G, --setgid=GID Set gid in entered namespace"
42//usage: "\n --preserve-credentials Don't touch uids or gids"
43//usage: "\n -r, --root[=DIR] Set root directory"
44//usage: "\n -w, --wd[=DIR] Set working directory"
45//usage: "\n -F, --no-fork Don't fork before exec'ing PROG"
46//usage:#else
47//usage:#define nsenter_full_usage "\n"
48//usage: "\n -t PID Target process to get namespaces from"
49//usage: "\n -m[FILE] Enter mount namespace"
50//usage: "\n -u[FILE] Enter UTS namespace (hostname etc)"
51//usage: "\n -i[FILE] Enter System V IPC namespace"
52//usage: "\n -n[FILE] Enter network namespace"
53//usage: "\n -p[FILE] Enter pid namespace"
54//usage: "\n -U[FILE] Enter user namespace"
55//usage: "\n -S UID Set uid in entered namespace"
56//usage: "\n -G GID Set gid in entered namespace"
57//usage: "\n -r[DIR] Set root directory"
58//usage: "\n -w[DIR] Set working directory"
59//usage: "\n -F Don't fork before exec'ing PROG"
60//usage:#endif
61
62#include <sched.h>
63#ifndef CLONE_NEWUTS
64# define CLONE_NEWUTS 0x04000000
65#endif
66#ifndef CLONE_NEWIPC
67# define CLONE_NEWIPC 0x08000000
68#endif
69#ifndef CLONE_NEWUSER
70# define CLONE_NEWUSER 0x10000000
71#endif
72#ifndef CLONE_NEWPID
73# define CLONE_NEWPID 0x20000000
74#endif
75#ifndef CLONE_NEWNET
76# define CLONE_NEWNET 0x40000000
77#endif
78
79#include "libbb.h"
80
81struct namespace_descr {
82 int flag; /* value passed to setns() */
83 char ns_nsfile8[8]; /* "ns/" + namespace file in process' procfs entry */
84};
85
86struct namespace_ctx {
87 char *path; /* optional path to a custom ns file */
88 int fd; /* opened namespace file descriptor */
89};
90
91enum {
92 OPT_user = 1 << 0,
93 OPT_ipc = 1 << 1,
94 OPT_uts = 1 << 2,
95 OPT_network = 1 << 3,
96 OPT_pid = 1 << 4,
97 OPT_mount = 1 << 5,
98 OPT_target = 1 << 6,
99 OPT_setuid = 1 << 7,
100 OPT_setgid = 1 << 8,
101 OPT_root = 1 << 9,
102 OPT_wd = 1 << 10,
103 OPT_nofork = 1 << 11,
104 OPT_prescred = (1 << 12) * ENABLE_FEATURE_NSENTER_LONG_OPTS,
105};
106enum {
107 NS_USR_POS = 0,
108 NS_IPC_POS,
109 NS_UTS_POS,
110 NS_NET_POS,
111 NS_PID_POS,
112 NS_MNT_POS,
113 NS_COUNT,
114};
115/*
116 * The order is significant in nsenter.
117 * The user namespace comes first, so that it is entered first.
118 * This gives an unprivileged user the potential to enter other namespaces.
119 */
120static const struct namespace_descr ns_list[] = {
121 { CLONE_NEWUSER, "ns/user", },
122 { CLONE_NEWIPC, "ns/ipc", },
123 { CLONE_NEWUTS, "ns/uts", },
124 { CLONE_NEWNET, "ns/net", },
125 { CLONE_NEWPID, "ns/pid", },
126 { CLONE_NEWNS, "ns/mnt", },
127};
128/*
129 * Upstream nsenter doesn't support the short option for --preserve-credentials
130 */
131static const char opt_str[] = "U::i::u::n::p::m::""t+S+G+r::w::F";
132
133#if ENABLE_FEATURE_NSENTER_LONG_OPTS
134static const char nsenter_longopts[] ALIGN1 =
135 "user\0" Optional_argument "U"
136 "ipc\0" Optional_argument "i"
137 "uts\0" Optional_argument "u"
138 "network\0" Optional_argument "n"
139 "pid\0" Optional_argument "p"
140 "mount\0" Optional_argument "m"
141 "target\0" Required_argument "t"
142 "setuid\0" Required_argument "S"
143 "setgid\0" Required_argument "G"
144 "root\0" Optional_argument "r"
145 "wd\0" Optional_argument "w"
146 "no-fork\0" No_argument "F"
147 "preserve-credentials\0" No_argument "\xff"
148 ;
149#endif
150
151/*
152 * Open a file and return the new descriptor. If a full path is provided in
153 * fs_path, then the file to which it points is opened. Otherwise (fd_path is
154 * NULL) the routine builds a path to a procfs file using the following
155 * template: '/proc/<target_pid>/<target_file>'.
156 */
157static int open_by_path_or_target(const char *path,
158 pid_t target_pid, const char *target_file)
159{
160 char proc_path_buf[sizeof("/proc/%u/1234567890") + sizeof(int)*3];
161
162 if (!path) {
163 if (target_pid == 0) {
164 /* Example:
165 * "nsenter -p PROG" - neither -pFILE nor -tPID given.
166 */
167 bb_show_usage();
168 }
169 snprintf(proc_path_buf, sizeof(proc_path_buf),
170 "/proc/%u/%s", (unsigned)target_pid, target_file);
171 path = proc_path_buf;
172 }
173
174 return xopen(path, O_RDONLY);
175}
176
177int nsenter_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
178int nsenter_main(int argc UNUSED_PARAM, char **argv)
179{
180 int i;
181 unsigned int opts;
182 const char *root_dir_str = NULL;
183 const char *wd_str = NULL;
184 struct namespace_ctx ns_ctx_list[NS_COUNT];
185 int setgroups_failed;
186 int root_fd, wd_fd;
187 int target_pid = 0;
188 int uid = 0;
189 int gid = 0;
190
191 memset(ns_ctx_list, 0, sizeof(ns_ctx_list));
192
193 IF_FEATURE_NSENTER_LONG_OPTS(applet_long_options = nsenter_longopts);
194 opts = getopt32(argv, opt_str,
195 &ns_ctx_list[NS_USR_POS].path,
196 &ns_ctx_list[NS_IPC_POS].path,
197 &ns_ctx_list[NS_UTS_POS].path,
198 &ns_ctx_list[NS_NET_POS].path,
199 &ns_ctx_list[NS_PID_POS].path,
200 &ns_ctx_list[NS_MNT_POS].path,
201 &target_pid, &uid, &gid,
202 &root_dir_str, &wd_str
203 );
204 argv += optind;
205
206 root_fd = wd_fd = -1;
207 if (opts & OPT_root)
208 root_fd = open_by_path_or_target(root_dir_str,
209 target_pid, "root");
210 if (opts & OPT_wd)
211 wd_fd = open_by_path_or_target(wd_str, target_pid, "cwd");
212
213 for (i = 0; i < NS_COUNT; i++) {
214 const struct namespace_descr *ns = &ns_list[i];
215 struct namespace_ctx *ns_ctx = &ns_ctx_list[i];
216
217 ns_ctx->fd = -1;
218 if (opts & (1 << i))
219 ns_ctx->fd = open_by_path_or_target(ns_ctx->path,
220 target_pid, ns->ns_nsfile8);
221 }
222
223 /*
224 * Entering the user namespace without --preserve-credentials implies
225 * --setuid & --setgid and clearing root's groups.
226 */
227 setgroups_failed = 0;
228 if ((opts & OPT_user) && !(opts & OPT_prescred)) {
229 opts |= (OPT_setuid | OPT_setgid);
230 /*
231 * We call setgroups() before and after setns() and only
232 * bail-out if it fails twice.
233 */
234 setgroups_failed = (setgroups(0, NULL) < 0);
235 }
236
237 for (i = 0; i < NS_COUNT; i++) {
238 const struct namespace_descr *ns = &ns_list[i];
239 struct namespace_ctx *ns_ctx = &ns_ctx_list[i];
240
241 if (ns_ctx->fd < 0)
242 continue;
243 if (setns(ns_ctx->fd, ns->flag)) {
244 bb_perror_msg_and_die(
245 "setns(): can't reassociate to namespace '%s'",
246 ns->ns_nsfile8 + 3 /* skip over "ns/" */
247 );
248 }
249 close(ns_ctx->fd); /* should close fds, to not confuse exec'ed PROG */
250 /*ns_ctx->fd = -1;*/
251 }
252
253 if (root_fd >= 0) {
254 if (wd_fd < 0) {
255 /*
256 * Save the current working directory if we're not
257 * changing it.
258 */
259 wd_fd = xopen(".", O_RDONLY);
260 }
261 xfchdir(root_fd);
262 xchroot(".");
263 close(root_fd);
264 /*root_fd = -1;*/
265 }
266
267 if (wd_fd >= 0) {
268 xfchdir(wd_fd);
269 close(wd_fd);
270 /*wd_fd = -1;*/
271 }
272
273 /*
274 * Entering the pid namespace implies forking unless it's been
275 * explicitly requested by the user not to.
276 */
277 if (!(opts & OPT_nofork) && (opts & OPT_pid)) {
278 xvfork_parent_waits_and_exits();
279 /* Child continues */
280 }
281
282 if (opts & OPT_setgid) {
283 if (setgroups(0, NULL) < 0 && setgroups_failed)
284 bb_perror_msg_and_die("setgroups");
285 xsetgid(gid);
286 }
287 if (opts & OPT_setuid)
288 xsetuid(uid);
289
290 exec_prog_or_SHELL(argv);
291}
diff --git a/util-linux/umount.c b/util-linux/umount.c
index 00910977d..30bef1686 100644
--- a/util-linux/umount.c
+++ b/util-linux/umount.c
@@ -30,6 +30,9 @@
30 30
31#include <mntent.h> 31#include <mntent.h>
32#include <sys/mount.h> 32#include <sys/mount.h>
33#ifndef MNT_DETACH
34# define MNT_DETACH 0x00000002
35#endif
33#include "libbb.h" 36#include "libbb.h"
34 37
35#if defined(__dietlibc__) 38#if defined(__dietlibc__)
diff --git a/util-linux/unshare.c b/util-linux/unshare.c
new file mode 100644
index 000000000..d05cfdb6c
--- /dev/null
+++ b/util-linux/unshare.c
@@ -0,0 +1,380 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Mini unshare implementation for busybox.
4 *
5 * Copyright (C) 2016 by Bartosz Golaszewski <bartekgola@gmail.com>
6 *
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */
9
10//config:config UNSHARE
11//config: bool "unshare"
12//config: default y
13//config: depends on LONG_OPTS && !NOMMU
14//config: select PLATFORM_LINUX
15//config: help
16//config: Run program with some namespaces unshared from parent.
17
18// depends on LONG_OPTS: it is awkward to exclude code which handles --propagation
19// and --setgroups based on LONG_OPTS, so instead applet requires LONG_OPTS.
20// depends on !NOMMU: we need fork()
21
22//applet:IF_UNSHARE(APPLET(unshare, BB_DIR_USR_BIN, BB_SUID_DROP))
23
24//kbuild:lib-$(CONFIG_UNSHARE) += unshare.o
25
26//usage:#define unshare_trivial_usage
27//usage: "[OPTIONS] [PROG [ARGS]]"
28//usage:#define unshare_full_usage "\n"
29//usage: "\n -m, --mount[=FILE] Unshare mount namespace"
30//usage: "\n -u, --uts[=FILE] Unshare UTS namespace (hostname etc.)"
31//usage: "\n -i, --ipc[=FILE] Unshare System V IPC namespace"
32//usage: "\n -n, --net[=FILE] Unshare network namespace"
33//usage: "\n -p, --pid[=FILE] Unshare PID namespace"
34//usage: "\n -U, --user[=FILE} Unshare user namespace"
35//usage: "\n -f, --fork Fork before execing PROG"
36//usage: "\n -r, --map-root-user Map current user to root (implies -u)"
37//usage: "\n --mount-proc[=DIR] Mount /proc filesystem first (implies -m)"
38//usage: "\n --propagation slave|shared|private|unchanged"
39//usage: "\n Modify mount propagation in mount namespace"
40//usage: "\n --setgroups allow|deny Control the setgroups syscall in user namespaces"
41
42#include <sched.h>
43#ifndef CLONE_NEWUTS
44# define CLONE_NEWUTS 0x04000000
45#endif
46#ifndef CLONE_NEWIPC
47# define CLONE_NEWIPC 0x08000000
48#endif
49#ifndef CLONE_NEWUSER
50# define CLONE_NEWUSER 0x10000000
51#endif
52#ifndef CLONE_NEWPID
53# define CLONE_NEWPID 0x20000000
54#endif
55#ifndef CLONE_NEWNET
56# define CLONE_NEWNET 0x40000000
57#endif
58
59#include <sys/mount.h>
60#ifndef MS_REC
61# define MS_REC (1 << 14)
62#endif
63#ifndef MS_PRIVATE
64# define MS_PRIVATE (1 << 18)
65#endif
66#ifndef MS_SLAVE
67# define MS_SLAVE (1 << 19)
68#endif
69#ifndef MS_SHARED
70# define MS_SHARED (1 << 20)
71#endif
72
73#include "libbb.h"
74
75static void mount_or_die(const char *source, const char *target,
76 const char *fstype, unsigned long mountflags)
77{
78 if (mount(source, target, fstype, mountflags, NULL)) {
79 bb_perror_msg_and_die("can't mount %s on %s (flags:0x%lx)",
80 source, target, mountflags);
81 /* fstype is always either NULL or "proc".
82 * "proc" is only used to mount /proc.
83 * No need to clutter up error message with fstype,
84 * it is easily deductible.
85 */
86 }
87}
88
89#define PATH_PROC_SETGROUPS "/proc/self/setgroups"
90#define PATH_PROC_UIDMAP "/proc/self/uid_map"
91#define PATH_PROC_GIDMAP "/proc/self/gid_map"
92
93struct namespace_descr {
94 int flag;
95 const char nsfile4[4];
96};
97
98struct namespace_ctx {
99 char *path;
100};
101
102enum {
103 OPT_mount = 1 << 0,
104 OPT_uts = 1 << 1,
105 OPT_ipc = 1 << 2,
106 OPT_network = 1 << 3,
107 OPT_pid = 1 << 4,
108 OPT_user = 1 << 5, /* OPT_user, NS_USR_POS, and ns_list[] index must match! */
109 OPT_fork = 1 << 6,
110 OPT_map_root = 1 << 7,
111 OPT_mount_proc = 1 << 8,
112 OPT_propagation = 1 << 9,
113 OPT_setgroups = 1 << 10,
114};
115enum {
116 NS_MNT_POS = 0,
117 NS_UTS_POS,
118 NS_IPC_POS,
119 NS_NET_POS,
120 NS_PID_POS,
121 NS_USR_POS, /* OPT_user, NS_USR_POS, and ns_list[] index must match! */
122 NS_COUNT,
123};
124static const struct namespace_descr ns_list[] = {
125 { CLONE_NEWNS, "mnt" },
126 { CLONE_NEWUTS, "uts" },
127 { CLONE_NEWIPC, "ipc" },
128 { CLONE_NEWNET, "net" },
129 { CLONE_NEWPID, "pid" },
130 { CLONE_NEWUSER, "user" }, /* OPT_user, NS_USR_POS, and ns_list[] index must match! */
131};
132
133/*
134 * Upstream unshare doesn't support short options for --mount-proc,
135 * --propagation, --setgroups.
136 * Optional arguments (namespace mountpoints) exist only for long opts,
137 * we are forced to use "fake" letters for them.
138 * '+': stop at first non-option.
139 */
140static const char opt_str[] = "+muinpU""fr""\xfd::""\xfe:""\xff:";
141static const char unshare_longopts[] ALIGN1 =
142 "mount\0" Optional_argument "\xf0"
143 "uts\0" Optional_argument "\xf1"
144 "ipc\0" Optional_argument "\xf2"
145 "network\0" Optional_argument "\xf3"
146 "pid\0" Optional_argument "\xf4"
147 "user\0" Optional_argument "\xf5"
148 "fork\0" No_argument "f"
149 "map-root-user\0" No_argument "r"
150 "mount-proc\0" Optional_argument "\xfd"
151 "propagation\0" Required_argument "\xfe"
152 "setgroups\0" Required_argument "\xff"
153;
154
155/* Ugly-looking string reuse trick */
156#define PRIVATE_STR "private\0""unchanged\0""shared\0""slave\0"
157#define PRIVATE_UNCHANGED_SHARED_SLAVE PRIVATE_STR
158
159static unsigned long parse_propagation(const char *prop_str)
160{
161 int i = index_in_strings(PRIVATE_UNCHANGED_SHARED_SLAVE, prop_str);
162 if (i < 0)
163 bb_error_msg_and_die("unrecognized: --%s=%s", "propagation", prop_str);
164 if (i == 0)
165 return MS_REC | MS_PRIVATE;
166 if (i == 1)
167 return 0;
168 if (i == 2)
169 return MS_REC | MS_SHARED;
170 return MS_REC | MS_SLAVE;
171}
172
173static void mount_namespaces(pid_t pid, struct namespace_ctx *ns_ctx_list)
174{
175 const struct namespace_descr *ns;
176 struct namespace_ctx *ns_ctx;
177 int i;
178
179 for (i = 0; i < NS_COUNT; i++) {
180 char nsf[sizeof("/proc/%u/ns/AAAA") + sizeof(int)*3];
181
182 ns = &ns_list[i];
183 ns_ctx = &ns_ctx_list[i];
184 if (!ns_ctx->path)
185 continue;
186 sprintf(nsf, "/proc/%u/ns/%.4s", (unsigned)pid, ns->nsfile4);
187 mount_or_die(nsf, ns_ctx->path, NULL, MS_BIND);
188 }
189}
190
191int unshare_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
192int unshare_main(int argc UNUSED_PARAM, char **argv)
193{
194 int i;
195 unsigned int opts;
196 int unsflags;
197 uintptr_t need_mount;
198 const char *proc_mnt_target;
199 const char *prop_str;
200 const char *setgrp_str;
201 unsigned long prop_flags;
202 uid_t reuid = geteuid();
203 gid_t regid = getegid();
204 struct fd_pair fdp;
205 pid_t child = child; /* for compiler */
206 struct namespace_ctx ns_ctx_list[NS_COUNT];
207
208 memset(ns_ctx_list, 0, sizeof(ns_ctx_list));
209 proc_mnt_target = "/proc";
210 prop_str = PRIVATE_STR;
211 setgrp_str = NULL;
212
213 opt_complementary =
214 "\xf0""m" /* long opts (via their "fake chars") imply short opts */
215 ":\xf1""u"
216 ":\xf2""i"
217 ":\xf3""n"
218 ":\xf4""p"
219 ":\xf5""U"
220 ":ru" /* --map-root-user or -r implies -u */
221 ":\xfd""m" /* --mount-proc implies -m */
222 ;
223 applet_long_options = unshare_longopts;
224 opts = getopt32(argv, opt_str,
225 &proc_mnt_target, &prop_str, &setgrp_str,
226 &ns_ctx_list[NS_MNT_POS].path,
227 &ns_ctx_list[NS_UTS_POS].path,
228 &ns_ctx_list[NS_IPC_POS].path,
229 &ns_ctx_list[NS_NET_POS].path,
230 &ns_ctx_list[NS_PID_POS].path,
231 &ns_ctx_list[NS_USR_POS].path
232 );
233 argv += optind;
234 //bb_error_msg("opts:0x%x", opts);
235 //bb_error_msg("mount:%s", ns_ctx_list[NS_MNT_POS].path);
236 //bb_error_msg("proc_mnt_target:%s", proc_mnt_target);
237 //bb_error_msg("prop_str:%s", prop_str);
238 //bb_error_msg("setgrp_str:%s", setgrp_str);
239 //exit(1);
240
241 if (setgrp_str) {
242 if (strcmp(setgrp_str, "allow") == 0) {
243 if (opts & OPT_map_root) {
244 bb_error_msg_and_die(
245 "--setgroups=allow and --map-root-user "
246 "are mutually exclusive"
247 );
248 }
249 } else {
250 /* It's not "allow", must be "deny" */
251 if (strcmp(setgrp_str, "deny") != 0)
252 bb_error_msg_and_die("unrecognized: --%s=%s",
253 "setgroups", setgrp_str);
254 }
255 }
256
257 unsflags = 0;
258 need_mount = 0;
259 for (i = 0; i < NS_COUNT; i++) {
260 const struct namespace_descr *ns = &ns_list[i];
261 struct namespace_ctx *ns_ctx = &ns_ctx_list[i];
262
263 if (opts & (1 << i))
264 unsflags |= ns->flag;
265
266 need_mount |= (uintptr_t)(ns_ctx->path);
267 }
268 /* need_mount != 0 if at least one FILE was given */
269
270 prop_flags = MS_REC | MS_PRIVATE;
271 /* Silently ignore --propagation if --mount is not requested. */
272 if (opts & OPT_mount)
273 prop_flags = parse_propagation(prop_str);
274
275 /*
276 * Special case: if we were requested to unshare the mount namespace
277 * AND to make any namespace persistent (by bind mounting it) we need
278 * to spawn a child process which will wait for the parent to call
279 * unshare(), then mount parent's namespaces while still in the
280 * previous namespace.
281 */
282 fdp.wr = -1;
283 if (need_mount && (opts & OPT_mount)) {
284 /*
285 * Can't use getppid() in child, as we can be unsharing the
286 * pid namespace.
287 */
288 pid_t ppid = getpid();
289
290 xpiped_pair(fdp);
291
292 child = xfork();
293 if (child == 0) {
294 /* Child */
295 close(fdp.wr);
296
297 /* Wait until parent calls unshare() */
298 read(fdp.rd, ns_ctx_list, 1); /* ...using bogus buffer */
299 /*close(fdp.rd);*/
300
301 /* Mount parent's unshared namespaces. */
302 mount_namespaces(ppid, ns_ctx_list);
303 return EXIT_SUCCESS;
304 }
305 /* Parent continues */
306 }
307
308 if (unshare(unsflags) != 0)
309 bb_perror_msg_and_die("unshare(0x%x)", unsflags);
310
311 if (fdp.wr >= 0) {
312 close(fdp.wr); /* Release child */
313 close(fdp.rd); /* should close fd, to not confuse exec'ed PROG */
314 }
315
316 if (need_mount) {
317 /* Wait for the child to finish mounting the namespaces. */
318 if (opts & OPT_mount) {
319 int exit_status = wait_for_exitstatus(child);
320 if (WIFEXITED(exit_status) &&
321 WEXITSTATUS(exit_status) != EXIT_SUCCESS)
322 return WEXITSTATUS(exit_status);
323 } else {
324 /*
325 * Regular way - we were requested to mount some other
326 * namespaces: mount them after the call to unshare().
327 */
328 mount_namespaces(getpid(), ns_ctx_list);
329 }
330 }
331
332 /*
333 * When we're unsharing the pid namespace, it's not the process that
334 * calls unshare() that is put into the new namespace, but its first
335 * child. The user may want to use this option to spawn a new process
336 * that'll become PID 1 in this new namespace.
337 */
338 if (opts & OPT_fork) {
339 xvfork_parent_waits_and_exits();
340 /* Child continues */
341 }
342
343 if (opts & OPT_map_root) {
344 char uidmap_buf[sizeof("%u 0 1") + sizeof(int)*3];
345
346 /*
347 * Since Linux 3.19 unprivileged writing of /proc/self/gid_map
348 * has been disabled unless /proc/self/setgroups is written
349 * first to permanently disable the ability to call setgroups
350 * in that user namespace.
351 */
352 xopen_xwrite_close(PATH_PROC_SETGROUPS, "deny");
353 sprintf(uidmap_buf, "%u 0 1", (unsigned)reuid);
354 xopen_xwrite_close(PATH_PROC_UIDMAP, uidmap_buf);
355 sprintf(uidmap_buf, "%u 0 1", (unsigned)regid);
356 xopen_xwrite_close(PATH_PROC_GIDMAP, uidmap_buf);
357 } else
358 if (setgrp_str) {
359 /* Write "allow" or "deny" */
360 xopen_xwrite_close(PATH_PROC_SETGROUPS, setgrp_str);
361 }
362
363 if (opts & OPT_mount) {
364 mount_or_die("none", "/", NULL, prop_flags);
365 }
366
367 if (opts & OPT_mount_proc) {
368 /*
369 * When creating a new pid namespace, we might want the pid
370 * subdirectories in /proc to remain consistent with the new
371 * process IDs. Without --mount-proc the pids in /proc would
372 * still reflect the old pid namespace. This is why we make
373 * /proc private here and then do a fresh mount.
374 */
375 mount_or_die("none", proc_mnt_target, NULL, MS_PRIVATE | MS_REC);
376 mount_or_die("proc", proc_mnt_target, "proc", MS_NOSUID | MS_NOEXEC | MS_NODEV);
377 }
378
379 exec_prog_or_SHELL(argv);
380}