aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--Makefile.flags2
-rw-r--r--archival/bbunzip.c11
-rw-r--r--archival/dpkg.c2
-rw-r--r--archival/dpkg_deb.c2
-rw-r--r--archival/libarchive/Kbuild.src9
-rw-r--r--configs/mingw32_defconfig1
-rw-r--r--configs/mingw64_defconfig1
-rw-r--r--coreutils/Kbuild.src20
-rw-r--r--coreutils/df.c20
-rw-r--r--coreutils/install.c3
-rw-r--r--coreutils/test.c2
-rw-r--r--examples/mdev.conf2
-rw-r--r--examples/var_service/README_distro_proposal.txt291
-rwxr-xr-xinclude/applets.h.sh11
-rw-r--r--include/libbb.h17
-rw-r--r--include/mingw.h2
-rw-r--r--init/init.c2
-rw-r--r--libbb/Config.src2
-rw-r--r--libbb/Kbuild.src8
-rw-r--r--libbb/appletlib.c32
-rw-r--r--libbb/make_directory.c15
-rw-r--r--libbb/update_passwd.c15
-rw-r--r--libbb/xatonum.c19
-rw-r--r--loginutils/login.c4
-rwxr-xr-xmake_single_applets.sh73
-rw-r--r--modutils/Config.src31
-rw-r--r--modutils/depmod.c7
-rw-r--r--modutils/insmod.c7
-rw-r--r--modutils/lsmod.c11
-rw-r--r--modutils/modprobe-small.c62
-rw-r--r--modutils/modprobe.c11
-rw-r--r--modutils/modutils.c16
-rw-r--r--modutils/rmmod.c7
-rw-r--r--networking/Config.src2
-rw-r--r--networking/ifupdown.c36
-rw-r--r--networking/ip.c162
-rw-r--r--networking/libiproute/Kbuild.src3
-rw-r--r--networking/libiproute/iproute.c24
-rw-r--r--networking/libiproute/iprule.c11
-rw-r--r--networking/tcpudp.c6
-rw-r--r--networking/udhcp/Config.src2
-rw-r--r--networking/udhcp/Kbuild.src2
-rw-r--r--procps/Kbuild.src2
-rw-r--r--procps/top.c5
-rw-r--r--runit/sv.c112
-rwxr-xr-xscripts/randomtest.loop1
-rw-r--r--selinux/runcon.c4
-rw-r--r--selinux/setfiles.c1
-rw-r--r--shell/Config.src45
-rw-r--r--shell/Kbuild.src2
-rw-r--r--shell/ash.c304
-rw-r--r--shell/ash_test/ash-misc/exitcode2.right4
-rwxr-xr-xshell/ash_test/ash-misc/exitcode2.tests12
-rw-r--r--shell/ash_test/ash-redir/redir_leak.right6
-rwxr-xr-xshell/ash_test/ash-redir/redir_leak.tests10
-rw-r--r--shell/hush.c130
-rw-r--r--shell/hush_test/hush-misc/exitcode2.right4
-rwxr-xr-xshell/hush_test/hush-misc/exitcode2.tests12
-rw-r--r--shell/hush_test/hush-redir/redir_leak.right6
-rwxr-xr-xshell/hush_test/hush-redir/redir_leak.tests10
-rw-r--r--shell/math.h2
-rw-r--r--sysklogd/logread.c3
-rw-r--r--testsuite/bzcat/bzcat-does-not-remove-compressed-file (renamed from testsuite/bunzip2/bzcat-does-not-remove-compressed-file)0
-rwxr-xr-xtestsuite/cpio.tests3
-rwxr-xr-xtestsuite/tar.tests4
-rw-r--r--util-linux/fstrim.c25
67 files changed, 1154 insertions, 523 deletions
diff --git a/Makefile b/Makefile
index ea8d16f34..d4d8db667 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
1VERSION = 1 1VERSION = 1
2PATCHLEVEL = 26 2PATCHLEVEL = 26
3SUBLEVEL = 0 3SUBLEVEL = 2
4EXTRAVERSION = .git 4EXTRAVERSION =
5NAME = Unnamed 5NAME = Unnamed
6 6
7# *DOCUMENTATION* 7# *DOCUMENTATION*
diff --git a/Makefile.flags b/Makefile.flags
index 6b25632a0..4fb57d7b4 100644
--- a/Makefile.flags
+++ b/Makefile.flags
@@ -127,7 +127,7 @@ endif
127ifeq ($(CONFIG_PLATFORM_MINGW32),y) 127ifeq ($(CONFIG_PLATFORM_MINGW32),y)
128CFLAGS += -Iwin32 -DHAVE_STRING_H=1 -DHAVE_CONFIG_H=0 -fno-builtin-stpcpy -fno-ident 128CFLAGS += -Iwin32 -DHAVE_STRING_H=1 -DHAVE_CONFIG_H=0 -fno-builtin-stpcpy -fno-ident
129EXEEXT = .exe 129EXEEXT = .exe
130LDLIBS += userenv ws2_32 130LDLIBS += userenv ws2_32 mingwex -l:libssp.a
131endif 131endif
132 132
133# Android has no separate crypt library 133# Android has no separate crypt library
diff --git a/archival/bbunzip.c b/archival/bbunzip.c
index e1eec6d4b..343aec9bd 100644
--- a/archival/bbunzip.c
+++ b/archival/bbunzip.c
@@ -9,6 +9,12 @@
9 9
10/* lzop_main() uses bbunpack(), need this: */ 10/* lzop_main() uses bbunpack(), need this: */
11//kbuild:lib-$(CONFIG_LZOP) += bbunzip.o 11//kbuild:lib-$(CONFIG_LZOP) += bbunzip.o
12//kbuild:lib-$(CONFIG_LZOPCAT) += bbunzip.o
13//kbuild:lib-$(CONFIG_UNLZOP) += bbunzip.o
14/* bzip2_main() too: */
15//kbuild:lib-$(CONFIG_BZIP2) += bbunzip.o
16/* gzip_main() too: */
17//kbuild:lib-$(CONFIG_GZIP) += bbunzip.o
12 18
13/* Note: must be kept in sync with archival/lzop.c */ 19/* Note: must be kept in sync with archival/lzop.c */
14enum { 20enum {
@@ -192,7 +198,10 @@ int FAST_FUNC bbunpack(char **argv,
192 return exitcode; 198 return exitcode;
193} 199}
194 200
195#if ENABLE_UNCOMPRESS || ENABLE_BUNZIP2 || ENABLE_UNLZMA || ENABLE_UNXZ 201#if ENABLE_UNCOMPRESS \
202 || ENABLE_BUNZIP2 || ENABLE_BZCAT \
203 || ENABLE_UNLZMA || ENABLE_LZCAT || ENABLE_LZMA \
204 || ENABLE_UNXZ || ENABLE_XZCAT || ENABLE_XZ
196static 205static
197char* FAST_FUNC make_new_name_generic(char *filename, const char *expected_ext) 206char* FAST_FUNC make_new_name_generic(char *filename, const char *expected_ext)
198{ 207{
diff --git a/archival/dpkg.c b/archival/dpkg.c
index df7a0db64..f133299e3 100644
--- a/archival/dpkg.c
+++ b/archival/dpkg.c
@@ -28,7 +28,7 @@
28 28
29//config:config DPKG 29//config:config DPKG
30//config: bool "dpkg" 30//config: bool "dpkg"
31//config: default n 31//config: default y
32//config: select FEATURE_SEAMLESS_GZ 32//config: select FEATURE_SEAMLESS_GZ
33//config: help 33//config: help
34//config: dpkg is a medium-level tool to install, build, remove and manage 34//config: dpkg is a medium-level tool to install, build, remove and manage
diff --git a/archival/dpkg_deb.c b/archival/dpkg_deb.c
index 86850469d..ebbc7f035 100644
--- a/archival/dpkg_deb.c
+++ b/archival/dpkg_deb.c
@@ -7,7 +7,7 @@
7 7
8//config:config DPKG_DEB 8//config:config DPKG_DEB
9//config: bool "dpkg_deb" 9//config: bool "dpkg_deb"
10//config: default n 10//config: default y
11//config: select FEATURE_SEAMLESS_GZ 11//config: select FEATURE_SEAMLESS_GZ
12//config: help 12//config: help
13//config: dpkg-deb unpacks and provides information about Debian archives. 13//config: dpkg-deb unpacks and provides information about Debian archives.
diff --git a/archival/libarchive/Kbuild.src b/archival/libarchive/Kbuild.src
index b159a786a..ad5c5c42d 100644
--- a/archival/libarchive/Kbuild.src
+++ b/archival/libarchive/Kbuild.src
@@ -48,16 +48,23 @@ lib-$(CONFIG_CPIO) += get_header_cpio.o
48lib-$(CONFIG_TAR) += get_header_tar.o unsafe_prefix.o 48lib-$(CONFIG_TAR) += get_header_tar.o unsafe_prefix.o
49lib-$(CONFIG_FEATURE_TAR_TO_COMMAND) += data_extract_to_command.o 49lib-$(CONFIG_FEATURE_TAR_TO_COMMAND) += data_extract_to_command.o
50lib-$(CONFIG_LZOP) += lzo1x_1.o lzo1x_1o.o lzo1x_d.o 50lib-$(CONFIG_LZOP) += lzo1x_1.o lzo1x_1o.o lzo1x_d.o
51lib-$(CONFIG_UNLZOP) += lzo1x_1.o lzo1x_1o.o lzo1x_d.o
52lib-$(CONFIG_LZOPCAT) += lzo1x_1.o lzo1x_1o.o lzo1x_d.o
51lib-$(CONFIG_LZOP_COMPR_HIGH) += lzo1x_9x.o 53lib-$(CONFIG_LZOP_COMPR_HIGH) += lzo1x_9x.o
52lib-$(CONFIG_BUNZIP2) += open_transformer.o decompress_bunzip2.o 54lib-$(CONFIG_BUNZIP2) += open_transformer.o decompress_bunzip2.o
55lib-$(CONFIG_BZCAT) += open_transformer.o decompress_bunzip2.o
53lib-$(CONFIG_UNLZMA) += open_transformer.o decompress_unlzma.o 56lib-$(CONFIG_UNLZMA) += open_transformer.o decompress_unlzma.o
57lib-$(CONFIG_LZCAT) += open_transformer.o decompress_unlzma.o
58lib-$(CONFIG_LZMA) += open_transformer.o decompress_unlzma.o
54lib-$(CONFIG_UNXZ) += open_transformer.o decompress_unxz.o 59lib-$(CONFIG_UNXZ) += open_transformer.o decompress_unxz.o
60lib-$(CONFIG_XZCAT) += open_transformer.o decompress_unxz.o
61lib-$(CONFIG_XZ) += open_transformer.o decompress_unxz.o
55lib-$(CONFIG_GUNZIP) += open_transformer.o decompress_gunzip.o 62lib-$(CONFIG_GUNZIP) += open_transformer.o decompress_gunzip.o
63lib-$(CONFIG_ZCAT) += open_transformer.o decompress_gunzip.o
56lib-$(CONFIG_UNCOMPRESS) += open_transformer.o decompress_uncompress.o 64lib-$(CONFIG_UNCOMPRESS) += open_transformer.o decompress_uncompress.o
57lib-$(CONFIG_UNZIP) += open_transformer.o decompress_gunzip.o unsafe_prefix.o 65lib-$(CONFIG_UNZIP) += open_transformer.o decompress_gunzip.o unsafe_prefix.o
58lib-$(CONFIG_RPM2CPIO) += open_transformer.o decompress_gunzip.o get_header_cpio.o 66lib-$(CONFIG_RPM2CPIO) += open_transformer.o decompress_gunzip.o get_header_cpio.o
59lib-$(CONFIG_RPM) += open_transformer.o decompress_gunzip.o get_header_cpio.o 67lib-$(CONFIG_RPM) += open_transformer.o decompress_gunzip.o get_header_cpio.o
60
61lib-$(CONFIG_GZIP) += open_transformer.o 68lib-$(CONFIG_GZIP) += open_transformer.o
62lib-$(CONFIG_BZIP2) += open_transformer.o 69lib-$(CONFIG_BZIP2) += open_transformer.o
63lib-$(CONFIG_LZOP) += open_transformer.o 70lib-$(CONFIG_LZOP) += open_transformer.o
diff --git a/configs/mingw32_defconfig b/configs/mingw32_defconfig
index 35e7b1297..5801e26a2 100644
--- a/configs/mingw32_defconfig
+++ b/configs/mingw32_defconfig
@@ -997,6 +997,7 @@ CONFIG_PS=y
997# CONFIG_FEATURE_RUNSVDIR_LOG is not set 997# CONFIG_FEATURE_RUNSVDIR_LOG is not set
998# CONFIG_SV is not set 998# CONFIG_SV is not set
999CONFIG_SV_DEFAULT_SERVICE_DIR="" 999CONFIG_SV_DEFAULT_SERVICE_DIR=""
1000# CONFIG_SVC is not set
1000# CONFIG_SVLOGD is not set 1001# CONFIG_SVLOGD is not set
1001# CONFIG_CHCON is not set 1002# CONFIG_CHCON is not set
1002# CONFIG_FEATURE_CHCON_LONG_OPTIONS is not set 1003# CONFIG_FEATURE_CHCON_LONG_OPTIONS is not set
diff --git a/configs/mingw64_defconfig b/configs/mingw64_defconfig
index a5051285b..558c07d56 100644
--- a/configs/mingw64_defconfig
+++ b/configs/mingw64_defconfig
@@ -997,6 +997,7 @@ CONFIG_PS=y
997# CONFIG_FEATURE_RUNSVDIR_LOG is not set 997# CONFIG_FEATURE_RUNSVDIR_LOG is not set
998# CONFIG_SV is not set 998# CONFIG_SV is not set
999CONFIG_SV_DEFAULT_SERVICE_DIR="" 999CONFIG_SV_DEFAULT_SERVICE_DIR=""
1000# CONFIG_SVC is not set
1000# CONFIG_SVLOGD is not set 1001# CONFIG_SVLOGD is not set
1001# CONFIG_CHCON is not set 1002# CONFIG_CHCON is not set
1002# CONFIG_FEATURE_CHCON_LONG_OPTIONS is not set 1003# CONFIG_FEATURE_CHCON_LONG_OPTIONS is not set
diff --git a/coreutils/Kbuild.src b/coreutils/Kbuild.src
index 8e2c097a3..d9a448781 100644
--- a/coreutils/Kbuild.src
+++ b/coreutils/Kbuild.src
@@ -10,12 +10,16 @@ lib-y:=
10 10
11INSERT 11INSERT
12 12
13lib-$(CONFIG_MORE) += cat.o # more uses it if stdout isn't a tty 13lib-$(CONFIG_MORE) += cat.o # more uses it if stdout isn't a tty
14lib-$(CONFIG_LESS) += cat.o # less too 14lib-$(CONFIG_LESS) += cat.o # less too
15lib-$(CONFIG_CRONTAB) += cat.o # crontab -l 15lib-$(CONFIG_CRONTAB) += cat.o # crontab -l
16lib-$(CONFIG_ADDUSER) += chown.o # used by adduser 16lib-$(CONFIG_ADDUSER) += chown.o # used by adduser
17lib-$(CONFIG_ADDGROUP) += chown.o # used by adduser 17lib-$(CONFIG_ADDGROUP) += chown.o # used by adduser
18lib-$(CONFIG_ASH) += echo.o # used by ash 18lib-$(CONFIG_ASH) += echo.o # used by ash
19lib-$(CONFIG_HUSH) += echo.o # used by hush 19lib-$(CONFIG_SH_IS_ASH) += echo.o # used by ash
20lib-$(CONFIG_FTPD) += ls.o # used by ftpd 20lib-$(CONFIG_BASH_IS_ASH) += echo.o # used by ash
21lib-$(CONFIG_HUSH) += echo.o # used by hush
22lib-$(CONFIG_SH_IS_HUSH) += echo.o # used by hush
23lib-$(CONFIG_BASH_IS_HUSH) += echo.o # used by hush
24lib-$(CONFIG_FTPD) += ls.o # used by ftpd
21lib-$(CONFIG_ASH_BUILTIN_PRINTF) += printf.o 25lib-$(CONFIG_ASH_BUILTIN_PRINTF) += printf.o
diff --git a/coreutils/df.c b/coreutils/df.c
index fdcdae675..79e4c4670 100644
--- a/coreutils/df.c
+++ b/coreutils/df.c
@@ -129,8 +129,19 @@ int df_main(int argc UNUSED_PARAM, char **argv)
129 if (opt & OPT_MEGA) 129 if (opt & OPT_MEGA)
130 df_disp_hr = 1024*1024; 130 df_disp_hr = 1024*1024;
131 131
132 if (opt & OPT_BSIZE) 132 if (opt & OPT_BSIZE) {
133 df_disp_hr = xatoul_range(chp, 1, ULONG_MAX); /* disallow 0 */ 133 /* GNU coreutils 8.25 accepts "-BMiB" form too */
134 int i;
135 for (i = 0; kmg_i_suffixes[i].suffix[0]; i++) {
136 if (strcmp(kmg_i_suffixes[i].suffix, chp) == 0) {
137 df_disp_hr = kmg_i_suffixes[i].mult;
138 goto got_it;
139 }
140 }
141 /* Range used to disallow 0 */
142 df_disp_hr = xatoul_range_sfx(chp, 1, ULONG_MAX, kmg_i_suffixes);
143 got_it: ;
144 }
134 145
135 /* From the manpage of df from coreutils-6.10: 146 /* From the manpage of df from coreutils-6.10:
136 * Disk space is shown in 1K blocks by default, unless the environment 147 * Disk space is shown in 1K blocks by default, unless the environment
@@ -203,6 +214,11 @@ int df_main(int argc UNUSED_PARAM, char **argv)
203 bb_simple_perror_msg(mount_point); 214 bb_simple_perror_msg(mount_point);
204 goto set_error; 215 goto set_error;
205 } 216 }
217 /* Some uclibc versions were seen to lose f_frsize
218 * (kernel does return it, but then uclibc does not copy it)
219 */
220 if (s.f_frsize == 0)
221 s.f_frsize = s.f_bsize;
206 222
207 if ((s.f_blocks > 0) || !mount_table || (opt & OPT_ALL)) { 223 if ((s.f_blocks > 0) || !mount_table || (opt & OPT_ALL)) {
208 if (opt & OPT_INODE) { 224 if (opt & OPT_INODE) {
diff --git a/coreutils/install.c b/coreutils/install.c
index e68589229..831f9b802 100644
--- a/coreutils/install.c
+++ b/coreutils/install.c
@@ -211,7 +211,8 @@ int install_main(int argc, char **argv)
211 char *ddir = xstrdup(dest); 211 char *ddir = xstrdup(dest);
212 bb_make_directory(dirname(ddir), 0755, mkdir_flags); 212 bb_make_directory(dirname(ddir), 0755, mkdir_flags);
213 /* errors are not checked. copy_file 213 /* errors are not checked. copy_file
214 * will fail if dir is not created. */ 214 * will fail if dir is not created.
215 */
215 free(ddir); 216 free(ddir);
216 } 217 }
217 if (isdir) 218 if (isdir)
diff --git a/coreutils/test.c b/coreutils/test.c
index df42590e4..67fdfde4f 100644
--- a/coreutils/test.c
+++ b/coreutils/test.c
@@ -55,6 +55,8 @@
55//kbuild:lib-$(CONFIG_TEST2) += test.o test_ptr_hack.o 55//kbuild:lib-$(CONFIG_TEST2) += test.o test_ptr_hack.o
56//kbuild:lib-$(CONFIG_ASH_BUILTIN_TEST) += test.o test_ptr_hack.o 56//kbuild:lib-$(CONFIG_ASH_BUILTIN_TEST) += test.o test_ptr_hack.o
57//kbuild:lib-$(CONFIG_HUSH) += test.o test_ptr_hack.o 57//kbuild:lib-$(CONFIG_HUSH) += test.o test_ptr_hack.o
58//kbuild:lib-$(CONFIG_SH_IS_HUSH) += test.o test_ptr_hack.o
59//kbuild:lib-$(CONFIG_BASH_IS_HUSH) += test.o test_ptr_hack.o
58 60
59/* "test --help" is special-cased to ignore --help */ 61/* "test --help" is special-cased to ignore --help */
60//usage:#define test_trivial_usage NOUSAGE_STR 62//usage:#define test_trivial_usage NOUSAGE_STR
diff --git a/examples/mdev.conf b/examples/mdev.conf
index 51795694d..fab1dc451 100644
--- a/examples/mdev.conf
+++ b/examples/mdev.conf
@@ -34,3 +34,5 @@ fd[0-9]* 0:11 660
34 34
35sd[a-z]* 0:6 660 35sd[a-z]* 0:6 660
36hd[a-z]* 0:6 660 36hd[a-z]* 0:6 660
37
38hw_random 0:0 600 =hwrng
diff --git a/examples/var_service/README_distro_proposal.txt b/examples/var_service/README_distro_proposal.txt
new file mode 100644
index 000000000..9b3fe04ba
--- /dev/null
+++ b/examples/var_service/README_distro_proposal.txt
@@ -0,0 +1,291 @@
1 A distro which already uses runit
2
3I installed Void Linux, in order to see what do they have.
4Xfce desktop looks fairly okay, network is up.
5ps tells me they did put X, dbus, NM and udev into runsvdir-supervised tree:
6
7 1 ? 00:00:01 runit
8 623 ? 00:00:00 runsvdir
9 629 ? 00:00:00 runsv
10 650 tty1 00:00:00 agetty
11 630 ? 00:00:00 runsv
12 644 ? 00:00:09 NetworkManager
13 1737 ? 00:00:00 dhclient
14 631 ? 00:00:00 runsv
15 639 tty4 00:00:00 agetty
16 632 ? 00:00:00 runsv
17 640 ? 00:00:00 sshd
18 1804 ? 00:00:00 sshd
19 1809 pts/3 00:00:00 sh
20 1818 pts/3 00:00:00 ps
21 633 ? 00:00:00 runsv
22 637 tty5 00:00:00 agetty
23 634 ? 00:00:00 runsv
24 796 ? 00:00:00 dhclient
25 635 ? 00:00:00 runsv
26 649 ? 00:00:00 uuidd
27 636 ? 00:00:00 runsv
28 647 ? 00:00:00 acpid
29 638 ? 00:00:00 runsv
30 652 ? 00:00:00 console-kit-dae
31 641 ? 00:00:00 runsv
32 651 tty6 00:00:00 agetty
33 642 ? 00:00:00 runsv
34 660 tty2 00:00:00 agetty
35 643 ? 00:00:00 runsv
36 657 ? 00:00:02 dbus-daemon
37 645 ? 00:00:00 runsv
38 658 ? 00:00:00 cgmanager
39 648 ? 00:00:00 runsv
40 656 tty3 00:00:00 agetty
41 653 ? 00:00:00 runsv
42 655 ? 00:00:00 lxdm-binary
43 698 tty7 00:00:14 Xorg
44 729 ? 00:00:00 lxdm-session
45 956 ? 00:00:00 sh
46 982 ? 00:00:00 xfce4-session
47 1006 ? 00:00:04 nm-applet
48 654 ? 00:00:00 runsv
49 659 ? 00:00:00 udevd
50
51Here is a link to Vod Linux's wiki:
52
53 https://wiki.voidlinux.eu/Runit
54
55Void Linux packages install their services as subdirectories of /etc/rc,
56such as /etc/sv/sshd, with a script file, "run", and a link
57"supervise" -> /run/runit/supervise.sshd
58
59For sshd, "run" contains:
60
61 #!/bin/sh
62 ssh-keygen -A >/dev/null 2>&1 # generate host keys if they don't exist
63 [ -r conf ] && . ./conf
64 exec /usr/bin/sshd -D $OPTS
65
66That's it from the POV of the packager.
67
68This is pretty minimalistic, and yet, it is already distro-specific:
69the link to /run/runit/* is conceptually wrong, it requires packagers
70to know that /etc/rc should not be mutable and thus they need to use
71a different location in filesystem for supervise/ directory.
72
73I think a good thing would be to require just one file: the "run" script.
74The rest should be handled by distro tooling, not by packager.
75
76A similar issue is arising with logging. It would be ideal if packagers
77would not need to know how a particular distro manages logs.
78Whatever their daemons print to stdout/stderr, should be automagically logged
79in a way distro prefers.
80
81* * * * * * * *
82
83 Proposed "standard" on how distros should use runit
84
85The original idea of services-as-directories belongs to D.J.Bernstein (djb),
86and his project to implement it is daemontools: https://cr.yp.to/daemontools.html
87
88There are several reimplementations of daemontools:
89- runit: by Gerrit Pape, http://smarden.org/runit/
90 (busybox has it included)
91- s6: by Laurent Bercot, http://skarnet.org/software/s6/
92
93
94It is not required that a specific clone should be used. Let evolution work.
95
96 Terminology
97
98daemon: any long running background program. Common examples are sshd, getty,
99ntpd, dhcp client...
100
101service: same as "daemon"
102
103service directory: a directory with an executable file (script) named "run"
104which (usually) execs daemon (possibly after some preparatory steps).
105It should start it not as a child or daemonized process, but by exec'ing it
106(inheriting the same PID and the place in the process tree).
107
108service monitor: a tool which watches a set of service directories.
109In daemontools package, it is called "svscan". In runit, it is called
110"runsvdir". In s6, it is called "s6-svscan".
111Service monitor starts a supervisor for each service directory.
112If it dies, it restarts it. If service directory disappears,
113service monitor will not be restarted if it dies.
114runit's service monitor (runsvdir) sends SIGTERM to supervisors
115whose directories disappeared.
116
117supervisor: a tool which monitors one service directory.
118It runs "run" script as its child. It restarts it if it dies.
119It can be instructed to start/top/signal its child.
120In daemontools package, it is called "supervise". In runit, it is called
121"runsv". In s6, it is called "s6-supervise".
122
123Conceptually, a daemontools clone can be designed such that it does not *have*
124the supervisor component: service monitor can directly monitor all its daemons
125(for example, this may be a good idea for memory-constrained systems).
126However all three existing projects (daemontools/runit/s6) do have a per-service
127supervisor process.
128
129log service: a service which is exclusively tasked with logging
130the output of another service. It is implemented as log/ subdirectory
131in a service directory. It has the same structure as "normal"
132service dirs: it has a "run" script which starts a logging tool.
133
134If log service exists, stdout of its "main" service is piped
135to log service. Stops/restarts of either of them do not sever the pipe
136between them.
137
138If log service exists, daemontools and s6 run a pair of supervisors
139(one for the daemon, one for the logger); runit runs only one supervisor
140per service, which is handling both of them (presumably this is done
141to use fewer processes and thus, fewer resources).
142
143
144 User API
145
146"Users" of service monitoring are authors of software which has daemons.
147They need to package their daemons to be installed as services at package
148install time. And they need to do this for many distros.
149The less distros diverge, the easier users' lives are.
150
151System-wide service dirs reside in a distro-specific location.
152The recommended location is /var/service. (However, since it is not
153a mandatory location, avoid depending on it in your run scripts).
154
155The install location for service dirs is /etc/rc:
156when e.g. ntpd daemon is installed, it creates the /etc/rc/ntpd
157directory with (minimally) one executable file (script) named "run"
158which starts ntpd daemon. It can have other files there.
159
160At boot, distro should copy /etc/rc/* to a suitable writable
161directory (common choice are /var/service, /run/service etc).
162It should create log/ directories in each subdirectory
163and create "run" files in them with suitable (for this particular distro)
164logging tool invocation, unless this directory chose to channel
165all logging from all daemons through service monitor process
166and log all of them into one file/database/whatever,
167in which case log/ directories should not be created.
168
169It is allowable for a distro to directly use /etc/rc/ as the only
170location of its service directories. (For example,
171/var/service may be a symlink to /etc/rc).
172However, it poses some problems:
173
174(1) Supervision tools will need to write to subdirectories:
175the control of running daemons is implemented via some files and fifos
176in automatically created supervise/ subdirectory in each /etc/rc/DIR.
177
178(2) Creation of a new service can race with the rescanning of /etc/rc/
179by service monitor: service monitor may see a directory with only some files
180present. If it attempts to start the service in this state, all sorts
181of bad things may happen. This may be worked around by various
182heuristics in service monitor which give new service a few seconds
183of "grace time" to be fully populated; but this is not yet
184implemented in any of three packages.
185
186Daemons' output file descriptors are handled somewhat awkwardly
187by various daemontools implementations. For example, for runit tools,
188daemons' stdout goes to wherever runsdir's stdout was directied;
189stderr goes to runsvdir, which in turn "rotates" it on its command line
190(which is visible in ps output).
191
192Hopefully this get changed/standardized; while it is not, the "run" file
193should start with a
194
195 exec 2>&1
196
197command, making stderr equivalent to stdout.
198An especially primitive service which does not want its output to be logged
199with standard tools can do
200
201 exec >LOGFILE 2>&1
202
203or even
204
205 exec >/dev/null 2>&1
206
207To prevent creation of distro-specific log/ directory, a service directory
208in /etc/rc can contain an empty "log" file.
209
210
211 Controlling daemons
212
213The "svc" tool is available for admins and scripts to control services.
214In particular, often one service needs to control another:
215e.g. ifplugd can detect that the network cable was just plugged in,
216and it needs to (re)start DHCP service for this network device.
217
218The name of this tool is not standard either, which is an obvious problem.
219I propose to fix this by implementing a tool with fixed name and API by all
220daemontools clones. Lets use original daemontools name and API. Thus:
221
222The following form must work:
223
224 svc -udopchaitkx DIR
225
226Options map to up/down/once/STOP/CONT/HUP/ALRM/INT/TERM/KILL/exit
227commands to the daemon being controlled.
228
229The form with one option letter must work. If multiple-option form
230is supported, there is no guarantee in which order they take effect:
231svc -it DIR can deliver TERM and INT in any order.
232
233If more than one DIR can be specified (which is not a requirement),
234there is no guarantee in which order commands are sent to them.
235
236If DIR has no slash and is not "." or "..", it is assumed to be
237relative to the system-wide service directory.
238
239The "svok DIR" tool exits 0 if service is running, and nonzero if not.
240
241The "svstat DIR1 DIR2..." prints one human-readable line for each directory,
242saying whether supervise is successfully running in that directory,
243and reporting the status information maintained by supervise.
244
245Other tools with different names and APIs may exist; however
246for portability scripts should use the above tools.
247
248Creation of a new service on a running system should be done atomically.
249To this end, first create and populate a new /etc/rc/DIR.
250
251Then "activate" it by running ??????? - this copies (or symlinks,
252depending on the distro) its files to the "live" service directory,
253whereever it is located on this distro.
254
255Removal of the service should be done as follows:
256svc -d DIR [DIR/log], then remove the service directory
257(this makes service monitor SIGTERM per-directory supervisors
258(if they exist in the implementation))
259
260
261 Implementation details
262
263Top-level service monitor program name is not standardized.
264[svscan, runsvdir, s6-svscan ...]
265
266It may run one per-directory supervisor, or two supervisors
267(one for DIR/ and one for DIR/log/); for memory-constrained systems
268an implementation is possible which itself controls all services, without
269intermediate supervisors.
270[runsvdir runs one "runsv DIR" per DIR, runsv handles DIR/log/ if that exists]
271[svscan runs a pair of "superwise DIR" and "superwise DIR/log"]
272
273Directores are remembered by device+inode numbers, not names. Renaming a directory
274does not affect the running service (unless it is renamed to a .dotdir).
275
276Removal (or .dotdiring) of a directory sends SIGTERM to any running services.
277
278Standard output of non-logged services goes to standard output of service monitor.
279Standard output of logger services goes to standard output of service monitor.
280Standard error of them always goes to standard error of service monitor.
281
282If you want to log standard error of your logged service along with its stdout, use
283"exec 2>&1" in the beginning of your "run" script.
284
285Whether stdout/stderr of service monitor is discarded (>/dev/null)
286or logged in some way is system-dependent.
287
288
289 Containers
290
291[What do containers need?]
diff --git a/include/applets.h.sh b/include/applets.h.sh
index bab4e0d72..be117cf84 100755
--- a/include/applets.h.sh
+++ b/include/applets.h.sh
@@ -4,11 +4,7 @@
4# enabling it. Run it after applets.h is generated. 4# enabling it. Run it after applets.h is generated.
5 5
6# CONFIG_applet names 6# CONFIG_applet names
7grep ^IF_ applets.h | grep -v IF_FEATURE_ | sed 's/IF_\([A-Z0-9._-]*\)(.*/\1/' \ 7grep ^IF_ applets.h | grep -v ^IF_FEATURE_ | sed 's/IF_\([A-Z0-9._-]*\)(.*/\1/' \
8| grep -v MODPROBE_SMALL \
9| sed 's/BB_SYSCTL/SYSCTL/' \
10| sed 's/TEST1/[/' \
11| sed 's/TEST2/[[/' \
12| sort | uniq \ 8| sort | uniq \
13>applets_APP1 9>applets_APP1
14 10
@@ -17,8 +13,11 @@ grep ^IF_ applets.h | sed -e's/ //g' -e's/.*(\([a-z[][^,]*\),.*/\1/' \
17| grep -v '^bash$' \ 13| grep -v '^bash$' \
18| grep -v '^sh$' \ 14| grep -v '^sh$' \
19| tr a-z A-Z \ 15| tr a-z A-Z \
16| sed 's/^SYSCTL$/BB_SYSCTL/' \
17| sed 's/^\[\[$/TEST1/' \
18| sed 's/^\[$/TEST2/' \
20| sort | uniq \ 19| sort | uniq \
21>applets_APP2 20>applets_APP2
22 21
23diff -u applets_APP1 applets_APP2 >applets_APP.diff 22diff -u applets_APP1 applets_APP2 >applets_APP.diff
24rm applets_APP1 applets_APP2 23#rm applets_APP1 applets_APP2
diff --git a/include/libbb.h b/include/libbb.h
index a6de5e97b..0b9cfb585 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -45,7 +45,7 @@
45#include <sys/stat.h> 45#include <sys/stat.h>
46#include <sys/time.h> 46#include <sys/time.h>
47#include <sys/types.h> 47#include <sys/types.h>
48#ifndef major 48#if !defined(major) || defined(__GLIBC__)
49# include <sys/sysmacros.h> 49# include <sys/sysmacros.h>
50#endif 50#endif
51#include <sys/wait.h> 51#include <sys/wait.h>
@@ -81,8 +81,6 @@
81#if ENABLE_SELINUX 81#if ENABLE_SELINUX
82# include <selinux/selinux.h> 82# include <selinux/selinux.h>
83# include <selinux/context.h> 83# include <selinux/context.h>
84# include <selinux/flask.h>
85# include <selinux/av_permissions.h>
86#endif 84#endif
87#if ENABLE_FEATURE_UTMP 85#if ENABLE_FEATURE_UTMP
88# if defined __UCLIBC__ && ( \ 86# if defined __UCLIBC__ && ( \
@@ -944,6 +942,7 @@ extern const struct suffix_mult bkm_suffixes[];
944#define km_suffixes (bkm_suffixes + 1) 942#define km_suffixes (bkm_suffixes + 1)
945extern const struct suffix_mult cwbkMG_suffixes[]; 943extern const struct suffix_mult cwbkMG_suffixes[];
946#define kMG_suffixes (cwbkMG_suffixes + 3) 944#define kMG_suffixes (cwbkMG_suffixes + 3)
945extern const struct suffix_mult kmg_i_suffixes[];
947 946
948#include "xatonum.h" 947#include "xatonum.h"
949/* Specialized: */ 948/* Specialized: */
@@ -1210,8 +1209,16 @@ int bb_cat(char** argv);
1210/* If shell needs them, they exist even if not enabled as applets */ 1209/* If shell needs them, they exist even if not enabled as applets */
1211int echo_main(int argc, char** argv) IF_ECHO(MAIN_EXTERNALLY_VISIBLE); 1210int echo_main(int argc, char** argv) IF_ECHO(MAIN_EXTERNALLY_VISIBLE);
1212int printf_main(int argc, char **argv) IF_PRINTF(MAIN_EXTERNALLY_VISIBLE); 1211int printf_main(int argc, char **argv) IF_PRINTF(MAIN_EXTERNALLY_VISIBLE);
1213int test_main(int argc, char **argv) IF_TEST(MAIN_EXTERNALLY_VISIBLE); 1212int test_main(int argc, char **argv)
1214int kill_main(int argc, char **argv) IF_KILL(MAIN_EXTERNALLY_VISIBLE); 1213#if ENABLE_TEST || ENABLE_TEST1 || ENABLE_TEST2
1214 MAIN_EXTERNALLY_VISIBLE
1215#endif
1216;
1217int kill_main(int argc, char **argv)
1218#if ENABLE_KILL || ENABLE_KILLALL || ENABLE_KILLALL5
1219 MAIN_EXTERNALLY_VISIBLE
1220#endif
1221;
1215/* Similar, but used by chgrp, not shell */ 1222/* Similar, but used by chgrp, not shell */
1216int chown_main(int argc, char **argv) IF_CHOWN(MAIN_EXTERNALLY_VISIBLE); 1223int chown_main(int argc, char **argv) IF_CHOWN(MAIN_EXTERNALLY_VISIBLE);
1217/* Used by ftpd */ 1224/* Used by ftpd */
diff --git a/include/mingw.h b/include/mingw.h
index 04700963c..569c2c704 100644
--- a/include/mingw.h
+++ b/include/mingw.h
@@ -448,7 +448,9 @@ DIR *mingw_opendir(const char *path);
448 * MinGW specific 448 * MinGW specific
449 */ 449 */
450#define is_dir_sep(c) ((c) == '/' || (c) == '\\') 450#define is_dir_sep(c) ((c) == '/' || (c) == '\\')
451#ifndef PRIuMAX
451#define PRIuMAX "I64u" 452#define PRIuMAX "I64u"
453#endif
452 454
453pid_t FAST_FUNC mingw_spawn(char **argv); 455pid_t FAST_FUNC mingw_spawn(char **argv);
454intptr_t FAST_FUNC mingw_spawn_proc(char **argv); 456intptr_t FAST_FUNC mingw_spawn_proc(char **argv);
diff --git a/init/init.c b/init/init.c
index 0813d1b5f..08cfa2f8c 100644
--- a/init/init.c
+++ b/init/init.c
@@ -83,7 +83,7 @@
83//config: 83//config:
84//config:config FEATURE_INIT_COREDUMPS 84//config:config FEATURE_INIT_COREDUMPS
85//config: bool "Support dumping core for child processes (debugging only)" 85//config: bool "Support dumping core for child processes (debugging only)"
86//config: default y 86//config: default n # not Y because this is a debug option
87//config: depends on INIT || LINUXRC 87//config: depends on INIT || LINUXRC
88//config: help 88//config: help
89//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
diff --git a/libbb/Config.src b/libbb/Config.src
index 00804e31e..172fbcc0e 100644
--- a/libbb/Config.src
+++ b/libbb/Config.src
@@ -152,7 +152,7 @@ config FEATURE_TAB_COMPLETION
152 152
153config FEATURE_USERNAME_COMPLETION 153config FEATURE_USERNAME_COMPLETION
154 bool "Username completion" 154 bool "Username completion"
155 default n 155 default y
156 depends on FEATURE_TAB_COMPLETION 156 depends on FEATURE_TAB_COMPLETION
157 help 157 help
158 Enable username completion. 158 Enable username completion.
diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src
index 39d9d907d..fc9371db1 100644
--- a/libbb/Kbuild.src
+++ b/libbb/Kbuild.src
@@ -135,6 +135,7 @@ lib-$(CONFIG_TFTPD) += udp_io.o
135lib-$(CONFIG_TCPSVD) += udp_io.o 135lib-$(CONFIG_TCPSVD) += udp_io.o
136lib-$(CONFIG_UDPSVD) += udp_io.o 136lib-$(CONFIG_UDPSVD) += udp_io.o
137lib-$(CONFIG_TRACEROUTE) += udp_io.o 137lib-$(CONFIG_TRACEROUTE) += udp_io.o
138lib-$(CONFIG_TRACEROUTE6) += udp_io.o
138 139
139lib-$(CONFIG_LOSETUP) += loop.o 140lib-$(CONFIG_LOSETUP) += loop.o
140lib-$(CONFIG_FEATURE_MOUNT_LOOP) += loop.o 141lib-$(CONFIG_FEATURE_MOUNT_LOOP) += loop.o
@@ -144,7 +145,7 @@ lib-$(CONFIG_ADDUSER) += update_passwd.o
144lib-$(CONFIG_DELGROUP) += update_passwd.o 145lib-$(CONFIG_DELGROUP) += update_passwd.o
145lib-$(CONFIG_DELUSER) += update_passwd.o 146lib-$(CONFIG_DELUSER) += update_passwd.o
146 147
147lib-$(CONFIG_FTPD) += correct_password.o 148lib-$(CONFIG_FTPD) += pw_encrypt.o correct_password.o
148lib-$(CONFIG_PASSWD) += pw_encrypt.o update_passwd.o obscure.o 149lib-$(CONFIG_PASSWD) += pw_encrypt.o update_passwd.o obscure.o
149lib-$(CONFIG_CHPASSWD) += pw_encrypt.o update_passwd.o 150lib-$(CONFIG_CHPASSWD) += pw_encrypt.o update_passwd.o
150lib-$(CONFIG_CRYPTPW) += pw_encrypt.o 151lib-$(CONFIG_CRYPTPW) += pw_encrypt.o
@@ -159,6 +160,7 @@ lib-$(CONFIG_FEATURE_FTP_AUTHENTICATION) += pw_encrypt.o
159lib-$(CONFIG_DF) += find_mount_point.o 160lib-$(CONFIG_DF) += find_mount_point.o
160lib-$(CONFIG_MKFS_MINIX) += find_mount_point.o 161lib-$(CONFIG_MKFS_MINIX) += find_mount_point.o
161lib-$(CONFIG_MKFS_EXT2) += find_mount_point.o 162lib-$(CONFIG_MKFS_EXT2) += find_mount_point.o
163lib-$(CONFIG_MKE2FS) += find_mount_point.o
162lib-$(CONFIG_MKFS_REISER) += find_mount_point.o 164lib-$(CONFIG_MKFS_REISER) += find_mount_point.o
163lib-$(CONFIG_FSCK_MINIX) += find_mount_point.o 165lib-$(CONFIG_FSCK_MINIX) += find_mount_point.o
164lib-$(CONFIG_MOUNT) += find_mount_point.o 166lib-$(CONFIG_MOUNT) += find_mount_point.o
@@ -171,11 +173,13 @@ lib-$(CONFIG_MPSTAT) += get_cpu_count.o
171lib-$(CONFIG_POWERTOP) += get_cpu_count.o 173lib-$(CONFIG_POWERTOP) += get_cpu_count.o
172 174
173lib-$(CONFIG_PING) += inet_cksum.o 175lib-$(CONFIG_PING) += inet_cksum.o
176lib-$(CONFIG_PING6) += inet_cksum.o
174lib-$(CONFIG_TRACEROUTE) += inet_cksum.o 177lib-$(CONFIG_TRACEROUTE) += inet_cksum.o
175lib-$(CONFIG_TRACEROUTE6) += inet_cksum.o 178lib-$(CONFIG_TRACEROUTE6) += inet_cksum.o
176lib-$(CONFIG_UDHCPC) += inet_cksum.o 179lib-$(CONFIG_UDHCPC) += inet_cksum.o
177lib-$(CONFIG_UDHCPC6) += inet_cksum.o 180lib-$(CONFIG_UDHCPC6) += inet_cksum.o
178lib-$(CONFIG_UDHCPD) += inet_cksum.o 181lib-$(CONFIG_UDHCPD) += inet_cksum.o
182lib-$(CONFIG_DHCPRELAY) += inet_cksum.o
179 183
180# We shouldn't build xregcomp.c if we don't need it - this ensures we don't 184# We shouldn't build xregcomp.c if we don't need it - this ensures we don't
181# require regex.h to be in the include dir even if we don't need it thereby 185# require regex.h to be in the include dir even if we don't need it thereby
@@ -184,6 +188,8 @@ lib-$(CONFIG_UDHCPD) += inet_cksum.o
184lib-$(CONFIG_AWK) += xregcomp.o 188lib-$(CONFIG_AWK) += xregcomp.o
185lib-$(CONFIG_SED) += xregcomp.o 189lib-$(CONFIG_SED) += xregcomp.o
186lib-$(CONFIG_GREP) += xregcomp.o 190lib-$(CONFIG_GREP) += xregcomp.o
191lib-$(CONFIG_EGREP) += xregcomp.o
192lib-$(CONFIG_FGREP) += xregcomp.o
187lib-$(CONFIG_EXPR) += xregcomp.o 193lib-$(CONFIG_EXPR) += xregcomp.o
188lib-$(CONFIG_MDEV) += xregcomp.o 194lib-$(CONFIG_MDEV) += xregcomp.o
189lib-$(CONFIG_LESS) += xregcomp.o 195lib-$(CONFIG_LESS) += xregcomp.o
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index 1fe0eb44f..ac3e414f5 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -334,21 +334,6 @@ static struct suid_config_t {
334 334
335static bool suid_cfg_readable; 335static bool suid_cfg_readable;
336 336
337/* check if u is member of group g */
338static int ingroup(uid_t u, gid_t g)
339{
340 struct group *grp = getgrgid(g);
341 if (grp) {
342 char **mem;
343 for (mem = grp->gr_mem; *mem; mem++) {
344 struct passwd *pwd = getpwnam(*mem);
345 if (pwd && (pwd->pw_uid == u))
346 return 1;
347 }
348 }
349 return 0;
350}
351
352/* libbb candidate */ 337/* libbb candidate */
353static char *get_trimmed_slice(char *s, char *e) 338static char *get_trimmed_slice(char *s, char *e)
354{ 339{
@@ -573,7 +558,22 @@ static inline void parse_config_file(void)
573# endif /* FEATURE_SUID_CONFIG */ 558# endif /* FEATURE_SUID_CONFIG */
574 559
575 560
576# if ENABLE_FEATURE_SUID 561# if ENABLE_FEATURE_SUID && NUM_APPLETS > 0
562/* check if u is member of group g */
563static int ingroup(uid_t u, gid_t g)
564{
565 struct group *grp = getgrgid(g);
566 if (grp) {
567 char **mem;
568 for (mem = grp->gr_mem; *mem; mem++) {
569 struct passwd *pwd = getpwnam(*mem);
570 if (pwd && (pwd->pw_uid == u))
571 return 1;
572 }
573 }
574 return 0;
575}
576
577static void check_suid(int applet_no) 577static void check_suid(int applet_no)
578{ 578{
579 gid_t rgid; /* real gid */ 579 gid_t rgid; /* real gid */
diff --git a/libbb/make_directory.c b/libbb/make_directory.c
index 3980376ec..840c525b0 100644
--- a/libbb/make_directory.c
+++ b/libbb/make_directory.c
@@ -35,9 +35,20 @@ int FAST_FUNC bb_make_directory(char *path, long mode, int flags)
35 char c; 35 char c;
36 struct stat st; 36 struct stat st;
37 37
38 /* Happens on bb_make_directory(dirname("no_slashes"),...) */ 38 /* "path" can be a result of dirname().
39 if (LONE_CHAR(path, '.')) 39 * dirname("no_slashes") returns ".", possibly read-only.
40 * musl dirname() can return read-only "/" too.
41 * We need writable string. And for "/", "." (and ".."?)
42 * nothing needs to be created anyway.
43 */
44 if (LONE_CHAR(path, '/'))
40 return 0; 45 return 0;
46 if (path[0] == '.') {
47 if (path[1] == '\0')
48 return 0; /* "." */
49// if (path[1] == '.' && path[2] == '\0')
50// return 0; /* ".." */
51 }
41 52
42 org_mask = cur_mask = (mode_t)-1L; 53 org_mask = cur_mask = (mode_t)-1L;
43 s = path; 54 s = path;
diff --git a/libbb/update_passwd.c b/libbb/update_passwd.c
index a2004f480..95423d19b 100644
--- a/libbb/update_passwd.c
+++ b/libbb/update_passwd.c
@@ -30,7 +30,18 @@ static void check_selinux_update_passwd(const char *username)
30 if (!seuser) 30 if (!seuser)
31 bb_error_msg_and_die("invalid context '%s'", context); 31 bb_error_msg_and_die("invalid context '%s'", context);
32 if (strcmp(seuser, username) != 0) { 32 if (strcmp(seuser, username) != 0) {
33 if (checkPasswdAccess(PASSWD__PASSWD) != 0) 33 security_class_t tclass;
34 access_vector_t av;
35
36 tclass = string_to_security_class("passwd");
37 if (tclass == 0)
38 goto die;
39 av = string_to_av_perm(tclass, "passwd");
40 if (av == 0)
41 goto die;
42
43 if (selinux_check_passwd_access(av) != 0)
44 die:
34 bb_error_msg_and_die("SELinux: access denied"); 45 bb_error_msg_and_die("SELinux: access denied");
35 } 46 }
36 if (ENABLE_FEATURE_CLEAN_UP) 47 if (ENABLE_FEATURE_CLEAN_UP)
@@ -169,6 +180,7 @@ int FAST_FUNC update_passwd(const char *filename,
169 if (!line) /* EOF/error */ 180 if (!line) /* EOF/error */
170 break; 181 break;
171 182
183#if ENABLE_FEATURE_ADDUSER_TO_GROUP || ENABLE_FEATURE_DEL_USER_FROM_GROUP
172 if (!name && member) { 184 if (!name && member) {
173 /* Delete member from all groups */ 185 /* Delete member from all groups */
174 /* line is "GROUP:PASSWD:[member1[,member2]...]" */ 186 /* line is "GROUP:PASSWD:[member1[,member2]...]" */
@@ -198,6 +210,7 @@ int FAST_FUNC update_passwd(const char *filename,
198 fprintf(new_fp, "%s\n", line); 210 fprintf(new_fp, "%s\n", line);
199 goto next; 211 goto next;
200 } 212 }
213#endif
201 214
202 cp = is_prefixed_with(line, name_colon); 215 cp = is_prefixed_with(line, name_colon);
203 if (!cp) { 216 if (!cp) {
diff --git a/libbb/xatonum.c b/libbb/xatonum.c
index 9dd5c3e7e..b63b7f54d 100644
--- a/libbb/xatonum.c
+++ b/libbb/xatonum.c
@@ -96,3 +96,22 @@ const struct suffix_mult cwbkMG_suffixes[] = {
96 /* coreutils also understands TPEZY suffixes for tera- and so on, with B suffix for decimal */ 96 /* coreutils also understands TPEZY suffixes for tera- and so on, with B suffix for decimal */
97 { "", 0 } 97 { "", 0 }
98}; 98};
99
100const struct suffix_mult kmg_i_suffixes[] = {
101 { "KiB", 1024 },
102 { "kiB", 1024 },
103 { "K", 1024 },
104 { "k", 1024 },
105 { "MiB", 1048576 },
106 { "miB", 1048576 },
107 { "M", 1048576 },
108 { "m", 1048576 },
109 { "GiB", 1073741824 },
110 { "giB", 1073741824 },
111 { "G", 1073741824 },
112 { "g", 1073741824 },
113 { "KB", 1000 },
114 { "MB", 1000000 },
115 { "GB", 1000000000 },
116 { "", 0 }
117};
diff --git a/loginutils/login.c b/loginutils/login.c
index 52abc1886..3ca8213bb 100644
--- a/loginutils/login.c
+++ b/loginutils/login.c
@@ -69,7 +69,9 @@
69#if ENABLE_SELINUX 69#if ENABLE_SELINUX
70# include <selinux/selinux.h> /* for is_selinux_enabled() */ 70# include <selinux/selinux.h> /* for is_selinux_enabled() */
71# include <selinux/get_context_list.h> /* for get_default_context() */ 71# include <selinux/get_context_list.h> /* for get_default_context() */
72# include <selinux/flask.h> /* for security class definitions */ 72# /* from deprecated <selinux/flask.h>: */
73# undef SECCLASS_CHR_FILE
74# define SECCLASS_CHR_FILE 10
73#endif 75#endif
74 76
75#if ENABLE_PAM 77#if ENABLE_PAM
diff --git a/make_single_applets.sh b/make_single_applets.sh
new file mode 100755
index 000000000..00f502eda
--- /dev/null
+++ b/make_single_applets.sh
@@ -0,0 +1,73 @@
1#!/bin/sh
2# This script expects that the tree was built with the desired .config:
3# in particular, it expects that include/applets.h is generated already.
4#
5# The script will try to rebuild each enabled applet in isolation.
6# All other options which chose general bbox config, applet features, etc,
7# are not modified for the builds.
8
9makeopts="-j9"
10
11# The list of all applet config symbols
12test -f include/applets.h || { echo "No include/applets.h file"; exit 1; }
13apps="`
14grep ^IF_ include/applets.h \
15| grep -v ^IF_FEATURE_ \
16| sed 's/IF_\([A-Z0-9._-]*\)(.*/\1/' \
17| sort | uniq
18`"
19
20# Take existing config
21test -f .config || { echo "No .config file"; exit 1; }
22cfg="`cat .config`"
23
24# Make a config with all applet symbols off
25allno="$cfg"
26for app in $apps; do
27 allno="`echo "$allno" | sed "s/^CONFIG_${app}=y\$/# CONFIG_${app} is not set/"`"
28done
29#echo "$allno" >.config_allno
30
31# Turn on each applet individually and build single-applet executable
32fail=0
33for app in $apps; do
34 # Only if it was indeed originally enabled...
35 { echo "$cfg" | grep -q "^CONFIG_${app}=y\$"; } || continue
36
37 echo "Making ${app}..."
38 mv .config .config.SV
39 echo "CONFIG_${app}=y" >.config
40 echo "$allno" | sed "/^# CONFIG_${app} is not set\$/d" >>.config
41
42 if test x"${app}" != x"SH_IS_ASH" && test x"${app}" != x"SH_IS_HUSH"; then
43 # $allno has all choices for "sh" aliasing set to off.
44 # "sh" aliasing defaults to "ash", not none.
45 # without this fix, "make oldconfig" sets it wrong,
46 # resulting in NUM_APPLETS = 2 (the second applet is "sh")
47 sed '/CONFIG_SH_IS_NONE/d' -i .config
48 echo "CONFIG_SH_IS_NONE=y" >>.config
49 fi
50
51 if ! yes '' | make oldconfig >busybox_make_${app}.log 2>&1; then
52 : $((fail++))
53 echo "Config error for ${app}"
54 mv .config busybox_config_${app}
55 elif ! make $makeopts >>busybox_make_${app}.log 2>&1; then
56 : $((fail++))
57 echo "Build error for ${app}"
58 mv .config busybox_config_${app}
59 elif ! grep -q '^#define NUM_APPLETS 1$' include/NUM_APPLETS.h; then
60 mv busybox busybox_${app}
61 : $((fail++))
62 echo "NUM_APPLETS != 1 for ${app}: `cat include/NUM_APPLETS.h`"
63 mv .config busybox_config_${app}
64 else
65 mv busybox busybox_${app}
66 rm busybox_make_${app}.log
67 fi
68 mv .config.SV .config
69 #exit
70done
71touch .config # or else next "make" can be confused
72echo "Failures: $fail"
73test $fail = 0 # set exitcode
diff --git a/modutils/Config.src b/modutils/Config.src
index 4227f356a..84ff34a08 100644
--- a/modutils/Config.src
+++ b/modutils/Config.src
@@ -5,6 +5,37 @@
5 5
6menu "Linux Module Utilities" 6menu "Linux Module Utilities"
7 7
8config MODPROBE_SMALL
9 bool "Simplified modutils"
10 default y
11 select PLATFORM_LINUX
12 help
13 Simplified modutils.
14
15 With this option modprobe does not require modules.dep file
16 and does not use /etc/modules.conf file.
17 It scans module files in /lib/modules/`uname -r` and
18 determines dependencies and module alias names on the fly.
19 This may make module loading slower, most notably
20 when one needs to load module by alias (this requires
21 scanning through module _bodies_).
22
23 At the first attempt to load a module by alias modprobe
24 will try to generate modules.dep.bb file in order to speed up
25 future loads by alias. Failure to do so (read-only /lib/modules,
26 etc) is not reported, and future modprobes will be slow too.
27
28 NB: modules.dep.bb file format is not compatible
29 with modules.dep file as created/used by standard module tools.
30
31 Additional module parameters can be stored in
32 /etc/modules/$module_name files.
33
34 Apart from modprobe, other utilities are also provided:
35 - insmod is an alias to modprobe
36 - rmmod is an alias to modprobe -r
37 - depmod generates modules.dep.bb
38
8INSERT 39INSERT
9 40
10comment "Options common to multiple modutils" 41comment "Options common to multiple modutils"
diff --git a/modutils/depmod.c b/modutils/depmod.c
index b9347027e..b7965ebd2 100644
--- a/modutils/depmod.c
+++ b/modutils/depmod.c
@@ -9,17 +9,18 @@
9 */ 9 */
10//config:config DEPMOD 10//config:config DEPMOD
11//config: bool "depmod" 11//config: bool "depmod"
12//config: default n 12//config: default y
13//config: depends on !MODPROBE_SMALL
14//config: select PLATFORM_LINUX 13//config: select PLATFORM_LINUX
15//config: help 14//config: help
16//config: depmod generates modules.dep (and potentially modules.alias 15//config: depmod generates modules.dep (and potentially modules.alias
17//config: and modules.symbols) that contain dependency information 16//config: and modules.symbols) that contain dependency information
18//config: for modprobe. 17//config: for modprobe.
19 18
20//applet:IF_DEPMOD(APPLET(depmod, BB_DIR_SBIN, BB_SUID_DROP)) 19//applet:IF_DEPMOD(IF_NOT_MODPROBE_SMALL(APPLET(depmod, BB_DIR_SBIN, BB_SUID_DROP)))
21 20
21//kbuild:ifneq ($(CONFIG_MODPROBE_SMALL),y)
22//kbuild:lib-$(CONFIG_DEPMOD) += depmod.o modutils.o 22//kbuild:lib-$(CONFIG_DEPMOD) += depmod.o modutils.o
23//kbuild:endif
23 24
24#include "libbb.h" 25#include "libbb.h"
25#include "modutils.h" 26#include "modutils.h"
diff --git a/modutils/insmod.c b/modutils/insmod.c
index 2ebf4beb9..f2c70e16f 100644
--- a/modutils/insmod.c
+++ b/modutils/insmod.c
@@ -8,15 +8,16 @@
8 */ 8 */
9//config:config INSMOD 9//config:config INSMOD
10//config: bool "insmod" 10//config: bool "insmod"
11//config: default n 11//config: default y
12//config: depends on !MODPROBE_SMALL
13//config: select PLATFORM_LINUX 12//config: select PLATFORM_LINUX
14//config: help 13//config: help
15//config: insmod is used to load specified modules in the running kernel. 14//config: insmod is used to load specified modules in the running kernel.
16 15
17//applet:IF_INSMOD(APPLET(insmod, BB_DIR_SBIN, BB_SUID_DROP)) 16//applet:IF_INSMOD(IF_NOT_MODPROBE_SMALL(APPLET(insmod, BB_DIR_SBIN, BB_SUID_DROP)))
18 17
18//kbuild:ifneq ($(CONFIG_MODPROBE_SMALL),y)
19//kbuild:lib-$(CONFIG_INSMOD) += insmod.o modutils.o 19//kbuild:lib-$(CONFIG_INSMOD) += insmod.o modutils.o
20//kbuild:endif
20 21
21#include "libbb.h" 22#include "libbb.h"
22#include "modutils.h" 23#include "modutils.h"
diff --git a/modutils/lsmod.c b/modutils/lsmod.c
index ee85fb0fb..24589420a 100644
--- a/modutils/lsmod.c
+++ b/modutils/lsmod.c
@@ -9,25 +9,26 @@
9 */ 9 */
10//config:config LSMOD 10//config:config LSMOD
11//config: bool "lsmod" 11//config: bool "lsmod"
12//config: default n 12//config: default y
13//config: depends on !MODPROBE_SMALL
14//config: select PLATFORM_LINUX 13//config: select PLATFORM_LINUX
15//config: help 14//config: help
16//config: lsmod is used to display a list of loaded modules. 15//config: lsmod is used to display a list of loaded modules.
17//config: 16//config:
18//config:config FEATURE_LSMOD_PRETTY_2_6_OUTPUT 17//config:config FEATURE_LSMOD_PRETTY_2_6_OUTPUT
19//config: bool "Pretty output" 18//config: bool "Pretty output"
20//config: default n 19//config: default y
21//config: depends on LSMOD 20//config: depends on LSMOD && !MODPROBE_SMALL
22//config: select PLATFORM_LINUX 21//config: select PLATFORM_LINUX
23//config: help 22//config: help
24//config: This option makes output format of lsmod adjusted to 23//config: This option makes output format of lsmod adjusted to
25//config: the format of module-init-tools for Linux kernel 2.6. 24//config: the format of module-init-tools for Linux kernel 2.6.
26//config: Increases size somewhat. 25//config: Increases size somewhat.
27 26
28//applet:IF_LSMOD(APPLET(lsmod, BB_DIR_SBIN, BB_SUID_DROP)) 27//applet:IF_LSMOD(IF_NOT_MODPROBE_SMALL(APPLET(lsmod, BB_DIR_SBIN, BB_SUID_DROP)))
29 28
29//kbuild:ifneq ($(CONFIG_MODPROBE_SMALL),y)
30//kbuild:lib-$(CONFIG_LSMOD) += lsmod.o modutils.o 30//kbuild:lib-$(CONFIG_LSMOD) += lsmod.o modutils.o
31//kbuild:endif
31 32
32//usage:#if !ENABLE_MODPROBE_SMALL 33//usage:#if !ENABLE_MODPROBE_SMALL
33//usage:#define lsmod_trivial_usage 34//usage:#define lsmod_trivial_usage
diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c
index 51ba42f7a..0fc9ea454 100644
--- a/modutils/modprobe-small.c
+++ b/modutils/modprobe-small.c
@@ -7,37 +7,9 @@
7 * 7 *
8 * Licensed under GPLv2, see file LICENSE in this source tree. 8 * Licensed under GPLv2, see file LICENSE in this source tree.
9 */ 9 */
10//config:config MODPROBE_SMALL 10
11//config: bool "Simplified modutils" 11/* config MODPROBE_SMALL is defined in Config.src to ensure better "make config" order */
12//config: default y 12
13//config: select PLATFORM_LINUX
14//config: help
15//config: Simplified modutils.
16//config:
17//config: With this option modprobe does not require modules.dep file
18//config: and does not use /etc/modules.conf file.
19//config: It scans module files in /lib/modules/`uname -r` and
20//config: determines dependencies and module alias names on the fly.
21//config: This may make module loading slower, most notably
22//config: when one needs to load module by alias (this requires
23//config: scanning through module _bodies_).
24//config:
25//config: At the first attempt to load a module by alias modprobe
26//config: will try to generate modules.dep.bb file in order to speed up
27//config: future loads by alias. Failure to do so (read-only /lib/modules,
28//config: etc) is not reported, and future modprobes will be slow too.
29//config:
30//config: NB: modules.dep.bb file format is not compatible
31//config: with modules.dep file as created/used by standard module tools.
32//config:
33//config: Additional module parameters can be stored in
34//config: /etc/modules/$module_name files.
35//config:
36//config: Apart from modprobe, other utilities are also provided:
37//config: - insmod is an alias to modprobe
38//config: - rmmod is an alias to modprobe -r
39//config: - depmod generates modules.dep.bb
40//config:
41//config:config FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE 13//config:config FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE
42//config: bool "Accept module options on modprobe command line" 14//config: bool "Accept module options on modprobe command line"
43//config: default y 15//config: default y
@@ -53,11 +25,11 @@
53//config: help 25//config: help
54//config: Check if the module is already loaded. 26//config: Check if the module is already loaded.
55 27
56//applet:IF_MODPROBE_SMALL(APPLET(modprobe, BB_DIR_SBIN, BB_SUID_DROP)) 28//applet:IF_MODPROBE(IF_MODPROBE_SMALL(APPLET(modprobe, BB_DIR_SBIN, BB_SUID_DROP)))
57//applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(depmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, depmod)) 29//applet:IF_DEPMOD(IF_MODPROBE_SMALL(APPLET_ODDNAME(depmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, depmod)))
58//applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(insmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, insmod)) 30//applet:IF_INSMOD(IF_MODPROBE_SMALL(APPLET_ODDNAME(insmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, insmod)))
59//applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(lsmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, lsmod)) 31//applet:IF_LSMOD(IF_MODPROBE_SMALL(APPLET_ODDNAME(lsmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, lsmod)))
60//applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(rmmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, rmmod)) 32//applet:IF_RMMOD(IF_MODPROBE_SMALL(APPLET_ODDNAME(rmmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, rmmod)))
61 33
62//kbuild:lib-$(CONFIG_MODPROBE_SMALL) += modprobe-small.o 34//kbuild:lib-$(CONFIG_MODPROBE_SMALL) += modprobe-small.o
63 35
@@ -67,8 +39,8 @@
67#include <fnmatch.h> 39#include <fnmatch.h>
68#include <sys/syscall.h> 40#include <sys/syscall.h>
69 41
70extern int init_module(void *module, unsigned long len, const char *options); 42#define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts)
71extern int delete_module(const char *module, unsigned flags); 43#define delete_module(mod, flags) syscall(__NR_delete_module, mod, flags)
72#ifdef __NR_finit_module 44#ifdef __NR_finit_module
73# define finit_module(fd, uargs, flags) syscall(__NR_finit_module, fd, uargs, flags) 45# define finit_module(fd, uargs, flags) syscall(__NR_finit_module, fd, uargs, flags)
74#endif 46#endif
@@ -958,7 +930,7 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
958 IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(char *options;) 930 IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(char *options;)
959 931
960 /* are we lsmod? -> just dump /proc/modules */ 932 /* are we lsmod? -> just dump /proc/modules */
961 if ('l' == applet0) { 933 if (ENABLE_LSMOD && 'l' == applet0) {
962 xprint_and_close_file(xfopen_for_read("/proc/modules")); 934 xprint_and_close_file(xfopen_for_read("/proc/modules"));
963 return EXIT_SUCCESS; 935 return EXIT_SUCCESS;
964 } 936 }
@@ -968,14 +940,14 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
968 /* Prevent ugly corner cases with no modules at all */ 940 /* Prevent ugly corner cases with no modules at all */
969 modinfo = xzalloc(sizeof(modinfo[0])); 941 modinfo = xzalloc(sizeof(modinfo[0]));
970 942
971 if ('i' != applet0) { /* not insmod */ 943 if (!ENABLE_INSMOD || 'i' != applet0) { /* not insmod */
972 /* Goto modules directory */ 944 /* Goto modules directory */
973 xchdir(CONFIG_DEFAULT_MODULES_DIR); 945 xchdir(CONFIG_DEFAULT_MODULES_DIR);
974 } 946 }
975 uname(&uts); /* never fails */ 947 uname(&uts); /* never fails */
976 948
977 /* depmod? */ 949 /* depmod? */
978 if ('d' == applet0) { 950 if (ENABLE_DEPMOD && 'd' == applet0) {
979 /* Supported: 951 /* Supported:
980 * -n: print result to stdout 952 * -n: print result to stdout
981 * -a: process all modules (default) 953 * -a: process all modules (default)
@@ -1014,11 +986,11 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
1014 argv += optind; 986 argv += optind;
1015 987
1016 /* are we rmmod? -> simulate modprobe -r */ 988 /* are we rmmod? -> simulate modprobe -r */
1017 if ('r' == applet0) { 989 if (ENABLE_RMMOD && 'r' == applet0) {
1018 option_mask32 |= OPT_r; 990 option_mask32 |= OPT_r;
1019 } 991 }
1020 992
1021 if ('i' != applet0) { /* not insmod */ 993 if (!ENABLE_INSMOD || 'i' != applet0) { /* not insmod */
1022 /* Goto $VERSION directory */ 994 /* Goto $VERSION directory */
1023 xchdir(uts.release); 995 xchdir(uts.release);
1024 } 996 }
@@ -1042,7 +1014,7 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
1042 argv[1] = NULL; 1014 argv[1] = NULL;
1043#endif 1015#endif
1044 1016
1045 if ('i' == applet0) { /* insmod */ 1017 if (ENABLE_INSMOD && 'i' == applet0) { /* insmod */
1046 size_t len; 1018 size_t len;
1047 void *map; 1019 void *map;
1048 1020
@@ -1062,7 +1034,7 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
1062 } 1034 }
1063 1035
1064 /* Try to load modprobe.dep.bb */ 1036 /* Try to load modprobe.dep.bb */
1065 if ('r' != applet0) { /* not rmmod */ 1037 if (!ENABLE_RMMOD || 'r' != applet0) { /* not rmmod */
1066 load_dep_bb(); 1038 load_dep_bb();
1067 } 1039 }
1068 1040
diff --git a/modutils/modprobe.c b/modutils/modprobe.c
index d404ef92f..09e3de6c3 100644
--- a/modutils/modprobe.c
+++ b/modutils/modprobe.c
@@ -9,8 +9,7 @@
9 */ 9 */
10//config:config MODPROBE 10//config:config MODPROBE
11//config: bool "modprobe" 11//config: bool "modprobe"
12//config: default n 12//config: default y
13//config: depends on !MODPROBE_SMALL
14//config: select PLATFORM_LINUX 13//config: select PLATFORM_LINUX
15//config: help 14//config: help
16//config: Handle the loading of modules, and their dependencies on a high 15//config: Handle the loading of modules, and their dependencies on a high
@@ -18,8 +17,8 @@
18//config: 17//config:
19//config:config FEATURE_MODPROBE_BLACKLIST 18//config:config FEATURE_MODPROBE_BLACKLIST
20//config: bool "Blacklist support" 19//config: bool "Blacklist support"
21//config: default n 20//config: default y
22//config: depends on MODPROBE 21//config: depends on MODPROBE && !MODPROBE_SMALL
23//config: select PLATFORM_LINUX 22//config: select PLATFORM_LINUX
24//config: help 23//config: help
25//config: Say 'y' here to enable support for the 'blacklist' command in 24//config: Say 'y' here to enable support for the 'blacklist' command in
@@ -28,9 +27,11 @@
28//config: hardware autodetection scripts to load modules like evdev, frame 27//config: hardware autodetection scripts to load modules like evdev, frame
29//config: buffer drivers etc. 28//config: buffer drivers etc.
30 29
31//applet:IF_MODPROBE(APPLET(modprobe, BB_DIR_SBIN, BB_SUID_DROP)) 30//applet:IF_MODPROBE(IF_NOT_MODPROBE_SMALL(APPLET(modprobe, BB_DIR_SBIN, BB_SUID_DROP)))
32 31
32//kbuild:ifneq ($(CONFIG_MODPROBE_SMALL),y)
33//kbuild:lib-$(CONFIG_MODPROBE) += modprobe.o modutils.o 33//kbuild:lib-$(CONFIG_MODPROBE) += modprobe.o modutils.o
34//kbuild:endif
34 35
35#include "libbb.h" 36#include "libbb.h"
36#include "modutils.h" 37#include "modutils.h"
diff --git a/modutils/modutils.c b/modutils/modutils.c
index d36caaf68..4204f06fe 100644
--- a/modutils/modutils.c
+++ b/modutils/modutils.c
@@ -7,17 +7,13 @@
7 */ 7 */
8#include "modutils.h" 8#include "modutils.h"
9 9
10#ifdef __UCLIBC__ 10#include <sys/syscall.h>
11extern int init_module(void *module, unsigned long len, const char *options); 11
12extern int delete_module(const char *module, unsigned int flags); 12#define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts)
13#else 13#if defined(__NR_finit_module)
14# include <sys/syscall.h> 14# define finit_module(fd, uargs, flags) syscall(__NR_finit_module, fd, uargs, flags)
15# define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts)
16# if defined(__NR_finit_module)
17# define finit_module(fd, uargs, flags) syscall(__NR_finit_module, fd, uargs, flags)
18# endif
19# define delete_module(mod, flags) syscall(__NR_delete_module, mod, flags)
20#endif 15#endif
16#define delete_module(mod, flags) syscall(__NR_delete_module, mod, flags)
21 17
22static module_entry *helper_get_module(module_db *db, const char *module, int create) 18static module_entry *helper_get_module(module_db *db, const char *module, int create)
23{ 19{
diff --git a/modutils/rmmod.c b/modutils/rmmod.c
index e0358838a..527696f63 100644
--- a/modutils/rmmod.c
+++ b/modutils/rmmod.c
@@ -9,15 +9,16 @@
9 */ 9 */
10//config:config RMMOD 10//config:config RMMOD
11//config: bool "rmmod" 11//config: bool "rmmod"
12//config: default n 12//config: default y
13//config: depends on !MODPROBE_SMALL
14//config: select PLATFORM_LINUX 13//config: select PLATFORM_LINUX
15//config: help 14//config: help
16//config: rmmod is used to unload specified modules from the kernel. 15//config: rmmod is used to unload specified modules from the kernel.
17 16
18//applet:IF_RMMOD(APPLET(rmmod, BB_DIR_SBIN, BB_SUID_DROP)) 17//applet:IF_RMMOD(IF_NOT_MODPROBE_SMALL(APPLET(rmmod, BB_DIR_SBIN, BB_SUID_DROP)))
19 18
19//kbuild:ifneq ($(CONFIG_MODPROBE_SMALL),y)
20//kbuild:lib-$(CONFIG_RMMOD) += rmmod.o modutils.o 20//kbuild:lib-$(CONFIG_RMMOD) += rmmod.o modutils.o
21//kbuild:endif
21 22
22//usage:#if !ENABLE_MODPROBE_SMALL 23//usage:#if !ENABLE_MODPROBE_SMALL
23//usage:#define rmmod_trivial_usage 24//usage:#define rmmod_trivial_usage
diff --git a/networking/Config.src b/networking/Config.src
index 527bdd15d..0adb1e2f9 100644
--- a/networking/Config.src
+++ b/networking/Config.src
@@ -53,7 +53,7 @@ source networking/udhcp/Config.in
53config IFUPDOWN_UDHCPC_CMD_OPTIONS 53config IFUPDOWN_UDHCPC_CMD_OPTIONS
54 string "ifup udhcpc command line options" 54 string "ifup udhcpc command line options"
55 default "-R -n" 55 default "-R -n"
56 depends on IFUPDOWN && UDHCPC 56 depends on IFUP || IFDOWN
57 help 57 help
58 Command line options to pass to udhcpc from ifup. 58 Command line options to pass to udhcpc from ifup.
59 Intended to alter options not available in /etc/network/interfaces. 59 Intended to alter options not available in /etc/network/interfaces.
diff --git a/networking/ifupdown.c b/networking/ifupdown.c
index 7ac517afd..1806a6ccc 100644
--- a/networking/ifupdown.c
+++ b/networking/ifupdown.c
@@ -51,41 +51,19 @@
51//config: This config option defines location of ifstate. 51//config: This config option defines location of ifstate.
52//config: 52//config:
53//config:config FEATURE_IFUPDOWN_IP 53//config:config FEATURE_IFUPDOWN_IP
54//config: bool "Use ip applet" 54//config: bool "Use ip tool (else ifconfig/route is used)"
55//config: default y 55//config: default y
56//config: depends on IFUP || IFDOWN 56//config: depends on IFUP || IFDOWN
57//config: help 57//config: help
58//config: Use the iproute "ip" command to implement "ifup" and "ifdown", rather 58//config: Use the iproute "ip" command to implement "ifup" and "ifdown", rather
59//config: than the default of using the older 'ifconfig' and 'route' utilities. 59//config: than the default of using the older "ifconfig" and "route" utilities.
60//config: 60//config:
61//config:config FEATURE_IFUPDOWN_IP_BUILTIN 61//config: If Y: you must install either the full-blown iproute2 package
62//config: bool "Use busybox ip applet" 62//config: or enable "ip" applet in Busybox, or the "ifup" and "ifdown" applets
63//config: default y 63//config: will not work.
64//config: depends on FEATURE_IFUPDOWN_IP
65//config: select PLATFORM_LINUX
66//config: select IP
67//config: select FEATURE_IP_ADDRESS
68//config: select FEATURE_IP_LINK
69//config: select FEATURE_IP_ROUTE
70//config: help
71//config: Use the busybox iproute "ip" applet to implement "ifupdown".
72//config:
73//config: If left disabled, you must install the full-blown iproute2
74//config: utility or the "ifup" and "ifdown" applets will not work.
75//config:
76//config:config FEATURE_IFUPDOWN_IFCONFIG_BUILTIN
77//config: bool "Use busybox ifconfig and route applets"
78//config: default n
79//config: depends on (IFUP || IFDOWN) && !FEATURE_IFUPDOWN_IP
80//config: select IFCONFIG
81//config: select ROUTE
82//config: help
83//config: Use the busybox iproute "ifconfig" and "route" applets to
84//config: implement the "ifup" and "ifdown" utilities.
85//config: 64//config:
86//config: If left disabled, you must install the full-blown ifconfig 65//config: If N: you must install either the full-blown ifconfig and route
87//config: and route utilities, or the "ifup" and "ifdown" applets will not 66//config: utilities, or enable these applets in Busybox.
88//config: work.
89//config: 67//config:
90//config:config FEATURE_IFUPDOWN_IPV4 68//config:config FEATURE_IFUPDOWN_IPV4
91//config: bool "Support for IPv4" 69//config: bool "Support for IPv4"
diff --git a/networking/ip.c b/networking/ip.c
index c3607b74f..939721e46 100644
--- a/networking/ip.c
+++ b/networking/ip.c
@@ -17,24 +17,72 @@
17//config: utility. You generally don't need "ip" to use busybox with 17//config: utility. You generally don't need "ip" to use busybox with
18//config: TCP/IP. 18//config: TCP/IP.
19//config: 19//config:
20//config:config IPADDR
21//config: bool "ipaddr"
22//config: default y
23//config: select FEATURE_IP_ADDRESS
24//config: select PLATFORM_LINUX
25//config: help
26//config: Support short form of ip addr: ipaddr
27//config:
28//config:config IPLINK
29//config: bool "iplink"
30//config: default y
31//config: select FEATURE_IP_LINK
32//config: select PLATFORM_LINUX
33//config: help
34//config: Support short form of ip link: iplink
35//config:
36//config:config IPROUTE
37//config: bool "iproute"
38//config: default y
39//config: select FEATURE_IP_ROUTE
40//config: select PLATFORM_LINUX
41//config: help
42//config: Support short form of ip route: iproute
43//config:
44//config:config IPTUNNEL
45//config: bool "iptunnel"
46//config: default y
47//config: select FEATURE_IP_TUNNEL
48//config: select PLATFORM_LINUX
49//config: help
50//config: Support short form of ip tunnel: iptunnel
51//config:
52//config:config IPRULE
53//config: bool "iprule"
54//config: default y
55//config: select FEATURE_IP_RULE
56//config: select PLATFORM_LINUX
57//config: help
58//config: Support short form of ip rule: iprule
59//config:
60//config:config IPNEIGH
61//config: bool "ipneigh"
62//config: default y
63//config: select FEATURE_IP_NEIGH
64//config: select PLATFORM_LINUX
65//config: help
66//config: Support short form of ip neigh: ipneigh
67//config:
20//config:config FEATURE_IP_ADDRESS 68//config:config FEATURE_IP_ADDRESS
21//config: bool "ip address" 69//config: bool "ip address"
22//config: default y 70//config: default y
23//config: depends on IP 71//config: depends on IP || IPADDR
24//config: help 72//config: help
25//config: Address manipulation support for the "ip" applet. 73//config: Address manipulation support for the "ip" applet.
26//config: 74//config:
27//config:config FEATURE_IP_LINK 75//config:config FEATURE_IP_LINK
28//config: bool "ip link" 76//config: bool "ip link"
29//config: default y 77//config: default y
30//config: depends on IP 78//config: depends on IP || IPLINK
31//config: help 79//config: help
32//config: Configure network devices with "ip". 80//config: Configure network devices with "ip".
33//config: 81//config:
34//config:config FEATURE_IP_ROUTE 82//config:config FEATURE_IP_ROUTE
35//config: bool "ip route" 83//config: bool "ip route"
36//config: default y 84//config: default y
37//config: depends on IP 85//config: depends on IP || IPROUTE
38//config: help 86//config: help
39//config: Add support for routing table management to "ip". 87//config: Add support for routing table management to "ip".
40//config: 88//config:
@@ -48,83 +96,35 @@
48//config:config FEATURE_IP_TUNNEL 96//config:config FEATURE_IP_TUNNEL
49//config: bool "ip tunnel" 97//config: bool "ip tunnel"
50//config: default y 98//config: default y
51//config: depends on IP 99//config: depends on IP || IPTUNNEL
52//config: help 100//config: help
53//config: Add support for tunneling commands to "ip". 101//config: Add support for tunneling commands to "ip".
54//config: 102//config:
55//config:config FEATURE_IP_RULE 103//config:config FEATURE_IP_RULE
56//config: bool "ip rule" 104//config: bool "ip rule"
57//config: default y 105//config: default y
58//config: depends on IP 106//config: depends on IP || IPRULE
59//config: help 107//config: help
60//config: Add support for rule commands to "ip". 108//config: Add support for rule commands to "ip".
61//config: 109//config:
62//config:config FEATURE_IP_NEIGH 110//config:config FEATURE_IP_NEIGH
63//config: bool "ip neighbor" 111//config: bool "ip neighbor"
64//config: default y 112//config: default y
65//config: depends on IP 113//config: depends on IP || IPNEIGH
66//config: help 114//config: help
67//config: Add support for neighbor commands to "ip". 115//config: Add support for neighbor commands to "ip".
68//config: 116//config:
69//config:config FEATURE_IP_SHORT_FORMS
70//config: bool "Support short forms of ip commands"
71//config: default y
72//config: depends on IP
73//config: help
74//config: Also support short-form of ip <OBJECT> commands:
75//config: ip addr -> ipaddr
76//config: ip link -> iplink
77//config: ip route -> iproute
78//config: ip tunnel -> iptunnel
79//config: ip rule -> iprule
80//config: ip neigh -> ipneigh
81//config:
82//config: Say N unless you desparately need the short form of the ip
83//config: object commands.
84//config:
85//config:config FEATURE_IP_RARE_PROTOCOLS 117//config:config FEATURE_IP_RARE_PROTOCOLS
86//config: bool "Support displaying rarely used link types" 118//config: bool "Support displaying rarely used link types"
87//config: default n 119//config: default n
88//config: depends on IP 120//config: depends on IP || IPADDR || IPLINK || IPROUTE || IPTUNNEL || IPRULE || IPNEIGH
89//config: help 121//config: help
90//config: If you are not going to use links of type "frad", "econet", 122//config: If you are not going to use links of type "frad", "econet",
91//config: "bif" etc, you probably don't need to enable this. 123//config: "bif" etc, you probably don't need to enable this.
92//config: Ethernet, wireless, infrared, ppp/slip, ip tunnelling 124//config: Ethernet, wireless, infrared, ppp/slip, ip tunnelling
93//config: link types are supported without this option selected. 125//config: link types are supported without this option selected.
94//config:
95//config:config IPADDR
96//config: bool
97//config: default y
98//config: depends on FEATURE_IP_SHORT_FORMS && FEATURE_IP_ADDRESS
99//config:
100//config:config IPLINK
101//config: bool
102//config: default y
103//config: depends on FEATURE_IP_SHORT_FORMS && FEATURE_IP_LINK
104//config:
105//config:config IPROUTE
106//config: bool
107//config: default y
108//config: depends on FEATURE_IP_SHORT_FORMS && FEATURE_IP_ROUTE
109//config:
110//config:config IPTUNNEL
111//config: bool
112//config: default y
113//config: depends on FEATURE_IP_SHORT_FORMS && FEATURE_IP_TUNNEL
114//config:
115//config:config IPRULE
116//config: bool
117//config: default y
118//config: depends on FEATURE_IP_SHORT_FORMS && FEATURE_IP_RULE
119//config:
120//config:config IPNEIGH
121//config: bool
122//config: default y
123//config: depends on FEATURE_IP_SHORT_FORMS && FEATURE_IP_NEIGH
124 126
125//applet:#if ENABLE_FEATURE_IP_ADDRESS || ENABLE_FEATURE_IP_ROUTE || ENABLE_FEATURE_IP_LINK || ENABLE_FEATURE_IP_TUNNEL || ENABLE_FEATURE_IP_RULE || ENABLE_FEATURE_IP_NEIGH
126//applet:IF_IP(APPLET(ip, BB_DIR_SBIN, BB_SUID_DROP)) 127//applet:IF_IP(APPLET(ip, BB_DIR_SBIN, BB_SUID_DROP))
127//applet:#endif
128//applet:IF_IPADDR(APPLET(ipaddr, BB_DIR_SBIN, BB_SUID_DROP)) 128//applet:IF_IPADDR(APPLET(ipaddr, BB_DIR_SBIN, BB_SUID_DROP))
129//applet:IF_IPLINK(APPLET(iplink, BB_DIR_SBIN, BB_SUID_DROP)) 129//applet:IF_IPLINK(APPLET(iplink, BB_DIR_SBIN, BB_SUID_DROP))
130//applet:IF_IPROUTE(APPLET(iproute, BB_DIR_SBIN, BB_SUID_DROP)) 130//applet:IF_IPROUTE(APPLET(iproute, BB_DIR_SBIN, BB_SUID_DROP))
@@ -133,6 +133,12 @@
133//applet:IF_IPNEIGH(APPLET(ipneigh, BB_DIR_SBIN, BB_SUID_DROP)) 133//applet:IF_IPNEIGH(APPLET(ipneigh, BB_DIR_SBIN, BB_SUID_DROP))
134 134
135//kbuild:lib-$(CONFIG_IP) += ip.o 135//kbuild:lib-$(CONFIG_IP) += ip.o
136//kbuild:lib-$(CONFIG_IPADDR) += ip.o
137//kbuild:lib-$(CONFIG_IPLINK) += ip.o
138//kbuild:lib-$(CONFIG_IPROUTE) += ip.o
139//kbuild:lib-$(CONFIG_IPRULE) += ip.o
140//kbuild:lib-$(CONFIG_IPTUNNEL) += ip.o
141//kbuild:lib-$(CONFIG_IPNEIGH) += ip.o
136 142
137/* would need to make the " | " optional depending on more than one selected: */ 143/* would need to make the " | " optional depending on more than one selected: */
138//usage:#define ip_trivial_usage 144//usage:#define ip_trivial_usage
@@ -218,62 +224,57 @@
218#include "libiproute/utils.h" 224#include "libiproute/utils.h"
219#include "libiproute/ip_common.h" 225#include "libiproute/ip_common.h"
220 226
221#if ENABLE_FEATURE_IP_ADDRESS \
222 || ENABLE_FEATURE_IP_ROUTE \
223 || ENABLE_FEATURE_IP_LINK \
224 || ENABLE_FEATURE_IP_TUNNEL \
225 || ENABLE_FEATURE_IP_RULE \
226 || ENABLE_FEATURE_IP_NEIGH
227
228static int FAST_FUNC ip_print_help(char **argv UNUSED_PARAM)
229{
230 bb_show_usage();
231}
232
233typedef int FAST_FUNC (*ip_func_ptr_t)(char**); 227typedef int FAST_FUNC (*ip_func_ptr_t)(char**);
234 228
229#if ENABLE_IPADDR \
230 || ENABLE_IPLINK \
231 || ENABLE_IPROUTE \
232 || ENABLE_IPRULE \
233 || ENABLE_IPTUNNEL \
234 || ENABLE_IPNEIGH
235static int ip_do(ip_func_ptr_t ip_func, char **argv) 235static int ip_do(ip_func_ptr_t ip_func, char **argv)
236{ 236{
237 argv = ip_parse_common_args(argv + 1); 237 argv = ip_parse_common_args(argv + 1);
238 return ip_func(argv); 238 return ip_func(argv);
239} 239}
240#endif
240 241
241#if ENABLE_FEATURE_IP_ADDRESS 242#if ENABLE_IPADDR
242int ipaddr_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 243int ipaddr_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
243int ipaddr_main(int argc UNUSED_PARAM, char **argv) 244int ipaddr_main(int argc UNUSED_PARAM, char **argv)
244{ 245{
245 return ip_do(do_ipaddr, argv); 246 return ip_do(do_ipaddr, argv);
246} 247}
247#endif 248#endif
248#if ENABLE_FEATURE_IP_LINK 249#if ENABLE_IPLINK
249int iplink_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 250int iplink_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
250int iplink_main(int argc UNUSED_PARAM, char **argv) 251int iplink_main(int argc UNUSED_PARAM, char **argv)
251{ 252{
252 return ip_do(do_iplink, argv); 253 return ip_do(do_iplink, argv);
253} 254}
254#endif 255#endif
255#if ENABLE_FEATURE_IP_ROUTE 256#if ENABLE_IPROUTE
256int iproute_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 257int iproute_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
257int iproute_main(int argc UNUSED_PARAM, char **argv) 258int iproute_main(int argc UNUSED_PARAM, char **argv)
258{ 259{
259 return ip_do(do_iproute, argv); 260 return ip_do(do_iproute, argv);
260} 261}
261#endif 262#endif
262#if ENABLE_FEATURE_IP_RULE 263#if ENABLE_IPRULE
263int iprule_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 264int iprule_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
264int iprule_main(int argc UNUSED_PARAM, char **argv) 265int iprule_main(int argc UNUSED_PARAM, char **argv)
265{ 266{
266 return ip_do(do_iprule, argv); 267 return ip_do(do_iprule, argv);
267} 268}
268#endif 269#endif
269#if ENABLE_FEATURE_IP_TUNNEL 270#if ENABLE_IPTUNNEL
270int iptunnel_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 271int iptunnel_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
271int iptunnel_main(int argc UNUSED_PARAM, char **argv) 272int iptunnel_main(int argc UNUSED_PARAM, char **argv)
272{ 273{
273 return ip_do(do_iptunnel, argv); 274 return ip_do(do_iptunnel, argv);
274} 275}
275#endif 276#endif
276#if ENABLE_FEATURE_IP_NEIGH 277#if ENABLE_IPNEIGH
277int ipneigh_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 278int ipneigh_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
278int ipneigh_main(int argc UNUSED_PARAM, char **argv) 279int ipneigh_main(int argc UNUSED_PARAM, char **argv)
279{ 280{
@@ -281,11 +282,16 @@ int ipneigh_main(int argc UNUSED_PARAM, char **argv)
281} 282}
282#endif 283#endif
283 284
285#if ENABLE_IP
286static int FAST_FUNC ip_print_help(char **argv UNUSED_PARAM)
287{
288 bb_show_usage();
289}
284 290
285int ip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 291int ip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
286int ip_main(int argc UNUSED_PARAM, char **argv) 292int ip_main(int argc UNUSED_PARAM, char **argv)
287{ 293{
288 static const char keywords[] ALIGN1 = 294 static const char keywords[] ALIGN1 = ""
289 IF_FEATURE_IP_ADDRESS("address\0") 295 IF_FEATURE_IP_ADDRESS("address\0")
290 IF_FEATURE_IP_ROUTE("route\0") 296 IF_FEATURE_IP_ROUTE("route\0")
291 IF_FEATURE_IP_ROUTE("r\0") 297 IF_FEATURE_IP_ROUTE("r\0")
@@ -310,10 +316,12 @@ int ip_main(int argc UNUSED_PARAM, char **argv)
310 int key; 316 int key;
311 317
312 argv = ip_parse_common_args(argv + 1); 318 argv = ip_parse_common_args(argv + 1);
313 key = *argv ? index_in_substrings(keywords, *argv++) : -1; 319 if (ARRAY_SIZE(ip_func_ptrs) > 1 && *argv)
320 key = index_in_substrings(keywords, *argv++);
321 else
322 key = -1;
314 ip_func = ip_func_ptrs[key + 1]; 323 ip_func = ip_func_ptrs[key + 1];
315 324
316 return ip_func(argv); 325 return ip_func(argv);
317} 326}
318 327#endif
319#endif /* any of ENABLE_FEATURE_IP_xxx is 1 */
diff --git a/networking/libiproute/Kbuild.src b/networking/libiproute/Kbuild.src
index c20e2fee8..056a58540 100644
--- a/networking/libiproute/Kbuild.src
+++ b/networking/libiproute/Kbuild.src
@@ -62,13 +62,16 @@ lib-$(CONFIG_FEATURE_IP_TUNNEL) += \
62lib-$(CONFIG_FEATURE_IP_RULE) += \ 62lib-$(CONFIG_FEATURE_IP_RULE) += \
63 ip_parse_common_args.o \ 63 ip_parse_common_args.o \
64 iprule.o \ 64 iprule.o \
65 libnetlink.o \
65 rt_names.o \ 66 rt_names.o \
67 rtm_map.o \
66 utils.o 68 utils.o
67 69
68lib-$(CONFIG_FEATURE_IP_NEIGH) += \ 70lib-$(CONFIG_FEATURE_IP_NEIGH) += \
69 ip_parse_common_args.o \ 71 ip_parse_common_args.o \
70 ipneigh.o \ 72 ipneigh.o \
71 libnetlink.o \ 73 libnetlink.o \
74 ll_addr.o \
72 ll_map.o \ 75 ll_map.o \
73 rt_names.o \ 76 rt_names.o \
74 utils.o 77 utils.o
diff --git a/networking/libiproute/iproute.c b/networking/libiproute/iproute.c
index 48dc6e3d9..0f2b89682 100644
--- a/networking/libiproute/iproute.c
+++ b/networking/libiproute/iproute.c
@@ -66,6 +66,7 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
66 inet_prefix dst; 66 inet_prefix dst;
67 inet_prefix src; 67 inet_prefix src;
68 int host_len = -1; 68 int host_len = -1;
69 uint32_t tid;
69 70
70 if (n->nlmsg_type != RTM_NEWROUTE && n->nlmsg_type != RTM_DELROUTE) { 71 if (n->nlmsg_type != RTM_NEWROUTE && n->nlmsg_type != RTM_DELROUTE) {
71 fprintf(stderr, "Not a route: %08x %08x %08x\n", 72 fprintf(stderr, "Not a route: %08x %08x %08x\n",
@@ -78,6 +79,14 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
78 if (len < 0) 79 if (len < 0)
79 bb_error_msg_and_die("wrong nlmsg len %d", len); 80 bb_error_msg_and_die("wrong nlmsg len %d", len);
80 81
82 memset(tb, 0, sizeof(tb));
83 parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);
84
85 if (tb[RTA_TABLE])
86 tid = *(uint32_t *)RTA_DATA(tb[RTA_TABLE]);
87 else
88 tid = r->rtm_table;
89
81 if (r->rtm_family == AF_INET6) 90 if (r->rtm_family == AF_INET6)
82 host_len = 128; 91 host_len = 128;
83 else if (r->rtm_family == AF_INET) 92 else if (r->rtm_family == AF_INET)
@@ -107,7 +116,7 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
107 } 116 }
108 } 117 }
109 } else { 118 } else {
110 if (G_filter.tb > 0 && G_filter.tb != r->rtm_table) { 119 if (G_filter.tb > 0 && G_filter.tb != tid) {
111 return 0; 120 return 0;
112 } 121 }
113 } 122 }
@@ -136,10 +145,8 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
136 return 0; 145 return 0;
137 } 146 }
138 147
139 memset(tb, 0, sizeof(tb));
140 memset(&src, 0, sizeof(src)); 148 memset(&src, 0, sizeof(src));
141 memset(&dst, 0, sizeof(dst)); 149 memset(&dst, 0, sizeof(dst));
142 parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);
143 150
144 if (tb[RTA_SRC]) { 151 if (tb[RTA_SRC]) {
145 src.bitlen = r->rtm_src_len; 152 src.bitlen = r->rtm_src_len;
@@ -258,6 +265,10 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
258 if (tb[RTA_OIF]) { 265 if (tb[RTA_OIF]) {
259 printf("dev %s ", ll_index_to_name(*(int*)RTA_DATA(tb[RTA_OIF]))); 266 printf("dev %s ", ll_index_to_name(*(int*)RTA_DATA(tb[RTA_OIF])));
260 } 267 }
268#if ENABLE_FEATURE_IP_RULE
269 if (tid && tid != RT_TABLE_MAIN && !G_filter.tb)
270 printf("table %s ", rtnl_rttable_n2a(tid));
271#endif
261 272
262 /* Todo: parse & show "proto kernel", "scope link" here */ 273 /* Todo: parse & show "proto kernel", "scope link" here */
263 274
@@ -419,7 +430,12 @@ IF_FEATURE_IP_RULE(ARG_table,)
419 NEXT_ARG(); 430 NEXT_ARG();
420 if (rtnl_rttable_a2n(&tid, *argv)) 431 if (rtnl_rttable_a2n(&tid, *argv))
421 invarg_1_to_2(*argv, "table"); 432 invarg_1_to_2(*argv, "table");
422 req.r.rtm_table = tid; 433 if (tid < 256)
434 req.r.rtm_table = tid;
435 else {
436 req.r.rtm_table = RT_TABLE_UNSPEC;
437 addattr32(&req.n, sizeof(req), RTA_TABLE, tid);
438 }
423#endif 439#endif
424 } else if (arg == ARG_dev || arg == ARG_oif) { 440 } else if (arg == ARG_dev || arg == ARG_oif) {
425 NEXT_ARG(); 441 NEXT_ARG();
diff --git a/networking/libiproute/iprule.c b/networking/libiproute/iprule.c
index c486834b0..8f3f86286 100644
--- a/networking/libiproute/iprule.c
+++ b/networking/libiproute/iprule.c
@@ -114,7 +114,9 @@ static int FAST_FUNC print_rule(const struct sockaddr_nl *who UNUSED_PARAM,
114 printf("iif %s ", (char*)RTA_DATA(tb[RTA_IIF])); 114 printf("iif %s ", (char*)RTA_DATA(tb[RTA_IIF]));
115 } 115 }
116 116
117 if (r->rtm_table) 117 if (tb[RTA_TABLE])
118 printf("lookup %s ", rtnl_rttable_n2a(*(uint32_t*)RTA_DATA(tb[RTA_TABLE])));
119 else if (r->rtm_table)
118 printf("lookup %s ", rtnl_rttable_n2a(r->rtm_table)); 120 printf("lookup %s ", rtnl_rttable_n2a(r->rtm_table));
119 121
120 if (tb[RTA_FLOW]) { 122 if (tb[RTA_FLOW]) {
@@ -256,7 +258,12 @@ static int iprule_modify(int cmd, char **argv)
256 NEXT_ARG(); 258 NEXT_ARG();
257 if (rtnl_rttable_a2n(&tid, *argv)) 259 if (rtnl_rttable_a2n(&tid, *argv))
258 invarg_1_to_2(*argv, "table ID"); 260 invarg_1_to_2(*argv, "table ID");
259 req.r.rtm_table = tid; 261 if (tid < 256)
262 req.r.rtm_table = tid;
263 else {
264 req.r.rtm_table = RT_TABLE_UNSPEC;
265 addattr32(&req.n, sizeof(req), RTA_TABLE, tid);
266 }
260 table_ok = 1; 267 table_ok = 1;
261 } else if (key == ARG_dev || 268 } else if (key == ARG_dev ||
262 key == ARG_iif 269 key == ARG_iif
diff --git a/networking/tcpudp.c b/networking/tcpudp.c
index 94c89b9ef..3a6c68646 100644
--- a/networking/tcpudp.c
+++ b/networking/tcpudp.c
@@ -107,10 +107,10 @@
107#include "libbb.h" 107#include "libbb.h"
108#include "common_bufsiz.h" 108#include "common_bufsiz.h"
109 109
110/* Wants <limits.h> etc, thus included after libbb.h: */
111#ifdef __linux__ 110#ifdef __linux__
112#include <linux/types.h> /* for __be32 etc */ 111/* from linux/netfilter_ipv4.h: */
113#include <linux/netfilter_ipv4.h> 112# undef SO_ORIGINAL_DST
113# define SO_ORIGINAL_DST 80
114#endif 114#endif
115 115
116// TODO: move into this file: 116// TODO: move into this file:
diff --git a/networking/udhcp/Config.src b/networking/udhcp/Config.src
index c34c8d6f0..90fb313b5 100644
--- a/networking/udhcp/Config.src
+++ b/networking/udhcp/Config.src
@@ -16,7 +16,6 @@ config UDHCPD
16config DHCPRELAY 16config DHCPRELAY
17 bool "dhcprelay" 17 bool "dhcprelay"
18 default y 18 default y
19 depends on UDHCPD
20 help 19 help
21 dhcprelay listens for dhcp requests on one or more interfaces 20 dhcprelay listens for dhcp requests on one or more interfaces
22 and forwards these requests to a different interface or dhcp 21 and forwards these requests to a different interface or dhcp
@@ -25,7 +24,6 @@ config DHCPRELAY
25config DUMPLEASES 24config DUMPLEASES
26 bool "Lease display utility (dumpleases)" 25 bool "Lease display utility (dumpleases)"
27 default y 26 default y
28 depends on UDHCPD
29 help 27 help
30 dumpleases displays the leases written out by the udhcpd server. 28 dumpleases displays the leases written out by the udhcpd server.
31 Lease times are stored in the file by time remaining in lease, or 29 Lease times are stored in the file by time remaining in lease, or
diff --git a/networking/udhcp/Kbuild.src b/networking/udhcp/Kbuild.src
index 5ea77df06..fcb725fbc 100644
--- a/networking/udhcp/Kbuild.src
+++ b/networking/udhcp/Kbuild.src
@@ -15,7 +15,7 @@ lib-$(CONFIG_UDHCPD) += common.o packet.o signalpipe.o socket.o
15lib-$(CONFIG_UDHCPC) += dhcpc.o 15lib-$(CONFIG_UDHCPC) += dhcpc.o
16lib-$(CONFIG_UDHCPD) += dhcpd.o arpping.o 16lib-$(CONFIG_UDHCPD) += dhcpd.o arpping.o
17lib-$(CONFIG_DUMPLEASES) += dumpleases.o 17lib-$(CONFIG_DUMPLEASES) += dumpleases.o
18lib-$(CONFIG_DHCPRELAY) += dhcprelay.o 18lib-$(CONFIG_DHCPRELAY) += dhcprelay.o common.o socket.o packet.o
19 19
20lib-$(CONFIG_FEATURE_UDHCPC_ARPING) += arpping.o 20lib-$(CONFIG_FEATURE_UDHCPC_ARPING) += arpping.o
21lib-$(CONFIG_FEATURE_UDHCP_RFC3397) += domain_codec.o 21lib-$(CONFIG_FEATURE_UDHCP_RFC3397) += domain_codec.o
diff --git a/procps/Kbuild.src b/procps/Kbuild.src
index 83af05a05..e7adc7340 100644
--- a/procps/Kbuild.src
+++ b/procps/Kbuild.src
@@ -9,3 +9,5 @@ lib-y:=
9INSERT 9INSERT
10 10
11lib-$(CONFIG_ASH) += kill.o # used for built-in kill by ash 11lib-$(CONFIG_ASH) += kill.o # used for built-in kill by ash
12lib-$(CONFIG_SH_IS_ASH) += kill.o # used for built-in kill by ash
13lib-$(CONFIG_BASH_IS_ASH) += kill.o # used for built-in kill by ash
diff --git a/procps/top.c b/procps/top.c
index c66cdb764..71207bac1 100644
--- a/procps/top.c
+++ b/procps/top.c
@@ -1042,7 +1042,9 @@ static unsigned handle_input(unsigned scan_mask, unsigned interval)
1042//usage: "Provide a view of process activity in real time." 1042//usage: "Provide a view of process activity in real time."
1043//usage: "\n""Read the status of all processes from /proc each SECONDS" 1043//usage: "\n""Read the status of all processes from /proc each SECONDS"
1044//usage: "\n""and display a screenful of them." 1044//usage: "\n""and display a screenful of them."
1045//usage: "\n""Keys:" 1045//usage: "\n"
1046//usage: IF_FEATURE_USE_TERMIOS(
1047//usage: "Keys:"
1046//usage: "\n"" N/M" 1048//usage: "\n"" N/M"
1047//usage: IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE("/P") 1049//usage: IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE("/P")
1048//usage: IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE("/T") 1050//usage: IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE("/T")
@@ -1062,6 +1064,7 @@ static unsigned handle_input(unsigned scan_mask, unsigned interval)
1062//usage: "\n"" Q,^C: exit" 1064//usage: "\n"" Q,^C: exit"
1063//usage: "\n" 1065//usage: "\n"
1064//usage: "\n""Options:" 1066//usage: "\n""Options:"
1067//usage: )
1065//usage: "\n"" -b Batch mode" 1068//usage: "\n"" -b Batch mode"
1066//usage: "\n"" -n N Exit after N iterations" 1069//usage: "\n"" -n N Exit after N iterations"
1067//usage: "\n"" -d N Delay between updates" 1070//usage: "\n"" -d N Delay between updates"
diff --git a/runit/sv.c b/runit/sv.c
index 42abbbbb5..9e2132259 100644
--- a/runit/sv.c
+++ b/runit/sv.c
@@ -166,26 +166,19 @@ Exit Codes
166//config: help 166//config: help
167//config: Default directory for services. 167//config: Default directory for services.
168//config: Defaults to "/var/service" 168//config: Defaults to "/var/service"
169//config:
170//config:config SVC
171//config: bool "svc"
172//config: default y
173//config: help
174//config: svc controls the state of services monitored by the runsv supervisor.
175//config: It is comaptible with daemontools command with the same name.
169 176
170//applet:IF_SV(APPLET(sv, BB_DIR_USR_BIN, BB_SUID_DROP)) 177//applet:IF_SV(APPLET(sv, BB_DIR_USR_BIN, BB_SUID_DROP))
178//applet:IF_SVC(APPLET(svc, BB_DIR_USR_BIN, BB_SUID_DROP))
171 179
172//kbuild:lib-$(CONFIG_SV) += sv.o 180//kbuild:lib-$(CONFIG_SV) += sv.o
173 181//kbuild:lib-$(CONFIG_SVC) += sv.o
174//usage:#define sv_trivial_usage
175//usage: "[-v] [-w SEC] CMD SERVICE_DIR..."
176//usage:#define sv_full_usage "\n\n"
177//usage: "Control services monitored by runsv supervisor.\n"
178//usage: "Commands (only first character is enough):\n"
179//usage: "\n"
180//usage: "status: query service status\n"
181//usage: "up: if service isn't running, start it. If service stops, restart it\n"
182//usage: "once: like 'up', but if service stops, don't restart it\n"
183//usage: "down: send TERM and CONT signals. If ./run exits, start ./finish\n"
184//usage: " if it exists. After it stops, don't restart service\n"
185//usage: "exit: send TERM and CONT signals to service and log service. If they exit,\n"
186//usage: " runsv exits too\n"
187//usage: "pause, cont, hup, alarm, interrupt, quit, 1, 2, term, kill: send\n"
188//usage: "STOP, CONT, HUP, ALRM, INT, QUIT, USR1, USR2, TERM, KILL signal to service"
189 182
190#include <sys/file.h> 183#include <sys/file.h>
191#include "libbb.h" 184#include "libbb.h"
@@ -452,8 +445,22 @@ static int control(const char *a)
452 return 1; 445 return 1;
453} 446}
454 447
455int sv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 448//usage:#define sv_trivial_usage
456int sv_main(int argc UNUSED_PARAM, char **argv) 449//usage: "[-v] [-w SEC] CMD SERVICE_DIR..."
450//usage:#define sv_full_usage "\n\n"
451//usage: "Control services monitored by runsv supervisor.\n"
452//usage: "Commands (only first character is enough):\n"
453//usage: "\n"
454//usage: "status: query service status\n"
455//usage: "up: if service isn't running, start it. If service stops, restart it\n"
456//usage: "once: like 'up', but if service stops, don't restart it\n"
457//usage: "down: send TERM and CONT signals. If ./run exits, start ./finish\n"
458//usage: " if it exists. After it stops, don't restart service\n"
459//usage: "exit: send TERM and CONT signals to service and log service. If they exit,\n"
460//usage: " runsv exits too\n"
461//usage: "pause, cont, hup, alarm, interrupt, quit, 1, 2, term, kill: send\n"
462//usage: "STOP, CONT, HUP, ALRM, INT, QUIT, USR1, USR2, TERM, KILL signal to service"
463static int sv(char **argv)
457{ 464{
458 char *x; 465 char *x;
459 char *action; 466 char *action;
@@ -634,3 +641,72 @@ int sv_main(int argc UNUSED_PARAM, char **argv)
634 } 641 }
635 return rc > 99 ? 99 : rc; 642 return rc > 99 ? 99 : rc;
636} 643}
644
645#if ENABLE_SV
646int sv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
647int sv_main(int argc UNUSED_PARAM, char **argv)
648{
649 return sv(argv);
650}
651#endif
652
653//usage:#define svc_trivial_usage
654//usage: "[-udopchaitkx] SERVICE_DIR..."
655//usage:#define svc_full_usage "\n\n"
656//usage: "Control services monitored by runsv supervisor"
657//usage: "\n"
658//usage: "\n"" -u If service is not running, start it; restart if it stops"
659//usage: "\n"" -d If service is running, send TERM+CONT signals; do not restart it"
660//usage: "\n"" -o Once: if service is not running, start it; do not restart it"
661//usage: "\n"" -pchaitk Send STOP, CONT, HUP, ALRM, INT, TERM, KILL signal to service"
662//usage: "\n"" -x Exit: runsv will exit as soon as the service is down"
663#if ENABLE_SVC
664int svc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
665int svc_main(int argc UNUSED_PARAM, char **argv)
666{
667 char command[2];
668 const char *optstring;
669 unsigned opts;
670
671 INIT_G();
672
673 optstring = "udopchaitkx";
674 opts = getopt32(argv, optstring);
675 argv += optind;
676 if (!argv[0] || !opts)
677 bb_show_usage();
678
679 argv -= 2;
680 if (optind > 2) {
681 argv--;
682 argv[2] = (char*)"--";
683 }
684 argv[0] = (char*)"sv";
685 argv[1] = command;
686 command[1] = '\0';
687
688 /* getopt32() was already called:
689 * reset the libc getopt() function, which keeps internal state.
690 */
691#ifdef __GLIBC__
692 optind = 0;
693#else /* BSD style */
694 optind = 1;
695 /* optreset = 1; */
696#endif
697
698 do {
699 if (opts & 1) {
700 int r;
701 command[0] = *optstring;
702 r = sv(argv);
703 if (r)
704 return 1;
705 }
706 optstring++;
707 opts >>= 1;
708 } while (opts);
709
710 return 0;
711}
712#endif
diff --git a/scripts/randomtest.loop b/scripts/randomtest.loop
index 758a8e862..710f5fd05 100755
--- a/scripts/randomtest.loop
+++ b/scripts/randomtest.loop
@@ -33,6 +33,7 @@ while sleep 1; do
33 ) 33 )
34 if test $? != 0; then 34 if test $? != 0; then
35 echo "Failed runtest in $dir" 35 echo "Failed runtest in $dir"
36 grep ^FAIL -- "$dir/testsuite/runtest.log"
36 exit 1 # you may comment this out... 37 exit 1 # you may comment this out...
37 let fail++ 38 let fail++
38 continue 39 continue
diff --git a/selinux/runcon.c b/selinux/runcon.c
index 366834e46..16f171101 100644
--- a/selinux/runcon.c
+++ b/selinux/runcon.c
@@ -68,7 +68,9 @@
68//usage: ) 68//usage: )
69 69
70#include <selinux/context.h> 70#include <selinux/context.h>
71#include <selinux/flask.h> 71/* from deprecated <selinux/flask.h>: */
72#undef SECCLASS_PROCESS
73#define SECCLASS_PROCESS 2
72 74
73#include "libbb.h" 75#include "libbb.h"
74 76
diff --git a/selinux/setfiles.c b/selinux/setfiles.c
index 4fc307f55..9fa5d3f30 100644
--- a/selinux/setfiles.c
+++ b/selinux/setfiles.c
@@ -77,6 +77,7 @@
77//usage: "\n if it has changed" 77//usage: "\n if it has changed"
78 78
79#include "libbb.h" 79#include "libbb.h"
80#include "common_bufsiz.h"
80#if ENABLE_FEATURE_SETFILES_CHECK_OPTION 81#if ENABLE_FEATURE_SETFILES_CHECK_OPTION
81#include <sepol/sepol.h> 82#include <sepol/sepol.h>
82#endif 83#endif
diff --git a/shell/Config.src b/shell/Config.src
index e4df35973..7f5f67050 100644
--- a/shell/Config.src
+++ b/shell/Config.src
@@ -5,34 +5,30 @@
5 5
6menu "Shells" 6menu "Shells"
7 7
8INSERT
9
10 8
11choice 9choice
12 prompt "Choose which shell is aliased to 'sh' name" 10 prompt "Choose which shell is aliased to 'sh' name"
13 default FEATURE_SH_IS_ASH 11 default SH_IS_ASH
14 help 12 help
15 Choose which shell you want to be executed by 'sh' alias. 13 Choose which shell you want to be executed by 'sh' alias.
16 The ash shell is the most bash compatible and full featured one. 14 The ash shell is the most bash compatible and full featured one.
17 15
18# note: cannot use "select ASH" here, it breaks "make allnoconfig" 16# note: cannot use "select ASH" here, it breaks "make allnoconfig"
19config FEATURE_SH_IS_ASH 17config SH_IS_ASH
20 depends on ASH
21 bool "ash"
22 depends on !NOMMU 18 depends on !NOMMU
19 bool "ash"
23 20
24config FEATURE_SH_IS_HUSH 21config SH_IS_HUSH
25 depends on HUSH
26 bool "hush" 22 bool "hush"
27 23
28config FEATURE_SH_IS_NONE 24config SH_IS_NONE
29 bool "none" 25 bool "none"
30 26
31endchoice 27endchoice
32 28
33choice 29choice
34 prompt "Choose which shell is aliased to 'bash' name" 30 prompt "Choose which shell is aliased to 'bash' name"
35 default FEATURE_BASH_IS_NONE 31 default BASH_IS_NONE
36 help 32 help
37 Choose which shell you want to be executed by 'bash' alias. 33 Choose which shell you want to be executed by 'bash' alias.
38 The ash shell is the most bash compatible and full featured one. 34 The ash shell is the most bash compatible and full featured one.
@@ -47,32 +43,33 @@ choice
47 can't be used for running them because it won't recongnize 43 can't be used for running them because it won't recongnize
48 "bash" as a supported applet name. 44 "bash" as a supported applet name.
49 45
50config FEATURE_BASH_IS_ASH 46config BASH_IS_ASH
51 depends on ASH
52 bool "ash"
53 depends on !NOMMU 47 depends on !NOMMU
48 bool "ash"
54 49
55config FEATURE_BASH_IS_HUSH 50config BASH_IS_HUSH
56 depends on HUSH
57 bool "hush" 51 bool "hush"
58 52
59config FEATURE_BASH_IS_NONE 53config BASH_IS_NONE
60 bool "none" 54 bool "none"
61 55
62endchoice 56endchoice
63 57
64 58
65config SH_MATH_SUPPORT 59INSERT
60
61
62config FEATURE_SH_MATH
66 bool "POSIX math support" 63 bool "POSIX math support"
67 default y 64 default y
68 depends on ASH || HUSH 65 depends on ASH || HUSH || SH_IS_ASH || BASH_IS_ASH || SH_IS_HUSH || BASH_IS_HUSH
69 help 66 help
70 Enable math support in the shell via $((...)) syntax. 67 Enable math support in the shell via $((...)) syntax.
71 68
72config SH_MATH_SUPPORT_64 69config FEATURE_SH_MATH_64
73 bool "Extend POSIX math support to 64 bit" 70 bool "Extend POSIX math support to 64 bit"
74 default y 71 default y
75 depends on SH_MATH_SUPPORT 72 depends on FEATURE_SH_MATH
76 help 73 help
77 Enable 64-bit math support in the shell. This will make the shell 74 Enable 64-bit math support in the shell. This will make the shell
78 slightly larger, but will allow computation with very large numbers. 75 slightly larger, but will allow computation with very large numbers.
@@ -81,14 +78,14 @@ config SH_MATH_SUPPORT_64
81config FEATURE_SH_EXTRA_QUIET 78config FEATURE_SH_EXTRA_QUIET
82 bool "Hide message on interactive shell startup" 79 bool "Hide message on interactive shell startup"
83 default y 80 default y
84 depends on HUSH || ASH 81 depends on ASH || HUSH || SH_IS_ASH || BASH_IS_ASH || SH_IS_HUSH || BASH_IS_HUSH
85 help 82 help
86 Remove the busybox introduction when starting a shell. 83 Remove the busybox introduction when starting a shell.
87 84
88config FEATURE_SH_STANDALONE 85config FEATURE_SH_STANDALONE
89 bool "Standalone shell" 86 bool "Standalone shell"
90 default n 87 default n
91 depends on (HUSH || ASH) 88 depends on ASH || HUSH || SH_IS_ASH || BASH_IS_ASH || SH_IS_HUSH || BASH_IS_HUSH
92 help 89 help
93 This option causes busybox shells to use busybox applets 90 This option causes busybox shells to use busybox applets
94 in preference to executables in the PATH whenever possible. For 91 in preference to executables in the PATH whenever possible. For
@@ -121,7 +118,7 @@ config FEATURE_SH_STANDALONE
121config FEATURE_SH_NOFORK 118config FEATURE_SH_NOFORK
122 bool "Run 'nofork' applets directly" 119 bool "Run 'nofork' applets directly"
123 default n 120 default n
124 depends on (HUSH || ASH) 121 depends on ASH || HUSH || SH_IS_ASH || BASH_IS_ASH || SH_IS_HUSH || BASH_IS_HUSH
125 help 122 help
126 This option causes busybox shells to not execute typical 123 This option causes busybox shells to not execute typical
127 fork/exec/wait sequence, but call <applet>_main directly, 124 fork/exec/wait sequence, but call <applet>_main directly,
@@ -139,7 +136,7 @@ config FEATURE_SH_NOFORK
139config FEATURE_SH_HISTFILESIZE 136config FEATURE_SH_HISTFILESIZE
140 bool "Use $HISTFILESIZE" 137 bool "Use $HISTFILESIZE"
141 default y 138 default y
142 depends on HUSH || ASH 139 depends on ASH || HUSH || SH_IS_ASH || BASH_IS_ASH || SH_IS_HUSH || BASH_IS_HUSH
143 help 140 help
144 This option makes busybox shells to use $HISTFILESIZE variable 141 This option makes busybox shells to use $HISTFILESIZE variable
145 to set shell history size. Note that its max value is capped 142 to set shell history size. Note that its max value is capped
diff --git a/shell/Kbuild.src b/shell/Kbuild.src
index c00aec92a..6bba4989f 100644
--- a/shell/Kbuild.src
+++ b/shell/Kbuild.src
@@ -8,4 +8,4 @@ lib-y:=
8 8
9INSERT 9INSERT
10 10
11lib-$(CONFIG_SH_MATH_SUPPORT) += math.o 11lib-$(CONFIG_FEATURE_SH_MATH) += math.o
diff --git a/shell/ash.c b/shell/ash.c
index 2e7f68c05..af1157709 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -30,80 +30,6 @@
30 * - fake $PPID 30 * - fake $PPID
31 */ 31 */
32 32
33/*
34 * The following should be set to reflect the type of system you have:
35 * JOBS -> 1 if you have Berkeley job control, 0 otherwise.
36 * define SYSV if you are running under System V.
37 * define DEBUG=1 to compile in debugging ('set -o debug' to turn on)
38 * define DEBUG=2 to compile in and turn on debugging.
39 *
40 * When debugging is on (DEBUG is 1 and "set -o debug" was executed),
41 * debugging info will be written to ./trace and a quit signal
42 * will generate a core dump.
43 */
44#define DEBUG 0
45/* Tweak debug output verbosity here */
46#define DEBUG_TIME 0
47#define DEBUG_PID 1
48#define DEBUG_SIG 1
49#define DEBUG_INTONOFF 0
50
51#define PROFILE 0
52
53#define JOBS ENABLE_ASH_JOB_CONTROL
54
55#include <setjmp.h>
56#include <fnmatch.h>
57#include <sys/times.h>
58#include <sys/utsname.h> /* for setting $HOSTNAME */
59
60#include "busybox.h" /* for applet_names */
61
62#if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
63/* Bionic at least up to version 24 has no glob() */
64# undef ENABLE_ASH_INTERNAL_GLOB
65# define ENABLE_ASH_INTERNAL_GLOB 1
66#endif
67
68#if !ENABLE_ASH_INTERNAL_GLOB
69# include <glob.h>
70#endif
71
72#include "unicode.h"
73#include "shell_common.h"
74#if ENABLE_SH_MATH_SUPPORT
75# include "math.h"
76#endif
77#if ENABLE_ASH_RANDOM_SUPPORT
78# include "random.h"
79#else
80# define CLEAR_RANDOM_T(rnd) ((void)0)
81#endif
82
83#include "NUM_APPLETS.h"
84#if NUM_APPLETS == 1
85/* STANDALONE does not make sense, and won't compile */
86# undef CONFIG_FEATURE_SH_STANDALONE
87# undef ENABLE_FEATURE_SH_STANDALONE
88# undef IF_FEATURE_SH_STANDALONE
89# undef IF_NOT_FEATURE_SH_STANDALONE
90# define ENABLE_FEATURE_SH_STANDALONE 0
91# define IF_FEATURE_SH_STANDALONE(...)
92# define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
93#endif
94
95#ifndef PIPE_BUF
96# define PIPE_BUF 4096 /* amount of buffering in a pipe */
97#endif
98
99#if !ENABLE_PLATFORM_MINGW32
100# define is_absolute_path(path) ((path)[0] == '/')
101#endif
102
103#if !BB_MMU
104# error "Do not even bother, ash will not run on NOMMU machine"
105#endif
106
107//config:config ASH 33//config:config ASH
108//config: bool "ash" 34//config: bool "ash"
109//config: default y 35//config: default y
@@ -118,14 +44,14 @@
118//config:config ASH_OPTIMIZE_FOR_SIZE 44//config:config ASH_OPTIMIZE_FOR_SIZE
119//config: bool "Optimize for size instead of speed" 45//config: bool "Optimize for size instead of speed"
120//config: default y 46//config: default y
121//config: depends on ASH 47//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH
122//config: help 48//config: help
123//config: Compile ash for reduced size at the price of speed. 49//config: Compile ash for reduced size at the price of speed.
124//config: 50//config:
125//config:config ASH_INTERNAL_GLOB 51//config:config ASH_INTERNAL_GLOB
126//config: bool "Use internal glob() implementation" 52//config: bool "Use internal glob() implementation"
127//config: default n 53//config: default y # Y is bigger, but because of uclibc glob() bug, let Y be default for now
128//config: depends on ASH 54//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH
129//config: help 55//config: help
130//config: Do not use glob() function from libc, use internal implementation. 56//config: Do not use glob() function from libc, use internal implementation.
131//config: Use this if you are getting "glob.h: No such file or directory" 57//config: Use this if you are getting "glob.h: No such file or directory"
@@ -134,7 +60,7 @@
134//config:config ASH_RANDOM_SUPPORT 60//config:config ASH_RANDOM_SUPPORT
135//config: bool "Pseudorandom generator and $RANDOM variable" 61//config: bool "Pseudorandom generator and $RANDOM variable"
136//config: default y 62//config: default y
137//config: depends on ASH 63//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH
138//config: help 64//config: help
139//config: Enable pseudorandom generator and dynamic variable "$RANDOM". 65//config: Enable pseudorandom generator and dynamic variable "$RANDOM".
140//config: Each read of "$RANDOM" will generate a new pseudorandom value. 66//config: Each read of "$RANDOM" will generate a new pseudorandom value.
@@ -145,7 +71,7 @@
145//config:config ASH_EXPAND_PRMT 71//config:config ASH_EXPAND_PRMT
146//config: bool "Expand prompt string" 72//config: bool "Expand prompt string"
147//config: default y 73//config: default y
148//config: depends on ASH 74//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH
149//config: help 75//config: help
150//config: "PS#" may contain volatile content, such as backquote commands. 76//config: "PS#" may contain volatile content, such as backquote commands.
151//config: This option recreates the prompt string from the environment 77//config: This option recreates the prompt string from the environment
@@ -154,70 +80,70 @@
154//config:config ASH_BASH_COMPAT 80//config:config ASH_BASH_COMPAT
155//config: bool "bash-compatible extensions" 81//config: bool "bash-compatible extensions"
156//config: default y 82//config: default y
157//config: depends on ASH 83//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH
158//config: help 84//config: help
159//config: Enable bash-compatible extensions. 85//config: Enable bash-compatible extensions.
160//config: 86//config:
161//config:config ASH_IDLE_TIMEOUT 87//config:config ASH_IDLE_TIMEOUT
162//config: bool "Idle timeout variable" 88//config: bool "Idle timeout variable"
163//config: default n 89//config: default n
164//config: depends on ASH 90//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH
165//config: help 91//config: help
166//config: Enables bash-like auto-logout after $TMOUT seconds of idle time. 92//config: Enables bash-like auto-logout after $TMOUT seconds of idle time.
167//config: 93//config:
168//config:config ASH_JOB_CONTROL 94//config:config ASH_JOB_CONTROL
169//config: bool "Job control" 95//config: bool "Job control"
170//config: default y 96//config: default y
171//config: depends on ASH 97//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH
172//config: help 98//config: help
173//config: Enable job control in the ash shell. 99//config: Enable job control in the ash shell.
174//config: 100//config:
175//config:config ASH_ALIAS 101//config:config ASH_ALIAS
176//config: bool "Alias support" 102//config: bool "Alias support"
177//config: default y 103//config: default y
178//config: depends on ASH 104//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH
179//config: help 105//config: help
180//config: Enable alias support in the ash shell. 106//config: Enable alias support in the ash shell.
181//config: 107//config:
182//config:config ASH_GETOPTS 108//config:config ASH_GETOPTS
183//config: bool "Builtin getopt to parse positional parameters" 109//config: bool "Builtin getopt to parse positional parameters"
184//config: default y 110//config: default y
185//config: depends on ASH 111//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH
186//config: help 112//config: help
187//config: Enable support for getopts builtin in ash. 113//config: Enable support for getopts builtin in ash.
188//config: 114//config:
189//config:config ASH_BUILTIN_ECHO 115//config:config ASH_BUILTIN_ECHO
190//config: bool "Builtin version of 'echo'" 116//config: bool "Builtin version of 'echo'"
191//config: default y 117//config: default y
192//config: depends on ASH 118//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH
193//config: help 119//config: help
194//config: Enable support for echo builtin in ash. 120//config: Enable support for echo builtin in ash.
195//config: 121//config:
196//config:config ASH_BUILTIN_PRINTF 122//config:config ASH_BUILTIN_PRINTF
197//config: bool "Builtin version of 'printf'" 123//config: bool "Builtin version of 'printf'"
198//config: default y 124//config: default y
199//config: depends on ASH 125//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH
200//config: help 126//config: help
201//config: Enable support for printf builtin in ash. 127//config: Enable support for printf builtin in ash.
202//config: 128//config:
203//config:config ASH_BUILTIN_TEST 129//config:config ASH_BUILTIN_TEST
204//config: bool "Builtin version of 'test'" 130//config: bool "Builtin version of 'test'"
205//config: default y 131//config: default y
206//config: depends on ASH 132//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH
207//config: help 133//config: help
208//config: Enable support for test builtin in ash. 134//config: Enable support for test builtin in ash.
209//config: 135//config:
210//config:config ASH_HELP 136//config:config ASH_HELP
211//config: bool "help builtin" 137//config: bool "help builtin"
212//config: default y 138//config: default y
213//config: depends on ASH 139//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH
214//config: help 140//config: help
215//config: Enable help builtin in ash. 141//config: Enable help builtin in ash.
216//config: 142//config:
217//config:config ASH_CMDCMD 143//config:config ASH_CMDCMD
218//config: bool "'command' command to override shell builtins" 144//config: bool "'command' command to override shell builtins"
219//config: default y 145//config: default y
220//config: depends on ASH 146//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH
221//config: help 147//config: help
222//config: Enable support for the ash 'command' builtin, which allows 148//config: Enable support for the ash 'command' builtin, which allows
223//config: you to run the specified command with the specified arguments, 149//config: you to run the specified command with the specified arguments,
@@ -225,19 +151,105 @@
225//config: 151//config:
226//config:config ASH_MAIL 152//config:config ASH_MAIL
227//config: bool "Check for new mail on interactive shells" 153//config: bool "Check for new mail on interactive shells"
228//config: default n 154//config: default y
229//config: depends on ASH 155//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH
230//config: help 156//config: help
231//config: Enable "check for new mail" function in the ash shell. 157//config: Enable "check for new mail" function in the ash shell.
232//config:
233 158
234//applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP)) 159//applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
235//applet:IF_FEATURE_SH_IS_ASH(APPLET_ODDNAME(sh, ash, BB_DIR_BIN, BB_SUID_DROP, sh)) 160//applet:IF_SH_IS_ASH(APPLET_ODDNAME(sh, ash, BB_DIR_BIN, BB_SUID_DROP, ash))
236//applet:IF_FEATURE_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, bash)) 161//applet:IF_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, ash))
237 162
238//kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o 163//kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
164//kbuild:lib-$(CONFIG_SH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
165//kbuild:lib-$(CONFIG_BASH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
239//kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o 166//kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
240 167
168/*
169 * The following should be set to reflect the type of system you have:
170 * JOBS -> 1 if you have Berkeley job control, 0 otherwise.
171 * define SYSV if you are running under System V.
172 * define DEBUG=1 to compile in debugging ('set -o debug' to turn on)
173 * define DEBUG=2 to compile in and turn on debugging.
174 *
175 * When debugging is on (DEBUG is 1 and "set -o debug" was executed),
176 * debugging info will be written to ./trace and a quit signal
177 * will generate a core dump.
178 */
179#define DEBUG 0
180/* Tweak debug output verbosity here */
181#define DEBUG_TIME 0
182#define DEBUG_PID 1
183#define DEBUG_SIG 1
184#define DEBUG_INTONOFF 0
185
186#define PROFILE 0
187
188#define JOBS ENABLE_ASH_JOB_CONTROL
189
190#include <setjmp.h>
191#include <fnmatch.h>
192#include <sys/times.h>
193#include <sys/utsname.h> /* for setting $HOSTNAME */
194
195#include "busybox.h" /* for applet_names */
196
197#if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
198/* Bionic at least up to version 24 has no glob() */
199# undef ENABLE_ASH_INTERNAL_GLOB
200# define ENABLE_ASH_INTERNAL_GLOB 1
201#endif
202
203#if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__)
204# error uClibc glob() is buggy, use ASH_INTERNAL_GLOB.
205# error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD"
206# error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b"
207# error glob() should unbackslash them and match. uClibc does not unbackslash,
208# error fails to match dirname, subsequently not expanding <pattern> in it.
209// Testcase:
210// if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug
211// if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n");
212#endif
213
214#if !ENABLE_ASH_INTERNAL_GLOB
215# include <glob.h>
216#endif
217
218#include "unicode.h"
219#include "shell_common.h"
220#if CONFIG_FEATURE_SH_MATH
221# include "math.h"
222#endif
223#if ENABLE_ASH_RANDOM_SUPPORT
224# include "random.h"
225#else
226# define CLEAR_RANDOM_T(rnd) ((void)0)
227#endif
228
229#include "NUM_APPLETS.h"
230#if NUM_APPLETS == 1
231/* STANDALONE does not make sense, and won't compile */
232# undef CONFIG_FEATURE_SH_STANDALONE
233# undef ENABLE_FEATURE_SH_STANDALONE
234# undef IF_FEATURE_SH_STANDALONE
235# undef IF_NOT_FEATURE_SH_STANDALONE
236# define ENABLE_FEATURE_SH_STANDALONE 0
237# define IF_FEATURE_SH_STANDALONE(...)
238# define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
239#endif
240
241#ifndef PIPE_BUF
242# define PIPE_BUF 4096 /* amount of buffering in a pipe */
243#endif
244
245#if !ENABLE_PLATFORM_MINGW32
246# define is_absolute_path(path) ((path)[0] == '/')
247#endif
248
249#if !BB_MMU
250# error "Do not even bother, ash will not run on NOMMU machine"
251#endif
252
241#if ENABLE_PLATFORM_MINGW32 253#if ENABLE_PLATFORM_MINGW32
242union node; 254union node;
243struct strlist; 255struct strlist;
@@ -1343,6 +1355,8 @@ ash_msg_and_raise_error(const char *msg, ...)
1343{ 1355{
1344 va_list ap; 1356 va_list ap;
1345 1357
1358 exitstatus = 2;
1359
1346 va_start(ap, msg); 1360 va_start(ap, msg);
1347 ash_vmsg_and_raise(EXERROR, msg, ap); 1361 ash_vmsg_and_raise(EXERROR, msg, ap);
1348 /* NOTREACHED */ 1362 /* NOTREACHED */
@@ -2205,6 +2219,7 @@ lookupvar(const char *name)
2205 return NULL; 2219 return NULL;
2206} 2220}
2207 2221
2222#if ENABLE_UNICODE_SUPPORT
2208static void 2223static void
2209reinit_unicode_for_ash(void) 2224reinit_unicode_for_ash(void)
2210{ 2225{
@@ -2221,6 +2236,9 @@ reinit_unicode_for_ash(void)
2221 reinit_unicode(s); 2236 reinit_unicode(s);
2222 } 2237 }
2223} 2238}
2239#else
2240# define reinit_unicode_for_ash() ((void)0)
2241#endif
2224 2242
2225/* 2243/*
2226 * Search the environment of a builtin command. 2244 * Search the environment of a builtin command.
@@ -2924,7 +2942,7 @@ pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2924 2942
2925#define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE 2943#define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2926 2944
2927#if ENABLE_SH_MATH_SUPPORT 2945#if ENABLE_FEATURE_SH_MATH
2928# define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12)) 2946# define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2929#else 2947#else
2930# define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8)) 2948# define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
@@ -3305,7 +3323,18 @@ static const uint8_t syntax_index_table[] ALIGN1 = {
3305# endif 3323# endif
3306}; 3324};
3307 3325
3326#if 1
3308# define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf) 3327# define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3328#else /* debug version, caught one signed char bug */
3329# define SIT(c, syntax) \
3330 ({ \
3331 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3332 bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3333 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3334 bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3335 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3336 })
3337#endif
3309 3338
3310#endif /* !USE_SIT_FUNCTION */ 3339#endif /* !USE_SIT_FUNCTION */
3311 3340
@@ -4765,7 +4794,7 @@ cmdputs(const char *s)
4765 case CTLBACKQ: 4794 case CTLBACKQ:
4766 str = "$(...)"; 4795 str = "$(...)";
4767 goto dostr; 4796 goto dostr;
4768#if ENABLE_SH_MATH_SUPPORT 4797#if ENABLE_FEATURE_SH_MATH
4769 case CTLARI: 4798 case CTLARI:
4770 str = "$(("; 4799 str = "$((";
4771 goto dostr; 4800 goto dostr;
@@ -5749,11 +5778,11 @@ redirect(union node *redir, int flags)
5749 /* Careful to not accidentally "save" 5778 /* Careful to not accidentally "save"
5750 * to the same fd as right side fd in N>&M */ 5779 * to the same fd as right side fd in N>&M */
5751 int minfd = right_fd < 10 ? 10 : right_fd + 1; 5780 int minfd = right_fd < 10 ? 10 : right_fd + 1;
5781#if defined(F_DUPFD_CLOEXEC)
5782 i = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
5783#else
5752 i = fcntl(fd, F_DUPFD, minfd); 5784 i = fcntl(fd, F_DUPFD, minfd);
5753/* You'd expect copy to be CLOEXECed. Currently these extra "saved" fds 5785#endif
5754 * are closed in popredir() in the child, preventing them from leaking
5755 * into child. (popredir() also cleans up the mess in case of failures)
5756 */
5757 if (i == -1) { 5786 if (i == -1) {
5758 i = errno; 5787 i = errno;
5759 if (i != EBADF) { 5788 if (i != EBADF) {
@@ -5768,6 +5797,9 @@ redirect(union node *redir, int flags)
5768 remember_to_close: 5797 remember_to_close:
5769 i = CLOSED; 5798 i = CLOSED;
5770 } else { /* fd is open, save its copy */ 5799 } else { /* fd is open, save its copy */
5800#if !defined(F_DUPFD_CLOEXEC)
5801 fcntl(i, F_SETFD, FD_CLOEXEC);
5802#endif
5771 /* "exec fd>&-" should not close fds 5803 /* "exec fd>&-" should not close fds
5772 * which point to script file(s). 5804 * which point to script file(s).
5773 * Force them to be restored afterwards */ 5805 * Force them to be restored afterwards */
@@ -5878,7 +5910,7 @@ redirectsafe(union node *redir, int flags)
5878 * We have to deal with backquotes, shell variables, and file metacharacters. 5910 * We have to deal with backquotes, shell variables, and file metacharacters.
5879 */ 5911 */
5880 5912
5881#if ENABLE_SH_MATH_SUPPORT 5913#if ENABLE_FEATURE_SH_MATH
5882static arith_t 5914static arith_t
5883ash_arith(const char *s) 5915ash_arith(const char *s)
5884{ 5916{
@@ -5966,7 +5998,7 @@ static struct arglist exparg;
5966/* 5998/*
5967 * Our own itoa(). 5999 * Our own itoa().
5968 */ 6000 */
5969#if !ENABLE_SH_MATH_SUPPORT 6001#if !ENABLE_FEATURE_SH_MATH
5970/* cvtnum() is used even if math support is off (to prepare $? values and such) */ 6002/* cvtnum() is used even if math support is off (to prepare $? values and such) */
5971typedef long arith_t; 6003typedef long arith_t;
5972# define ARITH_FMT "%ld" 6004# define ARITH_FMT "%ld"
@@ -6220,14 +6252,15 @@ memtodest(const char *p, size_t len, int syntax, int quotes)
6220 do { 6252 do {
6221 unsigned char c = *p++; 6253 unsigned char c = *p++;
6222 if (c) { 6254 if (c) {
6223 int n = SIT(c, syntax); 6255 if (quotes & QUOTES_ESC) {
6224 if ((quotes & QUOTES_ESC) 6256 int n = SIT(c, syntax);
6225 && ((n == CCTL) 6257 if (n == CCTL
6226 || (((quotes & EXP_FULL) || syntax != BASESYNTAX) 6258 || (((quotes & EXP_FULL) || syntax != BASESYNTAX)
6227 && n == CBACK) 6259 && n == CBACK
6228 ) 6260 )
6229 ) { 6261 ) {
6230 USTPUTC(CTLESC, q); 6262 USTPUTC(CTLESC, q);
6263 }
6231 } 6264 }
6232 } else if (!(quotes & QUOTES_KEEPNUL)) 6265 } else if (!(quotes & QUOTES_KEEPNUL))
6233 continue; 6266 continue;
@@ -6490,7 +6523,7 @@ expbackq(union node *cmd, int flag)
6490 stackblock() + startloc)); 6523 stackblock() + startloc));
6491} 6524}
6492 6525
6493#if ENABLE_SH_MATH_SUPPORT 6526#if ENABLE_FEATURE_SH_MATH
6494/* 6527/*
6495 * Expand arithmetic expression. Backup to start of expression, 6528 * Expand arithmetic expression. Backup to start of expression,
6496 * evaluate, place result in (backed up) result, adjust string position. 6529 * evaluate, place result in (backed up) result, adjust string position.
@@ -6572,7 +6605,7 @@ argstr(char *p, int flags, struct strlist *var_str_list)
6572 CTLESC, 6605 CTLESC,
6573 CTLVAR, 6606 CTLVAR,
6574 CTLBACKQ, 6607 CTLBACKQ,
6575#if ENABLE_SH_MATH_SUPPORT 6608#if ENABLE_FEATURE_SH_MATH
6576 CTLENDARI, 6609 CTLENDARI,
6577#endif 6610#endif
6578 '\0' 6611 '\0'
@@ -6608,7 +6641,7 @@ argstr(char *p, int flags, struct strlist *var_str_list)
6608 c = p[length]; 6641 c = p[length];
6609 if (c) { 6642 if (c) {
6610 if (!(c & 0x80) 6643 if (!(c & 0x80)
6611 IF_SH_MATH_SUPPORT(|| c == CTLENDARI) 6644 IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6612 ) { 6645 ) {
6613 /* c == '=' || c == ':' || c == CTLENDARI */ 6646 /* c == '=' || c == ':' || c == CTLENDARI */
6614 length++; 6647 length++;
@@ -6688,7 +6721,7 @@ argstr(char *p, int flags, struct strlist *var_str_list)
6688 expbackq(argbackq->n, flags | inquotes); 6721 expbackq(argbackq->n, flags | inquotes);
6689 argbackq = argbackq->next; 6722 argbackq = argbackq->next;
6690 goto start; 6723 goto start;
6691#if ENABLE_SH_MATH_SUPPORT 6724#if ENABLE_FEATURE_SH_MATH
6692 case CTLENDARI: 6725 case CTLENDARI:
6693 p--; 6726 p--;
6694 expari(flags | inquotes); 6727 expari(flags | inquotes);
@@ -9686,7 +9719,7 @@ static int helpcmd(int, char **) FAST_FUNC;
9686#if MAX_HISTORY 9719#if MAX_HISTORY
9687static int historycmd(int, char **) FAST_FUNC; 9720static int historycmd(int, char **) FAST_FUNC;
9688#endif 9721#endif
9689#if ENABLE_SH_MATH_SUPPORT 9722#if ENABLE_FEATURE_SH_MATH
9690static int letcmd(int, char **) FAST_FUNC; 9723static int letcmd(int, char **) FAST_FUNC;
9691#endif 9724#endif
9692static int readcmd(int, char **) FAST_FUNC; 9725static int readcmd(int, char **) FAST_FUNC;
@@ -9766,7 +9799,7 @@ static const struct builtincmd builtintab[] = {
9766 { BUILTIN_REGULAR "jobs" , jobscmd }, 9799 { BUILTIN_REGULAR "jobs" , jobscmd },
9767 { BUILTIN_REGULAR "kill" , killcmd }, 9800 { BUILTIN_REGULAR "kill" , killcmd },
9768#endif 9801#endif
9769#if ENABLE_SH_MATH_SUPPORT 9802#if ENABLE_FEATURE_SH_MATH
9770 { BUILTIN_NOSPEC "let" , letcmd }, 9803 { BUILTIN_NOSPEC "let" , letcmd },
9771#endif 9804#endif
9772 { BUILTIN_ASSIGN "local" , localcmd }, 9805 { BUILTIN_ASSIGN "local" , localcmd },
@@ -10004,11 +10037,13 @@ evalcommand(union node *cmd, int flags)
10004 } 10037 }
10005 10038
10006 if (status) { 10039 if (status) {
10040 bail:
10041 exitstatus = status;
10042
10007 /* We have a redirection error. */ 10043 /* We have a redirection error. */
10008 if (spclbltin > 0) 10044 if (spclbltin > 0)
10009 raise_exception(EXERROR); 10045 raise_exception(EXERROR);
10010 bail: 10046
10011 exitstatus = status;
10012 goto out; 10047 goto out;
10013 } 10048 }
10014 10049
@@ -10516,7 +10551,7 @@ pgetc(void)
10516 return g_parsefile->lastc[--g_parsefile->unget]; 10551 return g_parsefile->lastc[--g_parsefile->unget];
10517 10552
10518 if (--g_parsefile->left_in_line >= 0) 10553 if (--g_parsefile->left_in_line >= 0)
10519 c = (signed char)*g_parsefile->next_to_pgetc++; 10554 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10520 else 10555 else
10521 c = preadbuffer(); 10556 c = preadbuffer();
10522 10557
@@ -11840,13 +11875,13 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
11840 smallint quotef; 11875 smallint quotef;
11841 smallint dblquote; 11876 smallint dblquote;
11842 smallint oldstyle; 11877 smallint oldstyle;
11843 smallint prevsyntax; /* syntax before arithmetic */ 11878 IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */
11844#if ENABLE_ASH_EXPAND_PRMT 11879#if ENABLE_ASH_EXPAND_PRMT
11845 smallint pssyntax; /* we are expanding a prompt string */ 11880 smallint pssyntax; /* we are expanding a prompt string */
11846#endif 11881#endif
11847 int varnest; /* levels of variables expansion */ 11882 int varnest; /* levels of variables expansion */
11848 int arinest; /* levels of arithmetic expansion */ 11883 IF_FEATURE_SH_MATH(int arinest;) /* levels of arithmetic expansion */
11849 int parenlevel; /* levels of parens in arithmetic */ 11884 IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11850 int dqvarnest; /* levels of variables expansion within double quotes */ 11885 int dqvarnest; /* levels of variables expansion within double quotes */
11851 11886
11852 IF_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;) 11887 IF_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;)
@@ -11854,7 +11889,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
11854 startlinno = g_parsefile->linno; 11889 startlinno = g_parsefile->linno;
11855 bqlist = NULL; 11890 bqlist = NULL;
11856 quotef = 0; 11891 quotef = 0;
11857 prevsyntax = 0; 11892 IF_FEATURE_SH_MATH(prevsyntax = 0;)
11858#if ENABLE_ASH_EXPAND_PRMT 11893#if ENABLE_ASH_EXPAND_PRMT
11859 pssyntax = (syntax == PSSYNTAX); 11894 pssyntax = (syntax == PSSYNTAX);
11860 if (pssyntax) 11895 if (pssyntax)
@@ -11862,8 +11897,8 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
11862#endif 11897#endif
11863 dblquote = (syntax == DQSYNTAX); 11898 dblquote = (syntax == DQSYNTAX);
11864 varnest = 0; 11899 varnest = 0;
11865 arinest = 0; 11900 IF_FEATURE_SH_MATH(arinest = 0;)
11866 parenlevel = 0; 11901 IF_FEATURE_SH_MATH(parenlevel = 0;)
11867 dqvarnest = 0; 11902 dqvarnest = 0;
11868 11903
11869 STARTSTACKSTR(out); 11904 STARTSTACKSTR(out);
@@ -11970,7 +12005,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
11970 } 12005 }
11971 USTPUTC(c, out); 12006 USTPUTC(c, out);
11972 break; 12007 break;
11973#if ENABLE_SH_MATH_SUPPORT 12008#if ENABLE_FEATURE_SH_MATH
11974 case CLP: /* '(' in arithmetic */ 12009 case CLP: /* '(' in arithmetic */
11975 parenlevel++; 12010 parenlevel++;
11976 USTPUTC(c, out); 12011 USTPUTC(c, out);
@@ -12021,7 +12056,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
12021 } /* for (;;) */ 12056 } /* for (;;) */
12022 endword: 12057 endword:
12023 12058
12024#if ENABLE_SH_MATH_SUPPORT 12059#if ENABLE_FEATURE_SH_MATH
12025 if (syntax == ARISYNTAX) 12060 if (syntax == ARISYNTAX)
12026 raise_error_syntax("missing '))'"); 12061 raise_error_syntax("missing '))'");
12027#endif 12062#endif
@@ -12200,7 +12235,7 @@ parsesub: {
12200 } else if (c == '(') { 12235 } else if (c == '(') {
12201 /* $(command) or $((arith)) */ 12236 /* $(command) or $((arith)) */
12202 if (pgetc_eatbnl() == '(') { 12237 if (pgetc_eatbnl() == '(') {
12203#if ENABLE_SH_MATH_SUPPORT 12238#if ENABLE_FEATURE_SH_MATH
12204 PARSEARITH(); 12239 PARSEARITH();
12205#else 12240#else
12206 raise_error_syntax("you disabled math support for $((arith)) syntax"); 12241 raise_error_syntax("you disabled math support for $((arith)) syntax");
@@ -12455,7 +12490,7 @@ parsebackq: {
12455 goto parsebackq_newreturn; 12490 goto parsebackq_newreturn;
12456} 12491}
12457 12492
12458#if ENABLE_SH_MATH_SUPPORT 12493#if ENABLE_FEATURE_SH_MATH
12459/* 12494/*
12460 * Parse an arithmetic expansion (indicate start of one and set state) 12495 * Parse an arithmetic expansion (indicate start of one and set state)
12461 */ 12496 */
@@ -13532,7 +13567,7 @@ timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13532 return 0; 13567 return 0;
13533} 13568}
13534 13569
13535#if ENABLE_SH_MATH_SUPPORT 13570#if ENABLE_FEATURE_SH_MATH
13536/* 13571/*
13537 * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell. 13572 * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13538 * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc. 13573 * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
@@ -13871,15 +13906,6 @@ init(void)
13871//usage:#define ash_full_usage "\n\n" 13906//usage:#define ash_full_usage "\n\n"
13872//usage: "Unix shell interpreter" 13907//usage: "Unix shell interpreter"
13873 13908
13874//usage:#if ENABLE_FEATURE_SH_IS_ASH
13875//usage:# define sh_trivial_usage ash_trivial_usage
13876//usage:# define sh_full_usage ash_full_usage
13877//usage:#endif
13878//usage:#if ENABLE_FEATURE_BASH_IS_ASH
13879//usage:# define bash_trivial_usage ash_trivial_usage
13880//usage:# define bash_full_usage ash_full_usage
13881//usage:#endif
13882
13883/* 13909/*
13884 * Process the shell command line arguments. 13910 * Process the shell command line arguments.
13885 */ 13911 */
diff --git a/shell/ash_test/ash-misc/exitcode2.right b/shell/ash_test/ash-misc/exitcode2.right
new file mode 100644
index 000000000..f7cb983c6
--- /dev/null
+++ b/shell/ash_test/ash-misc/exitcode2.right
@@ -0,0 +1,4 @@
1./test.sh: line 1: syntax error: unexpected ")"
2Done:2
3./exitcode2.tests: line 11: can't open does_not_exist: no such file
4Done:1
diff --git a/shell/ash_test/ash-misc/exitcode2.tests b/shell/ash_test/ash-misc/exitcode2.tests
new file mode 100755
index 000000000..79a6ebd50
--- /dev/null
+++ b/shell/ash_test/ash-misc/exitcode2.tests
@@ -0,0 +1,12 @@
1# syntax error should return status 2
2cat >test.sh <<EOF
3)
4EOF
5chmod +x test.sh
6$THIS_SH ./test.sh
7echo Done:$?
8rm -f test.sh
9
10# redirection error with special builtin should return status 1
11(eval cat <does_not_exist)
12echo Done:$?
diff --git a/shell/ash_test/ash-redir/redir_leak.right b/shell/ash_test/ash-redir/redir_leak.right
new file mode 100644
index 000000000..b1c48292b
--- /dev/null
+++ b/shell/ash_test/ash-redir/redir_leak.right
@@ -0,0 +1,6 @@
14
24
34
44
54
64
diff --git a/shell/ash_test/ash-redir/redir_leak.tests b/shell/ash_test/ash-redir/redir_leak.tests
new file mode 100755
index 000000000..c8a9c6343
--- /dev/null
+++ b/shell/ash_test/ash-redir/redir_leak.tests
@@ -0,0 +1,10 @@
1# Each of these should show only four lines:
2# fds 0,1,2 are stdio; fd 3 is open by opendir() in ls.
3# This test detects bugs where redirects leave stray open fds.
4
5ls -1 /proc/self/fd | wc -l
6ls -1 /proc/self/fd >/proc/self/fd/1 | wc -l
7ls -1 /proc/self/fd >/proc/self/fd/1 2>&1 | wc -l
8echo "`ls -1 /proc/self/fd `" | wc -l
9echo "`ls -1 /proc/self/fd >/proc/self/fd/1 `" | wc -l
10echo "`ls -1 /proc/self/fd >/proc/self/fd/1 2>&1 `" | wc -l
diff --git a/shell/hush.c b/shell/hush.c
index bcd4dffee..a56d3b280 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -82,35 +82,6 @@
82 * $ "export" i=`echo 'aaa bbb'`; echo "$i" 82 * $ "export" i=`echo 'aaa bbb'`; echo "$i"
83 * aaa 83 * aaa
84 */ 84 */
85#if !(defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \
86 || defined(__APPLE__) \
87 )
88# include <malloc.h> /* for malloc_trim */
89#endif
90#include <glob.h>
91/* #include <dmalloc.h> */
92#if ENABLE_HUSH_CASE
93# include <fnmatch.h>
94#endif
95#include <sys/utsname.h> /* for setting $HOSTNAME */
96
97#include "busybox.h" /* for APPLET_IS_NOFORK/NOEXEC */
98#include "unicode.h"
99#include "shell_common.h"
100#include "math.h"
101#include "match.h"
102#if ENABLE_HUSH_RANDOM_SUPPORT
103# include "random.h"
104#else
105# define CLEAR_RANDOM_T(rnd) ((void)0)
106#endif
107#ifndef F_DUPFD_CLOEXEC
108# define F_DUPFD_CLOEXEC F_DUPFD
109#endif
110#ifndef PIPE_BUF
111# define PIPE_BUF 4096 /* amount of buffering in a pipe */
112#endif
113
114//config:config HUSH 85//config:config HUSH
115//config: bool "hush" 86//config: bool "hush"
116//config: default y 87//config: default y
@@ -128,7 +99,7 @@
128//config:config HUSH_BASH_COMPAT 99//config:config HUSH_BASH_COMPAT
129//config: bool "bash-compatible extensions" 100//config: bool "bash-compatible extensions"
130//config: default y 101//config: default y
131//config: depends on HUSH 102//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
132//config: help 103//config: help
133//config: Enable bash-compatible extensions. 104//config: Enable bash-compatible extensions.
134//config: 105//config:
@@ -142,14 +113,14 @@
142//config:config HUSH_HELP 113//config:config HUSH_HELP
143//config: bool "help builtin" 114//config: bool "help builtin"
144//config: default y 115//config: default y
145//config: depends on HUSH 116//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
146//config: help 117//config: help
147//config: Enable help builtin in hush. Code size + ~1 kbyte. 118//config: Enable help builtin in hush. Code size + ~1 kbyte.
148//config: 119//config:
149//config:config HUSH_INTERACTIVE 120//config:config HUSH_INTERACTIVE
150//config: bool "Interactive mode" 121//config: bool "Interactive mode"
151//config: default y 122//config: default y
152//config: depends on HUSH 123//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
153//config: help 124//config: help
154//config: Enable interactive mode (prompt and command editing). 125//config: Enable interactive mode (prompt and command editing).
155//config: Without this, hush simply reads and executes commands 126//config: Without this, hush simply reads and executes commands
@@ -177,35 +148,35 @@
177//config:config HUSH_TICK 148//config:config HUSH_TICK
178//config: bool "Process substitution" 149//config: bool "Process substitution"
179//config: default y 150//config: default y
180//config: depends on HUSH 151//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
181//config: help 152//config: help
182//config: Enable process substitution `command` and $(command) in hush. 153//config: Enable process substitution `command` and $(command) in hush.
183//config: 154//config:
184//config:config HUSH_IF 155//config:config HUSH_IF
185//config: bool "Support if/then/elif/else/fi" 156//config: bool "Support if/then/elif/else/fi"
186//config: default y 157//config: default y
187//config: depends on HUSH 158//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
188//config: help 159//config: help
189//config: Enable if/then/elif/else/fi in hush. 160//config: Enable if/then/elif/else/fi in hush.
190//config: 161//config:
191//config:config HUSH_LOOPS 162//config:config HUSH_LOOPS
192//config: bool "Support for, while and until loops" 163//config: bool "Support for, while and until loops"
193//config: default y 164//config: default y
194//config: depends on HUSH 165//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
195//config: help 166//config: help
196//config: Enable for, while and until loops in hush. 167//config: Enable for, while and until loops in hush.
197//config: 168//config:
198//config:config HUSH_CASE 169//config:config HUSH_CASE
199//config: bool "Support case ... esac statement" 170//config: bool "Support case ... esac statement"
200//config: default y 171//config: default y
201//config: depends on HUSH 172//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
202//config: help 173//config: help
203//config: Enable case ... esac statement in hush. +400 bytes. 174//config: Enable case ... esac statement in hush. +400 bytes.
204//config: 175//config:
205//config:config HUSH_FUNCTIONS 176//config:config HUSH_FUNCTIONS
206//config: bool "Support funcname() { commands; } syntax" 177//config: bool "Support funcname() { commands; } syntax"
207//config: default y 178//config: default y
208//config: depends on HUSH 179//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
209//config: help 180//config: help
210//config: Enable support for shell functions in hush. +800 bytes. 181//config: Enable support for shell functions in hush. +800 bytes.
211//config: 182//config:
@@ -219,7 +190,7 @@
219//config:config HUSH_RANDOM_SUPPORT 190//config:config HUSH_RANDOM_SUPPORT
220//config: bool "Pseudorandom generator and $RANDOM variable" 191//config: bool "Pseudorandom generator and $RANDOM variable"
221//config: default y 192//config: default y
222//config: depends on HUSH 193//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
223//config: help 194//config: help
224//config: Enable pseudorandom generator and dynamic variable "$RANDOM". 195//config: Enable pseudorandom generator and dynamic variable "$RANDOM".
225//config: Each read of "$RANDOM" will generate a new pseudorandom value. 196//config: Each read of "$RANDOM" will generate a new pseudorandom value.
@@ -227,14 +198,14 @@
227//config:config HUSH_EXPORT_N 198//config:config HUSH_EXPORT_N
228//config: bool "Support 'export -n' option" 199//config: bool "Support 'export -n' option"
229//config: default y 200//config: default y
230//config: depends on HUSH 201//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
231//config: help 202//config: help
232//config: export -n unexports variables. It is a bash extension. 203//config: export -n unexports variables. It is a bash extension.
233//config: 204//config:
234//config:config HUSH_MODE_X 205//config:config HUSH_MODE_X
235//config: bool "Support 'hush -x' option and 'set -x' command" 206//config: bool "Support 'hush -x' option and 'set -x' command"
236//config: default y 207//config: default y
237//config: depends on HUSH 208//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
238//config: help 209//config: help
239//config: This instructs hush to print commands before execution. 210//config: This instructs hush to print commands before execution.
240//config: Adds ~300 bytes. 211//config: Adds ~300 bytes.
@@ -245,14 +216,15 @@
245//config: select HUSH 216//config: select HUSH
246//config: help 217//config: help
247//config: msh is deprecated and will be removed, please migrate to hush. 218//config: msh is deprecated and will be removed, please migrate to hush.
248//config:
249 219
250//applet:IF_HUSH(APPLET(hush, BB_DIR_BIN, BB_SUID_DROP)) 220//applet:IF_HUSH(APPLET(hush, BB_DIR_BIN, BB_SUID_DROP))
251//applet:IF_MSH(APPLET(msh, BB_DIR_BIN, BB_SUID_DROP)) 221//applet:IF_MSH(APPLET_ODDNAME(msh, hush, BB_DIR_BIN, BB_SUID_DROP, hush))
252//applet:IF_FEATURE_SH_IS_HUSH(APPLET_ODDNAME(sh, hush, BB_DIR_BIN, BB_SUID_DROP, sh)) 222//applet:IF_SH_IS_HUSH(APPLET_ODDNAME(sh, hush, BB_DIR_BIN, BB_SUID_DROP, hush))
253//applet:IF_FEATURE_BASH_IS_HUSH(APPLET_ODDNAME(bash, hush, BB_DIR_BIN, BB_SUID_DROP, bash)) 223//applet:IF_BASH_IS_HUSH(APPLET_ODDNAME(bash, hush, BB_DIR_BIN, BB_SUID_DROP, hush))
254 224
255//kbuild:lib-$(CONFIG_HUSH) += hush.o match.o shell_common.o 225//kbuild:lib-$(CONFIG_HUSH) += hush.o match.o shell_common.o
226//kbuild:lib-$(CONFIG_SH_IS_HUSH) += hush.o match.o shell_common.o
227//kbuild:lib-$(CONFIG_BASH_IS_HUSH) += hush.o match.o shell_common.o
256//kbuild:lib-$(CONFIG_HUSH_RANDOM_SUPPORT) += random.o 228//kbuild:lib-$(CONFIG_HUSH_RANDOM_SUPPORT) += random.o
257 229
258/* -i (interactive) and -s (read stdin) are also accepted, 230/* -i (interactive) and -s (read stdin) are also accepted,
@@ -265,17 +237,34 @@
265//usage:#define hush_full_usage "\n\n" 237//usage:#define hush_full_usage "\n\n"
266//usage: "Unix shell interpreter" 238//usage: "Unix shell interpreter"
267 239
268//usage:#define msh_trivial_usage hush_trivial_usage 240#if !(defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \
269//usage:#define msh_full_usage hush_full_usage 241 || defined(__APPLE__) \
242 )
243# include <malloc.h> /* for malloc_trim */
244#endif
245#include <glob.h>
246/* #include <dmalloc.h> */
247#if ENABLE_HUSH_CASE
248# include <fnmatch.h>
249#endif
250#include <sys/utsname.h> /* for setting $HOSTNAME */
270 251
271//usage:#if ENABLE_FEATURE_SH_IS_HUSH 252#include "busybox.h" /* for APPLET_IS_NOFORK/NOEXEC */
272//usage:# define sh_trivial_usage hush_trivial_usage 253#include "unicode.h"
273//usage:# define sh_full_usage hush_full_usage 254#include "shell_common.h"
274//usage:#endif 255#include "math.h"
275//usage:#if ENABLE_FEATURE_BASH_IS_HUSH 256#include "match.h"
276//usage:# define bash_trivial_usage hush_trivial_usage 257#if ENABLE_HUSH_RANDOM_SUPPORT
277//usage:# define bash_full_usage hush_full_usage 258# include "random.h"
278//usage:#endif 259#else
260# define CLEAR_RANDOM_T(rnd) ((void)0)
261#endif
262#ifndef F_DUPFD_CLOEXEC
263# define F_DUPFD_CLOEXEC F_DUPFD
264#endif
265#ifndef PIPE_BUF
266# define PIPE_BUF 4096 /* amount of buffering in a pipe */
267#endif
279 268
280 269
281/* Build knobs */ 270/* Build knobs */
@@ -1148,6 +1137,9 @@ static void syntax_error_unexpected_ch(unsigned lineno UNUSED_PARAM, int ch)
1148 char msg[2]; 1137 char msg[2];
1149 msg[0] = ch; 1138 msg[0] = ch;
1150 msg[1] = '\0'; 1139 msg[1] = '\0';
1140#if HUSH_DEBUG >= 2
1141 bb_error_msg("hush.c:%u", lineno);
1142#endif
1151 bb_error_msg("syntax error: unexpected %s", ch == EOF ? "EOF" : msg); 1143 bb_error_msg("syntax error: unexpected %s", ch == EOF ? "EOF" : msg);
1152} 1144}
1153 1145
@@ -1574,9 +1566,8 @@ static sighandler_t install_sighandler(int sig, sighandler_t handler)
1574} 1566}
1575 1567
1576static void hush_exit(int exitcode) NORETURN; 1568static void hush_exit(int exitcode) NORETURN;
1577static void fflush_and__exit(void) NORETURN;
1578static void restore_ttypgrp_and__exit(void) NORETURN;
1579 1569
1570static void restore_ttypgrp_and__exit(void) NORETURN;
1580static void restore_ttypgrp_and__exit(void) 1571static void restore_ttypgrp_and__exit(void)
1581{ 1572{
1582 /* xfunc has failed! die die die */ 1573 /* xfunc has failed! die die die */
@@ -1585,6 +1576,8 @@ static void restore_ttypgrp_and__exit(void)
1585 hush_exit(xfunc_error_retval); 1576 hush_exit(xfunc_error_retval);
1586} 1577}
1587 1578
1579#if ENABLE_HUSH_JOB
1580
1588/* Needed only on some libc: 1581/* Needed only on some libc:
1589 * It was observed that on exit(), fgetc'ed buffered data 1582 * It was observed that on exit(), fgetc'ed buffered data
1590 * gets "unwound" via lseek(fd, -NUM, SEEK_CUR). 1583 * gets "unwound" via lseek(fd, -NUM, SEEK_CUR).
@@ -1598,14 +1591,13 @@ static void restore_ttypgrp_and__exit(void)
1598 * and in `cmd` handling. 1591 * and in `cmd` handling.
1599 * If set as die_func(), this makes xfunc_die() exit via _exit(), not exit(): 1592 * If set as die_func(), this makes xfunc_die() exit via _exit(), not exit():
1600 */ 1593 */
1594static void fflush_and__exit(void) NORETURN;
1601static void fflush_and__exit(void) 1595static void fflush_and__exit(void)
1602{ 1596{
1603 fflush_all(); 1597 fflush_all();
1604 _exit(xfunc_error_retval); 1598 _exit(xfunc_error_retval);
1605} 1599}
1606 1600
1607#if ENABLE_HUSH_JOB
1608
1609/* After [v]fork, in child: do not restore tty pgrp on xfunc death */ 1601/* After [v]fork, in child: do not restore tty pgrp on xfunc death */
1610# define disable_restore_tty_pgrp_on_exit() (die_func = fflush_and__exit) 1602# define disable_restore_tty_pgrp_on_exit() (die_func = fflush_and__exit)
1611/* After [v]fork, in parent: restore tty pgrp on xfunc death */ 1603/* After [v]fork, in parent: restore tty pgrp on xfunc death */
@@ -4011,7 +4003,7 @@ static int i_peek_and_eat_bkslash_nl(struct in_str *input)
4011 } 4003 }
4012} 4004}
4013 4005
4014#if ENABLE_HUSH_TICK || ENABLE_SH_MATH_SUPPORT || ENABLE_HUSH_DOLLAR_OPS 4006#if ENABLE_HUSH_TICK || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_DOLLAR_OPS
4015/* Subroutines for copying $(...) and `...` things */ 4007/* Subroutines for copying $(...) and `...` things */
4016static int add_till_backquote(o_string *dest, struct in_str *input, int in_dquote); 4008static int add_till_backquote(o_string *dest, struct in_str *input, int in_dquote);
4017/* '...' */ 4009/* '...' */
@@ -4179,7 +4171,7 @@ static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsign
4179 } 4171 }
4180 return ch; 4172 return ch;
4181} 4173}
4182#endif /* ENABLE_HUSH_TICK || ENABLE_SH_MATH_SUPPORT || ENABLE_HUSH_DOLLAR_OPS */ 4174#endif /* ENABLE_HUSH_TICK || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_DOLLAR_OPS */
4183 4175
4184/* Return code: 0 for OK, 1 for syntax error */ 4176/* Return code: 0 for OK, 1 for syntax error */
4185#if BB_MMU 4177#if BB_MMU
@@ -4333,13 +4325,13 @@ static int parse_dollar(o_string *as_string,
4333 o_addchr(dest, SPECIAL_VAR_SYMBOL); 4325 o_addchr(dest, SPECIAL_VAR_SYMBOL);
4334 break; 4326 break;
4335 } 4327 }
4336#if ENABLE_SH_MATH_SUPPORT || ENABLE_HUSH_TICK 4328#if ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_TICK
4337 case '(': { 4329 case '(': {
4338 unsigned pos; 4330 unsigned pos;
4339 4331
4340 ch = i_getch(input); 4332 ch = i_getch(input);
4341 nommu_addchr(as_string, ch); 4333 nommu_addchr(as_string, ch);
4342# if ENABLE_SH_MATH_SUPPORT 4334# if ENABLE_FEATURE_SH_MATH
4343 if (i_peek_and_eat_bkslash_nl(input) == '(') { 4335 if (i_peek_and_eat_bkslash_nl(input) == '(') {
4344 ch = i_getch(input); 4336 ch = i_getch(input);
4345 nommu_addchr(as_string, ch); 4337 nommu_addchr(as_string, ch);
@@ -5008,7 +5000,8 @@ static struct pipe *parse_stream(char **pstring,
5008 * if we see {, we call parse_group(..., end_trigger='}') 5000 * if we see {, we call parse_group(..., end_trigger='}')
5009 * and it will match } earlier (not here). */ 5001 * and it will match } earlier (not here). */
5010 syntax_error_unexpected_ch(ch); 5002 syntax_error_unexpected_ch(ch);
5011 goto parse_error; 5003 G.last_exitcode = 2;
5004 goto parse_error1;
5012 default: 5005 default:
5013 if (HUSH_DEBUG) 5006 if (HUSH_DEBUG)
5014 bb_error_msg_and_die("BUG: unexpected %c\n", ch); 5007 bb_error_msg_and_die("BUG: unexpected %c\n", ch);
@@ -5016,6 +5009,8 @@ static struct pipe *parse_stream(char **pstring,
5016 } /* while (1) */ 5009 } /* while (1) */
5017 5010
5018 parse_error: 5011 parse_error:
5012 G.last_exitcode = 1;
5013 parse_error1:
5019 { 5014 {
5020 struct parse_context *pctx; 5015 struct parse_context *pctx;
5021 IF_HAS_KEYWORDS(struct parse_context *p2;) 5016 IF_HAS_KEYWORDS(struct parse_context *p2;)
@@ -5049,7 +5044,6 @@ static struct pipe *parse_stream(char **pstring,
5049 } while (HAS_KEYWORDS && pctx); 5044 } while (HAS_KEYWORDS && pctx);
5050 5045
5051 o_free(&dest); 5046 o_free(&dest);
5052 G.last_exitcode = 1;
5053#if !BB_MMU 5047#if !BB_MMU
5054 if (pstring) 5048 if (pstring)
5055 *pstring = NULL; 5049 *pstring = NULL;
@@ -5217,7 +5211,7 @@ static char *encode_then_expand_string(const char *str, int process_bkslash, int
5217 return exp_str; 5211 return exp_str;
5218} 5212}
5219 5213
5220#if ENABLE_SH_MATH_SUPPORT 5214#if ENABLE_FEATURE_SH_MATH
5221static arith_t expand_and_evaluate_arith(const char *arg, const char **errmsg_p) 5215static arith_t expand_and_evaluate_arith(const char *arg, const char **errmsg_p)
5222{ 5216{
5223 arith_state_t math_state; 5217 arith_state_t math_state;
@@ -5469,7 +5463,7 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha
5469 } 5463 }
5470#endif 5464#endif
5471 else if (exp_op == ':') { 5465 else if (exp_op == ':') {
5472#if ENABLE_HUSH_BASH_COMPAT && ENABLE_SH_MATH_SUPPORT 5466#if ENABLE_HUSH_BASH_COMPAT && ENABLE_FEATURE_SH_MATH
5473 /* It's ${var:N[:M]} bashism. 5467 /* It's ${var:N[:M]} bashism.
5474 * Note that in encoded form it has TWO parts: 5468 * Note that in encoded form it has TWO parts:
5475 * var:N<SPECIAL_VAR_SYMBOL>M<SPECIAL_VAR_SYMBOL> 5469 * var:N<SPECIAL_VAR_SYMBOL>M<SPECIAL_VAR_SYMBOL>
@@ -5604,7 +5598,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
5604#if ENABLE_HUSH_TICK 5598#if ENABLE_HUSH_TICK
5605 o_string subst_result = NULL_O_STRING; 5599 o_string subst_result = NULL_O_STRING;
5606#endif 5600#endif
5607#if ENABLE_SH_MATH_SUPPORT 5601#if ENABLE_FEATURE_SH_MATH
5608 char arith_buf[sizeof(arith_t)*3 + 2]; 5602 char arith_buf[sizeof(arith_t)*3 + 2];
5609#endif 5603#endif
5610 5604
@@ -5698,7 +5692,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
5698 val = subst_result.data; 5692 val = subst_result.data;
5699 goto store_val; 5693 goto store_val;
5700#endif 5694#endif
5701#if ENABLE_SH_MATH_SUPPORT 5695#if ENABLE_FEATURE_SH_MATH
5702 case '+': { /* <SPECIAL_VAR_SYMBOL>+cmd<SPECIAL_VAR_SYMBOL> */ 5696 case '+': { /* <SPECIAL_VAR_SYMBOL>+cmd<SPECIAL_VAR_SYMBOL> */
5703 arith_t res; 5697 arith_t res;
5704 5698
diff --git a/shell/hush_test/hush-misc/exitcode2.right b/shell/hush_test/hush-misc/exitcode2.right
new file mode 100644
index 000000000..0a57b9b1b
--- /dev/null
+++ b/shell/hush_test/hush-misc/exitcode2.right
@@ -0,0 +1,4 @@
1hush: syntax error: unexpected )
2Done:2
3hush: can't open 'does_not_exist': No such file or directory
4Done:1
diff --git a/shell/hush_test/hush-misc/exitcode2.tests b/shell/hush_test/hush-misc/exitcode2.tests
new file mode 100755
index 000000000..79a6ebd50
--- /dev/null
+++ b/shell/hush_test/hush-misc/exitcode2.tests
@@ -0,0 +1,12 @@
1# syntax error should return status 2
2cat >test.sh <<EOF
3)
4EOF
5chmod +x test.sh
6$THIS_SH ./test.sh
7echo Done:$?
8rm -f test.sh
9
10# redirection error with special builtin should return status 1
11(eval cat <does_not_exist)
12echo Done:$?
diff --git a/shell/hush_test/hush-redir/redir_leak.right b/shell/hush_test/hush-redir/redir_leak.right
new file mode 100644
index 000000000..b1c48292b
--- /dev/null
+++ b/shell/hush_test/hush-redir/redir_leak.right
@@ -0,0 +1,6 @@
14
24
34
44
54
64
diff --git a/shell/hush_test/hush-redir/redir_leak.tests b/shell/hush_test/hush-redir/redir_leak.tests
new file mode 100755
index 000000000..c8a9c6343
--- /dev/null
+++ b/shell/hush_test/hush-redir/redir_leak.tests
@@ -0,0 +1,10 @@
1# Each of these should show only four lines:
2# fds 0,1,2 are stdio; fd 3 is open by opendir() in ls.
3# This test detects bugs where redirects leave stray open fds.
4
5ls -1 /proc/self/fd | wc -l
6ls -1 /proc/self/fd >/proc/self/fd/1 | wc -l
7ls -1 /proc/self/fd >/proc/self/fd/1 2>&1 | wc -l
8echo "`ls -1 /proc/self/fd `" | wc -l
9echo "`ls -1 /proc/self/fd >/proc/self/fd/1 `" | wc -l
10echo "`ls -1 /proc/self/fd >/proc/self/fd/1 2>&1 `" | wc -l
diff --git a/shell/math.h b/shell/math.h
index 864bee691..32e1ffe35 100644
--- a/shell/math.h
+++ b/shell/math.h
@@ -63,7 +63,7 @@
63 63
64PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN 64PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
65 65
66#if ENABLE_SH_MATH_SUPPORT_64 66#if ENABLE_FEATURE_SH_MATH_64
67typedef long long arith_t; 67typedef long long arith_t;
68#define ARITH_FMT "%lld" 68#define ARITH_FMT "%lld"
69#define strto_arith_t strtoull 69#define strto_arith_t strtoull
diff --git a/sysklogd/logread.c b/sysklogd/logread.c
index 5b999730a..1f0c6252d 100644
--- a/sysklogd/logread.c
+++ b/sysklogd/logread.c
@@ -11,7 +11,8 @@
11//config:config LOGREAD 11//config:config LOGREAD
12//config: bool "logread" 12//config: bool "logread"
13//config: default y 13//config: default y
14//config: depends on FEATURE_IPC_SYSLOG 14//WRONG: it should be compilable without SYSLOG=y:
15//WRONG: depends on FEATURE_IPC_SYSLOG
15//config: help 16//config: help
16//config: If you enabled Circular Buffer support, you almost 17//config: If you enabled Circular Buffer support, you almost
17//config: certainly want to enable this feature as well. This 18//config: certainly want to enable this feature as well. This
diff --git a/testsuite/bunzip2/bzcat-does-not-remove-compressed-file b/testsuite/bzcat/bzcat-does-not-remove-compressed-file
index 7d4016ec5..7d4016ec5 100644
--- a/testsuite/bunzip2/bzcat-does-not-remove-compressed-file
+++ b/testsuite/bzcat/bzcat-does-not-remove-compressed-file
diff --git a/testsuite/cpio.tests b/testsuite/cpio.tests
index d44c95b10..88ec086b6 100755
--- a/testsuite/cpio.tests
+++ b/testsuite/cpio.tests
@@ -127,6 +127,7 @@ testing "cpio extracts in existing directory" \
127" "" "" 127" "" ""
128SKIP= 128SKIP=
129 129
130optional FEATURE_CPIO_O
130testing "cpio uses by default uid/gid" \ 131testing "cpio uses by default uid/gid" \
131"echo $0 | cpio -o -H newc | cpio -tv 2>&1 | tail -n +2 | awk ' { print \$2 } '; echo \$?" \ 132"echo $0 | cpio -o -H newc | cpio -tv 2>&1 | tail -n +2 | awk ' { print \$2 } '; echo \$?" \
132"\ 133"\
@@ -135,6 +136,7 @@ $user/$group
135" "" "" 136" "" ""
136SKIP= 137SKIP=
137 138
139optional FEATURE_CPIO_O
138testing "cpio -R with create" \ 140testing "cpio -R with create" \
139"echo $0 | cpio -o -H newc -R 1234:5678 | cpio -tv 2>&1 | tail -n +2 | awk ' { print \$2 } '; echo \$?" \ 141"echo $0 | cpio -o -H newc -R 1234:5678 | cpio -tv 2>&1 | tail -n +2 | awk ' { print \$2 } '; echo \$?" \
140"\ 142"\
@@ -143,6 +145,7 @@ testing "cpio -R with create" \
143" "" "" 145" "" ""
144SKIP= 146SKIP=
145 147
148optional FEATURE_CPIO_O
146testing "cpio -R with extract" \ 149testing "cpio -R with extract" \
147"echo $0 | cpio -o -H newc | cpio -tv -R 8765:4321 2>&1 | tail -n +2 | awk ' { print \$2 } '; echo \$?" \ 150"echo $0 | cpio -o -H newc | cpio -tv -R 8765:4321 2>&1 | tail -n +2 | awk ' { print \$2 } '; echo \$?" \
148"\ 151"\
diff --git a/testsuite/tar.tests b/testsuite/tar.tests
index ffcbe9ba9..9f7ce1587 100755
--- a/testsuite/tar.tests
+++ b/testsuite/tar.tests
@@ -299,11 +299,11 @@ l4/V8LDoe90yiWJhOJvIypgEfxdyRThQkBVn/bI=
299" 299"
300SKIP= 300SKIP=
301 301
302optional UNICODE_SUPPORT 302optional UNICODE_SUPPORT FEATURE_TAR_GNU_EXTENSIONS FEATURE_SEAMLESS_BZ2 FEATURE_TAR_AUTODETECT
303testing "Pax-encoded UTF8 names and symlinks" '\ 303testing "Pax-encoded UTF8 names and symlinks" '\
304tar xvf ../tar.utf8.tar.bz2 2>&1; echo $? 304tar xvf ../tar.utf8.tar.bz2 2>&1; echo $?
305export LANG=en_US.UTF-8 305export LANG=en_US.UTF-8
306ls -l etc/ssl/certs/* | sed "s:.*etc/:etc/:" 306ls -l etc/ssl/certs/* | sed "s:.*etc/:etc/:" | sort
307unset LANG 307unset LANG
308rm -rf etc usr 308rm -rf etc usr
309' "\ 309' "\
diff --git a/util-linux/fstrim.c b/util-linux/fstrim.c
index 51400ef0b..fc51878b6 100644
--- a/util-linux/fstrim.c
+++ b/util-linux/fstrim.c
@@ -47,25 +47,6 @@ struct fstrim_range {
47#define FITRIM _IOWR('X', 121, struct fstrim_range) 47#define FITRIM _IOWR('X', 121, struct fstrim_range)
48#endif 48#endif
49 49
50static const struct suffix_mult fstrim_sfx[] = {
51 { "KiB", 1024 },
52 { "kiB", 1024 },
53 { "K", 1024 },
54 { "k", 1024 },
55 { "MiB", 1048576 },
56 { "miB", 1048576 },
57 { "M", 1048576 },
58 { "m", 1048576 },
59 { "GiB", 1073741824 },
60 { "giB", 1073741824 },
61 { "G", 1073741824 },
62 { "g", 1073741824 },
63 { "KB", 1000 },
64 { "MB", 1000000 },
65 { "GB", 1000000000 },
66 { "", 0 }
67};
68
69int fstrim_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 50int fstrim_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
70int fstrim_main(int argc UNUSED_PARAM, char **argv) 51int fstrim_main(int argc UNUSED_PARAM, char **argv)
71{ 52{
@@ -98,11 +79,11 @@ int fstrim_main(int argc UNUSED_PARAM, char **argv)
98 range.len = ULLONG_MAX; 79 range.len = ULLONG_MAX;
99 80
100 if (opts & OPT_o) 81 if (opts & OPT_o)
101 range.start = xatoull_sfx(arg_o, fstrim_sfx); 82 range.start = xatoull_sfx(arg_o, kmg_i_suffixes);
102 if (opts & OPT_l) 83 if (opts & OPT_l)
103 range.len = xatoull_sfx(arg_l, fstrim_sfx); 84 range.len = xatoull_sfx(arg_l, kmg_i_suffixes);
104 if (opts & OPT_m) 85 if (opts & OPT_m)
105 range.minlen = xatoull_sfx(arg_m, fstrim_sfx); 86 range.minlen = xatoull_sfx(arg_m, kmg_i_suffixes);
106 87
107 mp = argv[optind]; 88 mp = argv[optind];
108 if (find_block_device(mp)) { 89 if (find_block_device(mp)) {