aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2020-08-23 10:59:38 +0100
committerRon Yorston <rmy@pobox.com>2020-08-23 10:59:38 +0100
commit5dbbfe22dd28c3b3ecd5763cc8e60406136e87ce (patch)
tree64c983708f9f2a21a2fbec14a06d85057d886dfd
parent64ecd10486934c12336dac84c67a1939dce0e096 (diff)
parenta949399d178f7b052ada2099c62621736eafce44 (diff)
downloadbusybox-w32-5dbbfe22dd28c3b3ecd5763cc8e60406136e87ce.tar.gz
busybox-w32-5dbbfe22dd28c3b3ecd5763cc8e60406136e87ce.tar.bz2
busybox-w32-5dbbfe22dd28c3b3ecd5763cc8e60406136e87ce.zip
Merge branch 'busybox' into merge
-rw-r--r--Config.in12
-rw-r--r--configs/android2_defconfig1
-rw-r--r--configs/android_502_defconfig1
-rw-r--r--configs/android_defconfig1
-rw-r--r--configs/android_ndk_defconfig1
-rw-r--r--configs/cygwin_defconfig1
-rw-r--r--configs/freebsd_defconfig1
-rw-r--r--configs/mingw32_defconfig1
-rw-r--r--configs/mingw64_defconfig1
-rw-r--r--console-tools/chvt.c1
-rw-r--r--console-tools/deallocvt.c1
-rw-r--r--console-tools/dumpkmap.c1
-rw-r--r--console-tools/fgconsole.c1
-rw-r--r--console-tools/kbd_mode.c1
-rw-r--r--console-tools/loadfont.c2
-rw-r--r--console-tools/loadkmap.c1
-rw-r--r--console-tools/openvt.c1
-rw-r--r--console-tools/setconsole.c1
-rw-r--r--console-tools/setkeycodes.c1
-rw-r--r--console-tools/setlogcons.c1
-rw-r--r--console-tools/showkey.c1
-rw-r--r--coreutils/date.c1
-rw-r--r--coreutils/stat.c1
-rw-r--r--e2fsprogs/lsattr.c1
-rw-r--r--findutils/grep.c29
-rw-r--r--include/libbb.h7
-rw-r--r--klibc-utils/run-init.c1
-rw-r--r--libbb/Config.src2
-rw-r--r--libbb/Kbuild.src3
-rw-r--r--libbb/last_char_is.c15
-rw-r--r--mailutils/popmaildir.c2
-rw-r--r--miscutils/adjtimex.c1
-rw-r--r--miscutils/beep.c1
-rw-r--r--miscutils/conspy.c1
-rw-r--r--miscutils/crontab.c6
-rw-r--r--miscutils/devfsd.c2
-rw-r--r--miscutils/fbsplash.c1
-rw-r--r--miscutils/hdparm.c1
-rw-r--r--miscutils/i2c_tools.c5
-rw-r--r--miscutils/lsscsi.c28
-rw-r--r--miscutils/nandwrite.c2
-rw-r--r--miscutils/partprobe.c1
-rw-r--r--miscutils/raidautorun.c1
-rw-r--r--miscutils/readahead.c1
-rw-r--r--miscutils/rfkill.c1
-rw-r--r--miscutils/rx.c1
-rw-r--r--miscutils/setserial.c1
-rw-r--r--miscutils/ubi_tools.c6
-rw-r--r--miscutils/ubirename.c1
-rw-r--r--miscutils/watchdog.c1
-rw-r--r--modutils/depmod.c1
-rw-r--r--modutils/insmod.c1
-rw-r--r--modutils/lsmod.c1
-rw-r--r--modutils/modinfo.c1
-rw-r--r--modutils/modprobe.c1
-rw-r--r--modutils/rmmod.c1
-rw-r--r--networking/arp.c1
-rw-r--r--networking/arping.c1
-rw-r--r--networking/brctl.c1
-rw-r--r--networking/ether-wake.c1
-rw-r--r--networking/httpd.c192
-rw-r--r--networking/httpd_indexcgi.c80
-rw-r--r--networking/ifconfig.c1
-rw-r--r--networking/ifenslave.c1
-rw-r--r--networking/ifplugd.c1
-rw-r--r--networking/ip.c11
-rw-r--r--networking/libiproute/ip_common.h4
-rw-r--r--networking/libiproute/ipaddress.c104
-rw-r--r--networking/nameif.c1
-rw-r--r--networking/netstat.c1
-rw-r--r--networking/ntpd.c38
-rw-r--r--networking/parse_pasv_epsv.c2
-rw-r--r--networking/ping.c1
-rw-r--r--networking/route.c1
-rw-r--r--networking/slattach.c1
-rw-r--r--networking/tls.c2
-rw-r--r--networking/traceroute.c1
-rw-r--r--networking/tunctl.c1
-rw-r--r--networking/udhcp/Config.src2
-rw-r--r--networking/udhcp/dhcpc.c138
-rw-r--r--networking/udhcp/dhcpc.h1
-rw-r--r--networking/udhcp/domain_codec.c157
-rw-r--r--networking/vconfig.c1
-rw-r--r--networking/zcip.c1
-rw-r--r--procps/free.c1
-rw-r--r--procps/ps.c1
-rw-r--r--procps/uptime.c1
-rw-r--r--shell/ash_test/ash-read/read_d0.right1
-rwxr-xr-xshell/ash_test/ash-read/read_d0.tests1
-rw-r--r--shell/hush_test/hush-read/read_d0.right1
-rwxr-xr-xshell/hush_test/hush-read/read_d0.tests1
-rw-r--r--shell/shell_common.c6
-rw-r--r--sysklogd/klogd.c1
-rw-r--r--sysklogd/syslogd.c1
-rwxr-xr-xtestsuite/grep.tests8
-rw-r--r--util-linux/acpid.c1
-rw-r--r--util-linux/blkdiscard.c1
-rw-r--r--util-linux/blkid.c1
-rw-r--r--util-linux/dmesg.c1
-rw-r--r--util-linux/eject.c1
-rw-r--r--util-linux/fatattr.c1
-rw-r--r--util-linux/fbset.c1
-rw-r--r--util-linux/fdformat.c1
-rw-r--r--util-linux/fdisk.c1
-rw-r--r--util-linux/findfs.c1
-rw-r--r--util-linux/freeramdisk.c2
-rw-r--r--util-linux/fsfreeze.c1
-rw-r--r--util-linux/fstrim.c1
-rw-r--r--util-linux/hwclock.c15
-rw-r--r--util-linux/ionice.c1
-rw-r--r--util-linux/ipcs.c1
-rw-r--r--util-linux/losetup.c1
-rw-r--r--util-linux/lspci.c1
-rw-r--r--util-linux/lsusb.c1
-rw-r--r--util-linux/mdev.c1
-rw-r--r--util-linux/mkfs_ext2.c2
-rw-r--r--util-linux/mkfs_minix.c1
-rw-r--r--util-linux/mkfs_reiser.c1
-rw-r--r--util-linux/mkfs_vfat.c2
-rw-r--r--util-linux/mount.c1
-rw-r--r--util-linux/nsenter.c1
-rw-r--r--util-linux/pivot_root.c1
-rw-r--r--util-linux/readprofile.c1
-rw-r--r--util-linux/rtcwake.c1
-rw-r--r--util-linux/setarch.c3
-rw-r--r--util-linux/setpriv.c1
-rw-r--r--util-linux/swaponoff.c2
-rw-r--r--util-linux/switch_root.c1
-rw-r--r--util-linux/uevent.c1
-rw-r--r--util-linux/umount.c1
-rw-r--r--util-linux/unshare.c1
131 files changed, 572 insertions, 417 deletions
diff --git a/Config.in b/Config.in
index d18f3dac5..495ac4c13 100644
--- a/Config.in
+++ b/Config.in
@@ -326,7 +326,6 @@ config BUSYBOX_EXEC_PATH
326config SELINUX 326config SELINUX
327 bool "Support NSA Security Enhanced Linux" 327 bool "Support NSA Security Enhanced Linux"
328 default n 328 default n
329 select PLATFORM_LINUX
330 help 329 help
331 Enable support for SELinux in applets ls, ps, and id. Also provide 330 Enable support for SELinux in applets ls, ps, and id. Also provide
332 the option of compiling in SELinux applets. 331 the option of compiling in SELinux applets.
@@ -372,17 +371,6 @@ config FEATURE_SYSLOG
372 #This option is auto-selected when you select any applet which may 371 #This option is auto-selected when you select any applet which may
373 #send its output to syslog. You do not need to select it manually. 372 #send its output to syslog. You do not need to select it manually.
374 373
375config PLATFORM_LINUX
376 bool #No description makes it a hidden option
377 default n
378 #help
379 #For the most part, busybox requires only POSIX compatibility
380 #from the target system, but some applets and features use
381 #Linux-specific interfaces.
382 #
383 #This is automatically selected if any applet or feature requires
384 #Linux-specific interfaces. You do not need to select it manually.
385
386comment 'Settings for MINGW32' 374comment 'Settings for MINGW32'
387 375
388config GLOBBING 376config GLOBBING
diff --git a/configs/android2_defconfig b/configs/android2_defconfig
index 03323654d..d4b8f1616 100644
--- a/configs/android2_defconfig
+++ b/configs/android2_defconfig
@@ -16,7 +16,6 @@ CONFIG_HAVE_DOT_CONFIG=y
16# CONFIG_EXTRA_COMPAT is not set 16# CONFIG_EXTRA_COMPAT is not set
17# CONFIG_INCLUDE_SUSv2 is not set 17# CONFIG_INCLUDE_SUSv2 is not set
18# CONFIG_USE_PORTABLE_CODE is not set 18# CONFIG_USE_PORTABLE_CODE is not set
19CONFIG_PLATFORM_LINUX=y
20CONFIG_FEATURE_BUFFERS_USE_MALLOC=y 19CONFIG_FEATURE_BUFFERS_USE_MALLOC=y
21# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set 20# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set
22# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set 21# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set
diff --git a/configs/android_502_defconfig b/configs/android_502_defconfig
index 6b640bfb7..503157c12 100644
--- a/configs/android_502_defconfig
+++ b/configs/android_502_defconfig
@@ -87,7 +87,6 @@ CONFIG_DESKTOP=y
87# CONFIG_EXTRA_COMPAT is not set 87# CONFIG_EXTRA_COMPAT is not set
88CONFIG_INCLUDE_SUSv2=y 88CONFIG_INCLUDE_SUSv2=y
89# CONFIG_USE_PORTABLE_CODE is not set 89# CONFIG_USE_PORTABLE_CODE is not set
90CONFIG_PLATFORM_LINUX=y
91CONFIG_FEATURE_BUFFERS_USE_MALLOC=y 90CONFIG_FEATURE_BUFFERS_USE_MALLOC=y
92# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set 91# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set
93# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set 92# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set
diff --git a/configs/android_defconfig b/configs/android_defconfig
index 3b34f37aa..92a66048a 100644
--- a/configs/android_defconfig
+++ b/configs/android_defconfig
@@ -16,7 +16,6 @@ CONFIG_DESKTOP=y
16# CONFIG_EXTRA_COMPAT is not set 16# CONFIG_EXTRA_COMPAT is not set
17# CONFIG_INCLUDE_SUSv2 is not set 17# CONFIG_INCLUDE_SUSv2 is not set
18# CONFIG_USE_PORTABLE_CODE is not set 18# CONFIG_USE_PORTABLE_CODE is not set
19CONFIG_PLATFORM_LINUX=y
20CONFIG_FEATURE_BUFFERS_USE_MALLOC=y 19CONFIG_FEATURE_BUFFERS_USE_MALLOC=y
21# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set 20# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set
22# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set 21# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set
diff --git a/configs/android_ndk_defconfig b/configs/android_ndk_defconfig
index 7f65d544c..03d497d2e 100644
--- a/configs/android_ndk_defconfig
+++ b/configs/android_ndk_defconfig
@@ -16,7 +16,6 @@ CONFIG_DESKTOP=y
16# CONFIG_EXTRA_COMPAT is not set 16# CONFIG_EXTRA_COMPAT is not set
17# CONFIG_INCLUDE_SUSv2 is not set 17# CONFIG_INCLUDE_SUSv2 is not set
18# CONFIG_USE_PORTABLE_CODE is not set 18# CONFIG_USE_PORTABLE_CODE is not set
19CONFIG_PLATFORM_LINUX=y
20CONFIG_FEATURE_BUFFERS_USE_MALLOC=y 19CONFIG_FEATURE_BUFFERS_USE_MALLOC=y
21# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set 20# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set
22# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set 21# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set
diff --git a/configs/cygwin_defconfig b/configs/cygwin_defconfig
index ee370a61d..c09bc9281 100644
--- a/configs/cygwin_defconfig
+++ b/configs/cygwin_defconfig
@@ -16,7 +16,6 @@ CONFIG_DESKTOP=y
16# CONFIG_EXTRA_COMPAT is not set 16# CONFIG_EXTRA_COMPAT is not set
17CONFIG_INCLUDE_SUSv2=y 17CONFIG_INCLUDE_SUSv2=y
18# CONFIG_USE_PORTABLE_CODE is not set 18# CONFIG_USE_PORTABLE_CODE is not set
19CONFIG_PLATFORM_LINUX=y
20CONFIG_FEATURE_BUFFERS_USE_MALLOC=y 19CONFIG_FEATURE_BUFFERS_USE_MALLOC=y
21# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set 20# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set
22# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set 21# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set
diff --git a/configs/freebsd_defconfig b/configs/freebsd_defconfig
index 47e705963..6cbd54895 100644
--- a/configs/freebsd_defconfig
+++ b/configs/freebsd_defconfig
@@ -16,7 +16,6 @@ CONFIG_HAVE_DOT_CONFIG=y
16# CONFIG_EXTRA_COMPAT is not set 16# CONFIG_EXTRA_COMPAT is not set
17CONFIG_INCLUDE_SUSv2=y 17CONFIG_INCLUDE_SUSv2=y
18CONFIG_USE_PORTABLE_CODE=y 18CONFIG_USE_PORTABLE_CODE=y
19# CONFIG_PLATFORM_LINUX is not set
20CONFIG_FEATURE_BUFFERS_USE_MALLOC=y 19CONFIG_FEATURE_BUFFERS_USE_MALLOC=y
21# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set 20# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set
22# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set 21# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set
diff --git a/configs/mingw32_defconfig b/configs/mingw32_defconfig
index e6c4c9e7a..211c1ba80 100644
--- a/configs/mingw32_defconfig
+++ b/configs/mingw32_defconfig
@@ -38,7 +38,6 @@ CONFIG_BUSYBOX_EXEC_PATH=""
38# CONFIG_FEATURE_CLEAN_UP is not set 38# CONFIG_FEATURE_CLEAN_UP is not set
39# CONFIG_FEATURE_SYSLOG_INFO is not set 39# CONFIG_FEATURE_SYSLOG_INFO is not set
40# CONFIG_FEATURE_SYSLOG is not set 40# CONFIG_FEATURE_SYSLOG is not set
41CONFIG_PLATFORM_LINUX=y
42 41
43# 42#
44# Settings for MINGW32 43# Settings for MINGW32
diff --git a/configs/mingw64_defconfig b/configs/mingw64_defconfig
index a2aeec912..0368ff4aa 100644
--- a/configs/mingw64_defconfig
+++ b/configs/mingw64_defconfig
@@ -38,7 +38,6 @@ CONFIG_BUSYBOX_EXEC_PATH=""
38# CONFIG_FEATURE_CLEAN_UP is not set 38# CONFIG_FEATURE_CLEAN_UP is not set
39# CONFIG_FEATURE_SYSLOG_INFO is not set 39# CONFIG_FEATURE_SYSLOG_INFO is not set
40# CONFIG_FEATURE_SYSLOG is not set 40# CONFIG_FEATURE_SYSLOG is not set
41CONFIG_PLATFORM_LINUX=y
42 41
43# 42#
44# Settings for MINGW32 43# Settings for MINGW32
diff --git a/console-tools/chvt.c b/console-tools/chvt.c
index 75380a90b..7c2814d1c 100644
--- a/console-tools/chvt.c
+++ b/console-tools/chvt.c
@@ -9,7 +9,6 @@
9//config:config CHVT 9//config:config CHVT
10//config: bool "chvt (2 kb)" 10//config: bool "chvt (2 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX
13//config: help 12//config: help
14//config: This program is used to change to another terminal. 13//config: This program is used to change to another terminal.
15//config: Example: chvt 4 (change to terminal /dev/tty4) 14//config: Example: chvt 4 (change to terminal /dev/tty4)
diff --git a/console-tools/deallocvt.c b/console-tools/deallocvt.c
index 05731fb78..6cd54653c 100644
--- a/console-tools/deallocvt.c
+++ b/console-tools/deallocvt.c
@@ -10,7 +10,6 @@
10//config:config DEALLOCVT 10//config:config DEALLOCVT
11//config: bool "deallocvt (1.9 kb)" 11//config: bool "deallocvt (1.9 kb)"
12//config: default y 12//config: default y
13//config: select PLATFORM_LINUX
14//config: help 13//config: help
15//config: This program deallocates unused virtual consoles. 14//config: This program deallocates unused virtual consoles.
16 15
diff --git a/console-tools/dumpkmap.c b/console-tools/dumpkmap.c
index fd4fd5623..3d8de6bed 100644
--- a/console-tools/dumpkmap.c
+++ b/console-tools/dumpkmap.c
@@ -9,7 +9,6 @@
9//config:config DUMPKMAP 9//config:config DUMPKMAP
10//config: bool "dumpkmap (1.6 kb)" 10//config: bool "dumpkmap (1.6 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX
13//config: help 12//config: help
14//config: This program dumps the kernel's keyboard translation table to 13//config: This program dumps the kernel's keyboard translation table to
15//config: stdout, in binary format. You can then use loadkmap to load it. 14//config: stdout, in binary format. You can then use loadkmap to load it.
diff --git a/console-tools/fgconsole.c b/console-tools/fgconsole.c
index 554a32403..9bfb68017 100644
--- a/console-tools/fgconsole.c
+++ b/console-tools/fgconsole.c
@@ -9,7 +9,6 @@
9//config:config FGCONSOLE 9//config:config FGCONSOLE
10//config: bool "fgconsole (1.5 kb)" 10//config: bool "fgconsole (1.5 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX
13//config: help 12//config: help
14//config: This program prints active (foreground) console number. 13//config: This program prints active (foreground) console number.
15 14
diff --git a/console-tools/kbd_mode.c b/console-tools/kbd_mode.c
index cee37ab50..b0b963ee0 100644
--- a/console-tools/kbd_mode.c
+++ b/console-tools/kbd_mode.c
@@ -11,7 +11,6 @@
11//config:config KBD_MODE 11//config:config KBD_MODE
12//config: bool "kbd_mode (4.1 kb)" 12//config: bool "kbd_mode (4.1 kb)"
13//config: default y 13//config: default y
14//config: select PLATFORM_LINUX
15//config: help 14//config: help
16//config: This program reports and sets keyboard mode. 15//config: This program reports and sets keyboard mode.
17 16
diff --git a/console-tools/loadfont.c b/console-tools/loadfont.c
index caad7d9ac..7533b0aad 100644
--- a/console-tools/loadfont.c
+++ b/console-tools/loadfont.c
@@ -12,14 +12,12 @@
12//config:config LOADFONT 12//config:config LOADFONT
13//config: bool "loadfont (5.2 kb)" 13//config: bool "loadfont (5.2 kb)"
14//config: default y 14//config: default y
15//config: select PLATFORM_LINUX
16//config: help 15//config: help
17//config: This program loads a console font from standard input. 16//config: This program loads a console font from standard input.
18//config: 17//config:
19//config:config SETFONT 18//config:config SETFONT
20//config: bool "setfont (24 kb)" 19//config: bool "setfont (24 kb)"
21//config: default y 20//config: default y
22//config: select PLATFORM_LINUX
23//config: help 21//config: help
24//config: Allows to load console screen map. Useful for i18n. 22//config: Allows to load console screen map. Useful for i18n.
25//config: 23//config:
diff --git a/console-tools/loadkmap.c b/console-tools/loadkmap.c
index 91ef50884..c038e2d22 100644
--- a/console-tools/loadkmap.c
+++ b/console-tools/loadkmap.c
@@ -9,7 +9,6 @@
9//config:config LOADKMAP 9//config:config LOADKMAP
10//config: bool "loadkmap (1.8 kb)" 10//config: bool "loadkmap (1.8 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX
13//config: help 12//config: help
14//config: This program loads a keyboard translation table from 13//config: This program loads a keyboard translation table from
15//config: standard input. 14//config: standard input.
diff --git a/console-tools/openvt.c b/console-tools/openvt.c
index 9e6cffecc..db2f073b2 100644
--- a/console-tools/openvt.c
+++ b/console-tools/openvt.c
@@ -10,7 +10,6 @@
10//config:config OPENVT 10//config:config OPENVT
11//config: bool "openvt (7.2 kb)" 11//config: bool "openvt (7.2 kb)"
12//config: default y 12//config: default y
13//config: select PLATFORM_LINUX
14//config: help 13//config: help
15//config: This program is used to start a command on an unused 14//config: This program is used to start a command on an unused
16//config: virtual terminal. 15//config: virtual terminal.
diff --git a/console-tools/setconsole.c b/console-tools/setconsole.c
index 0bc587241..461a98c6a 100644
--- a/console-tools/setconsole.c
+++ b/console-tools/setconsole.c
@@ -10,7 +10,6 @@
10//config:config SETCONSOLE 10//config:config SETCONSOLE
11//config: bool "setconsole (3.6 kb)" 11//config: bool "setconsole (3.6 kb)"
12//config: default y 12//config: default y
13//config: select PLATFORM_LINUX
14//config: help 13//config: help
15//config: Redirect writes to /dev/console to another device, 14//config: Redirect writes to /dev/console to another device,
16//config: like the current tty while logged in via telnet. 15//config: like the current tty while logged in via telnet.
diff --git a/console-tools/setkeycodes.c b/console-tools/setkeycodes.c
index 259946dbb..5de18b8ea 100644
--- a/console-tools/setkeycodes.c
+++ b/console-tools/setkeycodes.c
@@ -11,7 +11,6 @@
11//config:config SETKEYCODES 11//config:config SETKEYCODES
12//config: bool "setkeycodes (2.1 kb)" 12//config: bool "setkeycodes (2.1 kb)"
13//config: default y 13//config: default y
14//config: select PLATFORM_LINUX
15//config: help 14//config: help
16//config: This program loads entries into the kernel's scancode-to-keycode 15//config: This program loads entries into the kernel's scancode-to-keycode
17//config: map, allowing unusual keyboards to generate usable keycodes. 16//config: map, allowing unusual keyboards to generate usable keycodes.
diff --git a/console-tools/setlogcons.c b/console-tools/setlogcons.c
index 0fad6600a..e9c2f516e 100644
--- a/console-tools/setlogcons.c
+++ b/console-tools/setlogcons.c
@@ -11,7 +11,6 @@
11//config:config SETLOGCONS 11//config:config SETLOGCONS
12//config: bool "setlogcons (1.8 kb)" 12//config: bool "setlogcons (1.8 kb)"
13//config: default y 13//config: default y
14//config: select PLATFORM_LINUX
15//config: help 14//config: help
16//config: This program redirects the output console of kernel messages. 15//config: This program redirects the output console of kernel messages.
17 16
diff --git a/console-tools/showkey.c b/console-tools/showkey.c
index 8f0e9d938..4d7a9b9e5 100644
--- a/console-tools/showkey.c
+++ b/console-tools/showkey.c
@@ -9,7 +9,6 @@
9//config:config SHOWKEY 9//config:config SHOWKEY
10//config: bool "showkey (4.7 kb)" 10//config: bool "showkey (4.7 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX
13//config: help 12//config: help
14//config: Shows keys pressed. 13//config: Shows keys pressed.
15 14
diff --git a/coreutils/date.c b/coreutils/date.c
index 37a47eb14..1a3ae506c 100644
--- a/coreutils/date.c
+++ b/coreutils/date.c
@@ -37,7 +37,6 @@
37//config: bool "Support %[num]N nanosecond format specifier" 37//config: bool "Support %[num]N nanosecond format specifier"
38//config: default n # stat's nanosecond field is a bit non-portable 38//config: default n # stat's nanosecond field is a bit non-portable
39//config: depends on DATE 39//config: depends on DATE
40//config: select PLATFORM_LINUX
41//config: help 40//config: help
42//config: Support %[num]N format specifier. Adds ~250 bytes of code. 41//config: Support %[num]N format specifier. Adds ~250 bytes of code.
43//config: 42//config:
diff --git a/coreutils/stat.c b/coreutils/stat.c
index 93cf03bf2..c332e5dc8 100644
--- a/coreutils/stat.c
+++ b/coreutils/stat.c
@@ -22,7 +22,6 @@
22//config: bool "Enable custom formats (-c)" 22//config: bool "Enable custom formats (-c)"
23//config: default y 23//config: default y
24//config: depends on STAT 24//config: depends on STAT
25//config: select PLATFORM_LINUX # statfs()
26//config: help 25//config: help
27//config: Without this, stat will not support the '-c format' option where 26//config: Without this, stat will not support the '-c format' option where
28//config: users can pass a custom format string for output. This adds about 27//config: users can pass a custom format string for output. This adds about
diff --git a/e2fsprogs/lsattr.c b/e2fsprogs/lsattr.c
index b36dd47a5..ed7b67c6f 100644
--- a/e2fsprogs/lsattr.c
+++ b/e2fsprogs/lsattr.c
@@ -12,7 +12,6 @@
12//config:config LSATTR 12//config:config LSATTR
13//config: bool "lsattr (5.5 kb)" 13//config: bool "lsattr (5.5 kb)"
14//config: default y 14//config: default y
15//config: select PLATFORM_LINUX
16//config: help 15//config: help
17//config: lsattr lists the file attributes on a second extended file system. 16//config: lsattr lists the file attributes on a second extended file system.
18 17
diff --git a/findutils/grep.c b/findutils/grep.c
index 55e9c0a8f..b456ed467 100644
--- a/findutils/grep.c
+++ b/findutils/grep.c
@@ -167,13 +167,11 @@ enum {
167 OPT_z = IF_EXTRA_COMPAT( (1 << OPTBIT_z)) + 0, 167 OPT_z = IF_EXTRA_COMPAT( (1 << OPTBIT_z)) + 0,
168}; 168};
169 169
170#define PRINT_FILES_WITH_MATCHES (option_mask32 & OPT_l)
171#define PRINT_LINE_NUM (option_mask32 & OPT_n) 170#define PRINT_LINE_NUM (option_mask32 & OPT_n)
172#define BE_QUIET (option_mask32 & OPT_q) 171#define BE_QUIET (option_mask32 & OPT_q)
173#define SUPPRESS_ERR_MSGS (option_mask32 & OPT_s) 172#define SUPPRESS_ERR_MSGS (option_mask32 & OPT_s)
174#define PRINT_MATCH_COUNTS (option_mask32 & OPT_c) 173#define PRINT_MATCH_COUNTS (option_mask32 & OPT_c)
175#define FGREP_FLAG (option_mask32 & OPT_F) 174#define FGREP_FLAG (option_mask32 & OPT_F)
176#define PRINT_FILES_WITHOUT_MATCHES (option_mask32 & OPT_L)
177#define NUL_DELIMITED (option_mask32 & OPT_z) 175#define NUL_DELIMITED (option_mask32 & OPT_z)
178 176
179struct globals { 177struct globals {
@@ -476,13 +474,13 @@ static int grep_file(FILE *file)
476 * even if errors were detected" */ 474 * even if errors were detected" */
477 exit(EXIT_SUCCESS); 475 exit(EXIT_SUCCESS);
478 } 476 }
479 /* if we're just printing filenames, we stop after the first match */ 477 /* -l "print filenames with matches": stop after the first match */
480 if (PRINT_FILES_WITH_MATCHES) { 478 if (option_mask32 & OPT_l) {
481 puts(cur_file); 479 puts(cur_file);
482 /* fall through to "return 1" */ 480 return 1;
483 } 481 }
484 /* OPT_L aka PRINT_FILES_WITHOUT_MATCHES: return early */ 482 /* -L "print filenames without matches": return early too */
485 return 1; /* one match */ 483 return 0; /* 0: we do not print fname, hence it's "not a match" */
486 } 484 }
487 485
488#if ENABLE_FEATURE_GREP_CONTEXT 486#if ENABLE_FEATURE_GREP_CONTEXT
@@ -602,15 +600,16 @@ static int grep_file(FILE *file)
602 printf("%d\n", nmatches); 600 printf("%d\n", nmatches);
603 } 601 }
604 602
605 /* grep -L: print just the filename */ 603 /* grep -L: "print filenames without matches" */
606 if (PRINT_FILES_WITHOUT_MATCHES) { 604 if (option_mask32 & OPT_L) {
607 /* nmatches is zero, no need to check it: 605 /* nmatches is zero, no need to check it:
608 * we return 1 early if we detected a match 606 * we return 0 early if -L and we detect a match
609 * and PRINT_FILES_WITHOUT_MATCHES is set */ 607 */
610 puts(cur_file); 608 puts(cur_file);
609 return 1; /* 1: we printed fname, hence it's "a match" */
611 } 610 }
612 611
613 return nmatches; 612 return nmatches != 0; /* we return not a count, but a boolean */
614} 613}
615 614
616#if ENABLE_FEATURE_CLEAN_UP 615#if ENABLE_FEATURE_CLEAN_UP
@@ -687,7 +686,7 @@ static int FAST_FUNC file_action_grep(const char *filename,
687 return 0; 686 return 0;
688 } 687 }
689 cur_file = filename; 688 cur_file = filename;
690 *(int*)matched += grep_file(file); 689 *(int*)matched |= grep_file(file);
691 fclose(file); 690 fclose(file);
692 return 1; 691 return 1;
693} 692}
@@ -844,7 +843,7 @@ int grep_main(int argc UNUSED_PARAM, char **argv)
844 if (stat(cur_file, &st) == 0 && S_ISDIR(st.st_mode)) { 843 if (stat(cur_file, &st) == 0 && S_ISDIR(st.st_mode)) {
845 if (!(option_mask32 & OPT_h)) 844 if (!(option_mask32 & OPT_h))
846 print_filename = 1; 845 print_filename = 1;
847 matched += grep_dir(cur_file); 846 matched |= grep_dir(cur_file);
848 goto grep_done; 847 goto grep_done;
849 } 848 }
850 } 849 }
@@ -857,7 +856,7 @@ int grep_main(int argc UNUSED_PARAM, char **argv)
857 continue; 856 continue;
858 } 857 }
859 } 858 }
860 matched += grep_file(file); 859 matched |= grep_file(file);
861 fclose_if_not_stdin(file); 860 fclose_if_not_stdin(file);
862 grep_done: ; 861 grep_done: ;
863 } while (*argv && *++argv); 862 } while (*argv && *++argv);
diff --git a/include/libbb.h b/include/libbb.h
index 32f4c4126..c09db66eb 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -2116,6 +2116,13 @@ unsigned sha3_end(sha3_ctx_t *ctx, void *resbuf) FAST_FUNC;
2116typedef struct md5_ctx_t md5sha_ctx_t; 2116typedef struct md5_ctx_t md5sha_ctx_t;
2117#define md5sha_hash md5_hash 2117#define md5sha_hash md5_hash
2118#define sha_end sha1_end 2118#define sha_end sha1_end
2119enum {
2120 MD5_OUTSIZE = 16,
2121 SHA1_OUTSIZE = 20,
2122 SHA256_OUTSIZE = 32,
2123 SHA512_OUTSIZE = 64,
2124 SHA3_OUTSIZE = 28,
2125};
2119 2126
2120extern uint32_t *global_crc32_table; 2127extern uint32_t *global_crc32_table;
2121uint32_t *crc32_filltable(uint32_t *tbl256, int endian) FAST_FUNC; 2128uint32_t *crc32_filltable(uint32_t *tbl256, int endian) FAST_FUNC;
diff --git a/klibc-utils/run-init.c b/klibc-utils/run-init.c
index 77fc0e60c..73c677bab 100644
--- a/klibc-utils/run-init.c
+++ b/klibc-utils/run-init.c
@@ -8,7 +8,6 @@
8//config:config RUN_INIT 8//config:config RUN_INIT
9//config: bool "run-init (7.7 kb)" 9//config: bool "run-init (7.7 kb)"
10//config: default y 10//config: default y
11//config: select PLATFORM_LINUX
12//config: help 11//config: help
13//config: The run-init utility is used from initramfs to select a new 12//config: The run-init utility is used from initramfs to select a new
14//config: root device. Under initramfs, you have to use this instead of 13//config: root device. Under initramfs, you have to use this instead of
diff --git a/libbb/Config.src b/libbb/Config.src
index 312aa1831..f97de8ef7 100644
--- a/libbb/Config.src
+++ b/libbb/Config.src
@@ -334,7 +334,6 @@ config FEATURE_VERBOSE_CP_MESSAGE
334config FEATURE_USE_SENDFILE 334config FEATURE_USE_SENDFILE
335 bool "Use sendfile system call" 335 bool "Use sendfile system call"
336 default y 336 default y
337 select PLATFORM_LINUX
338 help 337 help
339 When enabled, busybox will use the kernel sendfile() function 338 When enabled, busybox will use the kernel sendfile() function
340 instead of read/write loops to copy data between file descriptors 339 instead of read/write loops to copy data between file descriptors
@@ -376,7 +375,6 @@ config FEATURE_SKIP_ROOTFS
376config MONOTONIC_SYSCALL 375config MONOTONIC_SYSCALL
377 bool "Use clock_gettime(CLOCK_MONOTONIC) syscall" 376 bool "Use clock_gettime(CLOCK_MONOTONIC) syscall"
378 default y 377 default y
379 select PLATFORM_LINUX
380 help 378 help
381 Use clock_gettime(CLOCK_MONOTONIC) syscall for measuring 379 Use clock_gettime(CLOCK_MONOTONIC) syscall for measuring
382 time intervals (time, ping, traceroute etc need this). 380 time intervals (time, ping, traceroute etc need this).
diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src
index dab1e6dae..d7cbb7ff1 100644
--- a/libbb/Kbuild.src
+++ b/libbb/Kbuild.src
@@ -116,7 +116,8 @@ lib-$(CONFIG_PLATFORM_POSIX) += warn_ignoring_args.o
116lib-$(CONFIG_PLATFORM_POSIX) += write.o 116lib-$(CONFIG_PLATFORM_POSIX) += write.o
117lib-$(CONFIG_PLATFORM_POSIX) += xgethostbyname.o 117lib-$(CONFIG_PLATFORM_POSIX) += xgethostbyname.o
118 118
119lib-$(CONFIG_PLATFORM_LINUX) += match_fstype.o 119lib-$(CONFIG_MOUNT) += match_fstype.o
120lib-$(CONFIG_UMOUNT) += match_fstype.o
120 121
121lib-$(CONFIG_FEATURE_UTMP) += utmp.o 122lib-$(CONFIG_FEATURE_UTMP) += utmp.o
122 123
diff --git a/libbb/last_char_is.c b/libbb/last_char_is.c
index 918526e6c..fba05f974 100644
--- a/libbb/last_char_is.c
+++ b/libbb/last_char_is.c
@@ -11,14 +11,9 @@
11/* Find out if the last character of a string matches the one given */ 11/* Find out if the last character of a string matches the one given */
12char* FAST_FUNC last_char_is(const char *s, int c) 12char* FAST_FUNC last_char_is(const char *s, int c)
13{ 13{
14 if (s) { 14 if (!s[0])
15 size_t sz = strlen(s); 15 return NULL;
16 /* Don't underrun the buffer if the string length is 0 */ 16 while (s[1])
17 if (sz != 0) { 17 s++;
18 s += sz - 1; 18 return (*s == (char)c) ? (char *) s : NULL;
19 if ((unsigned char)*s == c)
20 return (char*)s;
21 }
22 }
23 return NULL;
24} 19}
diff --git a/mailutils/popmaildir.c b/mailutils/popmaildir.c
index 6927e3a58..c5522f1b7 100644
--- a/mailutils/popmaildir.c
+++ b/mailutils/popmaildir.c
@@ -156,7 +156,7 @@ int popmaildir_main(int argc UNUSED_PARAM, char **argv)
156 md5_ctx_t ctx; 156 md5_ctx_t ctx;
157 char hex[16 * 2 + 1]; 157 char hex[16 * 2 + 1];
158 } md5; 158 } md5;
159 uint32_t res[16 / 4]; 159 uint32_t res[MD5_OUTSIZE / 4];
160 160
161 char *s = strchr(buf, '>'); 161 char *s = strchr(buf, '>');
162 if (s) 162 if (s)
diff --git a/miscutils/adjtimex.c b/miscutils/adjtimex.c
index 8ca90d58a..a9de0f9aa 100644
--- a/miscutils/adjtimex.c
+++ b/miscutils/adjtimex.c
@@ -13,7 +13,6 @@
13//config:config ADJTIMEX 13//config:config ADJTIMEX
14//config: bool "adjtimex (4.7 kb)" 14//config: bool "adjtimex (4.7 kb)"
15//config: default y 15//config: default y
16//config: select PLATFORM_LINUX
17//config: help 16//config: help
18//config: Adjtimex reads and optionally sets adjustment parameters for 17//config: Adjtimex reads and optionally sets adjustment parameters for
19//config: the Linux clock adjustment algorithm. 18//config: the Linux clock adjustment algorithm.
diff --git a/miscutils/beep.c b/miscutils/beep.c
index 92faa1cd5..1669332fd 100644
--- a/miscutils/beep.c
+++ b/miscutils/beep.c
@@ -9,7 +9,6 @@
9//config:config BEEP 9//config:config BEEP
10//config: bool "beep (2.4 kb)" 10//config: bool "beep (2.4 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX
13//config: help 12//config: help
14//config: The beep applets beeps in a given freq/Hz. 13//config: The beep applets beeps in a given freq/Hz.
15//config: 14//config:
diff --git a/miscutils/conspy.c b/miscutils/conspy.c
index a0e0d4e4b..fac11d339 100644
--- a/miscutils/conspy.c
+++ b/miscutils/conspy.c
@@ -12,7 +12,6 @@
12//config:config CONSPY 12//config:config CONSPY
13//config: bool "conspy (10 kb)" 13//config: bool "conspy (10 kb)"
14//config: default y 14//config: default y
15//config: select PLATFORM_LINUX
16//config: help 15//config: help
17//config: A text-mode VNC like program for Linux virtual terminals. 16//config: A text-mode VNC like program for Linux virtual terminals.
18//config: example: conspy NUM shared access to console num 17//config: example: conspy NUM shared access to console num
diff --git a/miscutils/crontab.c b/miscutils/crontab.c
index c71d914fc..411a18a50 100644
--- a/miscutils/crontab.c
+++ b/miscutils/crontab.c
@@ -165,8 +165,12 @@ int crontab_main(int argc UNUSED_PARAM, char **argv)
165 close(fd); 165 close(fd);
166 xlseek(src_fd, 0, SEEK_SET); 166 xlseek(src_fd, 0, SEEK_SET);
167 } 167 }
168 close_on_exec_on(src_fd); /* don't want editor to see this fd */ 168 close(src_fd);
169 edit_file(pas, tmp_fname); 169 edit_file(pas, tmp_fname);
170 /* The src_fd needs to be reopened to handle editors that do
171 * save the buffer as new file and rename it to tmp_fname (so
172 * for example vim). */
173 src_fd = xopen3(tmp_fname, O_RDONLY, 0600);
170 /* fall through */ 174 /* fall through */
171 175
172 case 0: /* Replace (no -l, -e, or -r were given) */ 176 case 0: /* Replace (no -l, -e, or -r were given) */
diff --git a/miscutils/devfsd.c b/miscutils/devfsd.c
index d47ee4d47..17d8fb6b9 100644
--- a/miscutils/devfsd.c
+++ b/miscutils/devfsd.c
@@ -56,7 +56,6 @@
56//config:config DEVFSD 56//config:config DEVFSD
57//config: bool "devfsd (obsolete)" 57//config: bool "devfsd (obsolete)"
58//config: default n 58//config: default n
59//config: select PLATFORM_LINUX
60//config: select FEATURE_SYSLOG 59//config: select FEATURE_SYSLOG
61//config: help 60//config: help
62//config: This is deprecated and should NOT be used anymore. 61//config: This is deprecated and should NOT be used anymore.
@@ -99,7 +98,6 @@
99//config:config FEATURE_DEVFS 98//config:config FEATURE_DEVFS
100//config: bool "Use devfs names for all devices (obsolete)" 99//config: bool "Use devfs names for all devices (obsolete)"
101//config: default n 100//config: default n
102//config: select PLATFORM_LINUX
103//config: help 101//config: help
104//config: This is obsolete and should NOT be used anymore. 102//config: This is obsolete and should NOT be used anymore.
105//config: Use linux >= 2.6 (optionally with hotplug) and mdev instead! 103//config: Use linux >= 2.6 (optionally with hotplug) and mdev instead!
diff --git a/miscutils/fbsplash.c b/miscutils/fbsplash.c
index 141957809..2934d8eb7 100644
--- a/miscutils/fbsplash.c
+++ b/miscutils/fbsplash.c
@@ -23,7 +23,6 @@
23//config:config FBSPLASH 23//config:config FBSPLASH
24//config: bool "fbsplash (26 kb)" 24//config: bool "fbsplash (26 kb)"
25//config: default y 25//config: default y
26//config: select PLATFORM_LINUX
27//config: help 26//config: help
28//config: Shows splash image and progress bar on framebuffer device. 27//config: Shows splash image and progress bar on framebuffer device.
29//config: Can be used during boot phase of an embedded device. 28//config: Can be used during boot phase of an embedded device.
diff --git a/miscutils/hdparm.c b/miscutils/hdparm.c
index beabb1ad5..d25a2466e 100644
--- a/miscutils/hdparm.c
+++ b/miscutils/hdparm.c
@@ -14,7 +14,6 @@
14//config:config HDPARM 14//config:config HDPARM
15//config: bool "hdparm (25 kb)" 15//config: bool "hdparm (25 kb)"
16//config: default y 16//config: default y
17//config: select PLATFORM_LINUX
18//config: help 17//config: help
19//config: Get/Set hard drive parameters. Primarily intended for ATA 18//config: Get/Set hard drive parameters. Primarily intended for ATA
20//config: drives. 19//config: drives.
diff --git a/miscutils/i2c_tools.c b/miscutils/i2c_tools.c
index 82a559f74..cc8b99a92 100644
--- a/miscutils/i2c_tools.c
+++ b/miscutils/i2c_tools.c
@@ -11,35 +11,30 @@
11//config:config I2CGET 11//config:config I2CGET
12//config: bool "i2cget (5.5 kb)" 12//config: bool "i2cget (5.5 kb)"
13//config: default y 13//config: default y
14//config: select PLATFORM_LINUX
15//config: help 14//config: help
16//config: Read from I2C/SMBus chip registers. 15//config: Read from I2C/SMBus chip registers.
17//config: 16//config:
18//config:config I2CSET 17//config:config I2CSET
19//config: bool "i2cset (6.7 kb)" 18//config: bool "i2cset (6.7 kb)"
20//config: default y 19//config: default y
21//config: select PLATFORM_LINUX
22//config: help 20//config: help
23//config: Set I2C registers. 21//config: Set I2C registers.
24//config: 22//config:
25//config:config I2CDUMP 23//config:config I2CDUMP
26//config: bool "i2cdump (7.1 kb)" 24//config: bool "i2cdump (7.1 kb)"
27//config: default y 25//config: default y
28//config: select PLATFORM_LINUX
29//config: help 26//config: help
30//config: Examine I2C registers. 27//config: Examine I2C registers.
31//config: 28//config:
32//config:config I2CDETECT 29//config:config I2CDETECT
33//config: bool "i2cdetect (7.1 kb)" 30//config: bool "i2cdetect (7.1 kb)"
34//config: default y 31//config: default y
35//config: select PLATFORM_LINUX
36//config: help 32//config: help
37//config: Detect I2C chips. 33//config: Detect I2C chips.
38//config: 34//config:
39//config:config I2CTRANSFER 35//config:config I2CTRANSFER
40//config: bool "i2ctransfer (4.0 kb)" 36//config: bool "i2ctransfer (4.0 kb)"
41//config: default y 37//config: default y
42//config: select PLATFORM_LINUX
43//config: help 38//config: help
44//config: Send user-defined I2C messages in one transfer. 39//config: Send user-defined I2C messages in one transfer.
45//config: 40//config:
diff --git a/miscutils/lsscsi.c b/miscutils/lsscsi.c
index f737d33d9..8f7eda761 100644
--- a/miscutils/lsscsi.c
+++ b/miscutils/lsscsi.c
@@ -9,7 +9,6 @@
9//config:config LSSCSI 9//config:config LSSCSI
10//config: bool "lsscsi (2.5 kb)" 10//config: bool "lsscsi (2.5 kb)"
11//config: default y 11//config: default y
12//config: #select PLATFORM_LINUX
13//config: help 12//config: help
14//config: lsscsi is a utility for displaying information about SCSI buses in the 13//config: lsscsi is a utility for displaying information about SCSI buses in the
15//config: system and devices connected to them. 14//config: system and devices connected to them.
@@ -27,25 +26,21 @@
27 26
28static const char scsi_dir[] ALIGN1 = "/sys/bus/scsi/devices"; 27static const char scsi_dir[] ALIGN1 = "/sys/bus/scsi/devices";
29 28
30static char *get_line(const char *filename, char *buf, unsigned *bufsize_p) 29static char *get_line(const char *filename, char *buf, char *bufend)
31{ 30{
32 unsigned bufsize = *bufsize_p; 31 ssize_t sz = bufend - buf - 2; /* -2 for two NULs */
33 ssize_t sz;
34 32
35 if ((int)(bufsize - 2) <= 0) 33 if (sz <= 0)
36 return buf; 34 return buf;
37 35
38 sz = open_read_close(filename, buf, bufsize - 2); 36 sz = open_read_close(filename, buf, sz);
39 if (sz < 0) 37 if (sz < 0)
40 sz = 0; 38 sz = 0;
41 buf[sz] = '\0'; 39 buf[sz] = '\0';
42 40
43 sz = (trim(buf) - buf) + 1; 41 buf = trim(buf) + 1;
44 bufsize -= sz;
45 buf += sz;
46 buf[0] = '\0'; 42 buf[0] = '\0';
47 43
48 *bufsize_p = bufsize;
49 return buf; 44 return buf;
50} 45}
51 46
@@ -61,7 +56,6 @@ int lsscsi_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
61 while ((de = readdir(dir)) != NULL) { 56 while ((de = readdir(dir)) != NULL) {
62 char buf[256]; 57 char buf[256];
63 char *ptr; 58 char *ptr;
64 unsigned bufsize;
65 const char *vendor; 59 const char *vendor;
66 const char *type_str; 60 const char *type_str;
67 const char *type_name; 61 const char *type_name;
@@ -76,15 +70,17 @@ int lsscsi_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
76 if (chdir(de->d_name) != 0) 70 if (chdir(de->d_name) != 0)
77 continue; 71 continue;
78 72
79 bufsize = sizeof(buf);
80 vendor = buf; 73 vendor = buf;
81 ptr = get_line("vendor", buf, &bufsize); 74 ptr = get_line("vendor", buf, buf + sizeof(buf));
75
82 type_str = ptr; 76 type_str = ptr;
83 ptr = get_line("type", ptr, &bufsize); 77 ptr = get_line("type", ptr, buf + sizeof(buf));
78
84 model = ptr; 79 model = ptr;
85 ptr = get_line("model", ptr, &bufsize); 80 ptr = get_line("model", ptr, buf + sizeof(buf));
81
86 rev = ptr; 82 rev = ptr;
87 ptr = get_line("rev", ptr, &bufsize); 83 /*ptr =*/ get_line("rev", ptr, buf + sizeof(buf));
88 84
89 printf("[%s]\t", de->d_name); 85 printf("[%s]\t", de->d_name);
90 86
diff --git a/miscutils/nandwrite.c b/miscutils/nandwrite.c
index f111c6363..52bf49434 100644
--- a/miscutils/nandwrite.c
+++ b/miscutils/nandwrite.c
@@ -10,14 +10,12 @@
10//config:config NANDWRITE 10//config:config NANDWRITE
11//config: bool "nandwrite (4.8 kb)" 11//config: bool "nandwrite (4.8 kb)"
12//config: default y 12//config: default y
13//config: select PLATFORM_LINUX
14//config: help 13//config: help
15//config: Write to the specified MTD device, with bad blocks awareness 14//config: Write to the specified MTD device, with bad blocks awareness
16//config: 15//config:
17//config:config NANDDUMP 16//config:config NANDDUMP
18//config: bool "nanddump (5.2 kb)" 17//config: bool "nanddump (5.2 kb)"
19//config: default y 18//config: default y
20//config: select PLATFORM_LINUX
21//config: help 19//config: help
22//config: Dump the content of raw NAND chip 20//config: Dump the content of raw NAND chip
23 21
diff --git a/miscutils/partprobe.c b/miscutils/partprobe.c
index 0abed6ff1..0fb1927b7 100644
--- a/miscutils/partprobe.c
+++ b/miscutils/partprobe.c
@@ -7,7 +7,6 @@
7//config:config PARTPROBE 7//config:config PARTPROBE
8//config: bool "partprobe (3.5 kb)" 8//config: bool "partprobe (3.5 kb)"
9//config: default y 9//config: default y
10//config: select PLATFORM_LINUX
11//config: help 10//config: help
12//config: Ask kernel to rescan partition table. 11//config: Ask kernel to rescan partition table.
13 12
diff --git a/miscutils/raidautorun.c b/miscutils/raidautorun.c
index 39816ab1f..905862cf7 100644
--- a/miscutils/raidautorun.c
+++ b/miscutils/raidautorun.c
@@ -9,7 +9,6 @@
9//config:config RAIDAUTORUN 9//config:config RAIDAUTORUN
10//config: bool "raidautorun (1.3 kb)" 10//config: bool "raidautorun (1.3 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX
13//config: help 12//config: help
14//config: raidautorun tells the kernel md driver to 13//config: raidautorun tells the kernel md driver to
15//config: search and start RAID arrays. 14//config: search and start RAID arrays.
diff --git a/miscutils/readahead.c b/miscutils/readahead.c
index cc0ba5ba3..d2bed2092 100644
--- a/miscutils/readahead.c
+++ b/miscutils/readahead.c
@@ -13,7 +13,6 @@
13//config: bool "readahead (1.5 kb)" 13//config: bool "readahead (1.5 kb)"
14//config: default y 14//config: default y
15//config: depends on LFS 15//config: depends on LFS
16//config: select PLATFORM_LINUX
17//config: help 16//config: help
18//config: Preload the files listed on the command line into RAM cache so that 17//config: Preload the files listed on the command line into RAM cache so that
19//config: subsequent reads on these files will not block on disk I/O. 18//config: subsequent reads on these files will not block on disk I/O.
diff --git a/miscutils/rfkill.c b/miscutils/rfkill.c
index db7c83750..9d91ea82f 100644
--- a/miscutils/rfkill.c
+++ b/miscutils/rfkill.c
@@ -9,7 +9,6 @@
9//config:config RFKILL 9//config:config RFKILL
10//config: bool "rfkill (4.4 kb)" 10//config: bool "rfkill (4.4 kb)"
11//config: default n # doesn't build on Ubuntu 9.04 11//config: default n # doesn't build on Ubuntu 9.04
12//config: select PLATFORM_LINUX
13//config: help 12//config: help
14//config: Enable/disable wireless devices. 13//config: Enable/disable wireless devices.
15//config: 14//config:
diff --git a/miscutils/rx.c b/miscutils/rx.c
index 319ec1d49..d8b041480 100644
--- a/miscutils/rx.c
+++ b/miscutils/rx.c
@@ -17,7 +17,6 @@
17//config:config RX 17//config:config RX
18//config: bool "rx (2.9 kb)" 18//config: bool "rx (2.9 kb)"
19//config: default y 19//config: default y
20//config: select PLATFORM_LINUX
21//config: help 20//config: help
22//config: Receive files using the Xmodem protocol. 21//config: Receive files using the Xmodem protocol.
23 22
diff --git a/miscutils/setserial.c b/miscutils/setserial.c
index 71b274568..1e75bf433 100644
--- a/miscutils/setserial.c
+++ b/miscutils/setserial.c
@@ -10,7 +10,6 @@
10//config:config SETSERIAL 10//config:config SETSERIAL
11//config: bool "setserial (6.9 kb)" 11//config: bool "setserial (6.9 kb)"
12//config: default y 12//config: default y
13//config: select PLATFORM_LINUX
14//config: help 13//config: help
15//config: Retrieve or set Linux serial port. 14//config: Retrieve or set Linux serial port.
16 15
diff --git a/miscutils/ubi_tools.c b/miscutils/ubi_tools.c
index 8318df0f9..94a637eee 100644
--- a/miscutils/ubi_tools.c
+++ b/miscutils/ubi_tools.c
@@ -6,42 +6,36 @@
6//config:config UBIATTACH 6//config:config UBIATTACH
7//config: bool "ubiattach (4.2 kb)" 7//config: bool "ubiattach (4.2 kb)"
8//config: default y 8//config: default y
9//config: select PLATFORM_LINUX
10//config: help 9//config: help
11//config: Attach MTD device to an UBI device. 10//config: Attach MTD device to an UBI device.
12//config: 11//config:
13//config:config UBIDETACH 12//config:config UBIDETACH
14//config: bool "ubidetach (4.1 kb)" 13//config: bool "ubidetach (4.1 kb)"
15//config: default y 14//config: default y
16//config: select PLATFORM_LINUX
17//config: help 15//config: help
18//config: Detach MTD device from an UBI device. 16//config: Detach MTD device from an UBI device.
19//config: 17//config:
20//config:config UBIMKVOL 18//config:config UBIMKVOL
21//config: bool "ubimkvol (5.3 kb)" 19//config: bool "ubimkvol (5.3 kb)"
22//config: default y 20//config: default y
23//config: select PLATFORM_LINUX
24//config: help 21//config: help
25//config: Create a UBI volume. 22//config: Create a UBI volume.
26//config: 23//config:
27//config:config UBIRMVOL 24//config:config UBIRMVOL
28//config: bool "ubirmvol (4.9 kb)" 25//config: bool "ubirmvol (4.9 kb)"
29//config: default y 26//config: default y
30//config: select PLATFORM_LINUX
31//config: help 27//config: help
32//config: Delete a UBI volume. 28//config: Delete a UBI volume.
33//config: 29//config:
34//config:config UBIRSVOL 30//config:config UBIRSVOL
35//config: bool "ubirsvol (4.2 kb)" 31//config: bool "ubirsvol (4.2 kb)"
36//config: default y 32//config: default y
37//config: select PLATFORM_LINUX
38//config: help 33//config: help
39//config: Resize a UBI volume. 34//config: Resize a UBI volume.
40//config: 35//config:
41//config:config UBIUPDATEVOL 36//config:config UBIUPDATEVOL
42//config: bool "ubiupdatevol (5.2 kb)" 37//config: bool "ubiupdatevol (5.2 kb)"
43//config: default y 38//config: default y
44//config: select PLATFORM_LINUX
45//config: help 39//config: help
46//config: Update a UBI volume. 40//config: Update a UBI volume.
47 41
diff --git a/miscutils/ubirename.c b/miscutils/ubirename.c
index e7c56640c..06a0adacf 100644
--- a/miscutils/ubirename.c
+++ b/miscutils/ubirename.c
@@ -9,7 +9,6 @@
9//config:config UBIRENAME 9//config:config UBIRENAME
10//config: bool "ubirename (2.4 kb)" 10//config: bool "ubirename (2.4 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX
13//config: help 12//config: help
14//config: Utility to rename UBI volumes 13//config: Utility to rename UBI volumes
15 14
diff --git a/miscutils/watchdog.c b/miscutils/watchdog.c
index 86600b72f..8c8d7217f 100644
--- a/miscutils/watchdog.c
+++ b/miscutils/watchdog.c
@@ -11,7 +11,6 @@
11//config:config WATCHDOG 11//config:config WATCHDOG
12//config: bool "watchdog (5.3 kb)" 12//config: bool "watchdog (5.3 kb)"
13//config: default y 13//config: default y
14//config: select PLATFORM_LINUX
15//config: help 14//config: help
16//config: The watchdog utility is used with hardware or software watchdog 15//config: The watchdog utility is used with hardware or software watchdog
17//config: device drivers. It opens the specified watchdog device special file 16//config: device drivers. It opens the specified watchdog device special file
diff --git a/modutils/depmod.c b/modutils/depmod.c
index b5244fc60..318e7cdc7 100644
--- a/modutils/depmod.c
+++ b/modutils/depmod.c
@@ -10,7 +10,6 @@
10//config:config DEPMOD 10//config:config DEPMOD
11//config: bool "depmod (27 kb)" 11//config: bool "depmod (27 kb)"
12//config: default y 12//config: default y
13//config: select PLATFORM_LINUX
14//config: help 13//config: help
15//config: depmod generates modules.dep (and potentially modules.alias 14//config: depmod generates modules.dep (and potentially modules.alias
16//config: and modules.symbols) that contain dependency information 15//config: and modules.symbols) that contain dependency information
diff --git a/modutils/insmod.c b/modutils/insmod.c
index 4dc0b6608..bd79a0f26 100644
--- a/modutils/insmod.c
+++ b/modutils/insmod.c
@@ -9,7 +9,6 @@
9//config:config INSMOD 9//config:config INSMOD
10//config: bool "insmod (22 kb)" 10//config: bool "insmod (22 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX
13//config: help 12//config: help
14//config: insmod is used to load specified modules in the running kernel. 13//config: insmod is used to load specified modules in the running kernel.
15 14
diff --git a/modutils/lsmod.c b/modutils/lsmod.c
index 39dc8e6b7..2beb12362 100644
--- a/modutils/lsmod.c
+++ b/modutils/lsmod.c
@@ -10,7 +10,6 @@
10//config:config LSMOD 10//config:config LSMOD
11//config: bool "lsmod (1.9 kb)" 11//config: bool "lsmod (1.9 kb)"
12//config: default y 12//config: default y
13//config: select PLATFORM_LINUX
14//config: help 13//config: help
15//config: lsmod is used to display a list of loaded modules. 14//config: lsmod is used to display a list of loaded modules.
16//config: 15//config:
diff --git a/modutils/modinfo.c b/modutils/modinfo.c
index 1e63f745f..c5cdc7980 100644
--- a/modutils/modinfo.c
+++ b/modutils/modinfo.c
@@ -8,7 +8,6 @@
8//config:config MODINFO 8//config:config MODINFO
9//config: bool "modinfo (24 kb)" 9//config: bool "modinfo (24 kb)"
10//config: default y 10//config: default y
11//config: select PLATFORM_LINUX
12//config: help 11//config: help
13//config: Show information about a Linux Kernel module 12//config: Show information about a Linux Kernel module
14 13
diff --git a/modutils/modprobe.c b/modutils/modprobe.c
index 0a372a049..70c45903a 100644
--- a/modutils/modprobe.c
+++ b/modutils/modprobe.c
@@ -10,7 +10,6 @@
10//config:config MODPROBE 10//config:config MODPROBE
11//config: bool "modprobe (28 kb)" 11//config: bool "modprobe (28 kb)"
12//config: default y 12//config: default y
13//config: select PLATFORM_LINUX
14//config: help 13//config: help
15//config: Handle the loading of modules, and their dependencies on a high 14//config: Handle the loading of modules, and their dependencies on a high
16//config: level. 15//config: level.
diff --git a/modutils/rmmod.c b/modutils/rmmod.c
index 8d4639f50..2b3c39153 100644
--- a/modutils/rmmod.c
+++ b/modutils/rmmod.c
@@ -10,7 +10,6 @@
10//config:config RMMOD 10//config:config RMMOD
11//config: bool "rmmod (3.3 kb)" 11//config: bool "rmmod (3.3 kb)"
12//config: default y 12//config: default y
13//config: select PLATFORM_LINUX
14//config: help 13//config: help
15//config: rmmod is used to unload specified modules from the kernel. 14//config: rmmod is used to unload specified modules from the kernel.
16 15
diff --git a/networking/arp.c b/networking/arp.c
index 6519f8156..16783ab95 100644
--- a/networking/arp.c
+++ b/networking/arp.c
@@ -15,7 +15,6 @@
15//config:config ARP 15//config:config ARP
16//config: bool "arp (10 kb)" 16//config: bool "arp (10 kb)"
17//config: default y 17//config: default y
18//config: select PLATFORM_LINUX
19//config: help 18//config: help
20//config: Manipulate the system ARP cache. 19//config: Manipulate the system ARP cache.
21 20
diff --git a/networking/arping.c b/networking/arping.c
index 2a256aaa0..d44d7d697 100644
--- a/networking/arping.c
+++ b/networking/arping.c
@@ -8,7 +8,6 @@
8//config:config ARPING 8//config:config ARPING
9//config: bool "arping (9 kb)" 9//config: bool "arping (9 kb)"
10//config: default y 10//config: default y
11//config: select PLATFORM_LINUX
12//config: help 11//config: help
13//config: Ping hosts by ARP packets. 12//config: Ping hosts by ARP packets.
14 13
diff --git a/networking/brctl.c b/networking/brctl.c
index 2f4ac4a87..f057f9b60 100644
--- a/networking/brctl.c
+++ b/networking/brctl.c
@@ -12,7 +12,6 @@
12//config:config BRCTL 12//config:config BRCTL
13//config: bool "brctl (4.7 kb)" 13//config: bool "brctl (4.7 kb)"
14//config: default y 14//config: default y
15//config: select PLATFORM_LINUX
16//config: help 15//config: help
17//config: Manage ethernet bridges. 16//config: Manage ethernet bridges.
18//config: Supports addbr/delbr and addif/delif. 17//config: Supports addbr/delbr and addif/delif.
diff --git a/networking/ether-wake.c b/networking/ether-wake.c
index f45d43609..36e90acfb 100644
--- a/networking/ether-wake.c
+++ b/networking/ether-wake.c
@@ -66,7 +66,6 @@
66//config:config ETHER_WAKE 66//config:config ETHER_WAKE
67//config: bool "ether-wake (4.9 kb)" 67//config: bool "ether-wake (4.9 kb)"
68//config: default y 68//config: default y
69//config: select PLATFORM_LINUX
70//config: help 69//config: help
71//config: Send a magic packet to wake up sleeping machines. 70//config: Send a magic packet to wake up sleeping machines.
72 71
diff --git a/networking/httpd.c b/networking/httpd.c
index 5d2d2681c..19cc08fcb 100644
--- a/networking/httpd.c
+++ b/networking/httpd.c
@@ -214,6 +214,44 @@
214//config: help 214//config: help
215//config: Makes httpd send files using GZIP content encoding if the 215//config: Makes httpd send files using GZIP content encoding if the
216//config: client supports it and a pre-compressed <file>.gz exists. 216//config: client supports it and a pre-compressed <file>.gz exists.
217//config:
218//config:config FEATURE_HTTPD_ETAG
219//config: bool "Support caching via ETag header"
220//config: default y
221//config: depends on HTTPD
222//config: help
223//config: If server responds with ETag then next time client (browser)
224//config: resend it via If-None-Match header.
225//config: Then httpd will check if file wasn't modified and if not,
226//config: return 304 Not Modified status code.
227//config: The ETag value is constructed from last modification date
228//config: in unix epoch, and size: "hex(last_mod)-hex(file_size)".
229//config: It's not completely reliable as hash functions but fair enough.
230//config:
231//config:config FEATURE_HTTPD_LAST_MODIFIED
232//config: bool "Add Last-Modified header to response"
233//config: default y
234//config: depends on HTTPD
235//config: help
236//config: The Last-Modified header is used for cache validation.
237//config: The client sends last seen mtime to server in If-Modified-Since.
238//config: Both headers MUST be an RFC 1123 formatted, which is hard to parse.
239//config: Use ETag header instead.
240//config:
241//config:config FEATURE_HTTPD_DATE
242//config: bool "Add Date header to response"
243//config: default y
244//config: depends on HTTPD
245//config: help
246//config: RFC2616 says that server MUST add Date header to response.
247//config: But it is almost useless and can be omitted.
248//config:
249//config:config FEATURE_HTTPD_ACL_IP
250//config: bool "ACL IP"
251//config: default y
252//config: depends on HTTPD
253//config: help
254//config: Support IP deny/allow rules
217 255
218//applet:IF_HTTPD(APPLET(httpd, BB_DIR_USR_SBIN, BB_SUID_DROP)) 256//applet:IF_HTTPD(APPLET(httpd, BB_DIR_USR_SBIN, BB_SUID_DROP))
219 257
@@ -278,7 +316,7 @@ static void send_REQUEST_TIMEOUT_and_exit(int sig) NORETURN;
278 316
279static const char DEFAULT_PATH_HTTPD_CONF[] ALIGN1 = "/etc"; 317static const char DEFAULT_PATH_HTTPD_CONF[] ALIGN1 = "/etc";
280static const char HTTPD_CONF[] ALIGN1 = "httpd.conf"; 318static const char HTTPD_CONF[] ALIGN1 = "httpd.conf";
281static const char HTTP_200[] ALIGN1 = "HTTP/1.0 200 OK\r\n"; 319static const char HTTP_200[] ALIGN1 = "HTTP/1.1 200 OK\r\n";
282static const char index_html[] ALIGN1 = "index.html"; 320static const char index_html[] ALIGN1 = "index.html";
283 321
284typedef struct has_next_ptr { 322typedef struct has_next_ptr {
@@ -292,6 +330,7 @@ typedef struct Htaccess {
292 char before_colon[1]; /* really bigger, must be last */ 330 char before_colon[1]; /* really bigger, must be last */
293} Htaccess; 331} Htaccess;
294 332
333#if ENABLE_FEATURE_HTTPD_ACL_IP
295/* Must have "next" as a first member */ 334/* Must have "next" as a first member */
296typedef struct Htaccess_IP { 335typedef struct Htaccess_IP {
297 struct Htaccess_IP *next; 336 struct Htaccess_IP *next;
@@ -299,6 +338,7 @@ typedef struct Htaccess_IP {
299 unsigned mask; 338 unsigned mask;
300 int allow_deny; 339 int allow_deny;
301} Htaccess_IP; 340} Htaccess_IP;
341#endif
302 342
303/* Must have "next" as a first member */ 343/* Must have "next" as a first member */
304typedef struct Htaccess_Proxy { 344typedef struct Htaccess_Proxy {
@@ -319,6 +359,7 @@ enum {
319 HTTP_OK = 200, 359 HTTP_OK = 200,
320 HTTP_PARTIAL_CONTENT = 206, 360 HTTP_PARTIAL_CONTENT = 206,
321 HTTP_MOVED_TEMPORARILY = 302, 361 HTTP_MOVED_TEMPORARILY = 302,
362 HTTP_NOT_MODIFIED = 304,
322 HTTP_BAD_REQUEST = 400, /* malformed syntax */ 363 HTTP_BAD_REQUEST = 400, /* malformed syntax */
323 HTTP_UNAUTHORIZED = 401, /* authentication needed, respond with auth hdr */ 364 HTTP_UNAUTHORIZED = 401, /* authentication needed, respond with auth hdr */
324 HTTP_NOT_FOUND = 404, 365 HTTP_NOT_FOUND = 404,
@@ -336,7 +377,6 @@ enum {
336 HTTP_NO_CONTENT = 204, 377 HTTP_NO_CONTENT = 204,
337 HTTP_MULTIPLE_CHOICES = 300, 378 HTTP_MULTIPLE_CHOICES = 300,
338 HTTP_MOVED_PERMANENTLY = 301, 379 HTTP_MOVED_PERMANENTLY = 301,
339 HTTP_NOT_MODIFIED = 304,
340 HTTP_PAYMENT_REQUIRED = 402, 380 HTTP_PAYMENT_REQUIRED = 402,
341 HTTP_BAD_GATEWAY = 502, 381 HTTP_BAD_GATEWAY = 502,
342 HTTP_SERVICE_UNAVAILABLE = 503, /* overload, maintenance */ 382 HTTP_SERVICE_UNAVAILABLE = 503, /* overload, maintenance */
@@ -349,6 +389,9 @@ static const uint16_t http_response_type[] ALIGN2 = {
349 HTTP_PARTIAL_CONTENT, 389 HTTP_PARTIAL_CONTENT,
350#endif 390#endif
351 HTTP_MOVED_TEMPORARILY, 391 HTTP_MOVED_TEMPORARILY,
392#if ENABLE_FEATURE_HTTPD_ETAG
393 HTTP_NOT_MODIFIED,
394#endif
352 HTTP_REQUEST_TIMEOUT, 395 HTTP_REQUEST_TIMEOUT,
353 HTTP_NOT_IMPLEMENTED, 396 HTTP_NOT_IMPLEMENTED,
354#if ENABLE_FEATURE_HTTPD_BASIC_AUTH 397#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
@@ -365,7 +408,6 @@ static const uint16_t http_response_type[] ALIGN2 = {
365 HTTP_NO_CONTENT, 408 HTTP_NO_CONTENT,
366 HTTP_MULTIPLE_CHOICES, 409 HTTP_MULTIPLE_CHOICES,
367 HTTP_MOVED_PERMANENTLY, 410 HTTP_MOVED_PERMANENTLY,
368 HTTP_NOT_MODIFIED,
369 HTTP_BAD_GATEWAY, 411 HTTP_BAD_GATEWAY,
370 HTTP_SERVICE_UNAVAILABLE, 412 HTTP_SERVICE_UNAVAILABLE,
371#endif 413#endif
@@ -380,6 +422,9 @@ static const struct {
380 { "Partial Content", NULL }, 422 { "Partial Content", NULL },
381#endif 423#endif
382 { "Found", NULL }, 424 { "Found", NULL },
425#if ENABLE_FEATURE_HTTPD_ETAG
426 { "Not Modified" },
427#endif
383 { "Request Timeout", "No request appeared within 60 seconds" }, 428 { "Request Timeout", "No request appeared within 60 seconds" },
384 { "Not Implemented", "The requested method is not recognized" }, 429 { "Not Implemented", "The requested method is not recognized" },
385#if ENABLE_FEATURE_HTTPD_BASIC_AUTH 430#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
@@ -396,7 +441,6 @@ static const struct {
396 { "No Content" }, 441 { "No Content" },
397 { "Multiple Choices" }, 442 { "Multiple Choices" },
398 { "Moved Permanently" }, 443 { "Moved Permanently" },
399 { "Not Modified" },
400 { "Bad Gateway", "" }, 444 { "Bad Gateway", "" },
401 { "Service Unavailable", "" }, 445 { "Service Unavailable", "" },
402#endif 446#endif
@@ -410,6 +454,9 @@ struct globals {
410 smallint content_gzip; 454 smallint content_gzip;
411#endif 455#endif
412 time_t last_mod; 456 time_t last_mod;
457#if ENABLE_FEATURE_HTTPD_ETAG
458 char *if_none_match;
459#endif
413 char *rmt_ip_str; /* for $REMOTE_ADDR and $REMOTE_PORT */ 460 char *rmt_ip_str; /* for $REMOTE_ADDR and $REMOTE_PORT */
414 const char *bind_addr_or_port; 461 const char *bind_addr_or_port;
415 462
@@ -420,7 +467,9 @@ struct globals {
420 467
421 const char *found_mime_type; 468 const char *found_mime_type;
422 const char *found_moved_temporarily; 469 const char *found_moved_temporarily;
470#if ENABLE_FEATURE_HTTPD_ACL_IP
423 Htaccess_IP *ip_a_d; /* config allow/deny lines */ 471 Htaccess_IP *ip_a_d; /* config allow/deny lines */
472#endif
424 473
425 IF_FEATURE_HTTPD_BASIC_AUTH(const char *g_realm;) 474 IF_FEATURE_HTTPD_BASIC_AUTH(const char *g_realm;)
426 IF_FEATURE_HTTPD_BASIC_AUTH(char *remoteuser;) 475 IF_FEATURE_HTTPD_BASIC_AUTH(char *remoteuser;)
@@ -444,6 +493,9 @@ struct globals {
444#define sizeof_hdr_buf COMMON_BUFSIZE 493#define sizeof_hdr_buf COMMON_BUFSIZE
445 char *hdr_ptr; 494 char *hdr_ptr;
446 int hdr_cnt; 495 int hdr_cnt;
496#if ENABLE_FEATURE_HTTPD_ETAG
497 char etag[sizeof("'%llx-%llx'") + 2 * sizeof(long long)*3];
498#endif
447#if ENABLE_FEATURE_HTTPD_ERROR_PAGES 499#if ENABLE_FEATURE_HTTPD_ERROR_PAGES
448 const char *http_error_page[ARRAY_SIZE(http_response_type)]; 500 const char *http_error_page[ARRAY_SIZE(http_response_type)];
449#endif 501#endif
@@ -467,7 +519,6 @@ struct globals {
467#define found_mime_type (G.found_mime_type ) 519#define found_mime_type (G.found_mime_type )
468#define found_moved_temporarily (G.found_moved_temporarily) 520#define found_moved_temporarily (G.found_moved_temporarily)
469#define last_mod (G.last_mod ) 521#define last_mod (G.last_mod )
470#define ip_a_d (G.ip_a_d )
471#define g_realm (G.g_realm ) 522#define g_realm (G.g_realm )
472#define remoteuser (G.remoteuser ) 523#define remoteuser (G.remoteuser )
473#define file_size (G.file_size ) 524#define file_size (G.file_size )
@@ -528,11 +579,14 @@ static ALWAYS_INLINE void free_Htaccess_list(Htaccess **pptr)
528 free_llist((has_next_ptr**)pptr); 579 free_llist((has_next_ptr**)pptr);
529} 580}
530 581
582#if ENABLE_FEATURE_HTTPD_ACL_IP
531static ALWAYS_INLINE void free_Htaccess_IP_list(Htaccess_IP **pptr) 583static ALWAYS_INLINE void free_Htaccess_IP_list(Htaccess_IP **pptr)
532{ 584{
533 free_llist((has_next_ptr**)pptr); 585 free_llist((has_next_ptr**)pptr);
534} 586}
587#endif
535 588
589#if ENABLE_FEATURE_HTTPD_ACL_IP
536/* Returns presumed mask width in bits or < 0 on error. 590/* Returns presumed mask width in bits or < 0 on error.
537 * Updates strp, stores IP at provided pointer */ 591 * Updates strp, stores IP at provided pointer */
538static int scan_ip(const char **strp, unsigned *ipp, unsigned char endc) 592static int scan_ip(const char **strp, unsigned *ipp, unsigned char endc)
@@ -617,6 +671,7 @@ static int scan_ip_mask(const char *str, unsigned *ipp, unsigned *maskp)
617 *maskp = (uint32_t)(~mask); 671 *maskp = (uint32_t)(~mask);
618 return 0; 672 return 0;
619} 673}
674#endif
620 675
621/* 676/*
622 * Parse configuration file into in-memory linked list. 677 * Parse configuration file into in-memory linked list.
@@ -646,7 +701,9 @@ static void parse_conf(const char *path, int flag)
646 char buf[160]; 701 char buf[160];
647 702
648 /* discard old rules */ 703 /* discard old rules */
649 free_Htaccess_IP_list(&ip_a_d); 704#if ENABLE_FEATURE_HTTPD_ACL_IP
705 free_Htaccess_IP_list(&G.ip_a_d);
706#endif
650 flg_deny_all = 0; 707 flg_deny_all = 0;
651 /* retain previous auth and mime config only for subdir parse */ 708 /* retain previous auth and mime config only for subdir parse */
652 if (flag != SUBDIR_PARSE) { 709 if (flag != SUBDIR_PARSE) {
@@ -763,6 +820,7 @@ static void parse_conf(const char *path, int flag)
763 continue; 820 continue;
764 } 821 }
765 822
823#if ENABLE_FEATURE_HTTPD_ACL_IP
766 if (ch == 'A' || ch == 'D') { 824 if (ch == 'A' || ch == 'D') {
767 Htaccess_IP *pip; 825 Htaccess_IP *pip;
768 826
@@ -784,13 +842,13 @@ static void parse_conf(const char *path, int flag)
784 pip->allow_deny = ch; 842 pip->allow_deny = ch;
785 if (ch == 'D') { 843 if (ch == 'D') {
786 /* Deny:from_IP - prepend */ 844 /* Deny:from_IP - prepend */
787 pip->next = ip_a_d; 845 pip->next = G.ip_a_d;
788 ip_a_d = pip; 846 G.ip_a_d = pip;
789 } else { 847 } else {
790 /* A:from_IP - append (thus all D's precedes A's) */ 848 /* A:from_IP - append (thus all D's precedes A's) */
791 Htaccess_IP *prev_IP = ip_a_d; 849 Htaccess_IP *prev_IP = G.ip_a_d;
792 if (prev_IP == NULL) { 850 if (prev_IP == NULL) {
793 ip_a_d = pip; 851 G.ip_a_d = pip;
794 } else { 852 } else {
795 while (prev_IP->next) 853 while (prev_IP->next)
796 prev_IP = prev_IP->next; 854 prev_IP = prev_IP->next;
@@ -799,6 +857,7 @@ static void parse_conf(const char *path, int flag)
799 } 857 }
800 continue; 858 continue;
801 } 859 }
860#endif
802 861
803#if ENABLE_FEATURE_HTTPD_ERROR_PAGES 862#if ENABLE_FEATURE_HTTPD_ERROR_PAGES
804 if (flag == FIRST_PARSE && ch == 'E') { 863 if (flag == FIRST_PARSE && ch == 'E') {
@@ -1059,11 +1118,12 @@ static void log_and_exit(void)
1059 */ 1118 */
1060static void send_headers(unsigned responseNum) 1119static void send_headers(unsigned responseNum)
1061{ 1120{
1121#if ENABLE_FEATURE_HTTPD_DATE || ENABLE_FEATURE_HTTPD_LAST_MODIFIED
1062 static const char RFC1123FMT[] ALIGN1 = "%a, %d %b %Y %H:%M:%S GMT"; 1122 static const char RFC1123FMT[] ALIGN1 = "%a, %d %b %Y %H:%M:%S GMT";
1063 /* Fixed size 29-byte string. Example: Sun, 06 Nov 1994 08:49:37 GMT */ 1123 /* Fixed size 29-byte string. Example: Sun, 06 Nov 1994 08:49:37 GMT */
1064 char date_str[40]; /* using a bit larger buffer to paranoia reasons */ 1124 char date_str[40]; /* using a bit larger buffer to paranoia reasons */
1065
1066 struct tm tm; 1125 struct tm tm;
1126#endif
1067 const char *responseString = ""; 1127 const char *responseString = "";
1068 const char *infoString = NULL; 1128 const char *infoString = NULL;
1069#if ENABLE_FEATURE_HTTPD_ERROR_PAGES 1129#if ENABLE_FEATURE_HTTPD_ERROR_PAGES
@@ -1071,7 +1131,6 @@ static void send_headers(unsigned responseNum)
1071#endif 1131#endif
1072 unsigned len; 1132 unsigned len;
1073 unsigned i; 1133 unsigned i;
1074 time_t timer = time(NULL);
1075 1134
1076 for (i = 0; i < ARRAY_SIZE(http_response_type); i++) { 1135 for (i = 0; i < ARRAY_SIZE(http_response_type); i++) {
1077 if (http_response_type[i] == responseNum) { 1136 if (http_response_type[i] == responseNum) {
@@ -1092,15 +1151,24 @@ static void send_headers(unsigned responseNum)
1092 * always fit into those kbytes. 1151 * always fit into those kbytes.
1093 */ 1152 */
1094 1153
1095 strftime(date_str, sizeof(date_str), RFC1123FMT, gmtime_r(&timer, &tm)); 1154 {
1096 /* ^^^ using gmtime_r() instead of gmtime() to not use static data */ 1155#if ENABLE_FEATURE_HTTPD_DATE
1097 len = sprintf(iobuf, 1156 time_t timer = time(NULL);
1098 "HTTP/1.0 %u %s\r\n" 1157 strftime(date_str, sizeof(date_str), RFC1123FMT, gmtime_r(&timer, &tm));
1158 /* ^^^ using gmtime_r() instead of gmtime() to not use static data */
1159#endif
1160 len = sprintf(iobuf,
1161 "HTTP/1.1 %u %s\r\n"
1162#if ENABLE_FEATURE_HTTPD_DATE
1099 "Date: %s\r\n" 1163 "Date: %s\r\n"
1164#endif
1100 "Connection: close\r\n", 1165 "Connection: close\r\n",
1101 responseNum, responseString, 1166 responseNum, responseString
1102 date_str 1167#if ENABLE_FEATURE_HTTPD_DATE
1103 ); 1168 ,date_str
1169#endif
1170 );
1171 }
1104 1172
1105 if (responseNum != HTTP_OK || found_mime_type) { 1173 if (responseNum != HTTP_OK || found_mime_type) {
1106 len += sprintf(iobuf + len, 1174 len += sprintf(iobuf + len,
@@ -1120,7 +1188,7 @@ static void send_headers(unsigned responseNum)
1120#endif 1188#endif
1121 if (responseNum == HTTP_MOVED_TEMPORARILY) { 1189 if (responseNum == HTTP_MOVED_TEMPORARILY) {
1122 /* Responding to "GET /dir" with 1190 /* Responding to "GET /dir" with
1123 * "HTTP/1.0 302 Found" "Location: /dir/" 1191 * "HTTP/1.1 302 Found" "Location: /dir/"
1124 * - IOW, asking them to repeat with a slash. 1192 * - IOW, asking them to repeat with a slash.
1125 * Here, overflow IS possible, can't use sprintf: 1193 * Here, overflow IS possible, can't use sprintf:
1126 * mkdir test 1194 * mkdir test
@@ -1152,7 +1220,9 @@ static void send_headers(unsigned responseNum)
1152#endif 1220#endif
1153 1221
1154 if (file_size != -1) { /* file */ 1222 if (file_size != -1) { /* file */
1223#if ENABLE_FEATURE_HTTPD_LAST_MODIFIED
1155 strftime(date_str, sizeof(date_str), RFC1123FMT, gmtime_r(&last_mod, &tm)); 1224 strftime(date_str, sizeof(date_str), RFC1123FMT, gmtime_r(&last_mod, &tm));
1225#endif
1156#if ENABLE_FEATURE_HTTPD_RANGES 1226#if ENABLE_FEATURE_HTTPD_RANGES
1157 if (responseNum == HTTP_PARTIAL_CONTENT) { 1227 if (responseNum == HTTP_PARTIAL_CONTENT) {
1158 len += sprintf(iobuf + len, 1228 len += sprintf(iobuf + len,
@@ -1197,7 +1267,13 @@ static void send_headers(unsigned responseNum)
1197#if ENABLE_FEATURE_HTTPD_RANGES 1267#if ENABLE_FEATURE_HTTPD_RANGES
1198 "Accept-Ranges: bytes\r\n" 1268 "Accept-Ranges: bytes\r\n"
1199#endif 1269#endif
1270#if ENABLE_FEATURE_HTTPD_LAST_MODIFIED
1200 "Last-Modified: %s\r\n" 1271 "Last-Modified: %s\r\n"
1272#endif
1273#if ENABLE_FEATURE_HTTPD_ETAG
1274 "ETag: %s\r\n"
1275#endif
1276
1201 /* Because of 4.4 (5), we can forgo sending of "Content-Length" 1277 /* Because of 4.4 (5), we can forgo sending of "Content-Length"
1202 * since we close connection afterwards, but it helps clients 1278 * since we close connection afterwards, but it helps clients
1203 * to e.g. estimate download times, show progress bars etc. 1279 * to e.g. estimate download times, show progress bars etc.
@@ -1205,7 +1281,12 @@ static void send_headers(unsigned responseNum)
1205 * but de-facto standard is to send it (see comment below). 1281 * but de-facto standard is to send it (see comment below).
1206 */ 1282 */
1207 "Content-Length: %"OFF_FMT"u\r\n", 1283 "Content-Length: %"OFF_FMT"u\r\n",
1284#if ENABLE_FEATURE_HTTPD_LAST_MODIFIED
1208 date_str, 1285 date_str,
1286#endif
1287#if ENABLE_FEATURE_HTTPD_ETAG
1288 G.etag,
1289#endif
1209 file_size 1290 file_size
1210 ); 1291 );
1211 } 1292 }
@@ -1444,7 +1525,7 @@ static NOINLINE void cgi_io_loop_and_exit(int fromCgi_rd, int toCgi_wr, int post
1444 count = safe_read(fromCgi_rd, rbuf + out_cnt, IOBUF_SIZE - 8); 1525 count = safe_read(fromCgi_rd, rbuf + out_cnt, IOBUF_SIZE - 8);
1445 if (count <= 0) { 1526 if (count <= 0) {
1446 /* eof (or error) and there was no "HTTP", 1527 /* eof (or error) and there was no "HTTP",
1447 * send "HTTP/1.0 200 OK\r\n", then send received data */ 1528 * send "HTTP/1.1 200 OK\r\n", then send received data */
1448 if (out_cnt) { 1529 if (out_cnt) {
1449 full_write(STDOUT_FILENO, HTTP_200, sizeof(HTTP_200)-1); 1530 full_write(STDOUT_FILENO, HTTP_200, sizeof(HTTP_200)-1);
1450 full_write(STDOUT_FILENO, rbuf, out_cnt); 1531 full_write(STDOUT_FILENO, rbuf, out_cnt);
@@ -1455,10 +1536,10 @@ static NOINLINE void cgi_io_loop_and_exit(int fromCgi_rd, int toCgi_wr, int post
1455 count = 0; 1536 count = 0;
1456 /* "Status" header format is: "Status: 302 Redirected\r\n" */ 1537 /* "Status" header format is: "Status: 302 Redirected\r\n" */
1457 if (out_cnt >= 8 && memcmp(rbuf, "Status: ", 8) == 0) { 1538 if (out_cnt >= 8 && memcmp(rbuf, "Status: ", 8) == 0) {
1458 /* send "HTTP/1.0 " */ 1539 /* send "HTTP/1.1 " */
1459 if (full_write(STDOUT_FILENO, HTTP_200, 9) != 9) 1540 if (full_write(STDOUT_FILENO, HTTP_200, 9) != 9)
1460 break; 1541 break;
1461 /* skip "Status: " (including space, sending "HTTP/1.0 NNN" is wrong) */ 1542 /* skip "Status: " (including space, sending "HTTP/1.1 NNN" is wrong) */
1462 rbuf += 8; 1543 rbuf += 8;
1463 count = out_cnt - 8; 1544 count = out_cnt - 8;
1464 out_cnt = -1; /* buffering off */ 1545 out_cnt = -1; /* buffering off */
@@ -1474,7 +1555,7 @@ static NOINLINE void cgi_io_loop_and_exit(int fromCgi_rd, int toCgi_wr, int post
1474 full_write(s, "Content-type: text/plain\r\n\r\n", 28); 1555 full_write(s, "Content-type: text/plain\r\n\r\n", 28);
1475 } 1556 }
1476 * Counter-example of valid CGI without Content-type: 1557 * Counter-example of valid CGI without Content-type:
1477 * echo -en "HTTP/1.0 302 Found\r\n" 1558 * echo -en "HTTP/1.1 302 Found\r\n"
1478 * echo -en "Location: http://www.busybox.net\r\n" 1559 * echo -en "Location: http://www.busybox.net\r\n"
1479 * echo -en "\r\n" 1560 * echo -en "\r\n"
1480 */ 1561 */
@@ -1581,7 +1662,7 @@ static void send_cgi_and_exit(
1581 /* (Older versions of bbox seem to do some decoding) */ 1662 /* (Older versions of bbox seem to do some decoding) */
1582 setenv1("QUERY_STRING", g_query); 1663 setenv1("QUERY_STRING", g_query);
1583 putenv((char*)"SERVER_SOFTWARE=busybox httpd/"BB_VER); 1664 putenv((char*)"SERVER_SOFTWARE=busybox httpd/"BB_VER);
1584 putenv((char*)"SERVER_PROTOCOL=HTTP/1.0"); 1665 putenv((char*)"SERVER_PROTOCOL=HTTP/1.1");
1585 putenv((char*)"GATEWAY_INTERFACE=CGI/1.1"); 1666 putenv((char*)"GATEWAY_INTERFACE=CGI/1.1");
1586 /* Having _separate_ variables for IP and port defeats 1667 /* Having _separate_ variables for IP and port defeats
1587 * the purpose of having socket abstraction. Which "port" 1668 * the purpose of having socket abstraction. Which "port"
@@ -1732,6 +1813,7 @@ static NOINLINE void send_file_and_exit(const char *url, int what)
1732 } 1813 }
1733 } else { 1814 } else {
1734 fd = open(url, O_RDONLY); 1815 fd = open(url, O_RDONLY);
1816 /* file_size and last_mod are already populated */
1735 } 1817 }
1736 if (fd < 0) { 1818 if (fd < 0) {
1737 if (DEBUG) 1819 if (DEBUG)
@@ -1743,6 +1825,19 @@ static NOINLINE void send_file_and_exit(const char *url, int what)
1743 send_headers_and_exit(HTTP_NOT_FOUND); 1825 send_headers_and_exit(HTTP_NOT_FOUND);
1744 log_and_exit(); 1826 log_and_exit();
1745 } 1827 }
1828#if ENABLE_FEATURE_HTTPD_ETAG
1829 /* ETag is "hex(last_mod)-hex(file_size)" e.g. "5e132e20-417" */
1830 sprintf(G.etag, "\"%llx-%llx\"", (unsigned long long)last_mod, (unsigned long long)file_size);
1831
1832 if (G.if_none_match) {
1833 if (DEBUG)
1834 bb_perror_msg("If-None-Match and file's ETag are: '%s' '%s'\n", G.if_none_match, G.etag);
1835 /* Weak ETag comparision.
1836 * If-None-Match may have many ETags but they are quoted so we can use simple substring search */
1837 if (strstr(G.if_none_match, G.etag))
1838 send_headers_and_exit(HTTP_NOT_MODIFIED);
1839 }
1840#endif
1746 /* If you want to know about EPIPE below 1841 /* If you want to know about EPIPE below
1747 * (happens if you abort downloads from local httpd): */ 1842 * (happens if you abort downloads from local httpd): */
1748 signal(SIGPIPE, SIG_IGN); 1843 signal(SIGPIPE, SIG_IGN);
@@ -1878,11 +1973,12 @@ static NOINLINE void send_file_and_exit(const char *url, int what)
1878 log_and_exit(); 1973 log_and_exit();
1879} 1974}
1880 1975
1976#if ENABLE_FEATURE_HTTPD_ACL_IP
1881static void if_ip_denied_send_HTTP_FORBIDDEN_and_exit(unsigned remote_ip) 1977static void if_ip_denied_send_HTTP_FORBIDDEN_and_exit(unsigned remote_ip)
1882{ 1978{
1883 Htaccess_IP *cur; 1979 Htaccess_IP *cur;
1884 1980
1885 for (cur = ip_a_d; cur; cur = cur->next) { 1981 for (cur = G.ip_a_d; cur; cur = cur->next) {
1886#if DEBUG 1982#if DEBUG
1887 fprintf(stderr, 1983 fprintf(stderr,
1888 "checkPermIP: '%s' ? '%u.%u.%u.%u/%u.%u.%u.%u'\n", 1984 "checkPermIP: '%s' ? '%u.%u.%u.%u/%u.%u.%u.%u'\n",
@@ -1907,6 +2003,9 @@ static void if_ip_denied_send_HTTP_FORBIDDEN_and_exit(unsigned remote_ip)
1907 if (flg_deny_all) /* depends on whether we saw "D:*" */ 2003 if (flg_deny_all) /* depends on whether we saw "D:*" */
1908 send_headers_and_exit(HTTP_FORBIDDEN); 2004 send_headers_and_exit(HTTP_FORBIDDEN);
1909} 2005}
2006#else
2007# define if_ip_denied_send_HTTP_FORBIDDEN_and_exit(arg) ((void)0)
2008#endif
1910 2009
1911#if ENABLE_FEATURE_HTTPD_BASIC_AUTH 2010#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
1912 2011
@@ -2160,7 +2259,9 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
2160 char *urlcopy; 2259 char *urlcopy;
2161 char *urlp; 2260 char *urlp;
2162 char *tptr; 2261 char *tptr;
2262#if ENABLE_FEATURE_HTTPD_ACL_IP
2163 unsigned remote_ip; 2263 unsigned remote_ip;
2264#endif
2164#if ENABLE_FEATURE_HTTPD_CGI 2265#if ENABLE_FEATURE_HTTPD_CGI
2165 unsigned total_headers_len; 2266 unsigned total_headers_len;
2166#endif 2267#endif
@@ -2182,18 +2283,30 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
2182 * (IOW, server process doesn't need to waste 8k) */ 2283 * (IOW, server process doesn't need to waste 8k) */
2183 iobuf = xmalloc(IOBUF_SIZE); 2284 iobuf = xmalloc(IOBUF_SIZE);
2184 2285
2286 if (ENABLE_FEATURE_HTTPD_CGI || DEBUG || verbose) {
2287 /* NB: can be NULL (user runs httpd -i by hand?) */
2288 rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr->u.sa);
2289 }
2290 if (verbose) {
2291 /* this trick makes -v logging much simpler */
2292 if (rmt_ip_str)
2293 applet_name = rmt_ip_str;
2294 if (verbose > 2)
2295 bb_simple_error_msg("connected");
2296 }
2297#if ENABLE_FEATURE_HTTPD_ACL_IP
2185 remote_ip = 0; 2298 remote_ip = 0;
2186 if (fromAddr->u.sa.sa_family == AF_INET) { 2299 if (fromAddr->u.sa.sa_family == AF_INET) {
2187 remote_ip = ntohl(fromAddr->u.sin.sin_addr.s_addr); 2300 remote_ip = ntohl(fromAddr->u.sin.sin_addr.s_addr);
2188 } 2301 }
2189#if ENABLE_FEATURE_IPV6 2302# if ENABLE_FEATURE_IPV6
2190# if !ENABLE_PLATFORM_MINGW32 2303# if !ENABLE_PLATFORM_MINGW32
2191 if (fromAddr->u.sa.sa_family == AF_INET6 2304 if (fromAddr->u.sa.sa_family == AF_INET6
2192 && fromAddr->u.sin6.sin6_addr.s6_addr32[0] == 0 2305 && fromAddr->u.sin6.sin6_addr.s6_addr32[0] == 0
2193 && fromAddr->u.sin6.sin6_addr.s6_addr32[1] == 0 2306 && fromAddr->u.sin6.sin6_addr.s6_addr32[1] == 0
2194 && ntohl(fromAddr->u.sin6.sin6_addr.s6_addr32[2]) == 0xffff) 2307 && ntohl(fromAddr->u.sin6.sin6_addr.s6_addr32[2]) == 0xffff)
2195 remote_ip = ntohl(fromAddr->u.sin6.sin6_addr.s6_addr32[3]); 2308 remote_ip = ntohl(fromAddr->u.sin6.sin6_addr.s6_addr32[3]);
2196# else 2309# else
2197 if (fromAddr->u.sa.sa_family == AF_INET6 2310 if (fromAddr->u.sa.sa_family == AF_INET6
2198 && fromAddr->u.sin6.sin6_addr.s6_words[0] == 0 2311 && fromAddr->u.sin6.sin6_addr.s6_words[0] == 0
2199 && fromAddr->u.sin6.sin6_addr.s6_words[1] == 0 2312 && fromAddr->u.sin6.sin6_addr.s6_words[1] == 0
@@ -2201,20 +2314,10 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
2201 && fromAddr->u.sin6.sin6_addr.s6_words[3] == 0 2314 && fromAddr->u.sin6.sin6_addr.s6_words[3] == 0
2202 && ntohl(*(uint32_t *)(fromAddr->u.sin6.sin6_addr.s6_words+4)) == 0xffff) 2315 && ntohl(*(uint32_t *)(fromAddr->u.sin6.sin6_addr.s6_words+4)) == 0xffff)
2203 remote_ip = ntohl(*(uint32_t *)(fromAddr->u.sin6.sin6_addr.s6_words+6)); 2316 remote_ip = ntohl(*(uint32_t *)(fromAddr->u.sin6.sin6_addr.s6_words+6));
2317# endif
2204# endif 2318# endif
2205#endif
2206 if (ENABLE_FEATURE_HTTPD_CGI || DEBUG || verbose) {
2207 /* NB: can be NULL (user runs httpd -i by hand?) */
2208 rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr->u.sa);
2209 }
2210 if (verbose) {
2211 /* this trick makes -v logging much simpler */
2212 if (rmt_ip_str)
2213 applet_name = rmt_ip_str;
2214 if (verbose > 2)
2215 bb_simple_error_msg("connected");
2216 }
2217 if_ip_denied_send_HTTP_FORBIDDEN_and_exit(remote_ip); 2319 if_ip_denied_send_HTTP_FORBIDDEN_and_exit(remote_ip);
2320#endif
2218 2321
2219#ifdef SIGALRM 2322#ifdef SIGALRM
2220 /* Install timeout handler. get_line() needs it. */ 2323 /* Install timeout handler. get_line() needs it. */
@@ -2512,6 +2615,13 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
2512 continue; 2615 continue;
2513 } 2616 }
2514#endif 2617#endif
2618#if ENABLE_FEATURE_HTTPD_ETAG
2619 if (STRNCASECMP(iobuf, "If-None-Match:") == 0) {
2620 free(G.if_none_match);
2621 G.if_none_match = xstrdup(skip_whitespace(iobuf + sizeof("If-None-Match:") - 1));
2622 continue;
2623 }
2624#endif
2515#if ENABLE_FEATURE_HTTPD_CGI 2625#if ENABLE_FEATURE_HTTPD_CGI
2516 if (cgi_type != CGI_NONE) { 2626 if (cgi_type != CGI_NONE) {
2517 bool ct = (STRNCASECMP(iobuf, "Content-Type:") == 0); 2627 bool ct = (STRNCASECMP(iobuf, "Content-Type:") == 0);
diff --git a/networking/httpd_indexcgi.c b/networking/httpd_indexcgi.c
index 562cd7fbe..47b1159f4 100644
--- a/networking/httpd_indexcgi.c
+++ b/networking/httpd_indexcgi.c
@@ -52,43 +52,42 @@ httpd_indexcgi.c -o index.cgi
52 * to elements. Edit stylesheet to your liking and recompile. */ 52 * to elements. Edit stylesheet to your liking and recompile. */
53 53
54#define STYLE_STR \ 54#define STYLE_STR \
55"<style>" "\n"\ 55"<style>" \
56"table {" "\n"\ 56"table {" \
57 "width:100%;" "\n"\ 57 "width:100%;" \
58 "background-color:#fff5ee;" "\n"\ 58 "background-color:#fff5ee;" \
59 "border-width:1px;" /* 1px 1px 1px 1px; */ "\n"\ 59 "border-width:1px;" /* 1px 1px 1px 1px; */ \
60 "border-spacing:2px;" "\n"\ 60 "border-spacing:2px;" \
61 "border-style:solid;" /* solid solid solid solid; */ "\n"\ 61 "border-style:solid;" /* solid solid solid solid; */ \
62 "border-color:black;" /* black black black black; */ "\n"\ 62 "border-color:black;" /* black black black black; */ \
63 "border-collapse:collapse;" "\n"\ 63 "border-collapse:collapse" \
64"}" "\n"\ 64"}" \
65"th {" "\n"\ 65"th {" \
66 "border-width:1px;" /* 1px 1px 1px 1px; */ "\n"\ 66 "border-width:1px;" /* 1px 1px 1px 1px; */ \
67 "padding:1px;" /* 1px 1px 1px 1px; */ "\n"\ 67 "padding:1px;" /* 1px 1px 1px 1px; */ \
68 "border-style:solid;" /* solid solid solid solid; */ "\n"\ 68 "border-style:solid;" /* solid solid solid solid; */ \
69 "border-color:black;" /* black black black black; */ "\n"\ 69 "border-color:black" /* black black black black; */ \
70"}" "\n"\ 70"}" \
71"td {" "\n"\ 71"td {" \
72 /* top right bottom left */ \ 72 /* top right bottom left */ \
73 "border-width:0px 1px 0px 1px;" "\n"\ 73 "border-width:0 1px 0 1px;" \
74 "padding:1px;" /* 1px 1px 1px 1px; */ "\n"\ 74 "padding:1px;" /* 1px 1px 1px 1px; */ \
75 "border-style:solid;" /* solid solid solid solid; */ "\n"\ 75 "border-style:solid;" /* solid solid solid solid; */ \
76 "border-color:black;" /* black black black black; */ "\n"\ 76 "border-color:black;" /* black black black black; */ \
77 "white-space:nowrap;" "\n"\ 77 "white-space:nowrap" \
78"}" "\n"\ 78"}" \
79"tr.hdr { background-color:#eee5de; }" "\n"\ 79"tr:nth-child(odd) { background-color:#ffffff }" \
80"tr.o { background-color:#ffffff; }" "\n"\ 80"tr.hdr { background-color:#eee5de }" \
81/* tr.e { ... } - for even rows (currently none) */ \ 81"tr.foot { background-color:#eee5de }" \
82"tr.foot { background-color:#eee5de; }" "\n"\ 82"th.cnt { text-align:left }" \
83"th.cnt { text-align:left; }" "\n"\ 83"th.sz { text-align:right }" \
84"th.sz { text-align:right; }" "\n"\ 84"th.dt { text-align:right }" \
85"th.dt { text-align:right; }" "\n"\ 85"td.sz { text-align:right }" \
86"td.sz { text-align:right; }" "\n"\ 86"td.dt { text-align:right }" \
87"td.dt { text-align:right; }" "\n"\ 87"col.nm { width:98% }" \
88"col.nm { width:98%; }" "\n"\ 88"col.sz { width:1% }" \
89"col.sz { width:1%; }" "\n"\ 89"col.dt { width:1% }" \
90"col.dt { width:1%; }" "\n"\ 90"</style>" \
91"</style>" "\n"\
92 91
93typedef struct dir_list_t { 92typedef struct dir_list_t {
94 char *dl_name; 93 char *dl_name;
@@ -220,7 +219,6 @@ int main(int argc, char *argv[])
220 unsigned count_dirs; 219 unsigned count_dirs;
221 unsigned count_files; 220 unsigned count_files;
222 unsigned long long size_total; 221 unsigned long long size_total;
223 int odd;
224 DIR *dirp; 222 DIR *dirp;
225 char *location; 223 char *location;
226 224
@@ -291,7 +289,6 @@ int main(int argc, char *argv[])
291 "<col class=nm><col class=sz><col class=dt>" "\n" 289 "<col class=nm><col class=sz><col class=dt>" "\n"
292 "<tr class=hdr><th class=cnt>Name<th class=sz>Size<th class=dt>Last modified" "\n"); 290 "<tr class=hdr><th class=cnt>Name<th class=sz>Size<th class=dt>Last modified" "\n");
293 291
294 odd = 0;
295 count_dirs = 0; 292 count_dirs = 0;
296 count_files = 0; 293 count_files = 0;
297 size_total = 0; 294 size_total = 0;
@@ -307,9 +304,7 @@ int main(int argc, char *argv[])
307 } else 304 } else
308 goto next; 305 goto next;
309 306
310 fmt_str("<tr class="); 307 fmt_str("<tr><td class=nm><a href='");
311 *dst++ = (odd ? 'o' : 'e');
312 fmt_str("><td class=nm><a href='");
313 fmt_url(cdir->dl_name); /* %20 etc */ 308 fmt_url(cdir->dl_name); /* %20 etc */
314 if (S_ISDIR(cdir->dl_mode)) 309 if (S_ISDIR(cdir->dl_mode))
315 *dst++ = '/'; 310 *dst++ = '/';
@@ -330,7 +325,6 @@ int main(int argc, char *argv[])
330 fmt_02u(ptm->tm_sec); 325 fmt_02u(ptm->tm_sec);
331 *dst++ = '\n'; 326 *dst++ = '\n';
332 327
333 odd = 1 - odd;
334 next: 328 next:
335 cdir++; 329 cdir++;
336 } 330 }
diff --git a/networking/ifconfig.c b/networking/ifconfig.c
index b566d91a9..3c9a2dfb3 100644
--- a/networking/ifconfig.c
+++ b/networking/ifconfig.c
@@ -27,7 +27,6 @@
27//config:config IFCONFIG 27//config:config IFCONFIG
28//config: bool "ifconfig (12 kb)" 28//config: bool "ifconfig (12 kb)"
29//config: default y 29//config: default y
30//config: select PLATFORM_LINUX
31//config: help 30//config: help
32//config: Ifconfig is used to configure the kernel-resident network interfaces. 31//config: Ifconfig is used to configure the kernel-resident network interfaces.
33//config: 32//config:
diff --git a/networking/ifenslave.c b/networking/ifenslave.c
index 5e769b61d..bdb9894be 100644
--- a/networking/ifenslave.c
+++ b/networking/ifenslave.c
@@ -100,7 +100,6 @@
100//config:config IFENSLAVE 100//config:config IFENSLAVE
101//config: bool "ifenslave (13 kb)" 101//config: bool "ifenslave (13 kb)"
102//config: default y 102//config: default y
103//config: select PLATFORM_LINUX
104//config: help 103//config: help
105//config: Userspace application to bind several interfaces 104//config: Userspace application to bind several interfaces
106//config: to a logical interface (use with kernel bonding driver). 105//config: to a logical interface (use with kernel bonding driver).
diff --git a/networking/ifplugd.c b/networking/ifplugd.c
index fa18edd57..0d17b7d8c 100644
--- a/networking/ifplugd.c
+++ b/networking/ifplugd.c
@@ -9,7 +9,6 @@
9//config:config IFPLUGD 9//config:config IFPLUGD
10//config: bool "ifplugd (10 kb)" 10//config: bool "ifplugd (10 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX
13//config: help 12//config: help
14//config: Network interface plug detection daemon. 13//config: Network interface plug detection daemon.
15 14
diff --git a/networking/ip.c b/networking/ip.c
index 034ee4fc8..7d3faf7f8 100644
--- a/networking/ip.c
+++ b/networking/ip.c
@@ -11,7 +11,6 @@
11//config:config IP 11//config:config IP
12//config: bool "ip (35 kb)" 12//config: bool "ip (35 kb)"
13//config: default y 13//config: default y
14//config: select PLATFORM_LINUX
15//config: help 14//config: help
16//config: The "ip" applet is a TCP/IP interface configuration and routing 15//config: The "ip" applet is a TCP/IP interface configuration and routing
17//config: utility. 16//config: utility.
@@ -23,7 +22,6 @@
23//config: bool "ipaddr (14 kb)" 22//config: bool "ipaddr (14 kb)"
24//config: default y 23//config: default y
25//config: select FEATURE_IP_ADDRESS 24//config: select FEATURE_IP_ADDRESS
26//config: select PLATFORM_LINUX
27//config: help 25//config: help
28//config: Short form of "ip addr" 26//config: Short form of "ip addr"
29//config: 27//config:
@@ -31,7 +29,6 @@
31//config: bool "iplink (17 kb)" 29//config: bool "iplink (17 kb)"
32//config: default y 30//config: default y
33//config: select FEATURE_IP_LINK 31//config: select FEATURE_IP_LINK
34//config: select PLATFORM_LINUX
35//config: help 32//config: help
36//config: Short form of "ip link" 33//config: Short form of "ip link"
37//config: 34//config:
@@ -39,7 +36,6 @@
39//config: bool "iproute (15 kb)" 36//config: bool "iproute (15 kb)"
40//config: default y 37//config: default y
41//config: select FEATURE_IP_ROUTE 38//config: select FEATURE_IP_ROUTE
42//config: select PLATFORM_LINUX
43//config: help 39//config: help
44//config: Short form of "ip route" 40//config: Short form of "ip route"
45//config: 41//config:
@@ -47,7 +43,6 @@
47//config: bool "iptunnel (9.6 kb)" 43//config: bool "iptunnel (9.6 kb)"
48//config: default y 44//config: default y
49//config: select FEATURE_IP_TUNNEL 45//config: select FEATURE_IP_TUNNEL
50//config: select PLATFORM_LINUX
51//config: help 46//config: help
52//config: Short form of "ip tunnel" 47//config: Short form of "ip tunnel"
53//config: 48//config:
@@ -55,7 +50,6 @@
55//config: bool "iprule (10 kb)" 50//config: bool "iprule (10 kb)"
56//config: default y 51//config: default y
57//config: select FEATURE_IP_RULE 52//config: select FEATURE_IP_RULE
58//config: select PLATFORM_LINUX
59//config: help 53//config: help
60//config: Short form of "ip rule" 54//config: Short form of "ip rule"
61//config: 55//config:
@@ -63,7 +57,6 @@
63//config: bool "ipneigh (8.3 kb)" 57//config: bool "ipneigh (8.3 kb)"
64//config: default y 58//config: default y
65//config: select FEATURE_IP_NEIGH 59//config: select FEATURE_IP_NEIGH
66//config: select PLATFORM_LINUX
67//config: help 60//config: help
68//config: Short form of "ip neigh" 61//config: Short form of "ip neigh"
69//config: 62//config:
@@ -146,11 +139,13 @@
146//usage:#define ipaddr_trivial_usage 139//usage:#define ipaddr_trivial_usage
147//usage: "add|del IFADDR dev IFACE | show|flush [dev IFACE] [to PREFIX]" 140//usage: "add|del IFADDR dev IFACE | show|flush [dev IFACE] [to PREFIX]"
148//usage:#define ipaddr_full_usage "\n\n" 141//usage:#define ipaddr_full_usage "\n\n"
149//usage: "ipaddr add|change|replace|delete dev IFACE IFADDR\n" 142//usage: "ipaddr add|change|replace|delete dev IFACE [CONFFLAG-LIST] IFADDR\n"
150//usage: " IFADDR := PREFIX | ADDR peer PREFIX [broadcast ADDR|+|-]\n" 143//usage: " IFADDR := PREFIX | ADDR peer PREFIX [broadcast ADDR|+|-]\n"
151//usage: " [anycast ADDR] [label STRING] [scope SCOPE]\n" 144//usage: " [anycast ADDR] [label STRING] [scope SCOPE]\n"
152//usage: " PREFIX := ADDR[/MASK]\n" 145//usage: " PREFIX := ADDR[/MASK]\n"
153//usage: " SCOPE := [host|link|global|NUMBER]\n" 146//usage: " SCOPE := [host|link|global|NUMBER]\n"
147//usage: " CONFFLAG-LIST := [CONFFLAG-LIST] CONFFLAG\n"
148//usage: " CONFFLAG := [noprefixroute]\n"
154//usage: "ipaddr show|flush [dev IFACE] [scope SCOPE] [to PREFIX] [label PATTERN]" 149//usage: "ipaddr show|flush [dev IFACE] [scope SCOPE] [to PREFIX] [label PATTERN]"
155//usage: 150//usage:
156//--------------123456789.123456789.123456789.123456789.123456789.123456789.123456789.123....79 151//--------------123456789.123456789.123456789.123456789.123456789.123456789.123456789.123....79
diff --git a/networking/libiproute/ip_common.h b/networking/libiproute/ip_common.h
index 40171bed9..894e380f8 100644
--- a/networking/libiproute/ip_common.h
+++ b/networking/libiproute/ip_common.h
@@ -33,4 +33,8 @@ int FAST_FUNC do_iplink(char **argv);
33 33
34POP_SAVED_FUNCTION_VISIBILITY 34POP_SAVED_FUNCTION_VISIBILITY
35 35
36#ifndef INFINITY_LIFE_TIME
37#define INFINITY_LIFE_TIME 0xFFFFFFFFU
38#endif
39
36#endif 40#endif
diff --git a/networking/libiproute/ipaddress.c b/networking/libiproute/ipaddress.c
index 86cf3beea..71e8fb6a7 100644
--- a/networking/libiproute/ipaddress.c
+++ b/networking/libiproute/ipaddress.c
@@ -217,6 +217,7 @@ static int FAST_FUNC print_addrinfo(const struct sockaddr_nl *who UNUSED_PARAM,
217{ 217{
218 struct ifaddrmsg *ifa = NLMSG_DATA(n); 218 struct ifaddrmsg *ifa = NLMSG_DATA(n);
219 int len = n->nlmsg_len; 219 int len = n->nlmsg_len;
220 unsigned int ifa_flags;
220 struct rtattr *rta_tb[IFA_MAX+1]; 221 struct rtattr *rta_tb[IFA_MAX+1];
221 222
222 if (n->nlmsg_type != RTM_NEWADDR && n->nlmsg_type != RTM_DELADDR) 223 if (n->nlmsg_type != RTM_NEWADDR && n->nlmsg_type != RTM_DELADDR)
@@ -233,6 +234,8 @@ static int FAST_FUNC print_addrinfo(const struct sockaddr_nl *who UNUSED_PARAM,
233 //memset(rta_tb, 0, sizeof(rta_tb)); - parse_rtattr does this 234 //memset(rta_tb, 0, sizeof(rta_tb)); - parse_rtattr does this
234 parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(ifa), n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa))); 235 parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(ifa), n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)));
235 236
237 ifa_flags = rta_tb[IFA_FLAGS] ? *(__u32*)RTA_DATA(rta_tb[IFA_FLAGS]) : ifa->ifa_flags;
238
236 if (!rta_tb[IFA_LOCAL]) 239 if (!rta_tb[IFA_LOCAL])
237 rta_tb[IFA_LOCAL] = rta_tb[IFA_ADDRESS]; 240 rta_tb[IFA_LOCAL] = rta_tb[IFA_ADDRESS];
238 if (!rta_tb[IFA_ADDRESS]) 241 if (!rta_tb[IFA_ADDRESS])
@@ -242,7 +245,7 @@ static int FAST_FUNC print_addrinfo(const struct sockaddr_nl *who UNUSED_PARAM,
242 return 0; 245 return 0;
243 if ((G_filter.scope ^ ifa->ifa_scope) & G_filter.scopemask) 246 if ((G_filter.scope ^ ifa->ifa_scope) & G_filter.scopemask)
244 return 0; 247 return 0;
245 if ((G_filter.flags ^ ifa->ifa_flags) & G_filter.flagmask) 248 if ((G_filter.flags ^ ifa_flags) & G_filter.flagmask)
246 return 0; 249 return 0;
247 if (G_filter.label) { 250 if (G_filter.label) {
248 const char *label; 251 const char *label;
@@ -322,28 +325,32 @@ static int FAST_FUNC print_addrinfo(const struct sockaddr_nl *who UNUSED_PARAM,
322 ); 325 );
323 } 326 }
324 printf("scope %s ", rtnl_rtscope_n2a(ifa->ifa_scope)); 327 printf("scope %s ", rtnl_rtscope_n2a(ifa->ifa_scope));
325 if (ifa->ifa_flags & IFA_F_SECONDARY) { 328 if (ifa_flags & IFA_F_SECONDARY) {
326 ifa->ifa_flags &= ~IFA_F_SECONDARY; 329 ifa_flags &= ~IFA_F_SECONDARY;
327 printf("secondary "); 330 printf("secondary ");
328 } 331 }
329 if (ifa->ifa_flags & IFA_F_TENTATIVE) { 332 if (ifa_flags & IFA_F_TENTATIVE) {
330 ifa->ifa_flags &= ~IFA_F_TENTATIVE; 333 ifa_flags &= ~IFA_F_TENTATIVE;
331 printf("tentative "); 334 printf("tentative ");
332 } 335 }
333 if (ifa->ifa_flags & IFA_F_DADFAILED) { 336 if (ifa_flags & IFA_F_DADFAILED) {
334 ifa->ifa_flags &= ~IFA_F_DADFAILED; 337 ifa_flags &= ~IFA_F_DADFAILED;
335 printf("dadfailed "); 338 printf("dadfailed ");
336 } 339 }
337 if (ifa->ifa_flags & IFA_F_DEPRECATED) { 340 if (ifa_flags & IFA_F_DEPRECATED) {
338 ifa->ifa_flags &= ~IFA_F_DEPRECATED; 341 ifa_flags &= ~IFA_F_DEPRECATED;
339 printf("deprecated "); 342 printf("deprecated ");
340 } 343 }
341 if (!(ifa->ifa_flags & IFA_F_PERMANENT)) { 344 if (!(ifa_flags & IFA_F_PERMANENT)) {
342 printf("dynamic "); 345 printf("dynamic ");
343 } else 346 } else
344 ifa->ifa_flags &= ~IFA_F_PERMANENT; 347 ifa_flags &= ~IFA_F_PERMANENT;
345 if (ifa->ifa_flags) 348 if (ifa_flags & IFA_F_NOPREFIXROUTE) {
346 printf("flags %02x ", ifa->ifa_flags); 349 ifa_flags &= ~IFA_F_NOPREFIXROUTE;
350 printf("noprefixroute ");
351 }
352 if (ifa_flags)
353 printf("flags %02x ", ifa_flags);
347 if (rta_tb[IFA_LABEL]) 354 if (rta_tb[IFA_LABEL])
348 fputs((char*)RTA_DATA(rta_tb[IFA_LABEL]), stdout); 355 fputs((char*)RTA_DATA(rta_tb[IFA_LABEL]), stdout);
349 if (rta_tb[IFA_CACHEINFO]) { 356 if (rta_tb[IFA_CACHEINFO]) {
@@ -585,6 +592,14 @@ int FAST_FUNC ipaddr_list_or_flush(char **argv, int flush)
585 return 0; 592 return 0;
586} 593}
587 594
595static void set_lifetime(unsigned int *lifetime, char *argv, const char *errmsg)
596{
597 if (strcmp(argv, "forever") == 0)
598 *lifetime = INFINITY_LIFE_TIME;
599 else
600 *lifetime = get_u32(argv, errmsg);
601}
602
588static int default_scope(inet_prefix *lcl) 603static int default_scope(inet_prefix *lcl)
589{ 604{
590 if (lcl->family == AF_INET) { 605 if (lcl->family == AF_INET) {
@@ -600,10 +615,13 @@ static int ipaddr_modify(int cmd, int flags, char **argv)
600 /* If you add stuff here, update ipaddr_full_usage */ 615 /* If you add stuff here, update ipaddr_full_usage */
601 static const char option[] ALIGN1 = 616 static const char option[] ALIGN1 =
602 "peer\0""remote\0""broadcast\0""brd\0" 617 "peer\0""remote\0""broadcast\0""brd\0"
603 "anycast\0""scope\0""dev\0""label\0""local\0"; 618 "anycast\0""valid_lft\0""preferred_lft\0"
619 "scope\0""dev\0""label\0""noprefixroute\0""local\0";
604#define option_peer option 620#define option_peer option
605#define option_broadcast (option + sizeof("peer") + sizeof("remote")) 621#define option_broadcast (option + sizeof("peer") + sizeof("remote"))
606#define option_anycast (option_broadcast + sizeof("broadcast") + sizeof("brd")) 622#define option_anycast (option_broadcast + sizeof("broadcast") + sizeof("brd"))
623#define option_valid_lft (option_anycast + sizeof("anycast"))
624#define option_pref_lft (option_valid_lft + sizeof("valid_lft"))
607 struct rtnl_handle rth; 625 struct rtnl_handle rth;
608 struct { 626 struct {
609 struct nlmsghdr n; 627 struct nlmsghdr n;
@@ -612,6 +630,8 @@ static int ipaddr_modify(int cmd, int flags, char **argv)
612 } req; 630 } req;
613 char *d = NULL; 631 char *d = NULL;
614 char *l = NULL; 632 char *l = NULL;
633 char *valid_lftp = NULL;
634 char *preferred_lftp = NULL;
615 inet_prefix lcl; 635 inet_prefix lcl;
616 inet_prefix peer; 636 inet_prefix peer;
617 int local_len = 0; 637 int local_len = 0;
@@ -619,6 +639,9 @@ static int ipaddr_modify(int cmd, int flags, char **argv)
619 int brd_len = 0; 639 int brd_len = 0;
620 int any_len = 0; 640 int any_len = 0;
621 bool scoped = 0; 641 bool scoped = 0;
642 __u32 valid_lft = INFINITY_LIFE_TIME;
643 __u32 preferred_lft = INFINITY_LIFE_TIME;
644 unsigned int ifa_flags = 0;
622 645
623 memset(&req, 0, sizeof(req)); 646 memset(&req, 0, sizeof(req));
624 647
@@ -630,10 +653,9 @@ static int ipaddr_modify(int cmd, int flags, char **argv)
630 while (*argv) { 653 while (*argv) {
631 unsigned arg = index_in_strings(option, *argv); 654 unsigned arg = index_in_strings(option, *argv);
632 /* if search fails, "local" is assumed */ 655 /* if search fails, "local" is assumed */
633 if ((int)arg >= 0)
634 NEXT_ARG();
635 656
636 if (arg <= 1) { /* peer, remote */ 657 if (arg <= 1) { /* peer, remote */
658 NEXT_ARG();
637 if (peer_len) { 659 if (peer_len) {
638 duparg(option_peer, *argv); 660 duparg(option_peer, *argv);
639 } 661 }
@@ -646,6 +668,7 @@ static int ipaddr_modify(int cmd, int flags, char **argv)
646 req.ifa.ifa_prefixlen = peer.bitlen; 668 req.ifa.ifa_prefixlen = peer.bitlen;
647 } else if (arg <= 3) { /* broadcast, brd */ 669 } else if (arg <= 3) { /* broadcast, brd */
648 inet_prefix addr; 670 inet_prefix addr;
671 NEXT_ARG();
649 if (brd_len) { 672 if (brd_len) {
650 duparg(option_broadcast, *argv); 673 duparg(option_broadcast, *argv);
651 } 674 }
@@ -662,6 +685,7 @@ static int ipaddr_modify(int cmd, int flags, char **argv)
662 } 685 }
663 } else if (arg == 4) { /* anycast */ 686 } else if (arg == 4) { /* anycast */
664 inet_prefix addr; 687 inet_prefix addr;
688 NEXT_ARG();
665 if (any_len) { 689 if (any_len) {
666 duparg(option_anycast, *argv); 690 duparg(option_anycast, *argv);
667 } 691 }
@@ -671,20 +695,39 @@ static int ipaddr_modify(int cmd, int flags, char **argv)
671 } 695 }
672 addattr_l(&req.n, sizeof(req), IFA_ANYCAST, &addr.data, addr.bytelen); 696 addattr_l(&req.n, sizeof(req), IFA_ANYCAST, &addr.data, addr.bytelen);
673 any_len = addr.bytelen; 697 any_len = addr.bytelen;
674 } else if (arg == 5) { /* scope */ 698 } else if (arg == 5) { /* valid_lft */
699 if (valid_lftp)
700 duparg(option_valid_lft, *argv);
701 NEXT_ARG();
702 valid_lftp = *argv;
703 set_lifetime(&valid_lft, *argv, option_valid_lft);
704 } else if (arg == 6) { /* preferred_lft */
705 if (preferred_lftp)
706 duparg(option_pref_lft, *argv);
707 NEXT_ARG();
708 preferred_lftp = *argv;
709 set_lifetime(&preferred_lft, *argv, option_pref_lft);
710 } else if (arg == 7) { /* scope */
675 uint32_t scope = 0; 711 uint32_t scope = 0;
712 NEXT_ARG();
676 if (rtnl_rtscope_a2n(&scope, *argv)) { 713 if (rtnl_rtscope_a2n(&scope, *argv)) {
677 invarg_1_to_2(*argv, "scope"); 714 invarg_1_to_2(*argv, "scope");
678 } 715 }
679 req.ifa.ifa_scope = scope; 716 req.ifa.ifa_scope = scope;
680 scoped = 1; 717 scoped = 1;
681 } else if (arg == 6) { /* dev */ 718 } else if (arg == 8) { /* dev */
719 NEXT_ARG();
682 d = *argv; 720 d = *argv;
683 } else if (arg == 7) { /* label */ 721 } else if (arg == 9) { /* label */
722 NEXT_ARG();
684 l = *argv; 723 l = *argv;
685 addattr_l(&req.n, sizeof(req), IFA_LABEL, l, strlen(l) + 1); 724 addattr_l(&req.n, sizeof(req), IFA_LABEL, l, strlen(l) + 1);
725 } else if (arg == 10) { /* noprefixroute */
726 ifa_flags |= IFA_F_NOPREFIXROUTE;
686 } else { 727 } else {
687 /* local (specified or assumed) */ 728 /* local (specified or assumed) */
729 if ((int)arg >= 0)
730 NEXT_ARG();
688 if (local_len) { 731 if (local_len) {
689 duparg2("local", *argv); 732 duparg2("local", *argv);
690 } 733 }
@@ -698,6 +741,11 @@ static int ipaddr_modify(int cmd, int flags, char **argv)
698 argv++; 741 argv++;
699 } 742 }
700 743
744 if (ifa_flags <= 0xff)
745 req.ifa.ifa_flags = ifa_flags;
746 else
747 addattr32(&req.n, sizeof(req), IFA_FLAGS, ifa_flags);
748
701 if (!d) { 749 if (!d) {
702 /* There was no "dev IFACE", but we need that */ 750 /* There was no "dev IFACE", but we need that */
703 bb_simple_error_msg_and_die("need \"dev IFACE\""); 751 bb_simple_error_msg_and_die("need \"dev IFACE\"");
@@ -740,6 +788,24 @@ static int ipaddr_modify(int cmd, int flags, char **argv)
740 788
741 req.ifa.ifa_index = xll_name_to_index(d); 789 req.ifa.ifa_index = xll_name_to_index(d);
742 790
791 if (valid_lftp || preferred_lftp) {
792 struct ifa_cacheinfo cinfo = {};
793
794 if (!valid_lft) {
795 fprintf(stderr, "valid_lft is zero\n");
796 return 1;
797 }
798 if (valid_lft < preferred_lft) {
799 fprintf(stderr, "preferred_lft is greater than valid_lft\n");
800 return 1;
801 }
802
803 cinfo.ifa_prefered = preferred_lft;
804 cinfo.ifa_valid = valid_lft;
805 addattr_l(&req.n, sizeof(req), IFA_CACHEINFO, &cinfo,
806 sizeof(cinfo));
807 }
808
743 if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) 809 if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
744 return 2; 810 return 2;
745 811
diff --git a/networking/nameif.c b/networking/nameif.c
index 91d50536a..854594c83 100644
--- a/networking/nameif.c
+++ b/networking/nameif.c
@@ -12,7 +12,6 @@
12//config:config NAMEIF 12//config:config NAMEIF
13//config: bool "nameif (6.6 kb)" 13//config: bool "nameif (6.6 kb)"
14//config: default y 14//config: default y
15//config: select PLATFORM_LINUX
16//config: select FEATURE_SYSLOG 15//config: select FEATURE_SYSLOG
17//config: help 16//config: help
18//config: nameif is used to rename network interface by its MAC address. 17//config: nameif is used to rename network interface by its MAC address.
diff --git a/networking/netstat.c b/networking/netstat.c
index c7934423b..936610f89 100644
--- a/networking/netstat.c
+++ b/networking/netstat.c
@@ -16,7 +16,6 @@
16//config:config NETSTAT 16//config:config NETSTAT
17//config: bool "netstat (10 kb)" 17//config: bool "netstat (10 kb)"
18//config: default y 18//config: default y
19//config: select PLATFORM_LINUX
20//config: help 19//config: help
21//config: netstat prints information about the Linux networking subsystem. 20//config: netstat prints information about the Linux networking subsystem.
22//config: 21//config:
diff --git a/networking/ntpd.c b/networking/ntpd.c
index 0f12409f9..d721fe80c 100644
--- a/networking/ntpd.c
+++ b/networking/ntpd.c
@@ -43,7 +43,6 @@
43//config:config NTPD 43//config:config NTPD
44//config: bool "ntpd (22 kb)" 44//config: bool "ntpd (22 kb)"
45//config: default y 45//config: default y
46//config: select PLATFORM_LINUX
47//config: help 46//config: help
48//config: The NTP client/server daemon. 47//config: The NTP client/server daemon.
49//config: 48//config:
@@ -337,6 +336,9 @@ typedef struct {
337#endif 336#endif
338 int p_fd; 337 int p_fd;
339 int datapoint_idx; 338 int datapoint_idx;
339#if ENABLE_FEATURE_NTPD_SERVER
340 uint32_t p_refid;
341#endif
340 uint32_t lastpkt_refid; 342 uint32_t lastpkt_refid;
341 uint8_t lastpkt_status; 343 uint8_t lastpkt_status;
342 uint8_t lastpkt_stratum; 344 uint8_t lastpkt_stratum;
@@ -413,7 +415,9 @@ struct globals {
413 * in stratum 2+ packets, it's IPv4 address or 4 first bytes 415 * in stratum 2+ packets, it's IPv4 address or 4 first bytes
414 * of MD5 hash of IPv6 416 * of MD5 hash of IPv6
415 */ 417 */
418#if ENABLE_FEATURE_NTPD_SERVER
416 uint32_t refid; 419 uint32_t refid;
420#endif
417 uint8_t ntp_status; 421 uint8_t ntp_status;
418 /* precision is defined as the larger of the resolution and time to 422 /* precision is defined as the larger of the resolution and time to
419 * read the clock, in log2 units. For instance, the precision of a 423 * read the clock, in log2 units. For instance, the precision of a
@@ -836,6 +840,24 @@ reset_peer_stats(peer_t *p, double offset)
836 VERB6 bb_error_msg("%s->lastpkt_recv_time=%f", p->p_dotted, p->lastpkt_recv_time); 840 VERB6 bb_error_msg("%s->lastpkt_recv_time=%f", p->p_dotted, p->lastpkt_recv_time);
837} 841}
838 842
843#if ENABLE_FEATURE_NTPD_SERVER
844static uint32_t calculate_refid(len_and_sockaddr *lsa)
845{
846# if ENABLE_FEATURE_IPV6
847 if (lsa->u.sa.sa_family == AF_INET6) {
848 md5_ctx_t md5;
849 uint32_t res[MD5_OUTSIZE / 4];
850
851 md5_begin(&md5);
852 md5_hash(&md5, &lsa->u.sin6.sin6_addr, sizeof(lsa->u.sin6.sin6_addr));
853 md5_end(&md5, res);
854 return res[0];
855 }
856# endif
857 return lsa->u.sin.sin_addr.s_addr;
858}
859#endif
860
839static len_and_sockaddr* 861static len_and_sockaddr*
840resolve_peer_hostname(peer_t *p) 862resolve_peer_hostname(peer_t *p)
841{ 863{
@@ -847,6 +869,9 @@ resolve_peer_hostname(peer_t *p)
847 p->p_dotted = xmalloc_sockaddr2dotted_noport(&lsa->u.sa); 869 p->p_dotted = xmalloc_sockaddr2dotted_noport(&lsa->u.sa);
848 VERB1 if (strcmp(p->p_hostname, p->p_dotted) != 0) 870 VERB1 if (strcmp(p->p_hostname, p->p_dotted) != 0)
849 bb_error_msg("'%s' is %s", p->p_hostname, p->p_dotted); 871 bb_error_msg("'%s' is %s", p->p_hostname, p->p_dotted);
872#if ENABLE_FEATURE_NTPD_SERVER
873 p->p_refid = calculate_refid(p->p_lsa);
874#endif
850 p->dns_errors = 0; 875 p->dns_errors = 0;
851 return lsa; 876 return lsa;
852 } 877 }
@@ -1764,7 +1789,10 @@ update_local_clock(peer_t *p)
1764 1789
1765 G.reftime = G.cur_time; 1790 G.reftime = G.cur_time;
1766 G.ntp_status = p->lastpkt_status; 1791 G.ntp_status = p->lastpkt_status;
1767 G.refid = p->lastpkt_refid; 1792#if ENABLE_FEATURE_NTPD_SERVER
1793 /* Our current refid is the IPv4 (or md5-hashed IPv6) address of the peer we took time from: */
1794 G.refid = p->p_refid;
1795#endif
1768 G.rootdelay = p->lastpkt_rootdelay + p->lastpkt_delay; 1796 G.rootdelay = p->lastpkt_rootdelay + p->lastpkt_delay;
1769 dtemp = p->filter_jitter; // SQRT(SQUARE(p->filter_jitter) + SQUARE(G.cluster_jitter)); 1797 dtemp = p->filter_jitter; // SQRT(SQUARE(p->filter_jitter) + SQUARE(G.cluster_jitter));
1770 dtemp += MAXD(p->filter_dispersion + FREQ_TOLERANCE * (G.cur_time - p->lastpkt_recv_time) + abs_offset, MINDISP); 1798 dtemp += MAXD(p->filter_dispersion + FREQ_TOLERANCE * (G.cur_time - p->lastpkt_recv_time) + abs_offset, MINDISP);
@@ -2249,11 +2277,11 @@ recv_and_process_client_pkt(void /*int fd*/)
2249 * We don't support this. 2277 * We don't support this.
2250 */ 2278 */
2251 2279
2252#if ENABLE_FEATURE_NTP_AUTH 2280# if ENABLE_FEATURE_NTP_AUTH
2253 if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE_MD5_AUTH && size != NTP_MSGSIZE_SHA1_AUTH) 2281 if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE_MD5_AUTH && size != NTP_MSGSIZE_SHA1_AUTH)
2254#else 2282# else
2255 if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE_MD5_AUTH) 2283 if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE_MD5_AUTH)
2256#endif 2284# endif
2257 { 2285 {
2258 char *addr; 2286 char *addr;
2259 if (size < 0) { 2287 if (size < 0) {
diff --git a/networking/parse_pasv_epsv.c b/networking/parse_pasv_epsv.c
index 14f4d4258..314237be6 100644
--- a/networking/parse_pasv_epsv.c
+++ b/networking/parse_pasv_epsv.c
@@ -38,6 +38,8 @@ int FAST_FUNC parse_pasv_epsv(char *buf)
38 * Server's IP is N1.N2.N3.N4 (we ignore it) 38 * Server's IP is N1.N2.N3.N4 (we ignore it)
39 * Server's port for data connection is P1*256+P2 */ 39 * Server's port for data connection is P1*256+P2 */
40 ptr = strrchr(buf, ')'); 40 ptr = strrchr(buf, ')');
41 if (!ptr) ptr = strrchr(buf, '\r'); /* for PASV responses not ending with ')' */
42 if (!ptr) ptr = strrchr(buf, '\n'); /* for PASV responses not ending with ')' */
41 if (ptr) *ptr = '\0'; 43 if (ptr) *ptr = '\0';
42 44
43 ptr = strrchr(buf, ','); 45 ptr = strrchr(buf, ',');
diff --git a/networking/ping.c b/networking/ping.c
index a47342fee..47b6ab1b2 100644
--- a/networking/ping.c
+++ b/networking/ping.c
@@ -27,7 +27,6 @@
27//config:config PING 27//config:config PING
28//config: bool "ping (10 kb)" 28//config: bool "ping (10 kb)"
29//config: default y 29//config: default y
30//config: select PLATFORM_LINUX
31//config: help 30//config: help
32//config: ping uses the ICMP protocol's mandatory ECHO_REQUEST datagram to 31//config: ping uses the ICMP protocol's mandatory ECHO_REQUEST datagram to
33//config: elicit an ICMP ECHO_RESPONSE from a host or gateway. 32//config: elicit an ICMP ECHO_RESPONSE from a host or gateway.
diff --git a/networking/route.c b/networking/route.c
index e785b1da6..4d9aad6cc 100644
--- a/networking/route.c
+++ b/networking/route.c
@@ -27,7 +27,6 @@
27//config:config ROUTE 27//config:config ROUTE
28//config: bool "route (8.7 kb)" 28//config: bool "route (8.7 kb)"
29//config: default y 29//config: default y
30//config: select PLATFORM_LINUX
31//config: help 30//config: help
32//config: Route displays or manipulates the kernel's IP routing tables. 31//config: Route displays or manipulates the kernel's IP routing tables.
33 32
diff --git a/networking/slattach.c b/networking/slattach.c
index 659822a91..51fbc1f49 100644
--- a/networking/slattach.c
+++ b/networking/slattach.c
@@ -15,7 +15,6 @@
15//config:config SLATTACH 15//config:config SLATTACH
16//config: bool "slattach (6.2 kb)" 16//config: bool "slattach (6.2 kb)"
17//config: default y 17//config: default y
18//config: select PLATFORM_LINUX
19//config: help 18//config: help
20//config: slattach configures serial line as SLIP network interface. 19//config: slattach configures serial line as SLIP network interface.
21 20
diff --git a/networking/tls.c b/networking/tls.c
index 9e81afbad..c00ef5db0 100644
--- a/networking/tls.c
+++ b/networking/tls.c
@@ -212,8 +212,6 @@
212 212
213enum { 213enum {
214 SHA_INSIZE = 64, 214 SHA_INSIZE = 64,
215 SHA1_OUTSIZE = 20,
216 SHA256_OUTSIZE = 32,
217 215
218 AES128_KEYSIZE = 16, 216 AES128_KEYSIZE = 16,
219 AES256_KEYSIZE = 32, 217 AES256_KEYSIZE = 32,
diff --git a/networking/traceroute.c b/networking/traceroute.c
index 06d3f19da..5068f654b 100644
--- a/networking/traceroute.c
+++ b/networking/traceroute.c
@@ -212,7 +212,6 @@
212//config:config TRACEROUTE 212//config:config TRACEROUTE
213//config: bool "traceroute (11 kb)" 213//config: bool "traceroute (11 kb)"
214//config: default y 214//config: default y
215//config: select PLATFORM_LINUX
216//config: help 215//config: help
217//config: Utility to trace the route of IP packets. 216//config: Utility to trace the route of IP packets.
218//config: 217//config:
diff --git a/networking/tunctl.c b/networking/tunctl.c
index a0e3926e9..0f010e196 100644
--- a/networking/tunctl.c
+++ b/networking/tunctl.c
@@ -12,7 +12,6 @@
12//config:config TUNCTL 12//config:config TUNCTL
13//config: bool "tunctl (6.2 kb)" 13//config: bool "tunctl (6.2 kb)"
14//config: default y 14//config: default y
15//config: select PLATFORM_LINUX
16//config: help 15//config: help
17//config: tunctl creates or deletes tun devices. 16//config: tunctl creates or deletes tun devices.
18//config: 17//config:
diff --git a/networking/udhcp/Config.src b/networking/udhcp/Config.src
index 8ef24748e..7d04bb246 100644
--- a/networking/udhcp/Config.src
+++ b/networking/udhcp/Config.src
@@ -6,7 +6,6 @@
6config UDHCPD 6config UDHCPD
7 bool "udhcpd (21 kb)" 7 bool "udhcpd (21 kb)"
8 default y 8 default y
9 select PLATFORM_LINUX
10 help 9 help
11 udhcpd is a DHCP server geared primarily toward embedded systems, 10 udhcpd is a DHCP server geared primarily toward embedded systems,
12 while striving to be fully functional and RFC compliant. 11 while striving to be fully functional and RFC compliant.
@@ -62,7 +61,6 @@ config DHCPRELAY
62config UDHCPC 61config UDHCPC
63 bool "udhcpc (24 kb)" 62 bool "udhcpc (24 kb)"
64 default y 63 default y
65 select PLATFORM_LINUX
66 help 64 help
67 udhcpc is a DHCP client geared primarily toward embedded systems, 65 udhcpc is a DHCP client geared primarily toward embedded systems,
68 while striving to be fully functional and RFC compliant. 66 while striving to be fully functional and RFC compliant.
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index 50dfead63..e13eb3f9f 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -115,6 +115,13 @@ enum {
115 115
116 116
117/*** Script execution code ***/ 117/*** Script execution code ***/
118struct dhcp_optitem {
119 unsigned len;
120 uint8_t code;
121 uint8_t malloced;
122 uint8_t *data;
123 char *env;
124};
118 125
119/* get a rough idea of how long an option will be (rounding up...) */ 126/* get a rough idea of how long an option will be (rounding up...) */
120static const uint8_t len_of_option_as_string[] ALIGN1 = { 127static const uint8_t len_of_option_as_string[] ALIGN1 = {
@@ -186,15 +193,15 @@ static int good_hostname(const char *name)
186#endif 193#endif
187 194
188/* Create "opt_name=opt_value" string */ 195/* Create "opt_name=opt_value" string */
189static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_optflag *optflag, const char *opt_name) 196static NOINLINE char *xmalloc_optname_optval(const struct dhcp_optitem *opt_item, const struct dhcp_optflag *optflag, const char *opt_name)
190{ 197{
191 unsigned upper_length; 198 unsigned upper_length;
192 int len, type, optlen; 199 int len, type, optlen;
193 char *dest, *ret; 200 char *dest, *ret;
201 uint8_t *option;
194 202
195 /* option points to OPT_DATA, need to go back to get OPT_LEN */ 203 option = opt_item->data;
196 len = option[-OPT_DATA + OPT_LEN]; 204 len = opt_item->len;
197
198 type = optflag->flags & OPTION_TYPE_MASK; 205 type = optflag->flags & OPTION_TYPE_MASK;
199 optlen = dhcp_option_lengths[type]; 206 optlen = dhcp_option_lengths[type];
200 upper_length = len_of_option_as_string[type] 207 upper_length = len_of_option_as_string[type]
@@ -386,11 +393,70 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_
386 return ret; 393 return ret;
387} 394}
388 395
389static void putenvp(llist_t **envp, char *new_opt) 396static void optitem_unset_env_and_free(void *item)
390{ 397{
391 putenv(new_opt); 398 struct dhcp_optitem *opt_item = item;
399 bb_unsetenv_and_free(opt_item->env);
400 if (opt_item->malloced)
401 free(opt_item->data);
402 free(opt_item);
403}
404
405/* Used by static options (interface, siaddr, etc) */
406static void putenvp(char *new_opt)
407{
408 struct dhcp_optitem *opt_item;
409
410 opt_item = xzalloc(sizeof(*opt_item));
411 /* opt_item->code = 0, so it won't appear in concat_option's lookup */
412 /* opt_item->malloced = 0 */
413 /* opt_item->data = NULL */
414 opt_item->env = new_opt;
415 llist_add_to(&client_data.envp, opt_item);
392 log2(" %s", new_opt); 416 log2(" %s", new_opt);
393 llist_add_to(envp, new_opt); 417 putenv(new_opt);
418}
419
420/* Support RFC3396 Long Encoded Options */
421static struct dhcp_optitem *concat_option(uint8_t *data, uint8_t len, uint8_t code)
422{
423 llist_t *item;
424 struct dhcp_optitem *opt_item;
425
426 /* Check if an option with the code already exists.
427 * A possible optimization is to create a bitmap of all existing options in the packet,
428 * and iterate over the option list only if they exist.
429 * This will result in bigger code, and because dhcp packets don't have too many options it
430 * shouldn't have a big impact on performance.
431 */
432 for (item = client_data.envp; item != NULL; item = item->link) {
433 opt_item = (struct dhcp_optitem *)item->data;
434 if (opt_item->code == code) {
435 /* This option was seen already, concatenate */
436 uint8_t *new_data;
437
438 new_data = xmalloc(len + opt_item->len);
439 memcpy(
440 mempcpy(new_data, opt_item->data, opt_item->len),
441 data, len
442 );
443 opt_item->len += len;
444 if (opt_item->malloced)
445 free(opt_item->data);
446 opt_item->malloced = 1;
447 opt_item->data = new_data;
448 return opt_item;
449 }
450 }
451
452 /* This is a new option, add a new dhcp_optitem to the list */
453 opt_item = xzalloc(sizeof(*opt_item));
454 opt_item->code = code;
455 /* opt_item->malloced = 0 */
456 opt_item->data = data;
457 opt_item->len = len;
458 llist_add_to(&client_data.envp, opt_item);
459 return opt_item;
394} 460}
395 461
396static const char* get_optname(uint8_t code, const struct dhcp_optflag **dh) 462static const char* get_optname(uint8_t code, const struct dhcp_optflag **dh)
@@ -403,7 +469,7 @@ static const char* get_optname(uint8_t code, const struct dhcp_optflag **dh)
403 * and they'll count as unknown options. 469 * and they'll count as unknown options.
404 */ 470 */
405 for (*dh = dhcp_optflags; (*dh)->code && (*dh)->code < code; (*dh)++) 471 for (*dh = dhcp_optflags; (*dh)->code && (*dh)->code < code; (*dh)++)
406 continue; 472 continue;
407 473
408 if ((*dh)->code == code) 474 if ((*dh)->code == code)
409 return nth_string(dhcp_option_strings, (*dh - dhcp_optflags)); 475 return nth_string(dhcp_option_strings, (*dh - dhcp_optflags));
@@ -412,50 +478,54 @@ static const char* get_optname(uint8_t code, const struct dhcp_optflag **dh)
412} 478}
413 479
414/* put all the parameters into the environment */ 480/* put all the parameters into the environment */
415static llist_t *fill_envp(struct dhcp_packet *packet) 481static void fill_envp(struct dhcp_packet *packet)
416{ 482{
417 uint8_t *optptr; 483 uint8_t *optptr;
418 struct dhcp_scan_state scan_state; 484 struct dhcp_scan_state scan_state;
419 char *new_opt; 485 char *new_opt;
420 llist_t *envp = NULL;
421 486
422 putenvp(&envp, xasprintf("interface=%s", client_data.interface)); 487 putenvp(xasprintf("interface=%s", client_data.interface));
423 488
424 if (!packet) 489 if (!packet)
425 return envp; 490 return;
426 491
427 init_scan_state(packet, &scan_state); 492 init_scan_state(packet, &scan_state);
428 493
429 /* Iterate over the packet options. 494 /* Iterate over the packet options.
430 * Handle each option based on whether it's an unknown / known option. 495 * Handle each option based on whether it's an unknown / known option.
431 * There may be (although unlikely) duplicate options. For now, only the last 496 * Long options are supported in compliance with RFC 3396.
432 * appearing option will be stored in the environment, and all duplicates
433 * are freed properly.
434 * Long options may be implemented in the future (see RFC 3396) if needed.
435 */ 497 */
436 while ((optptr = udhcp_scan_options(packet, &scan_state)) != NULL) { 498 while ((optptr = udhcp_scan_options(packet, &scan_state)) != NULL) {
437 const struct dhcp_optflag *dh; 499 const struct dhcp_optflag *dh;
438 const char *opt_name; 500 const char *opt_name;
501 struct dhcp_optitem *opt_item;
439 uint8_t code = optptr[OPT_CODE]; 502 uint8_t code = optptr[OPT_CODE];
440 uint8_t len = optptr[OPT_LEN]; 503 uint8_t len = optptr[OPT_LEN];
441 uint8_t *data = optptr + OPT_DATA; 504 uint8_t *data = optptr + OPT_DATA;
442 505
506 opt_item = concat_option(data, len, code);
443 opt_name = get_optname(code, &dh); 507 opt_name = get_optname(code, &dh);
444 if (opt_name) { 508 if (opt_name) {
445 new_opt = xmalloc_optname_optval(data, dh, opt_name); 509 new_opt = xmalloc_optname_optval(opt_item, dh, opt_name);
446 if (code == DHCP_SUBNET && len == 4) { 510 if (opt_item->code == DHCP_SUBNET && opt_item->len == 4) {
511 /* Generate extra envvar for DHCP_SUBNET, $mask */
447 uint32_t subnet; 512 uint32_t subnet;
448 putenvp(&envp, new_opt); 513 move_from_unaligned32(subnet, opt_item->data);
449 move_from_unaligned32(subnet, data); 514 putenvp(xasprintf("mask=%u", mton(subnet)));
450 new_opt = xasprintf("mask=%u", mton(subnet));
451 } 515 }
452 } else { 516 } else {
453 unsigned ofs; 517 unsigned ofs;
454 new_opt = xmalloc(sizeof("optNNN=") + 1 + len*2); 518 new_opt = xmalloc(sizeof("optNNN=") + 1 + opt_item->len*2);
455 ofs = sprintf(new_opt, "opt%u=", code); 519 ofs = sprintf(new_opt, "opt%u=", opt_item->code);
456 bin2hex(new_opt + ofs, (char *)data, len)[0] = '\0'; 520 bin2hex(new_opt + ofs, (char *)opt_item->data, opt_item->len)[0] = '\0';
457 } 521 }
458 putenvp(&envp, new_opt); 522 log2(" %s", new_opt);
523 putenv(new_opt);
524 /* putenv will replace the existing environment variable in case of a duplicate.
525 * Free the previous occurrence (NULL if it's the first one).
526 */
527 free(opt_item->env);
528 opt_item->env = new_opt;
459 } 529 }
460 530
461 /* Export BOOTP fields. Fields we don't (yet?) export: 531 /* Export BOOTP fields. Fields we don't (yet?) export:
@@ -473,41 +543,38 @@ static llist_t *fill_envp(struct dhcp_packet *packet)
473 /* Most important one: yiaddr as $ip */ 543 /* Most important one: yiaddr as $ip */
474 new_opt = xmalloc(sizeof("ip=255.255.255.255")); 544 new_opt = xmalloc(sizeof("ip=255.255.255.255"));
475 sprint_nip(new_opt, "ip=", (uint8_t *) &packet->yiaddr); 545 sprint_nip(new_opt, "ip=", (uint8_t *) &packet->yiaddr);
476 putenvp(&envp, new_opt); 546 putenvp(new_opt);
477 547
478 if (packet->siaddr_nip) { 548 if (packet->siaddr_nip) {
479 /* IP address of next server to use in bootstrap */ 549 /* IP address of next server to use in bootstrap */
480 new_opt = xmalloc(sizeof("siaddr=255.255.255.255")); 550 new_opt = xmalloc(sizeof("siaddr=255.255.255.255"));
481 sprint_nip(new_opt, "siaddr=", (uint8_t *) &packet->siaddr_nip); 551 sprint_nip(new_opt, "siaddr=", (uint8_t *) &packet->siaddr_nip);
482 putenvp(&envp, new_opt); 552 putenvp(new_opt);
483 } 553 }
484 if (packet->gateway_nip) { 554 if (packet->gateway_nip) {
485 /* IP address of DHCP relay agent */ 555 /* IP address of DHCP relay agent */
486 new_opt = xmalloc(sizeof("giaddr=255.255.255.255")); 556 new_opt = xmalloc(sizeof("giaddr=255.255.255.255"));
487 sprint_nip(new_opt, "giaddr=", (uint8_t *) &packet->gateway_nip); 557 sprint_nip(new_opt, "giaddr=", (uint8_t *) &packet->gateway_nip);
488 putenvp(&envp, new_opt); 558 putenvp(new_opt);
489 } 559 }
490 if (!(scan_state.overload & FILE_FIELD) && packet->file[0]) { 560 if (!(scan_state.overload & FILE_FIELD) && packet->file[0]) {
491 /* watch out for invalid packets */ 561 /* watch out for invalid packets */
492 new_opt = xasprintf("boot_file=%."DHCP_PKT_FILE_LEN_STR"s", packet->file); 562 new_opt = xasprintf("boot_file=%."DHCP_PKT_FILE_LEN_STR"s", packet->file);
493 putenvp(&envp, new_opt); 563 putenvp(new_opt);
494 } 564 }
495 if (!(scan_state.overload & SNAME_FIELD) && packet->sname[0]) { 565 if (!(scan_state.overload & SNAME_FIELD) && packet->sname[0]) {
496 /* watch out for invalid packets */ 566 /* watch out for invalid packets */
497 new_opt = xasprintf("sname=%."DHCP_PKT_SNAME_LEN_STR"s", packet->sname); 567 new_opt = xasprintf("sname=%."DHCP_PKT_SNAME_LEN_STR"s", packet->sname);
498 putenvp(&envp, new_opt); 568 putenvp(new_opt);
499 } 569 }
500
501 return envp;
502} 570}
503 571
504/* Call a script with a par file and env vars */ 572/* Call a script with a par file and env vars */
505static void udhcp_run_script(struct dhcp_packet *packet, const char *name) 573static void udhcp_run_script(struct dhcp_packet *packet, const char *name)
506{ 574{
507 llist_t *envp;
508 char *argv[3]; 575 char *argv[3];
509 576
510 envp = fill_envp(packet); 577 fill_envp(packet);
511 578
512 /* call script */ 579 /* call script */
513 log1("executing %s %s", client_data.script, name); 580 log1("executing %s %s", client_data.script, name);
@@ -517,7 +584,8 @@ static void udhcp_run_script(struct dhcp_packet *packet, const char *name)
517 spawn_and_wait(argv); 584 spawn_and_wait(argv);
518 585
519 /* Free all allocated environment variables */ 586 /* Free all allocated environment variables */
520 llist_free(envp, (void (*)(void *))bb_unsetenv_and_free); 587 llist_free(client_data.envp, optitem_unset_env_and_free);
588 client_data.envp = NULL;
521} 589}
522 590
523 591
diff --git a/networking/udhcp/dhcpc.h b/networking/udhcp/dhcpc.h
index b407a6cdb..7ad01ea8f 100644
--- a/networking/udhcp/dhcpc.h
+++ b/networking/udhcp/dhcpc.h
@@ -21,6 +21,7 @@ struct client_data_t {
21 uint8_t *vendorclass; /* Optional vendor class-id to use */ 21 uint8_t *vendorclass; /* Optional vendor class-id to use */
22 uint8_t *hostname; /* Optional hostname to use */ 22 uint8_t *hostname; /* Optional hostname to use */
23 uint8_t *fqdn; /* Optional fully qualified domain name to use */ 23 uint8_t *fqdn; /* Optional fully qualified domain name to use */
24 llist_t *envp; /* list of DHCP options used for env vars */
24 25
25 unsigned first_secs; 26 unsigned first_secs;
26 unsigned last_secs; 27 unsigned last_secs;
diff --git a/networking/udhcp/domain_codec.c b/networking/udhcp/domain_codec.c
index 752c0a863..eab4da68b 100644
--- a/networking/udhcp/domain_codec.c
+++ b/networking/udhcp/domain_codec.c
@@ -10,10 +10,14 @@
10# define _GNU_SOURCE 10# define _GNU_SOURCE
11# define FAST_FUNC /* nothing */ 11# define FAST_FUNC /* nothing */
12# define xmalloc malloc 12# define xmalloc malloc
13# define xzalloc(s) calloc(s, 1)
14# define xstrdup strdup
15# define xrealloc realloc
13# include <stdlib.h> 16# include <stdlib.h>
14# include <stdint.h> 17# include <stdint.h>
15# include <string.h> 18# include <string.h>
16# include <stdio.h> 19# include <stdio.h>
20# include <ctype.h>
17#else 21#else
18# include "common.h" 22# include "common.h"
19#endif 23#endif
@@ -26,86 +30,77 @@
26 30
27 31
28/* Expand a RFC1035-compressed list of domain names "cstr", of length "clen"; 32/* Expand a RFC1035-compressed list of domain names "cstr", of length "clen";
29 * returns a newly allocated string containing the space-separated domains, 33 * return a newly allocated string containing the space-separated domains,
30 * prefixed with the contents of string pre, or NULL if an error occurs. 34 * prefixed with the contents of string pre, or NULL if an error occurs.
31 */ 35 */
32char* FAST_FUNC dname_dec(const uint8_t *cstr, int clen, const char *pre) 36char* FAST_FUNC dname_dec(const uint8_t *cstr, int clen, const char *pre)
33{ 37{
34 char *ret = ret; /* for compiler */ 38 char *ret, *end;
35 char *dst = NULL; 39 unsigned len, crtpos, retpos, depth;
36 40
37 /* We make two passes over the cstr string. First, we compute 41 crtpos = retpos = depth = 0;
38 * how long the resulting string would be. Then we allocate a 42 len = strlen(pre);
39 * new buffer of the required length, and fill it in with the 43 end = ret = xstrdup(pre);
40 * expanded content. The advantage of this approach is not 44
41 * having to deal with requiring callers to supply their own 45 /* Scan the string once, allocating new memory as needed */
42 * buffer, then having to check if it's sufficiently large, etc. 46 while (crtpos < clen) {
43 */
44 while (1) {
45 /* note: "return NULL" below are leak-safe since
46 * dst isn't allocated yet */
47 const uint8_t *c; 47 const uint8_t *c;
48 unsigned crtpos, retpos, depth, len; 48 c = cstr + crtpos;
49 49
50 crtpos = retpos = depth = len = 0; 50 if ((*c & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
51 while (crtpos < clen) { 51 /* pointer */
52 c = cstr + crtpos; 52 if (crtpos + 2 > clen) /* no offset to jump to? abort */
53 goto error;
54 if (retpos == 0) /* toplevel? save return spot */
55 retpos = crtpos + 2;
56 depth++;
57 crtpos = ((c[0] << 8) | c[1]) & 0x3fff; /* jump */
58 } else if (*c) {
59 unsigned label_len;
60 /* label */
61 if (crtpos + *c + 1 > clen) /* label too long? abort */
62 goto error;
63 ret = xrealloc(ret, len + *c + 1);
64 /* \3com ---> "com." */
65 end = (char *)mempcpy(ret + len, c + 1, *c);
66 *end = '.';
53 67
54 if ((*c & NS_CMPRSFLGS) == NS_CMPRSFLGS) { 68 label_len = *c + 1;
55 /* pointer */ 69 len += label_len;
56 if (crtpos + 2 > clen) /* no offset to jump to? abort */ 70 crtpos += label_len;
57 return NULL; 71 } else {
58 if (retpos == 0) /* toplevel? save return spot */ 72 /* NUL: end of current domain name */
59 retpos = crtpos + 2; 73 if (retpos == 0) {
60 depth++; 74 /* toplevel? keep going */
61 crtpos = ((c[0] & 0x3f) << 8) | c[1]; /* jump */ 75 crtpos++;
62 } else if (*c) {
63 /* label */
64 if (crtpos + *c + 1 > clen) /* label too long? abort */
65 return NULL;
66 if (dst)
67 /* \3com ---> "com." */
68 ((char*)mempcpy(dst + len, c + 1, *c))[0] = '.';
69 len += *c + 1;
70 crtpos += *c + 1;
71 } else { 76 } else {
72 /* NUL: end of current domain name */ 77 /* return to toplevel saved spot */
73 if (retpos == 0) { 78 crtpos = retpos;
74 /* toplevel? keep going */ 79 retpos = depth = 0;
75 crtpos++;
76 } else {
77 /* return to toplevel saved spot */
78 crtpos = retpos;
79 retpos = depth = 0;
80 }
81 if (dst && len != 0)
82 /* \4host\3com\0\4host and we are at \0:
83 * \3com was converted to "com.", change dot to space.
84 */
85 dst[len - 1] = ' ';
86 } 80 }
87 81
88 if (depth > NS_MAXDNSRCH /* too many jumps? abort, it's a loop */ 82 if (len != 0) {
89 || len > NS_MAXDNAME * NS_MAXDNSRCH /* result too long? abort */ 83 /* \4host\3com\0\4host and we are at \0:
90 ) { 84 * \3com was converted to "com.", change dot to space.
91 return NULL; 85 */
86 ret[len - 1] = ' ';
92 } 87 }
93 } 88 }
94 89
95 if (!len) /* expanded string has 0 length? abort */ 90 if (depth > NS_MAXDNSRCH /* too many jumps? abort, it's a loop */
96 return NULL; 91 || len > NS_MAXDNAME * NS_MAXDNSRCH /* result too long? abort */
97 92 ) {
98 if (!dst) { /* first pass? */ 93 goto error;
99 /* allocate dst buffer and copy pre */
100 unsigned plen = strlen(pre);
101 ret = xmalloc(plen + len);
102 dst = stpcpy(ret, pre);
103 } else {
104 dst[len - 1] = '\0';
105 break;
106 } 94 }
107 } 95 }
108 96
97 if (ret == end) { /* expanded string is empty? abort */
98 error:
99 free(ret);
100 return NULL;
101 }
102
103 *end = '\0';
109 return ret; 104 return ret;
110} 105}
111 106
@@ -115,42 +110,40 @@ char* FAST_FUNC dname_dec(const uint8_t *cstr, int clen, const char *pre)
115 */ 110 */
116static uint8_t *convert_dname(const char *src, int *retlen) 111static uint8_t *convert_dname(const char *src, int *retlen)
117{ 112{
118 uint8_t c, *res, *lenptr, *dst; 113 uint8_t *res, *lenptr, *dst;
119 int len;
120 114
121 res = xmalloc(strlen(src) + 2); 115 res = xzalloc(strlen(src) + 2);
122 dst = lenptr = res; 116 dst = lenptr = res;
123 dst++; 117 dst++;
124 118
125 for (;;) { 119 for (;;) {
120 uint8_t c;
121 int len;
122
126 c = (uint8_t)*src++; 123 c = (uint8_t)*src++;
127 if (c == '.' || c == '\0') { /* end of label */ 124 if (c == '.' || c == '\0') { /* end of label */
128 len = dst - lenptr - 1; 125 len = dst - lenptr - 1;
129 /* label too long, too short, or two '.'s in a row? abort */ 126 /* label too long, too short, or two '.'s in a row (len will be 0) */
130 if (len > NS_MAXLABEL || len == 0 || (c == '.' && *src == '.')) { 127 if (len > NS_MAXLABEL || len == 0)
131 free(res); 128 goto error;
132 *retlen = 0; 129
133 return NULL;
134 }
135 *lenptr = len; 130 *lenptr = len;
136 if (c == '\0' || *src == '\0') /* "" or ".": end of src */ 131 if (c == '\0' || *src == '\0') /* "" or ".": end of src */
137 break; 132 break;
138 lenptr = dst++; 133 lenptr = dst++;
139 continue; 134 continue;
140 } 135 }
141 if (c >= 'A' && c <= 'Z') /* uppercase? convert to lower */ 136 *dst++ = tolower(c);
142 c += ('a' - 'A');
143 *dst++ = c;
144 } 137 }
145 138
146 if (dst - res >= NS_MAXCDNAME) { /* dname too long? abort */ 139 *retlen = dst + 1 - res;
140 if (*retlen > NS_MAXCDNAME) { /* dname too long? abort */
141 error:
147 free(res); 142 free(res);
148 *retlen = 0; 143 *retlen = 0;
149 return NULL; 144 return NULL;
150 } 145 }
151 146
152 *dst++ = 0;
153 *retlen = dst - res;
154 return res; 147 return res;
155} 148}
156 149
@@ -245,6 +238,7 @@ int main(int argc, char **argv)
245 printf("test4:'%s'\n", DNAME_DEC("\4host\3com\0\xC0\5", "")); 238 printf("test4:'%s'\n", DNAME_DEC("\4host\3com\0\xC0\5", ""));
246 printf("test5:'%s'\n", DNAME_DEC("\4host\3com\0\xC0\5\1z\xC0\xA", "")); 239 printf("test5:'%s'\n", DNAME_DEC("\4host\3com\0\xC0\5\1z\xC0\xA", ""));
247 240
241#if 0
248#define DNAME_ENC(cache,source,lenp) dname_enc((uint8_t*)(cache), sizeof(cache), (source), (lenp)) 242#define DNAME_ENC(cache,source,lenp) dname_enc((uint8_t*)(cache), sizeof(cache), (source), (lenp))
249 encoded = dname_enc(NULL, 0, "test.net", &len); 243 encoded = dname_enc(NULL, 0, "test.net", &len);
250 printf("test6:'%s' len:%d\n", dname_dec(encoded, len, ""), len); 244 printf("test6:'%s' len:%d\n", dname_dec(encoded, len, ""), len);
@@ -252,6 +246,13 @@ int main(int argc, char **argv)
252 printf("test7:'%s' len:%d\n", dname_dec(encoded, len, ""), len); 246 printf("test7:'%s' len:%d\n", dname_dec(encoded, len, ""), len);
253 encoded = DNAME_ENC("\4test\3net\0", "test.net", &len); 247 encoded = DNAME_ENC("\4test\3net\0", "test.net", &len);
254 printf("test8:'%s' len:%d\n", dname_dec(encoded, len, ""), len); 248 printf("test8:'%s' len:%d\n", dname_dec(encoded, len, ""), len);
249#endif
250
251 encoded = dname_enc("test.net", &len);
252 printf("test6:'%s' len:%d\n", dname_dec(encoded, len, ""), len);
253 encoded = dname_enc("test.host.com", &len);
254 printf("test7:'%s' len:%d\n", dname_dec(encoded, len, ""), len);
255
255 return 0; 256 return 0;
256} 257}
257#endif 258#endif
diff --git a/networking/vconfig.c b/networking/vconfig.c
index 3cc5f2460..4f1fbe280 100644
--- a/networking/vconfig.c
+++ b/networking/vconfig.c
@@ -9,7 +9,6 @@
9//config:config VCONFIG 9//config:config VCONFIG
10//config: bool "vconfig (2.3 kb)" 10//config: bool "vconfig (2.3 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX
13//config: help 12//config: help
14//config: Creates, removes, and configures VLAN interfaces 13//config: Creates, removes, and configures VLAN interfaces
15 14
diff --git a/networking/zcip.c b/networking/zcip.c
index 134dfb2df..311dfbe4c 100644
--- a/networking/zcip.c
+++ b/networking/zcip.c
@@ -16,7 +16,6 @@
16//config:config ZCIP 16//config:config ZCIP
17//config: bool "zcip (8.4 kb)" 17//config: bool "zcip (8.4 kb)"
18//config: default y 18//config: default y
19//config: select PLATFORM_LINUX
20//config: select FEATURE_SYSLOG 19//config: select FEATURE_SYSLOG
21//config: help 20//config: help
22//config: ZCIP provides ZeroConf IPv4 address selection, according to RFC 3927. 21//config: ZCIP provides ZeroConf IPv4 address selection, according to RFC 3927.
diff --git a/procps/free.c b/procps/free.c
index 1e5d36742..b33506b9e 100644
--- a/procps/free.c
+++ b/procps/free.c
@@ -9,7 +9,6 @@
9//config:config FREE 9//config:config FREE
10//config: bool "free (3.1 kb)" 10//config: bool "free (3.1 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX #sysinfo()
13//config: help 12//config: help
14//config: free displays the total amount of free and used physical and swap 13//config: free displays the total amount of free and used physical and swap
15//config: memory in the system, as well as the buffers used by the kernel. 14//config: memory in the system, as well as the buffers used by the kernel.
diff --git a/procps/ps.c b/procps/ps.c
index 22905ddff..a4de11379 100644
--- a/procps/ps.c
+++ b/procps/ps.c
@@ -33,7 +33,6 @@
33//config: 33//config:
34//config:config FEATURE_PS_TIME 34//config:config FEATURE_PS_TIME
35//config: bool "Enable -o time and -o etime specifiers" 35//config: bool "Enable -o time and -o etime specifiers"
36//config: select PLATFORM_LINUX # statfs()
37//config: default y 36//config: default y
38//config: depends on (PS || MINIPS) && DESKTOP 37//config: depends on (PS || MINIPS) && DESKTOP
39//config: 38//config:
diff --git a/procps/uptime.c b/procps/uptime.c
index 31581271f..4fd0c9d2d 100644
--- a/procps/uptime.c
+++ b/procps/uptime.c
@@ -14,7 +14,6 @@
14//config:config UPTIME 14//config:config UPTIME
15//config: bool "uptime (3.7 kb)" 15//config: bool "uptime (3.7 kb)"
16//config: default y 16//config: default y
17//config: select PLATFORM_LINUX #sysinfo()
18//config: help 17//config: help
19//config: uptime gives a one line display of the current time, how long 18//config: uptime gives a one line display of the current time, how long
20//config: the system has been running, how many users are currently logged 19//config: the system has been running, how many users are currently logged
diff --git a/shell/ash_test/ash-read/read_d0.right b/shell/ash_test/ash-read/read_d0.right
new file mode 100644
index 000000000..9daeafb98
--- /dev/null
+++ b/shell/ash_test/ash-read/read_d0.right
@@ -0,0 +1 @@
test
diff --git a/shell/ash_test/ash-read/read_d0.tests b/shell/ash_test/ash-read/read_d0.tests
new file mode 100755
index 000000000..630d80787
--- /dev/null
+++ b/shell/ash_test/ash-read/read_d0.tests
@@ -0,0 +1 @@
printf 'test\0zest\n' | (read -d '' reply; echo "$reply")
diff --git a/shell/hush_test/hush-read/read_d0.right b/shell/hush_test/hush-read/read_d0.right
new file mode 100644
index 000000000..9daeafb98
--- /dev/null
+++ b/shell/hush_test/hush-read/read_d0.right
@@ -0,0 +1 @@
test
diff --git a/shell/hush_test/hush-read/read_d0.tests b/shell/hush_test/hush-read/read_d0.tests
new file mode 100755
index 000000000..630d80787
--- /dev/null
+++ b/shell/hush_test/hush-read/read_d0.tests
@@ -0,0 +1 @@
printf 'test\0zest\n' | (read -d '' reply; echo "$reply")
diff --git a/shell/shell_common.c b/shell/shell_common.c
index e50a79b78..a6ee60851 100644
--- a/shell/shell_common.c
+++ b/shell/shell_common.c
@@ -271,8 +271,10 @@ shell_builtin_read(struct builtin_read_params *params)
271#endif 271#endif
272 272
273 c = buffer[bufpos]; 273 c = buffer[bufpos];
274 if (c == '\0' || (ENABLE_PLATFORM_MINGW32 && c == '\r')) 274#if ENABLE_PLATFORM_MINGW32
275 if (c == '\r')
275 continue; 276 continue;
277#endif
276 if (!(read_flags & BUILTIN_READ_RAW)) { 278 if (!(read_flags & BUILTIN_READ_RAW)) {
277 if (backslash) { 279 if (backslash) {
278 backslash = 0; 280 backslash = 0;
@@ -287,6 +289,8 @@ shell_builtin_read(struct builtin_read_params *params)
287 } 289 }
288 if (c == delim) /* '\n' or -d CHAR */ 290 if (c == delim) /* '\n' or -d CHAR */
289 break; 291 break;
292 if (c == '\0')
293 continue;
290 294
291 /* $IFS splitting. NOT done if we run "read" 295 /* $IFS splitting. NOT done if we run "read"
292 * without variable names (bash compat). 296 * without variable names (bash compat).
diff --git a/sysklogd/klogd.c b/sysklogd/klogd.c
index bdd0b6325..c0ec1c0bf 100644
--- a/sysklogd/klogd.c
+++ b/sysklogd/klogd.c
@@ -33,7 +33,6 @@
33//config: bool "Use the klogctl() interface" 33//config: bool "Use the klogctl() interface"
34//config: default y 34//config: default y
35//config: depends on KLOGD 35//config: depends on KLOGD
36//config: select PLATFORM_LINUX
37//config: help 36//config: help
38//config: The klogd applet supports two interfaces for reading 37//config: The klogd applet supports two interfaces for reading
39//config: kernel messages. Linux provides the klogctl() interface 38//config: kernel messages. Linux provides the klogctl() interface
diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c
index ab50f4a28..f61da9de5 100644
--- a/sysklogd/syslogd.c
+++ b/sysklogd/syslogd.c
@@ -109,7 +109,6 @@
109//config: bool "Linux kernel printk buffer support" 109//config: bool "Linux kernel printk buffer support"
110//config: default y 110//config: default y
111//config: depends on SYSLOGD 111//config: depends on SYSLOGD
112//config: select PLATFORM_LINUX
113//config: help 112//config: help
114//config: When you enable this feature, the syslogd utility will 113//config: When you enable this feature, the syslogd utility will
115//config: write system log message to the Linux kernel's printk buffer. 114//config: write system log message to the Linux kernel's printk buffer.
diff --git a/testsuite/grep.tests b/testsuite/grep.tests
index e38278810..66498a989 100755
--- a/testsuite/grep.tests
+++ b/testsuite/grep.tests
@@ -96,6 +96,14 @@ testing "grep -x -F (partial match 1)" "grep -x -F foo input ; echo \$?" \
96testing "grep -x -F (partial match 2)" "grep -x -F foo input ; echo \$?" \ 96testing "grep -x -F (partial match 2)" "grep -x -F foo input ; echo \$?" \
97 "1\n" "bar foo\n" "" 97 "1\n" "bar foo\n" ""
98 98
99# -L "show filenames which do not match" has inverted exitcode (if it printed something, it's "success")
100testing "grep -L exitcode 0" "grep -L qwe input; echo \$?" \
101 "input\n0\n" "asd\n" ""
102testing "grep -L exitcode 0 #2" "grep -L qwe input -; echo \$?" \
103 "(standard input)\n0\n" "qwe\n" "asd\n"
104testing "grep -L exitcode 1" "grep -L qwe input; echo \$?" \
105 "1\n" "qwe\n" ""
106
99optional EGREP 107optional EGREP
100testing "grep -E supports extended regexps" "grep -E fo+" "foo\n" "" \ 108testing "grep -E supports extended regexps" "grep -E fo+" "foo\n" "" \
101 "b\ar\nfoo\nbaz" 109 "b\ar\nfoo\nbaz"
diff --git a/util-linux/acpid.c b/util-linux/acpid.c
index fc8215cce..d473e24fc 100644
--- a/util-linux/acpid.c
+++ b/util-linux/acpid.c
@@ -9,7 +9,6 @@
9//config:config ACPID 9//config:config ACPID
10//config: bool "acpid (9 kb)" 10//config: bool "acpid (9 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX
13//config: help 12//config: help
14//config: acpid listens to ACPI events coming either in textual form from 13//config: acpid listens to ACPI events coming either in textual form from
15//config: /proc/acpi/event (though it is marked deprecated it is still widely 14//config: /proc/acpi/event (though it is marked deprecated it is still widely
diff --git a/util-linux/blkdiscard.c b/util-linux/blkdiscard.c
index a77c7d057..ff2101ed0 100644
--- a/util-linux/blkdiscard.c
+++ b/util-linux/blkdiscard.c
@@ -8,7 +8,6 @@
8//config:config BLKDISCARD 8//config:config BLKDISCARD
9//config: bool "blkdiscard (4.3 kb)" 9//config: bool "blkdiscard (4.3 kb)"
10//config: default y 10//config: default y
11//config: select PLATFORM_LINUX
12//config: help 11//config: help
13//config: blkdiscard discards sectors on a given device. 12//config: blkdiscard discards sectors on a given device.
14 13
diff --git a/util-linux/blkid.c b/util-linux/blkid.c
index 008ae5d9e..4a820771f 100644
--- a/util-linux/blkid.c
+++ b/util-linux/blkid.c
@@ -9,7 +9,6 @@
9//config:config BLKID 9//config:config BLKID
10//config: bool "blkid (12 kb)" 10//config: bool "blkid (12 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX
13//config: select VOLUMEID 12//config: select VOLUMEID
14//config: help 13//config: help
15//config: Lists labels and UUIDs of all filesystems. 14//config: Lists labels and UUIDs of all filesystems.
diff --git a/util-linux/dmesg.c b/util-linux/dmesg.c
index a1f269142..dc4e57169 100644
--- a/util-linux/dmesg.c
+++ b/util-linux/dmesg.c
@@ -11,7 +11,6 @@
11//config:config DMESG 11//config:config DMESG
12//config: bool "dmesg (3.7 kb)" 12//config: bool "dmesg (3.7 kb)"
13//config: default y 13//config: default y
14//config: select PLATFORM_LINUX
15//config: help 14//config: help
16//config: dmesg is used to examine or control the kernel ring buffer. When the 15//config: dmesg is used to examine or control the kernel ring buffer. When the
17//config: Linux kernel prints messages to the system log, they are stored in 16//config: Linux kernel prints messages to the system log, they are stored in
diff --git a/util-linux/eject.c b/util-linux/eject.c
index 3ccb4ae89..29b0a86bd 100644
--- a/util-linux/eject.c
+++ b/util-linux/eject.c
@@ -15,7 +15,6 @@
15//config:config EJECT 15//config:config EJECT
16//config: bool "eject (4 kb)" 16//config: bool "eject (4 kb)"
17//config: default y 17//config: default y
18//config: select PLATFORM_LINUX
19//config: help 18//config: help
20//config: Used to eject cdroms. (defaults to /dev/cdrom) 19//config: Used to eject cdroms. (defaults to /dev/cdrom)
21//config: 20//config:
diff --git a/util-linux/fatattr.c b/util-linux/fatattr.c
index 770b1d2f9..afd70c45d 100644
--- a/util-linux/fatattr.c
+++ b/util-linux/fatattr.c
@@ -11,7 +11,6 @@
11//config:config FATATTR 11//config:config FATATTR
12//config: bool "fatattr (1.9 kb)" 12//config: bool "fatattr (1.9 kb)"
13//config: default y 13//config: default y
14//config: select PLATFORM_LINUX
15//config: help 14//config: help
16//config: fatattr lists or changes the file attributes on a fat file system. 15//config: fatattr lists or changes the file attributes on a fat file system.
17 16
diff --git a/util-linux/fbset.c b/util-linux/fbset.c
index 699a19372..0b9a9a6bc 100644
--- a/util-linux/fbset.c
+++ b/util-linux/fbset.c
@@ -14,7 +14,6 @@
14//config:config FBSET 14//config:config FBSET
15//config: bool "fbset (5.9 kb)" 15//config: bool "fbset (5.9 kb)"
16//config: default y 16//config: default y
17//config: select PLATFORM_LINUX
18//config: help 17//config: help
19//config: fbset is used to show or change the settings of a Linux frame buffer 18//config: fbset is used to show or change the settings of a Linux frame buffer
20//config: device. The frame buffer device provides a simple and unique 19//config: device. The frame buffer device provides a simple and unique
diff --git a/util-linux/fdformat.c b/util-linux/fdformat.c
index e1c8561d6..f0466fdbd 100644
--- a/util-linux/fdformat.c
+++ b/util-linux/fdformat.c
@@ -8,7 +8,6 @@
8//config:config FDFORMAT 8//config:config FDFORMAT
9//config: bool "fdformat (4.4 kb)" 9//config: bool "fdformat (4.4 kb)"
10//config: default y 10//config: default y
11//config: select PLATFORM_LINUX
12//config: help 11//config: help
13//config: fdformat is used to low-level format a floppy disk. 12//config: fdformat is used to low-level format a floppy disk.
14 13
diff --git a/util-linux/fdisk.c b/util-linux/fdisk.c
index f568fe92c..0fb2e3e17 100644
--- a/util-linux/fdisk.c
+++ b/util-linux/fdisk.c
@@ -10,7 +10,6 @@
10//config:config FDISK 10//config:config FDISK
11//config: bool "fdisk (37 kb)" 11//config: bool "fdisk (37 kb)"
12//config: default y 12//config: default y
13//config: select PLATFORM_LINUX
14//config: help 13//config: help
15//config: The fdisk utility is used to divide hard disks into one or more 14//config: The fdisk utility is used to divide hard disks into one or more
16//config: logical disks, which are generally called partitions. This utility 15//config: logical disks, which are generally called partitions. This utility
diff --git a/util-linux/findfs.c b/util-linux/findfs.c
index 7ca9dc96b..f5621a1fa 100644
--- a/util-linux/findfs.c
+++ b/util-linux/findfs.c
@@ -10,7 +10,6 @@
10//config:config FINDFS 10//config:config FINDFS
11//config: bool "findfs (12 kb)" 11//config: bool "findfs (12 kb)"
12//config: default y 12//config: default y
13//config: select PLATFORM_LINUX
14//config: select VOLUMEID 13//config: select VOLUMEID
15//config: help 14//config: help
16//config: Prints the name of a filesystem with given label or UUID. 15//config: Prints the name of a filesystem with given label or UUID.
diff --git a/util-linux/freeramdisk.c b/util-linux/freeramdisk.c
index d27113d97..309169d25 100644
--- a/util-linux/freeramdisk.c
+++ b/util-linux/freeramdisk.c
@@ -11,7 +11,6 @@
11//config:config FDFLUSH 11//config:config FDFLUSH
12//config: bool "fdflush (1.3 kb)" 12//config: bool "fdflush (1.3 kb)"
13//config: default y 13//config: default y
14//config: select PLATFORM_LINUX
15//config: help 14//config: help
16//config: fdflush is only needed when changing media on slightly-broken 15//config: fdflush is only needed when changing media on slightly-broken
17//config: removable media drives. It is used to make Linux believe that a 16//config: removable media drives. It is used to make Linux believe that a
@@ -24,7 +23,6 @@
24//config:config FREERAMDISK 23//config:config FREERAMDISK
25//config: bool "freeramdisk (1.3 kb)" 24//config: bool "freeramdisk (1.3 kb)"
26//config: default y 25//config: default y
27//config: select PLATFORM_LINUX
28//config: help 26//config: help
29//config: Linux allows you to create ramdisks. This utility allows you to 27//config: Linux allows you to create ramdisks. This utility allows you to
30//config: delete them and completely free all memory that was used for the 28//config: delete them and completely free all memory that was used for the
diff --git a/util-linux/fsfreeze.c b/util-linux/fsfreeze.c
index fb0b3c4bd..6e2ff0a54 100644
--- a/util-linux/fsfreeze.c
+++ b/util-linux/fsfreeze.c
@@ -7,7 +7,6 @@
7//config:config FSFREEZE 7//config:config FSFREEZE
8//config: bool "fsfreeze (3.5 kb)" 8//config: bool "fsfreeze (3.5 kb)"
9//config: default y 9//config: default y
10//config: select PLATFORM_LINUX
11//config: select LONG_OPTS 10//config: select LONG_OPTS
12//config: help 11//config: help
13//config: Halt new accesses and flush writes on a mounted filesystem. 12//config: Halt new accesses and flush writes on a mounted filesystem.
diff --git a/util-linux/fstrim.c b/util-linux/fstrim.c
index 48948e839..8d29a6d54 100644
--- a/util-linux/fstrim.c
+++ b/util-linux/fstrim.c
@@ -10,7 +10,6 @@
10//config:config FSTRIM 10//config:config FSTRIM
11//config: bool "fstrim (4.4 kb)" 11//config: bool "fstrim (4.4 kb)"
12//config: default y 12//config: default y
13//config: select PLATFORM_LINUX
14//config: help 13//config: help
15//config: Discard unused blocks on a mounted filesystem. 14//config: Discard unused blocks on a mounted filesystem.
16 15
diff --git a/util-linux/hwclock.c b/util-linux/hwclock.c
index dc97d8fb4..e85bca2b2 100644
--- a/util-linux/hwclock.c
+++ b/util-linux/hwclock.c
@@ -9,7 +9,6 @@
9//config:config HWCLOCK 9//config:config HWCLOCK
10//config: bool "hwclock (5.8 kb)" 10//config: bool "hwclock (5.8 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX
13//config: help 12//config: help
14//config: The hwclock utility is used to read and set the hardware clock 13//config: The hwclock utility is used to read and set the hardware clock
15//config: on a system. This is primarily used to set the current time on 14//config: on a system. This is primarily used to set the current time on
@@ -122,16 +121,20 @@ static void to_sys_clock(const char **pp_rtcname, int utc)
122 struct timeval tv; 121 struct timeval tv;
123 struct timezone tz; 122 struct timezone tz;
124 123
125 tz.tz_minuteswest = timezone/60; 124 tz.tz_minuteswest = timezone / 60;
126 /* ^^^ used to also subtract 60*daylight, but it's wrong: 125 /* ^^^ used to also subtract 60*daylight, but it's wrong:
127 * daylight!=0 means "this timezone has some DST 126 * daylight!=0 means "this timezone has some DST
128 * during the year", not "DST is in effect now". 127 * during the year", not "DST is in effect now".
129 */ 128 */
130 tz.tz_dsttime = 0; 129 tz.tz_dsttime = 0;
131 130
131 /* glibc v2.31+ returns an error if both args are non-NULL */
132 if (settimeofday(NULL, &tz))
133 bb_simple_perror_msg_and_die("settimeofday");
134
132 tv.tv_sec = read_rtc(pp_rtcname, NULL, utc); 135 tv.tv_sec = read_rtc(pp_rtcname, NULL, utc);
133 tv.tv_usec = 0; 136 tv.tv_usec = 0;
134 if (settimeofday(&tv, &tz)) 137 if (settimeofday(&tv, NULL))
135 bb_simple_perror_msg_and_die("settimeofday"); 138 bb_simple_perror_msg_and_die("settimeofday");
136} 139}
137 140
@@ -283,7 +286,11 @@ static void set_system_clock_timezone(int utc)
283 gettimeofday(&tv, NULL); 286 gettimeofday(&tv, NULL);
284 if (!utc) 287 if (!utc)
285 tv.tv_sec += tz.tz_minuteswest * 60; 288 tv.tv_sec += tz.tz_minuteswest * 60;
286 if (settimeofday(&tv, &tz)) 289
290 /* glibc v2.31+ returns an error if both args are non-NULL */
291 if (settimeofday(NULL, &tz))
292 bb_simple_perror_msg_and_die("settimeofday");
293 if (settimeofday(&tv, NULL))
287 bb_simple_perror_msg_and_die("settimeofday"); 294 bb_simple_perror_msg_and_die("settimeofday");
288} 295}
289 296
diff --git a/util-linux/ionice.c b/util-linux/ionice.c
index daf64d537..40c04d5e0 100644
--- a/util-linux/ionice.c
+++ b/util-linux/ionice.c
@@ -9,7 +9,6 @@
9//config:config IONICE 9//config:config IONICE
10//config: bool "ionice (3.8 kb)" 10//config: bool "ionice (3.8 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX
13//config: help 12//config: help
14//config: Set/set program io scheduling class and priority 13//config: Set/set program io scheduling class and priority
15//config: Requires kernel >= 2.6.13 14//config: Requires kernel >= 2.6.13
diff --git a/util-linux/ipcs.c b/util-linux/ipcs.c
index df86cfb9d..ef2529c05 100644
--- a/util-linux/ipcs.c
+++ b/util-linux/ipcs.c
@@ -10,7 +10,6 @@
10//config:config IPCS 10//config:config IPCS
11//config: bool "ipcs (11 kb)" 11//config: bool "ipcs (11 kb)"
12//config: default y 12//config: default y
13//config: select PLATFORM_LINUX
14//config: help 13//config: help
15//config: The ipcs utility is used to provide information on the currently 14//config: The ipcs utility is used to provide information on the currently
16//config: allocated System V interprocess (IPC) objects in the system. 15//config: allocated System V interprocess (IPC) objects in the system.
diff --git a/util-linux/losetup.c b/util-linux/losetup.c
index cc6c2b1d5..ac8b79502 100644
--- a/util-linux/losetup.c
+++ b/util-linux/losetup.c
@@ -9,7 +9,6 @@
9//config:config LOSETUP 9//config:config LOSETUP
10//config: bool "losetup (5.5 kb)" 10//config: bool "losetup (5.5 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX
13//config: help 12//config: help
14//config: losetup is used to associate or detach a loop device with a regular 13//config: losetup is used to associate or detach a loop device with a regular
15//config: file or block device, and to query the status of a loop device. This 14//config: file or block device, and to query the status of a loop device. This
diff --git a/util-linux/lspci.c b/util-linux/lspci.c
index a6b4e850f..2f0b5fab9 100644
--- a/util-linux/lspci.c
+++ b/util-linux/lspci.c
@@ -9,7 +9,6 @@
9//config:config LSPCI 9//config:config LSPCI
10//config: bool "lspci (6.3 kb)" 10//config: bool "lspci (6.3 kb)"
11//config: default y 11//config: default y
12//config: #select PLATFORM_LINUX
13//config: help 12//config: help
14//config: lspci is a utility for displaying information about PCI buses in the 13//config: lspci is a utility for displaying information about PCI buses in the
15//config: system and devices connected to them. 14//config: system and devices connected to them.
diff --git a/util-linux/lsusb.c b/util-linux/lsusb.c
index e27aa7f31..64a00eee2 100644
--- a/util-linux/lsusb.c
+++ b/util-linux/lsusb.c
@@ -9,7 +9,6 @@
9//config:config LSUSB 9//config:config LSUSB
10//config: bool "lsusb (4.2 kb)" 10//config: bool "lsusb (4.2 kb)"
11//config: default y 11//config: default y
12//config: #select PLATFORM_LINUX
13//config: help 12//config: help
14//config: lsusb is a utility for displaying information about USB buses in the 13//config: lsusb is a utility for displaying information about USB buses in the
15//config: system and devices connected to them. 14//config: system and devices connected to them.
diff --git a/util-linux/mdev.c b/util-linux/mdev.c
index 207a112c1..f42bebc20 100644
--- a/util-linux/mdev.c
+++ b/util-linux/mdev.c
@@ -10,7 +10,6 @@
10//config:config MDEV 10//config:config MDEV
11//config: bool "mdev (17 kb)" 11//config: bool "mdev (17 kb)"
12//config: default y 12//config: default y
13//config: select PLATFORM_LINUX
14//config: help 13//config: help
15//config: mdev is a mini-udev implementation for dynamically creating device 14//config: mdev is a mini-udev implementation for dynamically creating device
16//config: nodes in the /dev directory. 15//config: nodes in the /dev directory.
diff --git a/util-linux/mkfs_ext2.c b/util-linux/mkfs_ext2.c
index d568f4be5..1f525d75b 100644
--- a/util-linux/mkfs_ext2.c
+++ b/util-linux/mkfs_ext2.c
@@ -10,14 +10,12 @@
10//config:config MKE2FS 10//config:config MKE2FS
11//config: bool "mke2fs (10 kb)" 11//config: bool "mke2fs (10 kb)"
12//config: default y 12//config: default y
13//config: select PLATFORM_LINUX
14//config: help 13//config: help
15//config: Utility to create EXT2 filesystems. 14//config: Utility to create EXT2 filesystems.
16//config: 15//config:
17//config:config MKFS_EXT2 16//config:config MKFS_EXT2
18//config: bool "mkfs.ext2 (10 kb)" 17//config: bool "mkfs.ext2 (10 kb)"
19//config: default y 18//config: default y
20//config: select PLATFORM_LINUX
21//config: help 19//config: help
22//config: Alias to "mke2fs". 20//config: Alias to "mke2fs".
23 21
diff --git a/util-linux/mkfs_minix.c b/util-linux/mkfs_minix.c
index 8f791cf66..3c72e5419 100644
--- a/util-linux/mkfs_minix.c
+++ b/util-linux/mkfs_minix.c
@@ -65,7 +65,6 @@
65//config:config MKFS_MINIX 65//config:config MKFS_MINIX
66//config: bool "mkfs.minix (10 kb)" 66//config: bool "mkfs.minix (10 kb)"
67//config: default y 67//config: default y
68//config: select PLATFORM_LINUX
69//config: help 68//config: help
70//config: The minix filesystem is a nice, small, compact, read-write filesystem 69//config: The minix filesystem is a nice, small, compact, read-write filesystem
71//config: with little overhead. If you wish to be able to create minix 70//config: with little overhead. If you wish to be able to create minix
diff --git a/util-linux/mkfs_reiser.c b/util-linux/mkfs_reiser.c
index d2eaf5f94..44a743147 100644
--- a/util-linux/mkfs_reiser.c
+++ b/util-linux/mkfs_reiser.c
@@ -9,7 +9,6 @@
9//config:config MKFS_REISER 9//config:config MKFS_REISER
10//config: bool "mkfs_reiser" 10//config: bool "mkfs_reiser"
11//config: default n 11//config: default n
12//config: select PLATFORM_LINUX
13//config: help 12//config: help
14//config: Utility to create ReiserFS filesystems. 13//config: Utility to create ReiserFS filesystems.
15//config: Note: this applet needs a lot of testing and polishing. 14//config: Note: this applet needs a lot of testing and polishing.
diff --git a/util-linux/mkfs_vfat.c b/util-linux/mkfs_vfat.c
index 16c1fac00..844d965f8 100644
--- a/util-linux/mkfs_vfat.c
+++ b/util-linux/mkfs_vfat.c
@@ -10,14 +10,12 @@
10//config:config MKDOSFS 10//config:config MKDOSFS
11//config: bool "mkdosfs (7.2 kb)" 11//config: bool "mkdosfs (7.2 kb)"
12//config: default y 12//config: default y
13//config: select PLATFORM_LINUX
14//config: help 13//config: help
15//config: Utility to create FAT32 filesystems. 14//config: Utility to create FAT32 filesystems.
16//config: 15//config:
17//config:config MKFS_VFAT 16//config:config MKFS_VFAT
18//config: bool "mkfs.vfat (7.2 kb)" 17//config: bool "mkfs.vfat (7.2 kb)"
19//config: default y 18//config: default y
20//config: select PLATFORM_LINUX
21//config: help 19//config: help
22//config: Alias to "mkdosfs". 20//config: Alias to "mkdosfs".
23 21
diff --git a/util-linux/mount.c b/util-linux/mount.c
index 84c85c057..b92e2c297 100644
--- a/util-linux/mount.c
+++ b/util-linux/mount.c
@@ -20,7 +20,6 @@
20//config:config MOUNT 20//config:config MOUNT
21//config: bool "mount (23 kb)" 21//config: bool "mount (23 kb)"
22//config: default y 22//config: default y
23//config: select PLATFORM_LINUX
24//config: help 23//config: help
25//config: All files and filesystems in Unix are arranged into one big directory 24//config: All files and filesystems in Unix are arranged into one big directory
26//config: tree. The 'mount' utility is used to graft a filesystem onto a 25//config: tree. The 'mount' utility is used to graft a filesystem onto a
diff --git a/util-linux/nsenter.c b/util-linux/nsenter.c
index 304f2d748..c48dcf885 100644
--- a/util-linux/nsenter.c
+++ b/util-linux/nsenter.c
@@ -9,7 +9,6 @@
9//config:config NSENTER 9//config:config NSENTER
10//config: bool "nsenter (6.5 kb)" 10//config: bool "nsenter (6.5 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX
13//config: help 12//config: help
14//config: Run program with namespaces of other processes. 13//config: Run program with namespaces of other processes.
15 14
diff --git a/util-linux/pivot_root.c b/util-linux/pivot_root.c
index 41f29da32..ecc891100 100644
--- a/util-linux/pivot_root.c
+++ b/util-linux/pivot_root.c
@@ -11,7 +11,6 @@
11//config:config PIVOT_ROOT 11//config:config PIVOT_ROOT
12//config: bool "pivot_root (1.1 kb)" 12//config: bool "pivot_root (1.1 kb)"
13//config: default y 13//config: default y
14//config: select PLATFORM_LINUX
15//config: help 14//config: help
16//config: The pivot_root utility swaps the mount points for the root filesystem 15//config: The pivot_root utility swaps the mount points for the root filesystem
17//config: with some other mounted filesystem. This allows you to do all sorts 16//config: with some other mounted filesystem. This allows you to do all sorts
diff --git a/util-linux/readprofile.c b/util-linux/readprofile.c
index c4ea374be..32d9987e7 100644
--- a/util-linux/readprofile.c
+++ b/util-linux/readprofile.c
@@ -34,7 +34,6 @@
34//config:config READPROFILE 34//config:config READPROFILE
35//config: bool "readprofile (7.1 kb)" 35//config: bool "readprofile (7.1 kb)"
36//config: default y 36//config: default y
37//config: #select PLATFORM_LINUX
38//config: help 37//config: help
39//config: This allows you to parse /proc/profile for basic profiling. 38//config: This allows you to parse /proc/profile for basic profiling.
40 39
diff --git a/util-linux/rtcwake.c b/util-linux/rtcwake.c
index cad0f9d64..823e55662 100644
--- a/util-linux/rtcwake.c
+++ b/util-linux/rtcwake.c
@@ -25,7 +25,6 @@
25//config:config RTCWAKE 25//config:config RTCWAKE
26//config: bool "rtcwake (6.8 kb)" 26//config: bool "rtcwake (6.8 kb)"
27//config: default y 27//config: default y
28//config: select PLATFORM_LINUX
29//config: help 28//config: help
30//config: Enter a system sleep state until specified wakeup time. 29//config: Enter a system sleep state until specified wakeup time.
31 30
diff --git a/util-linux/setarch.c b/util-linux/setarch.c
index 57051a683..cf8ef0064 100644
--- a/util-linux/setarch.c
+++ b/util-linux/setarch.c
@@ -9,7 +9,6 @@
9//config:config SETARCH 9//config:config SETARCH
10//config: bool "setarch (3.6 kb)" 10//config: bool "setarch (3.6 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX
13//config: help 12//config: help
14//config: The linux32 utility is used to create a 32bit environment for the 13//config: The linux32 utility is used to create a 32bit environment for the
15//config: specified program (usually a shell). It only makes sense to have 14//config: specified program (usually a shell). It only makes sense to have
@@ -19,14 +18,12 @@
19//config:config LINUX32 18//config:config LINUX32
20//config: bool "linux32 (3.3 kb)" 19//config: bool "linux32 (3.3 kb)"
21//config: default y 20//config: default y
22//config: select PLATFORM_LINUX
23//config: help 21//config: help
24//config: Alias to "setarch linux32". 22//config: Alias to "setarch linux32".
25//config: 23//config:
26//config:config LINUX64 24//config:config LINUX64
27//config: bool "linux64 (3.3 kb)" 25//config: bool "linux64 (3.3 kb)"
28//config: default y 26//config: default y
29//config: select PLATFORM_LINUX
30//config: help 27//config: help
31//config: Alias to "setarch linux64". 28//config: Alias to "setarch linux64".
32 29
diff --git a/util-linux/setpriv.c b/util-linux/setpriv.c
index e5cf96957..37e8821a1 100644
--- a/util-linux/setpriv.c
+++ b/util-linux/setpriv.c
@@ -9,7 +9,6 @@
9//config:config SETPRIV 9//config:config SETPRIV
10//config: bool "setpriv (6.6 kb)" 10//config: bool "setpriv (6.6 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX
13//config: select LONG_OPTS 12//config: select LONG_OPTS
14//config: help 13//config: help
15//config: Run a program with different Linux privilege settings. 14//config: Run a program with different Linux privilege settings.
diff --git a/util-linux/swaponoff.c b/util-linux/swaponoff.c
index 567869cc7..e2ff4b5cc 100644
--- a/util-linux/swaponoff.c
+++ b/util-linux/swaponoff.c
@@ -9,7 +9,6 @@
9//config:config SWAPON 9//config:config SWAPON
10//config: bool "swapon (15 kb)" 10//config: bool "swapon (15 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX
13//config: help 12//config: help
14//config: Once you have created some swap space using 'mkswap', you also need 13//config: Once you have created some swap space using 'mkswap', you also need
15//config: to enable your swap space with the 'swapon' utility. The 'swapoff' 14//config: to enable your swap space with the 'swapon' utility. The 'swapoff'
@@ -36,7 +35,6 @@
36//config:config SWAPOFF 35//config:config SWAPOFF
37//config: bool "swapoff (14 kb)" 36//config: bool "swapoff (14 kb)"
38//config: default y 37//config: default y
39//config: select PLATFORM_LINUX
40//config: 38//config:
41//config:config FEATURE_SWAPONOFF_LABEL 39//config:config FEATURE_SWAPONOFF_LABEL
42//config: bool "Support specifying devices by label or UUID" 40//config: bool "Support specifying devices by label or UUID"
diff --git a/util-linux/switch_root.c b/util-linux/switch_root.c
index a483893ed..c65096c27 100644
--- a/util-linux/switch_root.c
+++ b/util-linux/switch_root.c
@@ -9,7 +9,6 @@
9//config:config SWITCH_ROOT 9//config:config SWITCH_ROOT
10//config: bool "switch_root (5.5 kb)" 10//config: bool "switch_root (5.5 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX
13//config: help 12//config: help
14//config: The switch_root utility is used from initramfs to select a new 13//config: The switch_root utility is used from initramfs to select a new
15//config: root device. Under initramfs, you have to use this instead of 14//config: root device. Under initramfs, you have to use this instead of
diff --git a/util-linux/uevent.c b/util-linux/uevent.c
index 7a1d7d4a7..57d9328ef 100644
--- a/util-linux/uevent.c
+++ b/util-linux/uevent.c
@@ -6,7 +6,6 @@
6//config:config UEVENT 6//config:config UEVENT
7//config: bool "uevent (3.1 kb)" 7//config: bool "uevent (3.1 kb)"
8//config: default y 8//config: default y
9//config: select PLATFORM_LINUX
10//config: help 9//config: help
11//config: uevent is a netlink listener for kernel uevent notifications 10//config: uevent is a netlink listener for kernel uevent notifications
12//config: sent via netlink. It is usually used for dynamic device creation. 11//config: sent via netlink. It is usually used for dynamic device creation.
diff --git a/util-linux/umount.c b/util-linux/umount.c
index 077b635c8..63a3bf504 100644
--- a/util-linux/umount.c
+++ b/util-linux/umount.c
@@ -10,7 +10,6 @@
10//config:config UMOUNT 10//config:config UMOUNT
11//config: bool "umount (5.1 kb)" 11//config: bool "umount (5.1 kb)"
12//config: default y 12//config: default y
13//config: select PLATFORM_LINUX
14//config: help 13//config: help
15//config: When you want to remove a mounted filesystem from its current mount 14//config: When you want to remove a mounted filesystem from its current mount
16//config: point, for example when you are shutting down the system, the 15//config: point, for example when you are shutting down the system, the
diff --git a/util-linux/unshare.c b/util-linux/unshare.c
index a943e7b03..2087413e8 100644
--- a/util-linux/unshare.c
+++ b/util-linux/unshare.c
@@ -10,7 +10,6 @@
10//config: bool "unshare (7.2 kb)" 10//config: bool "unshare (7.2 kb)"
11//config: default y 11//config: default y
12//config: depends on !NOMMU 12//config: depends on !NOMMU
13//config: select PLATFORM_LINUX
14//config: select LONG_OPTS 13//config: select LONG_OPTS
15//config: help 14//config: help
16//config: Run program with some namespaces unshared from parent. 15//config: Run program with some namespaces unshared from parent.