aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2017-02-08 20:09:29 +0000
committerRon Yorston <rmy@pobox.com>2017-02-08 20:09:29 +0000
commit373275a708bafb88fa4f0519de2166154f44fed9 (patch)
tree4587b4fd3f695e0f3705b2a217e199f3144df931
parentb74b2619779b1deb903b7766261807df1e9b1f7f (diff)
parentc2b18583a3df06aeecf535c3cea6856aa1f2e205 (diff)
downloadbusybox-w32-373275a708bafb88fa4f0519de2166154f44fed9.tar.gz
busybox-w32-373275a708bafb88fa4f0519de2166154f44fed9.tar.bz2
busybox-w32-373275a708bafb88fa4f0519de2166154f44fed9.zip
Merge branch 'busybox' into merge
-rw-r--r--Config.in34
-rw-r--r--archival/Config.src10
-rw-r--r--archival/ar.c2
-rw-r--r--archival/bbunzip.c76
-rw-r--r--archival/bzip2.c16
-rw-r--r--archival/cpio.c4
-rw-r--r--archival/gzip.c28
-rw-r--r--archival/libarchive/Kbuild.src3
-rw-r--r--archival/libarchive/data_extract_all.c6
-rw-r--r--archival/libarchive/decompress_bunzip2.c6
-rw-r--r--archival/libarchive/decompress_unlzma.c31
-rw-r--r--archival/lzop.c3
-rw-r--r--archival/tar.c35
-rw-r--r--archival/unzip.c489
-rw-r--r--configs/TEST_nommu_defconfig17
-rw-r--r--configs/TEST_noprintf_defconfig10
-rw-r--r--configs/TEST_rh9_defconfig17
-rw-r--r--configs/android2_defconfig17
-rw-r--r--configs/android_502_defconfig17
-rw-r--r--configs/android_defconfig17
-rw-r--r--configs/android_ndk_defconfig17
-rw-r--r--configs/cygwin_defconfig14
-rw-r--r--configs/freebsd_defconfig14
-rw-r--r--console-tools/loadfont.c8
-rw-r--r--console-tools/setconsole.c2
-rw-r--r--coreutils/Config.src16
-rw-r--r--coreutils/Kbuild.src9
-rw-r--r--coreutils/chown.c2
-rw-r--r--coreutils/cp.c4
-rw-r--r--coreutils/dd.c4
-rw-r--r--coreutils/df.c8
-rw-r--r--coreutils/echo.c9
-rw-r--r--coreutils/env.c2
-rw-r--r--coreutils/expand.c13
-rw-r--r--coreutils/head.c4
-rw-r--r--coreutils/install.c2
-rw-r--r--coreutils/link.c41
-rw-r--r--coreutils/ls.c556
-rw-r--r--coreutils/md5_sha1_sum.c3
-rw-r--r--coreutils/mkdir.c2
-rw-r--r--coreutils/mv.c2
-rw-r--r--coreutils/printf.c5
-rw-r--r--coreutils/split.c2
-rw-r--r--coreutils/tail.c7
-rw-r--r--coreutils/test.c17
-rw-r--r--coreutils/wc.c4
-rw-r--r--coreutils/who.c1
-rw-r--r--debianutils/run_parts.c2
-rw-r--r--debianutils/start_stop_daemon.c13
-rw-r--r--docs/nofork_noexec.txt39
-rw-r--r--e2fsprogs/fsck.c2
-rw-r--r--editors/Config.src2
-rw-r--r--editors/diff.c2
-rw-r--r--editors/vi.c50
-rwxr-xr-xexamples/depmod2
-rw-r--r--findutils/find.c14
-rw-r--r--findutils/grep.c1
-rw-r--r--include/libbb.h124
-rw-r--r--include/platform.h15
-rw-r--r--include/usage.src.h8
-rw-r--r--init/halt.c3
-rw-r--r--init/init.c14
-rw-r--r--libbb/Config.src17
-rw-r--r--libbb/appletlib.c6
-rw-r--r--libbb/crc32.c2
-rw-r--r--libbb/dump.c171
-rw-r--r--libbb/getopt32.c4
-rw-r--r--libbb/hash_md5_sha.c127
-rw-r--r--libbb/hash_md5prime.c3
-rw-r--r--libbb/lineedit.c2
-rw-r--r--libbb/match_fstype.c20
-rw-r--r--libbb/procps.c24
-rw-r--r--libbb/pw_encrypt.c2
-rw-r--r--libbb/pw_encrypt_sha.c18
-rw-r--r--libbb/vfork_daemon_rexec.c38
-rw-r--r--libbb/xfuncs.c37
-rw-r--r--loginutils/Config.src2
-rw-r--r--loginutils/add-remove-shell.c1
-rw-r--r--loginutils/addgroup.c6
-rw-r--r--loginutils/adduser.c4
-rw-r--r--loginutils/chpasswd.c12
-rw-r--r--loginutils/cryptpw.c14
-rw-r--r--loginutils/deluser.c2
-rw-r--r--loginutils/getty.c2
-rw-r--r--loginutils/login.c6
-rw-r--r--loginutils/passwd.c2
-rw-r--r--loginutils/su.c9
-rw-r--r--loginutils/vlock.c8
-rwxr-xr-xmake_single_applets.sh13
-rw-r--r--miscutils/chat.c1
-rw-r--r--miscutils/conspy.c17
-rw-r--r--miscutils/crond.c2
-rw-r--r--miscutils/devfsd.c2
-rw-r--r--miscutils/flash_lock_unlock.c3
-rw-r--r--miscutils/hdparm.c12
-rw-r--r--miscutils/last.c2
-rw-r--r--miscutils/less.c5
-rw-r--r--miscutils/microcom.c1
-rw-r--r--miscutils/nandwrite.c4
-rw-r--r--miscutils/rx.c3
-rw-r--r--miscutils/taskset.c217
-rw-r--r--miscutils/ubi_tools.c11
-rw-r--r--modutils/Config.src90
-rw-r--r--modutils/insmod.c6
-rw-r--r--modutils/lsmod.c3
-rw-r--r--modutils/modprobe-small.c169
-rw-r--r--modutils/modprobe.c9
-rw-r--r--modutils/modutils.c2
-rw-r--r--modutils/modutils.h4
-rw-r--r--networking/ftpd.c51
-rw-r--r--networking/ftpgetput.c2
-rw-r--r--networking/hostname.c1
-rw-r--r--networking/httpd.c70
-rw-r--r--networking/ifupdown.c11
-rw-r--r--networking/inetd.c6
-rw-r--r--networking/ip.c124
-rw-r--r--networking/ipcalc.c12
-rw-r--r--networking/netstat.c2
-rw-r--r--networking/ntpd.c4
-rw-r--r--networking/ping.c10
-rw-r--r--networking/ssl_client.c55
-rw-r--r--networking/tc.c30
-rw-r--r--networking/telnet.c15
-rw-r--r--networking/tftp.c4
-rw-r--r--networking/tls.c1815
-rw-r--r--networking/tls.h99
-rw-r--r--networking/tls_aes.c1776
-rw-r--r--networking/tls_aes.h10
-rw-r--r--networking/tls_pstm.c2263
-rw-r--r--networking/tls_pstm.h286
-rw-r--r--networking/tls_pstm_montgomery_reduce.c427
-rw-r--r--networking/tls_pstm_mul_comba.c781
-rw-r--r--networking/tls_pstm_sqr_comba.c1111
-rw-r--r--networking/tls_rsa.c211
-rw-r--r--networking/tls_rsa.h20
-rw-r--r--networking/tls_symmetric.h511
-rw-r--r--networking/traceroute.c2
-rw-r--r--networking/udhcp/Config.src4
-rw-r--r--networking/udhcp/common.c2
-rw-r--r--networking/udhcp/dumpleases.c2
-rw-r--r--networking/wget.c226
-rw-r--r--printutils/lpr.c1
-rw-r--r--procps/Config.src2
-rw-r--r--procps/Kbuild.src4
-rw-r--r--procps/kill.c49
-rw-r--r--procps/nmeter.c2
-rw-r--r--procps/pgrep.c1
-rw-r--r--procps/pidof.c8
-rw-r--r--procps/powertop.c28
-rw-r--r--procps/ps.c24
-rw-r--r--procps/pstree.c4
-rw-r--r--procps/top.c42
-rw-r--r--procps/uptime.c4
-rw-r--r--runit/chpst.c3
-rwxr-xr-xscripts/gen_build_files.sh4
-rwxr-xr-xscripts/trylink14
-rw-r--r--selinux/chcon.c12
-rw-r--r--selinux/runcon.c10
-rw-r--r--selinux/setfiles.c1
-rw-r--r--shell/Config.src22
-rw-r--r--shell/ash.c465
-rw-r--r--shell/ash_test/ash-misc/source_argv_and_shift.right4
-rwxr-xr-xshell/ash_test/ash-misc/source_argv_and_shift.tests12
-rw-r--r--shell/hush.c1092
-rw-r--r--shell/hush_test/hush-misc/source_argv_and_shift.right4
-rwxr-xr-xshell/hush_test/hush-misc/source_argv_and_shift.tests12
-rw-r--r--shell/shell_common.c2
-rw-r--r--sysklogd/syslogd.c6
-rwxr-xr-xtestsuite/cryptpw.tests28
-rwxr-xr-xtestsuite/mdev.tests2
-rwxr-xr-xtestsuite/runtest10
-rwxr-xr-xtestsuite/unzip.tests4
-rw-r--r--util-linux/Config.src2
-rw-r--r--util-linux/dmesg.c2
-rw-r--r--util-linux/fbset.c4
-rw-r--r--util-linux/fdisk.c6
-rw-r--r--util-linux/freeramdisk.c1
-rw-r--r--util-linux/fsck_minix.c6
-rw-r--r--util-linux/fstrim.c6
-rw-r--r--util-linux/getopt.c8
-rw-r--r--util-linux/hexdump.c40
-rw-r--r--util-linux/hexdump_xxd.c146
-rw-r--r--util-linux/hwclock.c4
-rw-r--r--util-linux/mkfs_ext2.c3
-rw-r--r--util-linux/mkfs_minix.c1
-rw-r--r--util-linux/mkfs_vfat.c3
-rw-r--r--util-linux/more.c106
-rw-r--r--util-linux/mount.c4
-rw-r--r--util-linux/nsenter.c26
-rw-r--r--util-linux/rdate.c38
-rw-r--r--util-linux/rtcwake.c8
-rw-r--r--util-linux/setarch.c1
-rw-r--r--util-linux/swaponoff.c3
-rw-r--r--util-linux/umount.c4
-rw-r--r--util-linux/unshare.c16
-rw-r--r--util-linux/volume_id/bcache.c4
-rw-r--r--util-linux/volume_id/btrfs.c4
-rw-r--r--util-linux/volume_id/cramfs.c4
-rw-r--r--util-linux/volume_id/exfat.c2
-rw-r--r--util-linux/volume_id/ext.c4
-rw-r--r--util-linux/volume_id/f2fs.c2
-rw-r--r--util-linux/volume_id/fat.c4
-rw-r--r--util-linux/volume_id/hfs.c4
-rw-r--r--util-linux/volume_id/iso9660.c4
-rw-r--r--util-linux/volume_id/jfs.c4
-rw-r--r--util-linux/volume_id/linux_raid.c4
-rw-r--r--util-linux/volume_id/linux_swap.c4
-rw-r--r--util-linux/volume_id/luks.c4
-rw-r--r--util-linux/volume_id/nilfs.c2
-rw-r--r--util-linux/volume_id/ntfs.c4
-rw-r--r--util-linux/volume_id/ocfs2.c4
-rw-r--r--util-linux/volume_id/reiserfs.c4
-rw-r--r--util-linux/volume_id/romfs.c4
-rw-r--r--util-linux/volume_id/squashfs.c2
-rw-r--r--util-linux/volume_id/sysv.c4
-rw-r--r--util-linux/volume_id/ubifs.c2
-rw-r--r--util-linux/volume_id/udf.c4
-rw-r--r--util-linux/volume_id/unused_highpoint.c4
-rw-r--r--util-linux/volume_id/unused_hpfs.c4
-rw-r--r--util-linux/volume_id/unused_isw_raid.c4
-rw-r--r--util-linux/volume_id/unused_lsi_raid.c4
-rw-r--r--util-linux/volume_id/unused_lvm.c4
-rw-r--r--util-linux/volume_id/unused_mac.c4
-rw-r--r--util-linux/volume_id/unused_minix.c4
-rw-r--r--util-linux/volume_id/unused_msdos.c4
-rw-r--r--util-linux/volume_id/unused_nvidia_raid.c4
-rw-r--r--util-linux/volume_id/unused_promise_raid.c4
-rw-r--r--util-linux/volume_id/unused_silicon_raid.c4
-rw-r--r--util-linux/volume_id/unused_ufs.c4
-rw-r--r--util-linux/volume_id/unused_via_raid.c4
-rw-r--r--util-linux/volume_id/xfs.c4
231 files changed, 12695 insertions, 2708 deletions
diff --git a/Config.in b/Config.in
index 594b16b76..086812908 100644
--- a/Config.in
+++ b/Config.in
@@ -36,7 +36,7 @@ config DESKTOP
36 36
37 If you are preparing your build to be used on an embedded box 37 If you are preparing your build to be used on an embedded box
38 where you have tighter control over the entire set of userspace 38 where you have tighter control over the entire set of userspace
39 tools, you can unselect this option for smaller code size. 39 tools, you can unselect this option for smaller code size.
40 40
41config EXTRA_COMPAT 41config EXTRA_COMPAT
42 bool "Provide compatible behavior for rare corner cases (bigger code)" 42 bool "Provide compatible behavior for rare corner cases (bigger code)"
@@ -64,17 +64,6 @@ config USE_PORTABLE_CODE
64 compiler other than gcc. 64 compiler other than gcc.
65 If you do use gcc, this option may needlessly increase code size. 65 If you do use gcc, this option may needlessly increase code size.
66 66
67config PLATFORM_LINUX
68 bool "Enable Linux-specific applets and features"
69 default y
70 help
71 For the most part, busybox requires only POSIX compatibility
72 from the target system, but some applets and features use
73 Linux-specific interfaces.
74
75 Answering 'N' here will disable such applets and hide the
76 corresponding configuration options.
77
78config SHOW_USAGE 67config SHOW_USAGE
79 bool "Show applet usage messages" 68 bool "Show applet usage messages"
80 default y 69 default y
@@ -138,14 +127,14 @@ config INSTALL_NO_USR
138 never to /usr/bin or /usr/sbin. 127 never to /usr/bin or /usr/sbin.
139 128
140config PAM 129config PAM
141 bool "Support for PAM (Pluggable Authentication Modules)" 130 bool "Support PAM (Pluggable Authentication Modules)"
142 default n 131 default n
143 help 132 help
144 Use PAM in some busybox applets (currently login and httpd) instead 133 Use PAM in some busybox applets (currently login and httpd) instead
145 of direct access to password database. 134 of direct access to password database.
146 135
147config LONG_OPTS 136config LONG_OPTS
148 bool "Support for --long-options" 137 bool "Support --long-options"
149 default y 138 default y
150 help 139 help
151 Enable this if you want busybox applets to use the gnu --long-option 140 Enable this if you want busybox applets to use the gnu --long-option
@@ -212,7 +201,7 @@ config PID_FILE_PATH
212 specify a pidfile path. 201 specify a pidfile path.
213 202
214config FEATURE_SUID 203config FEATURE_SUID
215 bool "Support for SUID/SGID handling" 204 bool "Support SUID/SGID handling"
216 default y 205 default y
217 help 206 help
218 With this option you can install the busybox binary belonging 207 With this option you can install the busybox binary belonging
@@ -352,6 +341,17 @@ config FEATURE_HAVE_RPC
352 # This is automatically selected if any of enabled applets need it. 341 # This is automatically selected if any of enabled applets need it.
353 # You do not need to select it manually. 342 # You do not need to select it manually.
354 343
344config PLATFORM_LINUX
345 bool #No description makes it a hidden option
346 default n
347 #help
348 # For the most part, busybox requires only POSIX compatibility
349 # from the target system, but some applets and features use
350 # Linux-specific interfaces.
351 #
352 # This is automatically selected if any applet or feature requires
353 # Linux-specific interfaces. You do not need to select it manually.
354
355comment 'Build Options' 355comment 'Build Options'
356 356
357config STATIC 357config STATIC
@@ -647,6 +647,8 @@ config DEBUG_SANITIZE
647 catch bad memory accesses (e.g. buffer overflows), but will make 647 catch bad memory accesses (e.g. buffer overflows), but will make
648 the executable larger and slow down runtime a bit. 648 the executable larger and slow down runtime a bit.
649 649
650 This adds -fsanitize=foo options to gcc command line.
651
650 If you aren't developing/testing busybox, say N here. 652 If you aren't developing/testing busybox, say N here.
651 653
652config UNIT_TEST 654config UNIT_TEST
@@ -661,7 +663,7 @@ config WERROR
661 bool "Abort compilation on any warning" 663 bool "Abort compilation on any warning"
662 default n 664 default n
663 help 665 help
664 Selecting this will add -Werror to gcc command line. 666 This adds -Werror to gcc command line.
665 667
666 Most people should answer N. 668 Most people should answer N.
667 669
diff --git a/archival/Config.src b/archival/Config.src
index 5e7cfc0a4..0c97f3d7c 100644
--- a/archival/Config.src
+++ b/archival/Config.src
@@ -8,32 +8,22 @@ menu "Archival Utilities"
8config FEATURE_SEAMLESS_XZ 8config FEATURE_SEAMLESS_XZ
9 bool "Make tar, rpm, modprobe etc understand .xz data" 9 bool "Make tar, rpm, modprobe etc understand .xz data"
10 default y 10 default y
11 help
12 Make tar, rpm, modprobe etc understand .xz data.
13 11
14config FEATURE_SEAMLESS_LZMA 12config FEATURE_SEAMLESS_LZMA
15 bool "Make tar, rpm, modprobe etc understand .lzma data" 13 bool "Make tar, rpm, modprobe etc understand .lzma data"
16 default y 14 default y
17 help
18 Make tar, rpm, modprobe etc understand .lzma data.
19 15
20config FEATURE_SEAMLESS_BZ2 16config FEATURE_SEAMLESS_BZ2
21 bool "Make tar, rpm, modprobe etc understand .bz2 data" 17 bool "Make tar, rpm, modprobe etc understand .bz2 data"
22 default y 18 default y
23 help
24 Make tar, rpm, modprobe etc understand .bz2 data.
25 19
26config FEATURE_SEAMLESS_GZ 20config FEATURE_SEAMLESS_GZ
27 bool "Make tar, rpm, modprobe etc understand .gz data" 21 bool "Make tar, rpm, modprobe etc understand .gz data"
28 default y 22 default y
29 help
30 Make tar, rpm, modprobe etc understand .gz data.
31 23
32config FEATURE_SEAMLESS_Z 24config FEATURE_SEAMLESS_Z
33 bool "Make tar, rpm, modprobe etc understand .Z data" 25 bool "Make tar, rpm, modprobe etc understand .Z data"
34 default n # it is ancient 26 default n # it is ancient
35 help
36 Make tar, rpm, modprobe etc understand .Z data.
37 27
38INSERT 28INSERT
39 29
diff --git a/archival/ar.c b/archival/ar.c
index a850868f6..f9f712fde 100644
--- a/archival/ar.c
+++ b/archival/ar.c
@@ -31,7 +31,7 @@
31//config: probably say N here: most compilers come with their own ar utility. 31//config: probably say N here: most compilers come with their own ar utility.
32//config: 32//config:
33//config:config FEATURE_AR_LONG_FILENAMES 33//config:config FEATURE_AR_LONG_FILENAMES
34//config: bool "Support for long filenames (not needed for debs)" 34//config: bool "Support long filenames (not needed for debs)"
35//config: default y 35//config: default y
36//config: depends on AR 36//config: depends on AR
37//config: help 37//config: help
diff --git a/archival/bbunzip.c b/archival/bbunzip.c
index 343aec9bd..311c7333e 100644
--- a/archival/bbunzip.c
+++ b/archival/bbunzip.c
@@ -12,9 +12,9 @@
12//kbuild:lib-$(CONFIG_LZOPCAT) += bbunzip.o 12//kbuild:lib-$(CONFIG_LZOPCAT) += bbunzip.o
13//kbuild:lib-$(CONFIG_UNLZOP) += bbunzip.o 13//kbuild:lib-$(CONFIG_UNLZOP) += bbunzip.o
14/* bzip2_main() too: */ 14/* bzip2_main() too: */
15//kbuild:lib-$(CONFIG_BZIP2) += bbunzip.o 15//kbuild:lib-$(CONFIG_FEATURE_BZIP2_DECOMPRESS) += bbunzip.o
16/* gzip_main() too: */ 16/* gzip_main() too: */
17//kbuild:lib-$(CONFIG_GZIP) += bbunzip.o 17//kbuild:lib-$(CONFIG_FEATURE_GZIP_DECOMPRESS) += bbunzip.o
18 18
19/* Note: must be kept in sync with archival/lzop.c */ 19/* Note: must be kept in sync with archival/lzop.c */
20enum { 20enum {
@@ -25,7 +25,7 @@ enum {
25 OPT_QUIET = 1 << 3, 25 OPT_QUIET = 1 << 3,
26 OPT_DECOMPRESS = 1 << 4, 26 OPT_DECOMPRESS = 1 << 4,
27 OPT_TEST = 1 << 5, 27 OPT_TEST = 1 << 5,
28 SEAMLESS_MAGIC = (1 << 31) * SEAMLESS_COMPRESSION, 28 SEAMLESS_MAGIC = (1 << 31) * ENABLE_ZCAT * SEAMLESS_COMPRESSION,
29}; 29};
30 30
31static 31static
@@ -127,7 +127,7 @@ int FAST_FUNC bbunpack(char **argv,
127 127
128 if (!(option_mask32 & SEAMLESS_MAGIC)) { 128 if (!(option_mask32 & SEAMLESS_MAGIC)) {
129 init_transformer_state(&xstate); 129 init_transformer_state(&xstate);
130 xstate.signature_skipped = 0; 130 /*xstate.signature_skipped = 0; - already is */
131 /*xstate.src_fd = STDIN_FILENO; - already is */ 131 /*xstate.src_fd = STDIN_FILENO; - already is */
132 xstate.dst_fd = STDOUT_FILENO; 132 xstate.dst_fd = STDOUT_FILENO;
133 status = unpacker(&xstate); 133 status = unpacker(&xstate);
@@ -199,7 +199,7 @@ int FAST_FUNC bbunpack(char **argv,
199} 199}
200 200
201#if ENABLE_UNCOMPRESS \ 201#if ENABLE_UNCOMPRESS \
202 || ENABLE_BUNZIP2 || ENABLE_BZCAT \ 202 || ENABLE_FEATURE_BZIP2_DECOMPRESS \
203 || ENABLE_UNLZMA || ENABLE_LZCAT || ENABLE_LZMA \ 203 || ENABLE_UNLZMA || ENABLE_LZCAT || ENABLE_LZMA \
204 || ENABLE_UNXZ || ENABLE_XZCAT || ENABLE_XZ 204 || ENABLE_UNXZ || ENABLE_XZCAT || ENABLE_XZ
205static 205static
@@ -297,6 +297,7 @@ int uncompress_main(int argc UNUSED_PARAM, char **argv)
297//config:config GUNZIP 297//config:config GUNZIP
298//config: bool "gunzip" 298//config: bool "gunzip"
299//config: default y 299//config: default y
300//config: select FEATURE_GZIP_DECOMPRESS
300//config: help 301//config: help
301//config: gunzip is used to decompress archives created by gzip. 302//config: gunzip is used to decompress archives created by gzip.
302//config: You can use the `-t' option to test the integrity of 303//config: You can use the `-t' option to test the integrity of
@@ -305,6 +306,7 @@ int uncompress_main(int argc UNUSED_PARAM, char **argv)
305//config:config ZCAT 306//config:config ZCAT
306//config: bool "zcat" 307//config: bool "zcat"
307//config: default y 308//config: default y
309//config: select FEATURE_GZIP_DECOMPRESS
308//config: help 310//config: help
309//config: Alias to "gunzip -c". 311//config: Alias to "gunzip -c".
310//config: 312//config:
@@ -312,14 +314,11 @@ int uncompress_main(int argc UNUSED_PARAM, char **argv)
312//config: bool "Enable long options" 314//config: bool "Enable long options"
313//config: default y 315//config: default y
314//config: depends on (GUNZIP || ZCAT) && LONG_OPTS 316//config: depends on (GUNZIP || ZCAT) && LONG_OPTS
315//config: help
316//config: Enable use of long options.
317 317
318//applet:IF_GUNZIP(APPLET(gunzip, BB_DIR_BIN, BB_SUID_DROP)) 318//applet:IF_GUNZIP(APPLET(gunzip, BB_DIR_BIN, BB_SUID_DROP))
319// APPLET_ODDNAME:name main location suid_type help
319//applet:IF_ZCAT(APPLET_ODDNAME(zcat, gunzip, BB_DIR_BIN, BB_SUID_DROP, zcat)) 320//applet:IF_ZCAT(APPLET_ODDNAME(zcat, gunzip, BB_DIR_BIN, BB_SUID_DROP, zcat))
320//kbuild:lib-$(CONFIG_GUNZIP) += bbunzip.o 321#if ENABLE_FEATURE_GZIP_DECOMPRESS
321//kbuild:lib-$(CONFIG_ZCAT) += bbunzip.o
322#if ENABLE_GUNZIP || ENABLE_ZCAT
323static 322static
324char* FAST_FUNC make_new_name_gunzip(char *filename, const char *expected_ext UNUSED_PARAM) 323char* FAST_FUNC make_new_name_gunzip(char *filename, const char *expected_ext UNUSED_PARAM)
325{ 324{
@@ -387,7 +386,7 @@ int gunzip_main(int argc UNUSED_PARAM, char **argv)
387 386
388 return bbunpack(argv, unpack_gz_stream, make_new_name_gunzip, /*unused:*/ NULL); 387 return bbunpack(argv, unpack_gz_stream, make_new_name_gunzip, /*unused:*/ NULL);
389} 388}
390#endif 389#endif /* FEATURE_GZIP_DECOMPRESS */
391 390
392 391
393/* 392/*
@@ -410,6 +409,7 @@ int gunzip_main(int argc UNUSED_PARAM, char **argv)
410//config:config BUNZIP2 409//config:config BUNZIP2
411//config: bool "bunzip2" 410//config: bool "bunzip2"
412//config: default y 411//config: default y
412//config: select FEATURE_BZIP2_DECOMPRESS
413//config: help 413//config: help
414//config: bunzip2 is a compression utility using the Burrows-Wheeler block 414//config: bunzip2 is a compression utility using the Burrows-Wheeler block
415//config: sorting text compression algorithm, and Huffman coding. Compression 415//config: sorting text compression algorithm, and Huffman coding. Compression
@@ -423,14 +423,14 @@ int gunzip_main(int argc UNUSED_PARAM, char **argv)
423//config:config BZCAT 423//config:config BZCAT
424//config: bool "bzcat" 424//config: bool "bzcat"
425//config: default y 425//config: default y
426//config: select FEATURE_BZIP2_DECOMPRESS
426//config: help 427//config: help
427//config: Alias to "bunzip2 -c". 428//config: Alias to "bunzip2 -c".
428 429
429//applet:IF_BUNZIP2(APPLET(bunzip2, BB_DIR_USR_BIN, BB_SUID_DROP)) 430//applet:IF_BUNZIP2(APPLET(bunzip2, BB_DIR_USR_BIN, BB_SUID_DROP))
431// APPLET_ODDNAME:name main location suid_type help
430//applet:IF_BZCAT(APPLET_ODDNAME(bzcat, bunzip2, BB_DIR_USR_BIN, BB_SUID_DROP, bzcat)) 432//applet:IF_BZCAT(APPLET_ODDNAME(bzcat, bunzip2, BB_DIR_USR_BIN, BB_SUID_DROP, bzcat))
431//kbuild:lib-$(CONFIG_BUNZIP2) += bbunzip.o 433#if ENABLE_FEATURE_BZIP2_DECOMPRESS
432//kbuild:lib-$(CONFIG_BZCAT) += bbunzip.o
433#if ENABLE_BUNZIP2 || ENABLE_BZCAT
434int bunzip2_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 434int bunzip2_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
435int bunzip2_main(int argc UNUSED_PARAM, char **argv) 435int bunzip2_main(int argc UNUSED_PARAM, char **argv)
436{ 436{
@@ -471,26 +471,6 @@ int bunzip2_main(int argc UNUSED_PARAM, char **argv)
471//usage: "[FILE]..." 471//usage: "[FILE]..."
472//usage:#define lzcat_full_usage "\n\n" 472//usage:#define lzcat_full_usage "\n\n"
473//usage: "Decompress to stdout" 473//usage: "Decompress to stdout"
474//usage:
475//usage:#define unxz_trivial_usage
476//usage: "[-cf] [FILE]..."
477//usage:#define unxz_full_usage "\n\n"
478//usage: "Decompress FILE (or stdin)\n"
479//usage: "\n -c Write to stdout"
480//usage: "\n -f Force"
481//usage:
482//usage:#define xz_trivial_usage
483//usage: "-d [-cf] [FILE]..."
484//usage:#define xz_full_usage "\n\n"
485//usage: "Decompress FILE (or stdin)\n"
486//usage: "\n -d Decompress"
487//usage: "\n -c Write to stdout"
488//usage: "\n -f Force"
489//usage:
490//usage:#define xzcat_trivial_usage
491//usage: "[FILE]..."
492//usage:#define xzcat_full_usage "\n\n"
493//usage: "Decompress to stdout"
494 474
495//config:config UNLZMA 475//config:config UNLZMA
496//config: bool "unlzma" 476//config: bool "unlzma"
@@ -524,7 +504,7 @@ int bunzip2_main(int argc UNUSED_PARAM, char **argv)
524//config: IOW: you'll get lzma applet, but it will always require -d option. 504//config: IOW: you'll get lzma applet, but it will always require -d option.
525//config: 505//config:
526//config:config FEATURE_LZMA_FAST 506//config:config FEATURE_LZMA_FAST
527//config: bool "Optimize unlzma for speed" 507//config: bool "Optimize for speed"
528//config: default n 508//config: default n
529//config: depends on UNLZMA || LZCAT || LZMA 509//config: depends on UNLZMA || LZCAT || LZMA
530//config: help 510//config: help
@@ -532,8 +512,9 @@ int bunzip2_main(int argc UNUSED_PARAM, char **argv)
532//config: a 1K bigger binary. 512//config: a 1K bigger binary.
533 513
534//applet:IF_UNLZMA(APPLET(unlzma, BB_DIR_USR_BIN, BB_SUID_DROP)) 514//applet:IF_UNLZMA(APPLET(unlzma, BB_DIR_USR_BIN, BB_SUID_DROP))
515// APPLET_ODDNAME:name main location suid_type help
535//applet:IF_LZCAT(APPLET_ODDNAME(lzcat, unlzma, BB_DIR_USR_BIN, BB_SUID_DROP, lzcat)) 516//applet:IF_LZCAT(APPLET_ODDNAME(lzcat, unlzma, BB_DIR_USR_BIN, BB_SUID_DROP, lzcat))
536//applet:IF_LZMA(APPLET_ODDNAME(lzma, unlzma, BB_DIR_USR_BIN, BB_SUID_DROP, lzma)) 517//applet:IF_LZMA( APPLET_ODDNAME(lzma, unlzma, BB_DIR_USR_BIN, BB_SUID_DROP, lzma))
537//kbuild:lib-$(CONFIG_UNLZMA) += bbunzip.o 518//kbuild:lib-$(CONFIG_UNLZMA) += bbunzip.o
538//kbuild:lib-$(CONFIG_LZCAT) += bbunzip.o 519//kbuild:lib-$(CONFIG_LZCAT) += bbunzip.o
539//kbuild:lib-$(CONFIG_LZMA) += bbunzip.o 520//kbuild:lib-$(CONFIG_LZMA) += bbunzip.o
@@ -557,6 +538,26 @@ int unlzma_main(int argc UNUSED_PARAM, char **argv)
557#endif 538#endif
558 539
559 540
541//usage:#define unxz_trivial_usage
542//usage: "[-cf] [FILE]..."
543//usage:#define unxz_full_usage "\n\n"
544//usage: "Decompress FILE (or stdin)\n"
545//usage: "\n -c Write to stdout"
546//usage: "\n -f Force"
547//usage:
548//usage:#define xz_trivial_usage
549//usage: "-d [-cf] [FILE]..."
550//usage:#define xz_full_usage "\n\n"
551//usage: "Decompress FILE (or stdin)\n"
552//usage: "\n -d Decompress"
553//usage: "\n -c Write to stdout"
554//usage: "\n -f Force"
555//usage:
556//usage:#define xzcat_trivial_usage
557//usage: "[FILE]..."
558//usage:#define xzcat_full_usage "\n\n"
559//usage: "Decompress to stdout"
560
560//config:config UNXZ 561//config:config UNXZ
561//config: bool "unxz" 562//config: bool "unxz"
562//config: default y 563//config: default y
@@ -577,8 +578,9 @@ int unlzma_main(int argc UNUSED_PARAM, char **argv)
577//config: IOW: you'll get xz applet, but it will always require -d option. 578//config: IOW: you'll get xz applet, but it will always require -d option.
578 579
579//applet:IF_UNXZ(APPLET(unxz, BB_DIR_USR_BIN, BB_SUID_DROP)) 580//applet:IF_UNXZ(APPLET(unxz, BB_DIR_USR_BIN, BB_SUID_DROP))
581// APPLET_ODDNAME:name main location suid_type help
580//applet:IF_XZCAT(APPLET_ODDNAME(xzcat, unxz, BB_DIR_USR_BIN, BB_SUID_DROP, xzcat)) 582//applet:IF_XZCAT(APPLET_ODDNAME(xzcat, unxz, BB_DIR_USR_BIN, BB_SUID_DROP, xzcat))
581//applet:IF_XZ(APPLET_ODDNAME(xz, unxz, BB_DIR_USR_BIN, BB_SUID_DROP, xz)) 583//applet:IF_XZ( APPLET_ODDNAME(xz, unxz, BB_DIR_USR_BIN, BB_SUID_DROP, xz))
582//kbuild:lib-$(CONFIG_UNXZ) += bbunzip.o 584//kbuild:lib-$(CONFIG_UNXZ) += bbunzip.o
583//kbuild:lib-$(CONFIG_XZCAT) += bbunzip.o 585//kbuild:lib-$(CONFIG_XZCAT) += bbunzip.o
584//kbuild:lib-$(CONFIG_XZ) += bbunzip.o 586//kbuild:lib-$(CONFIG_XZ) += bbunzip.o
diff --git a/archival/bzip2.c b/archival/bzip2.c
index 47fa29af3..7e38e78b3 100644
--- a/archival/bzip2.c
+++ b/archival/bzip2.c
@@ -19,6 +19,15 @@
19//config: 19//config:
20//config: Unless you have a specific application which requires bzip2, you 20//config: Unless you have a specific application which requires bzip2, you
21//config: should probably say N here. 21//config: should probably say N here.
22//config:
23//config:config FEATURE_BZIP2_DECOMPRESS
24//config: bool "Enable decompression"
25//config: default y
26//config: depends on BZIP2 || BUNZIP2 || BZCAT
27//config: help
28//config: Enable -d (--decompress) and -t (--test) options for bzip2.
29//config: This will be automatically selected if bunzip2 or bzcat is
30//config: enabled.
22 31
23//applet:IF_BZIP2(APPLET(bzip2, BB_DIR_USR_BIN, BB_SUID_DROP)) 32//applet:IF_BZIP2(APPLET(bzip2, BB_DIR_USR_BIN, BB_SUID_DROP))
24//kbuild:lib-$(CONFIG_BZIP2) += bzip2.o 33//kbuild:lib-$(CONFIG_BZIP2) += bzip2.o
@@ -28,7 +37,10 @@
28//usage:#define bzip2_full_usage "\n\n" 37//usage:#define bzip2_full_usage "\n\n"
29//usage: "Compress FILEs (or stdin) with bzip2 algorithm\n" 38//usage: "Compress FILEs (or stdin) with bzip2 algorithm\n"
30//usage: "\n -1..9 Compression level" 39//usage: "\n -1..9 Compression level"
40//usage: IF_FEATURE_BZIP2_DECOMPRESS(
31//usage: "\n -d Decompress" 41//usage: "\n -d Decompress"
42//usage: "\n -t Test file integrity"
43//usage: )
32//usage: "\n -c Write to stdout" 44//usage: "\n -c Write to stdout"
33//usage: "\n -f Force" 45//usage: "\n -f Force"
34 46
@@ -184,8 +196,8 @@ int bzip2_main(int argc UNUSED_PARAM, char **argv)
184 196
185 opt_complementary = "s2"; /* -s means -2 (compatibility) */ 197 opt_complementary = "s2"; /* -s means -2 (compatibility) */
186 /* Must match bbunzip's constants OPT_STDOUT, OPT_FORCE! */ 198 /* Must match bbunzip's constants OPT_STDOUT, OPT_FORCE! */
187 opt = getopt32(argv, "cfv" IF_BUNZIP2("dt") "123456789qzs"); 199 opt = getopt32(argv, "cfv" IF_FEATURE_BZIP2_DECOMPRESS("dt") "123456789qzs");
188#if ENABLE_BUNZIP2 /* bunzip2_main may not be visible... */ 200#if ENABLE_FEATURE_BZIP2_DECOMPRESS /* bunzip2_main may not be visible... */
189 if (opt & 0x18) // -d and/or -t 201 if (opt & 0x18) // -d and/or -t
190 return bunzip2_main(argc, argv); 202 return bunzip2_main(argc, argv);
191 opt >>= 5; 203 opt >>= 5;
diff --git a/archival/cpio.c b/archival/cpio.c
index 540218cb2..683f0bb1f 100644
--- a/archival/cpio.c
+++ b/archival/cpio.c
@@ -29,7 +29,7 @@
29//config: should probably say N here. 29//config: should probably say N here.
30//config: 30//config:
31//config:config FEATURE_CPIO_O 31//config:config FEATURE_CPIO_O
32//config: bool "Support for archive creation" 32//config: bool "Support archive creation"
33//config: default y 33//config: default y
34//config: depends on CPIO 34//config: depends on CPIO
35//config: help 35//config: help
@@ -37,7 +37,7 @@
37//config: format only. 37//config: format only.
38//config: 38//config:
39//config:config FEATURE_CPIO_P 39//config:config FEATURE_CPIO_P
40//config: bool "Support for passthrough mode" 40//config: bool "Support passthrough mode"
41//config: default y 41//config: default y
42//config: depends on FEATURE_CPIO_O 42//config: depends on FEATURE_CPIO_O
43//config: help 43//config: help
diff --git a/archival/gzip.c b/archival/gzip.c
index 9e0bee815..e698c26cd 100644
--- a/archival/gzip.c
+++ b/archival/gzip.c
@@ -48,11 +48,9 @@ aa: 85.1% -- replaced with aa.gz
48//config: bool "Enable long options" 48//config: bool "Enable long options"
49//config: default y 49//config: default y
50//config: depends on GZIP && LONG_OPTS 50//config: depends on GZIP && LONG_OPTS
51//config: help
52//config: Enable use of long options, increases size by about 106 Bytes
53//config: 51//config:
54//config:config GZIP_FAST 52//config:config GZIP_FAST
55//config: int "Trade memory for gzip speed (0:small,slow - 2:fast,big)" 53//config: int "Trade memory for speed (0:small,slow - 2:fast,big)"
56//config: default 0 54//config: default 0
57//config: range 0 2 55//config: range 0 2
58//config: depends on GZIP 56//config: depends on GZIP
@@ -72,19 +70,29 @@ aa: 85.1% -- replaced with aa.gz
72//config: is 6. If levels 1-3 are specified, 4 is used. 70//config: is 6. If levels 1-3 are specified, 4 is used.
73//config: If this option is not selected, -N options are ignored and -9 71//config: If this option is not selected, -N options are ignored and -9
74//config: is used. 72//config: is used.
73//config:
74//config:config FEATURE_GZIP_DECOMPRESS
75//config: bool "Enable decompression"
76//config: default y
77//config: depends on GZIP || GUNZIP || ZCAT
78//config: help
79//config: Enable -d (--decompress) and -t (--test) options for gzip.
80//config: This will be automatically selected if gunzip or zcat is
81//config: enabled.
75 82
76//applet:IF_GZIP(APPLET(gzip, BB_DIR_BIN, BB_SUID_DROP)) 83//applet:IF_GZIP(APPLET(gzip, BB_DIR_BIN, BB_SUID_DROP))
77//kbuild:lib-$(CONFIG_GZIP) += gzip.o 84//kbuild:lib-$(CONFIG_GZIP) += gzip.o
78 85
79//usage:#define gzip_trivial_usage 86//usage:#define gzip_trivial_usage
80//usage: "[-cf" IF_GUNZIP("d") IF_FEATURE_GZIP_LEVELS("123456789") "] [FILE]..." 87//usage: "[-cf" IF_FEATURE_GZIP_DECOMPRESS("dt") IF_FEATURE_GZIP_LEVELS("123456789") "] [FILE]..."
81//usage:#define gzip_full_usage "\n\n" 88//usage:#define gzip_full_usage "\n\n"
82//usage: "Compress FILEs (or stdin)\n" 89//usage: "Compress FILEs (or stdin)\n"
83//usage: IF_FEATURE_GZIP_LEVELS( 90//usage: IF_FEATURE_GZIP_LEVELS(
84//usage: "\n -1..9 Compression level" 91//usage: "\n -1..9 Compression level"
85//usage: ) 92//usage: )
86//usage: IF_GUNZIP( 93//usage: IF_FEATURE_GZIP_DECOMPRESS(
87//usage: "\n -d Decompress" 94//usage: "\n -d Decompress"
95//usage: "\n -t Test file integrity"
88//usage: ) 96//usage: )
89//usage: "\n -c Write to stdout" 97//usage: "\n -c Write to stdout"
90//usage: "\n -f Force" 98//usage: "\n -f Force"
@@ -2154,7 +2162,7 @@ static const char gzip_longopts[] ALIGN1 =
2154 "to-stdout\0" No_argument "c" 2162 "to-stdout\0" No_argument "c"
2155 "force\0" No_argument "f" 2163 "force\0" No_argument "f"
2156 "verbose\0" No_argument "v" 2164 "verbose\0" No_argument "v"
2157#if ENABLE_GUNZIP 2165#if ENABLE_FEATURE_GZIP_DECOMPRESS
2158 "decompress\0" No_argument "d" 2166 "decompress\0" No_argument "d"
2159 "uncompress\0" No_argument "d" 2167 "uncompress\0" No_argument "d"
2160 "test\0" No_argument "t" 2168 "test\0" No_argument "t"
@@ -2181,7 +2189,7 @@ static const char gzip_longopts[] ALIGN1 =
2181 */ 2189 */
2182 2190
2183int gzip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 2191int gzip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
2184#if ENABLE_GUNZIP 2192#if ENABLE_FEATURE_GZIP_DECOMPRESS
2185int gzip_main(int argc, char **argv) 2193int gzip_main(int argc, char **argv)
2186#else 2194#else
2187int gzip_main(int argc UNUSED_PARAM, char **argv) 2195int gzip_main(int argc UNUSED_PARAM, char **argv)
@@ -2211,13 +2219,13 @@ int gzip_main(int argc UNUSED_PARAM, char **argv)
2211 applet_long_options = gzip_longopts; 2219 applet_long_options = gzip_longopts;
2212#endif 2220#endif
2213 /* Must match bbunzip's constants OPT_STDOUT, OPT_FORCE! */ 2221 /* Must match bbunzip's constants OPT_STDOUT, OPT_FORCE! */
2214 opt = getopt32(argv, "cfv" IF_GUNZIP("dt") "qn123456789"); 2222 opt = getopt32(argv, "cfv" IF_FEATURE_GZIP_DECOMPRESS("dt") "qn123456789");
2215#if ENABLE_GUNZIP /* gunzip_main may not be visible... */ 2223#if ENABLE_FEATURE_GZIP_DECOMPRESS /* gunzip_main may not be visible... */
2216 if (opt & 0x18) // -d and/or -t 2224 if (opt & 0x18) // -d and/or -t
2217 return gunzip_main(argc, argv); 2225 return gunzip_main(argc, argv);
2218#endif 2226#endif
2219#ifdef ENABLE_FEATURE_GZIP_LEVELS 2227#ifdef ENABLE_FEATURE_GZIP_LEVELS
2220 opt >>= ENABLE_GUNZIP ? 7 : 5; /* drop cfv[dt]qn bits */ 2228 opt >>= ENABLE_FEATURE_GZIP_DECOMPRESS ? 7 : 5; /* drop cfv[dt]qn bits */
2221 if (opt == 0) 2229 if (opt == 0)
2222 opt = 1 << 6; /* default: 6 */ 2230 opt = 1 << 6; /* default: 6 */
2223 opt = ffs(opt >> 4); /* Maps -1..-4 to [0], -5 to [1] ... -9 to [5] */ 2231 opt = ffs(opt >> 4); /* Maps -1..-4 to [0], -5 to [1] ... -9 to [5] */
diff --git a/archival/libarchive/Kbuild.src b/archival/libarchive/Kbuild.src
index ad5c5c42d..eaf67451f 100644
--- a/archival/libarchive/Kbuild.src
+++ b/archival/libarchive/Kbuild.src
@@ -53,12 +53,15 @@ lib-$(CONFIG_LZOPCAT) += lzo1x_1.o lzo1x_1o.o lzo1x_d.o
53lib-$(CONFIG_LZOP_COMPR_HIGH) += lzo1x_9x.o 53lib-$(CONFIG_LZOP_COMPR_HIGH) += lzo1x_9x.o
54lib-$(CONFIG_BUNZIP2) += open_transformer.o decompress_bunzip2.o 54lib-$(CONFIG_BUNZIP2) += open_transformer.o decompress_bunzip2.o
55lib-$(CONFIG_BZCAT) += open_transformer.o decompress_bunzip2.o 55lib-$(CONFIG_BZCAT) += open_transformer.o decompress_bunzip2.o
56lib-$(CONFIG_FEATURE_UNZIP_BZIP2) += open_transformer.o decompress_bunzip2.o
56lib-$(CONFIG_UNLZMA) += open_transformer.o decompress_unlzma.o 57lib-$(CONFIG_UNLZMA) += open_transformer.o decompress_unlzma.o
57lib-$(CONFIG_LZCAT) += open_transformer.o decompress_unlzma.o 58lib-$(CONFIG_LZCAT) += open_transformer.o decompress_unlzma.o
58lib-$(CONFIG_LZMA) += open_transformer.o decompress_unlzma.o 59lib-$(CONFIG_LZMA) += open_transformer.o decompress_unlzma.o
60lib-$(CONFIG_FEATURE_UNZIP_LZMA) += open_transformer.o decompress_unlzma.o
59lib-$(CONFIG_UNXZ) += open_transformer.o decompress_unxz.o 61lib-$(CONFIG_UNXZ) += open_transformer.o decompress_unxz.o
60lib-$(CONFIG_XZCAT) += open_transformer.o decompress_unxz.o 62lib-$(CONFIG_XZCAT) += open_transformer.o decompress_unxz.o
61lib-$(CONFIG_XZ) += open_transformer.o decompress_unxz.o 63lib-$(CONFIG_XZ) += open_transformer.o decompress_unxz.o
64lib-$(CONFIG_FEATURE_UNZIP_XZ) += open_transformer.o decompress_unxz.o
62lib-$(CONFIG_GUNZIP) += open_transformer.o decompress_gunzip.o 65lib-$(CONFIG_GUNZIP) += open_transformer.o decompress_gunzip.o
63lib-$(CONFIG_ZCAT) += open_transformer.o decompress_gunzip.o 66lib-$(CONFIG_ZCAT) += open_transformer.o decompress_gunzip.o
64lib-$(CONFIG_UNCOMPRESS) += open_transformer.o decompress_uncompress.o 67lib-$(CONFIG_UNCOMPRESS) += open_transformer.o decompress_uncompress.o
diff --git a/archival/libarchive/data_extract_all.c b/archival/libarchive/data_extract_all.c
index bd034afdc..1830ffb8d 100644
--- a/archival/libarchive/data_extract_all.c
+++ b/archival/libarchive/data_extract_all.c
@@ -127,8 +127,9 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
127 if (hard_link) { 127 if (hard_link) {
128 res = link(hard_link, dst_name); 128 res = link(hard_link, dst_name);
129 if (res != 0 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) { 129 if (res != 0 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) {
130 /* shared message */
130 bb_perror_msg("can't create %slink " 131 bb_perror_msg("can't create %slink "
131 "from %s to %s", "hard", 132 "%s to %s", "hard",
132 dst_name, 133 dst_name,
133 hard_link); 134 hard_link);
134 } 135 }
@@ -181,8 +182,9 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
181 if (res != 0 182 if (res != 0
182 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) 183 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
183 ) { 184 ) {
185 /* shared message */
184 bb_perror_msg("can't create %slink " 186 bb_perror_msg("can't create %slink "
185 "from %s to %s", "sym", 187 "%s to %s", "sym",
186 dst_name, 188 dst_name,
187 file_header->link_target); 189 file_header->link_target);
188 } 190 }
diff --git a/archival/libarchive/decompress_bunzip2.c b/archival/libarchive/decompress_bunzip2.c
index fe5953da2..4fb989c29 100644
--- a/archival/libarchive/decompress_bunzip2.c
+++ b/archival/libarchive/decompress_bunzip2.c
@@ -134,7 +134,7 @@ static unsigned get_bits(bunzip_data *bd, int bits_wanted)
134 134
135 /* Avoid 32-bit overflow (dump bit buffer to top of output) */ 135 /* Avoid 32-bit overflow (dump bit buffer to top of output) */
136 if (bit_count >= 24) { 136 if (bit_count >= 24) {
137 bits = bd->inbufBits & ((1 << bit_count) - 1); 137 bits = bd->inbufBits & ((1U << bit_count) - 1);
138 bits_wanted -= bit_count; 138 bits_wanted -= bit_count;
139 bits <<= bits_wanted; 139 bits <<= bits_wanted;
140 bit_count = 0; 140 bit_count = 0;
@@ -158,11 +158,11 @@ static int get_next_block(bunzip_data *bd)
158{ 158{
159 struct group_data *hufGroup; 159 struct group_data *hufGroup;
160 int dbufCount, dbufSize, groupCount, *base, *limit, selector, 160 int dbufCount, dbufSize, groupCount, *base, *limit, selector,
161 i, j, t, runPos, symCount, symTotal, nSelectors, byteCount[256]; 161 i, j, runPos, symCount, symTotal, nSelectors, byteCount[256];
162 int runCnt = runCnt; /* for compiler */ 162 int runCnt = runCnt; /* for compiler */
163 uint8_t uc, symToByte[256], mtfSymbol[256], *selectors; 163 uint8_t uc, symToByte[256], mtfSymbol[256], *selectors;
164 uint32_t *dbuf; 164 uint32_t *dbuf;
165 unsigned origPtr; 165 unsigned origPtr, t;
166 166
167 dbuf = bd->dbuf; 167 dbuf = bd->dbuf;
168 dbufSize = bd->dbufSize; 168 dbufSize = bd->dbufSize;
diff --git a/archival/libarchive/decompress_unlzma.c b/archival/libarchive/decompress_unlzma.c
index c8622f97b..a9040877e 100644
--- a/archival/libarchive/decompress_unlzma.c
+++ b/archival/libarchive/decompress_unlzma.c
@@ -278,9 +278,10 @@ unpack_lzma_stream(transformer_state_t *xstate)
278 278
279 if (state >= LZMA_NUM_LIT_STATES) { 279 if (state >= LZMA_NUM_LIT_STATES) {
280 int match_byte; 280 int match_byte;
281 uint32_t pos = buffer_pos - rep0; 281 uint32_t pos;
282 282
283 while (pos >= header.dict_size) 283 pos = buffer_pos - rep0;
284 if ((int32_t)pos < 0)
284 pos += header.dict_size; 285 pos += header.dict_size;
285 match_byte = buffer[pos]; 286 match_byte = buffer[pos];
286 do { 287 do {
@@ -336,9 +337,11 @@ unpack_lzma_stream(transformer_state_t *xstate)
336 ); 337 );
337 if (!rc_is_bit_1(rc, prob2)) { 338 if (!rc_is_bit_1(rc, prob2)) {
338#if ENABLE_FEATURE_LZMA_FAST 339#if ENABLE_FEATURE_LZMA_FAST
339 uint32_t pos = buffer_pos - rep0; 340 uint32_t pos;
340 state = state < LZMA_NUM_LIT_STATES ? 9 : 11; 341 state = state < LZMA_NUM_LIT_STATES ? 9 : 11;
341 while (pos >= header.dict_size) 342
343 pos = buffer_pos - rep0;
344 if ((int32_t)pos < 0)
342 pos += header.dict_size; 345 pos += header.dict_size;
343 previous_byte = buffer[pos]; 346 previous_byte = buffer[pos];
344 goto one_byte1; 347 goto one_byte1;
@@ -429,10 +432,25 @@ unpack_lzma_stream(transformer_state_t *xstate)
429 } 432 }
430 433
431 len += LZMA_MATCH_MIN_LEN; 434 len += LZMA_MATCH_MIN_LEN;
435 /*
436 * LZMA SDK has this optimized:
437 * it precalculates size and copies many bytes
438 * in a loop with simpler checks, a-la:
439 * do
440 * *(dest) = *(dest + ofs);
441 * while (++dest != lim);
442 * and
443 * do {
444 * buffer[buffer_pos++] = buffer[pos];
445 * if (++pos == header.dict_size)
446 * pos = 0;
447 * } while (--cur_len != 0);
448 * Our code is slower (more checks per byte copy):
449 */
432 IF_NOT_FEATURE_LZMA_FAST(string:) 450 IF_NOT_FEATURE_LZMA_FAST(string:)
433 do { 451 do {
434 uint32_t pos = buffer_pos - rep0; 452 uint32_t pos = buffer_pos - rep0;
435 while (pos >= header.dict_size) 453 if ((int32_t)pos < 0)
436 pos += header.dict_size; 454 pos += header.dict_size;
437 previous_byte = buffer[pos]; 455 previous_byte = buffer[pos];
438 IF_NOT_FEATURE_LZMA_FAST(one_byte2:) 456 IF_NOT_FEATURE_LZMA_FAST(one_byte2:)
@@ -448,6 +466,9 @@ unpack_lzma_stream(transformer_state_t *xstate)
448 } while (len != 0 && buffer_pos < header.dst_size); 466 } while (len != 0 && buffer_pos < header.dst_size);
449 /* FIXME: ...........^^^^^ 467 /* FIXME: ...........^^^^^
450 * shouldn't it be "global_pos + buffer_pos < header.dst_size"? 468 * shouldn't it be "global_pos + buffer_pos < header.dst_size"?
469 * It probably should, but it is a "do we accidentally
470 * unpack more bytes than expected?" check - which
471 * never happens for well-formed compression data...
451 */ 472 */
452 } 473 }
453 } 474 }
diff --git a/archival/lzop.c b/archival/lzop.c
index e0e90ac6c..ca61add3c 100644
--- a/archival/lzop.c
+++ b/archival/lzop.c
@@ -53,7 +53,8 @@
53//config: and take up 3.2K of code. 53//config: and take up 3.2K of code.
54 54
55//applet:IF_LZOP(APPLET(lzop, BB_DIR_BIN, BB_SUID_DROP)) 55//applet:IF_LZOP(APPLET(lzop, BB_DIR_BIN, BB_SUID_DROP))
56//applet:IF_UNLZOP(APPLET_ODDNAME(unlzop, lzop, BB_DIR_USR_BIN, BB_SUID_DROP, unlzop)) 56// APPLET_ODDNAME:name main location suid_type help
57//applet:IF_UNLZOP( APPLET_ODDNAME(unlzop, lzop, BB_DIR_USR_BIN, BB_SUID_DROP, unlzop))
57//applet:IF_LZOPCAT(APPLET_ODDNAME(lzopcat, lzop, BB_DIR_USR_BIN, BB_SUID_DROP, lzopcat)) 58//applet:IF_LZOPCAT(APPLET_ODDNAME(lzopcat, lzop, BB_DIR_USR_BIN, BB_SUID_DROP, lzopcat))
58//kbuild:lib-$(CONFIG_LZOP) += lzop.o 59//kbuild:lib-$(CONFIG_LZOP) += lzop.o
59//kbuild:lib-$(CONFIG_UNLZOP) += lzop.o 60//kbuild:lib-$(CONFIG_UNLZOP) += lzop.o
diff --git a/archival/tar.c b/archival/tar.c
index c87d23597..34e3052ce 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -49,13 +49,15 @@
49//config: create compressed archives. It's probably the most widely used 49//config: create compressed archives. It's probably the most widely used
50//config: UNIX archive program. 50//config: UNIX archive program.
51//config: 51//config:
52//config:config FEATURE_TAR_LONG_OPTIONS
53//config: bool "Enable long options"
54//config: default y
55//config: depends on TAR && LONG_OPTS
56//config:
52//config:config FEATURE_TAR_CREATE 57//config:config FEATURE_TAR_CREATE
53//config: bool "Enable archive creation" 58//config: bool "Enable -c (archive creation)"
54//config: default y 59//config: default y
55//config: depends on TAR 60//config: depends on TAR
56//config: help
57//config: If you enable this option you'll be able to create
58//config: tar archives using the `-c' option.
59//config: 61//config:
60//config:config FEATURE_TAR_AUTODETECT 62//config:config FEATURE_TAR_AUTODETECT
61//config: bool "Autodetect compressed tarballs" 63//config: bool "Autodetect compressed tarballs"
@@ -74,7 +76,7 @@
74//config: a list of files to include or exclude from an archive. 76//config: a list of files to include or exclude from an archive.
75//config: 77//config:
76//config:config FEATURE_TAR_OLDGNU_COMPATIBILITY 78//config:config FEATURE_TAR_OLDGNU_COMPATIBILITY
77//config: bool "Support for old tar header format" 79//config: bool "Support old tar header format"
78//config: default y 80//config: default y
79//config: depends on TAR || DPKG 81//config: depends on TAR || DPKG
80//config: help 82//config: help
@@ -93,22 +95,12 @@
93//config: tarballs still exist. 95//config: tarballs still exist.
94//config: 96//config:
95//config:config FEATURE_TAR_GNU_EXTENSIONS 97//config:config FEATURE_TAR_GNU_EXTENSIONS
96//config: bool "Support for GNU tar extensions (long filenames)" 98//config: bool "Support GNU tar extensions (long filenames)"
97//config: default y 99//config: default y
98//config: depends on TAR || DPKG 100//config: depends on TAR || DPKG
99//config: help
100//config: With this option busybox supports GNU long filenames and
101//config: linknames.
102//config:
103//config:config FEATURE_TAR_LONG_OPTIONS
104//config: bool "Enable long options"
105//config: default y
106//config: depends on TAR && LONG_OPTS
107//config: help
108//config: Enable use of long options, increases size by about 400 Bytes
109//config: 101//config:
110//config:config FEATURE_TAR_TO_COMMAND 102//config:config FEATURE_TAR_TO_COMMAND
111//config: bool "Support for writing to an external program" 103//config: bool "Support writing to an external program (--to-command)"
112//config: default y 104//config: default y
113//config: depends on TAR && FEATURE_TAR_LONG_OPTIONS 105//config: depends on TAR && FEATURE_TAR_LONG_OPTIONS
114//config: help 106//config: help
@@ -121,20 +113,17 @@
121//config: default y 113//config: default y
122//config: depends on TAR 114//config: depends on TAR
123//config: help 115//config: help
124//config: Enables use of user and group names in tar. This affects contents 116//config: Enable use of user and group names in tar. This affects contents
125//config: listings (-t) and preserving permissions when unpacking (-p). 117//config: listings (-t) and preserving permissions when unpacking (-p).
126//config: +200 bytes. 118//config: +200 bytes.
127//config: 119//config:
128//config:config FEATURE_TAR_NOPRESERVE_TIME 120//config:config FEATURE_TAR_NOPRESERVE_TIME
129//config: bool "Enable -m (do not preserve time) option" 121//config: bool "Enable -m (do not preserve time) GNU option"
130//config: default y 122//config: default y
131//config: depends on TAR 123//config: depends on TAR
132//config: help
133//config: With this option busybox supports GNU tar -m
134//config: (do not preserve time) option.
135//config: 124//config:
136//config:config FEATURE_TAR_SELINUX 125//config:config FEATURE_TAR_SELINUX
137//config: bool "Support for extracting SELinux labels" 126//config: bool "Support extracting SELinux labels"
138//config: default n 127//config: default n
139//config: depends on TAR && SELINUX 128//config: depends on TAR && SELINUX
140//config: help 129//config: help
diff --git a/archival/unzip.c b/archival/unzip.c
index 9ad03d0e2..56989fa0b 100644
--- a/archival/unzip.c
+++ b/archival/unzip.c
@@ -34,6 +34,23 @@
34//config: ZIP files without deleted/updated files, SFX archives etc, 34//config: ZIP files without deleted/updated files, SFX archives etc,
35//config: you can reduce code size by unselecting this option. 35//config: you can reduce code size by unselecting this option.
36//config: To support less trivial ZIPs, say Y. 36//config: To support less trivial ZIPs, say Y.
37//config:
38//config:config FEATURE_UNZIP_BZIP2
39//config: bool "Support compression method 12 (bzip2)"
40//config: default y
41//config: depends on FEATURE_UNZIP_CDF && DESKTOP
42// FEATURE_UNZIP_CDF is needed, otherwise we can't find start of next file
43// DESKTOP is needed to get back uncompressed length
44//config:
45//config:config FEATURE_UNZIP_LZMA
46//config: bool "Support compression method 14 (lzma)"
47//config: default y
48//config: depends on FEATURE_UNZIP_CDF && DESKTOP
49//config:
50//config:config FEATURE_UNZIP_XZ
51//config: bool "Support compression method 95 (xz)"
52//config: default y
53//config: depends on FEATURE_UNZIP_CDF && DESKTOP
37 54
38//applet:IF_UNZIP(APPLET(unzip, BB_DIR_USR_BIN, BB_SUID_DROP)) 55//applet:IF_UNZIP(APPLET(unzip, BB_DIR_USR_BIN, BB_SUID_DROP))
39//kbuild:lib-$(CONFIG_UNZIP) += unzip.o 56//kbuild:lib-$(CONFIG_UNZIP) += unzip.o
@@ -65,8 +82,8 @@
65enum { 82enum {
66#if BB_BIG_ENDIAN 83#if BB_BIG_ENDIAN
67 ZIP_FILEHEADER_MAGIC = 0x504b0304, 84 ZIP_FILEHEADER_MAGIC = 0x504b0304,
68 ZIP_CDF_MAGIC = 0x504b0102, /* central directory's file header */ 85 ZIP_CDF_MAGIC = 0x504b0102, /* CDF item */
69 ZIP_CDE_MAGIC = 0x504b0506, /* "end of central directory" record */ 86 ZIP_CDE_MAGIC = 0x504b0506, /* End of CDF */
70 ZIP_DD_MAGIC = 0x504b0708, 87 ZIP_DD_MAGIC = 0x504b0708,
71#else 88#else
72 ZIP_FILEHEADER_MAGIC = 0x04034b50, 89 ZIP_FILEHEADER_MAGIC = 0x04034b50,
@@ -94,16 +111,16 @@ typedef union {
94 /* filename follows (not NUL terminated) */ 111 /* filename follows (not NUL terminated) */
95 /* extra field follows */ 112 /* extra field follows */
96 /* data follows */ 113 /* data follows */
97 } formatted PACKED; 114 } fmt PACKED;
98} zip_header_t; /* PACKED - gcc 4.2.1 doesn't like it (spews warning) */ 115} zip_header_t; /* PACKED - gcc 4.2.1 doesn't like it (spews warning) */
99 116
100#define FIX_ENDIANNESS_ZIP(zip_header) \ 117#define FIX_ENDIANNESS_ZIP(zip) \
101do { if (BB_BIG_ENDIAN) { \ 118do { if (BB_BIG_ENDIAN) { \
102 (zip_header).formatted.crc32 = SWAP_LE32((zip_header).formatted.crc32 ); \ 119 (zip).fmt.crc32 = SWAP_LE32((zip).fmt.crc32 ); \
103 (zip_header).formatted.cmpsize = SWAP_LE32((zip_header).formatted.cmpsize ); \ 120 (zip).fmt.cmpsize = SWAP_LE32((zip).fmt.cmpsize ); \
104 (zip_header).formatted.ucmpsize = SWAP_LE32((zip_header).formatted.ucmpsize ); \ 121 (zip).fmt.ucmpsize = SWAP_LE32((zip).fmt.ucmpsize ); \
105 (zip_header).formatted.filename_len = SWAP_LE16((zip_header).formatted.filename_len); \ 122 (zip).fmt.filename_len = SWAP_LE16((zip).fmt.filename_len); \
106 (zip_header).formatted.extra_len = SWAP_LE16((zip_header).formatted.extra_len ); \ 123 (zip).fmt.extra_len = SWAP_LE16((zip).fmt.extra_len ); \
107}} while (0) 124}} while (0)
108 125
109#define CDF_HEADER_LEN 42 126#define CDF_HEADER_LEN 42
@@ -121,39 +138,39 @@ typedef union {
121 uint32_t crc32; /* 12-15 */ 138 uint32_t crc32; /* 12-15 */
122 uint32_t cmpsize; /* 16-19 */ 139 uint32_t cmpsize; /* 16-19 */
123 uint32_t ucmpsize; /* 20-23 */ 140 uint32_t ucmpsize; /* 20-23 */
124 uint16_t file_name_length; /* 24-25 */ 141 uint16_t filename_len; /* 24-25 */
125 uint16_t extra_field_length; /* 26-27 */ 142 uint16_t extra_len; /* 26-27 */
126 uint16_t file_comment_length; /* 28-29 */ 143 uint16_t file_comment_length; /* 28-29 */
127 uint16_t disk_number_start; /* 30-31 */ 144 uint16_t disk_number_start; /* 30-31 */
128 uint16_t internal_file_attributes; /* 32-33 */ 145 uint16_t internal_attributes; /* 32-33 */
129 uint32_t external_file_attributes PACKED; /* 34-37 */ 146 uint32_t external_attributes PACKED; /* 34-37 */
130 uint32_t relative_offset_of_local_header PACKED; /* 38-41 */ 147 uint32_t relative_offset_of_local_header PACKED; /* 38-41 */
131 /* filename follows (not NUL terminated) */ 148 /* filename follows (not NUL terminated) */
132 /* extra field follows */ 149 /* extra field follows */
133 /* comment follows */ 150 /* file comment follows */
134 } formatted PACKED; 151 } fmt PACKED;
135} cdf_header_t; 152} cdf_header_t;
136 153
137#define FIX_ENDIANNESS_CDF(cdf_header) \ 154#define FIX_ENDIANNESS_CDF(cdf) \
138do { if (BB_BIG_ENDIAN) { \ 155do { if (BB_BIG_ENDIAN) { \
139 (cdf_header).formatted.version_made_by = SWAP_LE16((cdf_header).formatted.version_made_by); \ 156 (cdf).fmt.version_made_by = SWAP_LE16((cdf).fmt.version_made_by); \
140 (cdf_header).formatted.version_needed = SWAP_LE16((cdf_header).formatted.version_needed); \ 157 (cdf).fmt.version_needed = SWAP_LE16((cdf).fmt.version_needed); \
141 (cdf_header).formatted.method = SWAP_LE16((cdf_header).formatted.method ); \ 158 (cdf).fmt.method = SWAP_LE16((cdf).fmt.method ); \
142 (cdf_header).formatted.modtime = SWAP_LE16((cdf_header).formatted.modtime ); \ 159 (cdf).fmt.modtime = SWAP_LE16((cdf).fmt.modtime ); \
143 (cdf_header).formatted.moddate = SWAP_LE16((cdf_header).formatted.moddate ); \ 160 (cdf).fmt.moddate = SWAP_LE16((cdf).fmt.moddate ); \
144 (cdf_header).formatted.crc32 = SWAP_LE32((cdf_header).formatted.crc32 ); \ 161 (cdf).fmt.crc32 = SWAP_LE32((cdf).fmt.crc32 ); \
145 (cdf_header).formatted.cmpsize = SWAP_LE32((cdf_header).formatted.cmpsize ); \ 162 (cdf).fmt.cmpsize = SWAP_LE32((cdf).fmt.cmpsize ); \
146 (cdf_header).formatted.ucmpsize = SWAP_LE32((cdf_header).formatted.ucmpsize ); \ 163 (cdf).fmt.ucmpsize = SWAP_LE32((cdf).fmt.ucmpsize ); \
147 (cdf_header).formatted.file_name_length = SWAP_LE16((cdf_header).formatted.file_name_length); \ 164 (cdf).fmt.filename_len = SWAP_LE16((cdf).fmt.filename_len); \
148 (cdf_header).formatted.extra_field_length = SWAP_LE16((cdf_header).formatted.extra_field_length); \ 165 (cdf).fmt.extra_len = SWAP_LE16((cdf).fmt.extra_len ); \
149 (cdf_header).formatted.file_comment_length = SWAP_LE16((cdf_header).formatted.file_comment_length); \ 166 (cdf).fmt.file_comment_length = SWAP_LE16((cdf).fmt.file_comment_length); \
150 (cdf_header).formatted.external_file_attributes = SWAP_LE32((cdf_header).formatted.external_file_attributes); \ 167 (cdf).fmt.external_attributes = SWAP_LE32((cdf).fmt.external_attributes); \
151}} while (0) 168}} while (0)
152 169
153#define CDE_HEADER_LEN 16 170#define CDE_LEN 16
154 171
155typedef union { 172typedef union {
156 uint8_t raw[CDE_HEADER_LEN]; 173 uint8_t raw[CDE_LEN];
157 struct { 174 struct {
158 /* uint32_t signature; 50 4b 05 06 */ 175 /* uint32_t signature; 50 4b 05 06 */
159 uint16_t this_disk_no; 176 uint16_t this_disk_no;
@@ -162,14 +179,14 @@ typedef union {
162 uint16_t cdf_entries_total; 179 uint16_t cdf_entries_total;
163 uint32_t cdf_size; 180 uint32_t cdf_size;
164 uint32_t cdf_offset; 181 uint32_t cdf_offset;
165 /* uint16_t file_comment_length; */ 182 /* uint16_t archive_comment_length; */
166 /* .ZIP file comment (variable size) */ 183 /* archive comment follows */
167 } formatted PACKED; 184 } fmt PACKED;
168} cde_header_t; 185} cde_t;
169 186
170#define FIX_ENDIANNESS_CDE(cde_header) \ 187#define FIX_ENDIANNESS_CDE(cde) \
171do { if (BB_BIG_ENDIAN) { \ 188do { if (BB_BIG_ENDIAN) { \
172 (cde_header).formatted.cdf_offset = SWAP_LE32((cde_header).formatted.cdf_offset); \ 189 (cde).fmt.cdf_offset = SWAP_LE32((cde).fmt.cdf_offset); \
173}} while (0) 190}} while (0)
174 191
175struct BUG { 192struct BUG {
@@ -178,13 +195,13 @@ struct BUG {
178 * even though the elements are all in the right place. 195 * even though the elements are all in the right place.
179 */ 196 */
180 char BUG_zip_header_must_be_26_bytes[ 197 char BUG_zip_header_must_be_26_bytes[
181 offsetof(zip_header_t, formatted.extra_len) + 2 198 offsetof(zip_header_t, fmt.extra_len) + 2
182 == ZIP_HEADER_LEN ? 1 : -1]; 199 == ZIP_HEADER_LEN ? 1 : -1];
183 char BUG_cdf_header_must_be_42_bytes[ 200 char BUG_cdf_header_must_be_42_bytes[
184 offsetof(cdf_header_t, formatted.relative_offset_of_local_header) + 4 201 offsetof(cdf_header_t, fmt.relative_offset_of_local_header) + 4
185 == CDF_HEADER_LEN ? 1 : -1]; 202 == CDF_HEADER_LEN ? 1 : -1];
186 char BUG_cde_header_must_be_16_bytes[ 203 char BUG_cde_must_be_16_bytes[
187 sizeof(cde_header_t) == CDE_HEADER_LEN ? 1 : -1]; 204 sizeof(cde_t) == CDE_LEN ? 1 : -1];
188}; 205};
189 206
190 207
@@ -210,7 +227,7 @@ enum { zip_fd = 3 };
210/* NB: does not preserve file position! */ 227/* NB: does not preserve file position! */
211static uint32_t find_cdf_offset(void) 228static uint32_t find_cdf_offset(void)
212{ 229{
213 cde_header_t cde_header; 230 cde_t cde;
214 unsigned char *buf; 231 unsigned char *buf;
215 unsigned char *p; 232 unsigned char *p;
216 off_t end; 233 off_t end;
@@ -231,7 +248,7 @@ static uint32_t find_cdf_offset(void)
231 248
232 found = BAD_CDF_OFFSET; 249 found = BAD_CDF_OFFSET;
233 p = buf; 250 p = buf;
234 while (p <= buf + PEEK_FROM_END - CDE_HEADER_LEN - 4) { 251 while (p <= buf + PEEK_FROM_END - CDE_LEN - 4) {
235 if (*p != 'P') { 252 if (*p != 'P') {
236 p++; 253 p++;
237 continue; 254 continue;
@@ -243,19 +260,19 @@ static uint32_t find_cdf_offset(void)
243 if (*++p != 6) 260 if (*++p != 6)
244 continue; 261 continue;
245 /* we found CDE! */ 262 /* we found CDE! */
246 memcpy(cde_header.raw, p + 1, CDE_HEADER_LEN); 263 memcpy(cde.raw, p + 1, CDE_LEN);
247 FIX_ENDIANNESS_CDE(cde_header); 264 FIX_ENDIANNESS_CDE(cde);
248 /* 265 /*
249 * I've seen .ZIP files with seemingly valid CDEs 266 * I've seen .ZIP files with seemingly valid CDEs
250 * where cdf_offset points past EOF - ?? 267 * where cdf_offset points past EOF - ??
251 * This check ignores such CDEs: 268 * This check ignores such CDEs:
252 */ 269 */
253 if (cde_header.formatted.cdf_offset < end + (p - buf)) { 270 if (cde.fmt.cdf_offset < end + (p - buf)) {
254 found = cde_header.formatted.cdf_offset; 271 found = cde.fmt.cdf_offset;
255 dbg("Possible cdf_offset:0x%x at 0x%"OFF_FMT"x", 272 dbg("Possible cdf_offset:0x%x at 0x%"OFF_FMT"x",
256 (unsigned)found, end + (p-3 - buf)); 273 (unsigned)found, end + (p-3 - buf));
257 dbg(" cdf_offset+cdf_size:0x%x", 274 dbg(" cdf_offset+cdf_size:0x%x",
258 (unsigned)(found + SWAP_LE32(cde_header.formatted.cdf_size))); 275 (unsigned)(found + SWAP_LE32(cde.fmt.cdf_size)));
259 /* 276 /*
260 * We do not "break" here because only the last CDE is valid. 277 * We do not "break" here because only the last CDE is valid.
261 * I've seen a .zip archive which contained a .zip file, 278 * I've seen a .zip archive which contained a .zip file,
@@ -269,7 +286,7 @@ static uint32_t find_cdf_offset(void)
269 return found; 286 return found;
270}; 287};
271 288
272static uint32_t read_next_cdf(uint32_t cdf_offset, cdf_header_t *cdf_ptr) 289static uint32_t read_next_cdf(uint32_t cdf_offset, cdf_header_t *cdf)
273{ 290{
274 uint32_t magic; 291 uint32_t magic;
275 292
@@ -279,23 +296,25 @@ static uint32_t read_next_cdf(uint32_t cdf_offset, cdf_header_t *cdf_ptr)
279 dbg("Reading CDF at 0x%x", (unsigned)cdf_offset); 296 dbg("Reading CDF at 0x%x", (unsigned)cdf_offset);
280 xlseek(zip_fd, cdf_offset, SEEK_SET); 297 xlseek(zip_fd, cdf_offset, SEEK_SET);
281 xread(zip_fd, &magic, 4); 298 xread(zip_fd, &magic, 4);
282 /* Central Directory End? */ 299 /* Central Directory End? Assume CDF has ended.
300 * (more correct method is to use cde.cdf_entries_total counter)
301 */
283 if (magic == ZIP_CDE_MAGIC) { 302 if (magic == ZIP_CDE_MAGIC) {
284 dbg("got ZIP_CDE_MAGIC"); 303 dbg("got ZIP_CDE_MAGIC");
285 return 0; /* EOF */ 304 return 0; /* EOF */
286 } 305 }
287 xread(zip_fd, cdf_ptr->raw, CDF_HEADER_LEN); 306 xread(zip_fd, cdf->raw, CDF_HEADER_LEN);
288 307
289 FIX_ENDIANNESS_CDF(*cdf_ptr); 308 FIX_ENDIANNESS_CDF(*cdf);
290 dbg(" file_name_length:%u extra_field_length:%u file_comment_length:%u", 309 dbg(" filename_len:%u extra_len:%u file_comment_length:%u",
291 (unsigned)cdf_ptr->formatted.file_name_length, 310 (unsigned)cdf->fmt.filename_len,
292 (unsigned)cdf_ptr->formatted.extra_field_length, 311 (unsigned)cdf->fmt.extra_len,
293 (unsigned)cdf_ptr->formatted.file_comment_length 312 (unsigned)cdf->fmt.file_comment_length
294 ); 313 );
295 cdf_offset += 4 + CDF_HEADER_LEN 314 cdf_offset += 4 + CDF_HEADER_LEN
296 + cdf_ptr->formatted.file_name_length 315 + cdf->fmt.filename_len
297 + cdf_ptr->formatted.extra_field_length 316 + cdf->fmt.extra_len
298 + cdf_ptr->formatted.file_comment_length; 317 + cdf->fmt.file_comment_length;
299 318
300 return cdf_offset; 319 return cdf_offset;
301}; 320};
@@ -318,34 +337,67 @@ static void unzip_create_leading_dirs(const char *fn)
318 free(name); 337 free(name);
319} 338}
320 339
321static void unzip_extract(zip_header_t *zip_header, int dst_fd) 340static void unzip_extract(zip_header_t *zip, int dst_fd)
322{ 341{
323 if (zip_header->formatted.method == 0) { 342 transformer_state_t xstate;
343
344 if (zip->fmt.method == 0) {
324 /* Method 0 - stored (not compressed) */ 345 /* Method 0 - stored (not compressed) */
325 off_t size = zip_header->formatted.ucmpsize; 346 off_t size = zip->fmt.ucmpsize;
326 if (size) 347 if (size)
327 bb_copyfd_exact_size(zip_fd, dst_fd, size); 348 bb_copyfd_exact_size(zip_fd, dst_fd, size);
328 } else { 349 return;
350 }
351
352 init_transformer_state(&xstate);
353 xstate.bytes_in = zip->fmt.cmpsize;
354 xstate.src_fd = zip_fd;
355 xstate.dst_fd = dst_fd;
356 if (zip->fmt.method == 8) {
329 /* Method 8 - inflate */ 357 /* Method 8 - inflate */
330 transformer_state_t xstate;
331 init_transformer_state(&xstate);
332 xstate.bytes_in = zip_header->formatted.cmpsize;
333 xstate.src_fd = zip_fd;
334 xstate.dst_fd = dst_fd;
335 if (inflate_unzip(&xstate) < 0) 358 if (inflate_unzip(&xstate) < 0)
336 bb_error_msg_and_die("inflate error"); 359 bb_error_msg_and_die("inflate error");
337 /* Validate decompression - crc */ 360 /* Validate decompression - crc */
338 if (zip_header->formatted.crc32 != (xstate.crc32 ^ 0xffffffffL)) { 361 if (zip->fmt.crc32 != (xstate.crc32 ^ 0xffffffffL)) {
339 bb_error_msg_and_die("crc error"); 362 bb_error_msg_and_die("crc error");
340 } 363 }
341 /* Validate decompression - size */
342 if (zip_header->formatted.ucmpsize != xstate.bytes_out) {
343 /* Don't die. Who knows, maybe len calculation
344 * was botched somewhere. After all, crc matched! */
345 bb_error_msg("bad length");
346 }
347 } 364 }
348 /* TODO? method 12: bzip2, method 14: LZMA */ 365#if ENABLE_FEATURE_UNZIP_BZIP2
366 else if (zip->fmt.method == 12) {
367 /* Tested. Unpacker reads too much, but we use CDF
368 * and will seek to the correct beginning of next file.
369 */
370 xstate.bytes_out = unpack_bz2_stream(&xstate);
371 if (xstate.bytes_out < 0)
372 bb_error_msg_and_die("inflate error");
373 }
374#endif
375#if ENABLE_FEATURE_UNZIP_LZMA
376 else if (zip->fmt.method == 14) {
377 /* Not tested yet */
378 xstate.bytes_out = unpack_lzma_stream(&xstate);
379 if (xstate.bytes_out < 0)
380 bb_error_msg_and_die("inflate error");
381 }
382#endif
383#if ENABLE_FEATURE_UNZIP_XZ
384 else if (zip->fmt.method == 95) {
385 /* Not tested yet */
386 xstate.bytes_out = unpack_xz_stream(&xstate);
387 if (xstate.bytes_out < 0)
388 bb_error_msg_and_die("inflate error");
389 }
390#endif
391 else {
392 bb_error_msg_and_die("unsupported method %u", zip->fmt.method);
393 }
394
395 /* Validate decompression - size */
396 if (zip->fmt.ucmpsize != xstate.bytes_out) {
397 /* Don't die. Who knows, maybe len calculation
398 * was botched somewhere. After all, crc matched! */
399 bb_error_msg("bad length");
400 }
349} 401}
350 402
351static void my_fgets80(char *buf80) 403static void my_fgets80(char *buf80)
@@ -566,7 +618,7 @@ int unzip_main(int argc, char **argv)
566 total_entries = 0; 618 total_entries = 0;
567 cdf_offset = find_cdf_offset(); /* try to seek to the end, find CDE and CDF start */ 619 cdf_offset = find_cdf_offset(); /* try to seek to the end, find CDE and CDF start */
568 while (1) { 620 while (1) {
569 zip_header_t zip_header; 621 zip_header_t zip;
570 mode_t dir_mode = 0777; 622 mode_t dir_mode = 0777;
571#if ENABLE_FEATURE_UNZIP_CDF 623#if ENABLE_FEATURE_UNZIP_CDF
572 mode_t file_mode = 0666; 624 mode_t file_mode = 0666;
@@ -592,7 +644,7 @@ int unzip_main(int argc, char **argv)
592 644
593 /* Check magic number */ 645 /* Check magic number */
594 xread(zip_fd, &magic, 4); 646 xread(zip_fd, &magic, 4);
595 /* Central directory? It's at the end, so exit */ 647 /* CDF item? Assume there are no more files, exit */
596 if (magic == ZIP_CDF_MAGIC) { 648 if (magic == ZIP_CDF_MAGIC) {
597 dbg("got ZIP_CDF_MAGIC"); 649 dbg("got ZIP_CDF_MAGIC");
598 break; 650 break;
@@ -608,71 +660,70 @@ int unzip_main(int argc, char **argv)
608 bb_error_msg_and_die("invalid zip magic %08X", (int)magic); 660 bb_error_msg_and_die("invalid zip magic %08X", (int)magic);
609 dbg("got ZIP_FILEHEADER_MAGIC"); 661 dbg("got ZIP_FILEHEADER_MAGIC");
610 662
611 xread(zip_fd, zip_header.raw, ZIP_HEADER_LEN); 663 xread(zip_fd, zip.raw, ZIP_HEADER_LEN);
612 FIX_ENDIANNESS_ZIP(zip_header); 664 FIX_ENDIANNESS_ZIP(zip);
613 if ((zip_header.formatted.method != 0) 665 if (zip.fmt.zip_flags & SWAP_LE16(0x0008)) {
614 && (zip_header.formatted.method != 8) 666 bb_error_msg_and_die("zip flag %s is not supported",
615 ) { 667 "8 (streaming)");
616 /* TODO? method 12: bzip2, method 14: LZMA */
617 bb_error_msg_and_die("unsupported method %d", zip_header.formatted.method);
618 }
619 if (zip_header.formatted.zip_flags & SWAP_LE16(0x0009)) {
620 bb_error_msg_and_die("zip flags 1 and 8 are not supported");
621 } 668 }
622 } 669 }
623#if ENABLE_FEATURE_UNZIP_CDF 670#if ENABLE_FEATURE_UNZIP_CDF
624 else { 671 else {
625 /* cdf_offset is valid (and we know the file is seekable) */ 672 /* cdf_offset is valid (and we know the file is seekable) */
626 cdf_header_t cdf_header; 673 cdf_header_t cdf;
627 cdf_offset = read_next_cdf(cdf_offset, &cdf_header); 674 cdf_offset = read_next_cdf(cdf_offset, &cdf);
628 if (cdf_offset == 0) /* EOF? */ 675 if (cdf_offset == 0) /* EOF? */
629 break; 676 break;
630# if 1 677# if 1
631 xlseek(zip_fd, 678 xlseek(zip_fd,
632 SWAP_LE32(cdf_header.formatted.relative_offset_of_local_header) + 4, 679 SWAP_LE32(cdf.fmt.relative_offset_of_local_header) + 4,
633 SEEK_SET); 680 SEEK_SET);
634 xread(zip_fd, zip_header.raw, ZIP_HEADER_LEN); 681 xread(zip_fd, zip.raw, ZIP_HEADER_LEN);
635 FIX_ENDIANNESS_ZIP(zip_header); 682 FIX_ENDIANNESS_ZIP(zip);
636 if (zip_header.formatted.zip_flags & SWAP_LE16(0x0008)) { 683 if (zip.fmt.zip_flags & SWAP_LE16(0x0008)) {
637 /* 0x0008 - streaming. [u]cmpsize can be reliably gotten 684 /* 0x0008 - streaming. [u]cmpsize can be reliably gotten
638 * only from Central Directory. 685 * only from Central Directory.
639 */ 686 */
640 zip_header.formatted.crc32 = cdf_header.formatted.crc32; 687 zip.fmt.crc32 = cdf.fmt.crc32;
641 zip_header.formatted.cmpsize = cdf_header.formatted.cmpsize; 688 zip.fmt.cmpsize = cdf.fmt.cmpsize;
642 zip_header.formatted.ucmpsize = cdf_header.formatted.ucmpsize; 689 zip.fmt.ucmpsize = cdf.fmt.ucmpsize;
643 } 690 }
644# else 691# else
645 /* CDF has the same data as local header, no need to read the latter */ 692 /* CDF has the same data as local header, no need to read the latter...
646 memcpy(&zip_header.formatted.version, 693 * ...not really. An archive was seen with cdf.extra_len == 6 but
647 &cdf_header.formatted.version_needed, ZIP_HEADER_LEN); 694 * zip.extra_len == 0.
695 */
696 memcpy(&zip.fmt.version,
697 &cdf.fmt.version_needed, ZIP_HEADER_LEN);
648 xlseek(zip_fd, 698 xlseek(zip_fd,
649 SWAP_LE32(cdf_header.formatted.relative_offset_of_local_header) + 4 + ZIP_HEADER_LEN, 699 SWAP_LE32(cdf.fmt.relative_offset_of_local_header) + 4 + ZIP_HEADER_LEN,
650 SEEK_SET); 700 SEEK_SET);
651# endif 701# endif
652 if ((cdf_header.formatted.version_made_by >> 8) == 3) { 702 if ((cdf.fmt.version_made_by >> 8) == 3) {
653 /* This archive is created on Unix */ 703 /* This archive is created on Unix */
654 dir_mode = file_mode = (cdf_header.formatted.external_file_attributes >> 16); 704 dir_mode = file_mode = (cdf.fmt.external_attributes >> 16);
655 } 705 }
656 } 706 }
657#endif 707#endif
658 708
659 if (zip_header.formatted.zip_flags & SWAP_LE16(0x0001)) { 709 if (zip.fmt.zip_flags & SWAP_LE16(0x0001)) {
660 /* 0x0001 - encrypted */ 710 /* 0x0001 - encrypted */
661 bb_error_msg_and_die("zip flag 1 (encryption) is not supported"); 711 bb_error_msg_and_die("zip flag %s is not supported",
712 "1 (encryption)");
662 } 713 }
663 dbg("File cmpsize:0x%x extra_len:0x%x ucmpsize:0x%x", 714 dbg("File cmpsize:0x%x extra_len:0x%x ucmpsize:0x%x",
664 (unsigned)zip_header.formatted.cmpsize, 715 (unsigned)zip.fmt.cmpsize,
665 (unsigned)zip_header.formatted.extra_len, 716 (unsigned)zip.fmt.extra_len,
666 (unsigned)zip_header.formatted.ucmpsize 717 (unsigned)zip.fmt.ucmpsize
667 ); 718 );
668 719
669 /* Read filename */ 720 /* Read filename */
670 free(dst_fn); 721 free(dst_fn);
671 dst_fn = xzalloc(zip_header.formatted.filename_len + 1); 722 dst_fn = xzalloc(zip.fmt.filename_len + 1);
672 xread(zip_fd, dst_fn, zip_header.formatted.filename_len); 723 xread(zip_fd, dst_fn, zip.fmt.filename_len);
673 724
674 /* Skip extra header bytes */ 725 /* Skip extra header bytes */
675 unzip_skip(zip_header.formatted.extra_len); 726 unzip_skip(zip.fmt.extra_len);
676 727
677 /* Guard against "/abspath", "/../" and similar attacks */ 728 /* Guard against "/abspath", "/../" and similar attacks */
678 overlapping_strcpy(dst_fn, strip_unsafe_prefix(dst_fn)); 729 overlapping_strcpy(dst_fn, strip_unsafe_prefix(dst_fn));
@@ -681,129 +732,129 @@ int unzip_main(int argc, char **argv)
681 if (find_list_entry(zreject, dst_fn) 732 if (find_list_entry(zreject, dst_fn)
682 || (zaccept && !find_list_entry(zaccept, dst_fn)) 733 || (zaccept && !find_list_entry(zaccept, dst_fn))
683 ) { /* Skip entry */ 734 ) { /* Skip entry */
684 i = 'n'; 735 goto skip_cmpsize;
685 } else { 736 }
686 if (listing) { 737
687 /* List entry */ 738 if (listing) {
688 char dtbuf[sizeof("mm-dd-yyyy hh:mm")]; 739 /* List entry */
689 sprintf(dtbuf, "%02u-%02u-%04u %02u:%02u", 740 char dtbuf[sizeof("mm-dd-yyyy hh:mm")];
690 (zip_header.formatted.moddate >> 5) & 0xf, // mm: 0x01e0 741 sprintf(dtbuf, "%02u-%02u-%04u %02u:%02u",
691 (zip_header.formatted.moddate) & 0x1f, // dd: 0x001f 742 (zip.fmt.moddate >> 5) & 0xf, // mm: 0x01e0
692 (zip_header.formatted.moddate >> 9) + 1980, // yy: 0xfe00 743 (zip.fmt.moddate) & 0x1f, // dd: 0x001f
693 (zip_header.formatted.modtime >> 11), // hh: 0xf800 744 (zip.fmt.moddate >> 9) + 1980, // yy: 0xfe00
694 (zip_header.formatted.modtime >> 5) & 0x3f // mm: 0x07e0 745 (zip.fmt.modtime >> 11), // hh: 0xf800
695 // seconds/2 are not shown, encoded in ----------- 0x001f 746 (zip.fmt.modtime >> 5) & 0x3f // mm: 0x07e0
696 ); 747 // seconds/2 not shown, encoded in -- 0x001f
697 if (!verbose) { 748 );
698 // " Length Date Time Name\n" 749 if (!verbose) {
699 // "--------- ---------- ----- ----" 750 // " Length Date Time Name\n"
700 printf( "%9u " "%s " "%s\n", 751 // "--------- ---------- ----- ----"
701 (unsigned)zip_header.formatted.ucmpsize, 752 printf( "%9u " "%s " "%s\n",
702 dtbuf, 753 (unsigned)zip.fmt.ucmpsize,
703 dst_fn); 754 dtbuf,
704 } else { 755 dst_fn);
705 unsigned long percents = zip_header.formatted.ucmpsize - zip_header.formatted.cmpsize; 756 } else {
706 if ((int32_t)percents < 0) 757 char method6[7];
707 percents = 0; /* happens if ucmpsize < cmpsize */ 758 unsigned long percents;
708 percents = percents * 100; 759
709 if (zip_header.formatted.ucmpsize) 760 sprintf(method6, "%6u", zip.fmt.method);
710 percents /= zip_header.formatted.ucmpsize; 761 if (zip.fmt.method == 0) {
711 // " Length Method Size Cmpr Date Time CRC-32 Name\n" 762 strcpy(method6, "Stored");
712 // "-------- ------ ------- ---- ---------- ----- -------- ----" 763 }
713 printf( "%8u %s" "%9u%4u%% " "%s " "%08x " "%s\n", 764 if (zip.fmt.method == 8) {
714 (unsigned)zip_header.formatted.ucmpsize, 765 strcpy(method6, "Defl:N");
715 zip_header.formatted.method == 0 ? "Stored" : "Defl:N", /* Defl is method 8 */ 766 /* normal, maximum, fast, superfast */
716/* TODO: show other methods? 767 IF_DESKTOP(method6[5] = "NXFS"[(zip.fmt.zip_flags >> 1) & 3];)
717 * 1 - Shrunk
718 * 2 - Reduced with compression factor 1
719 * 3 - Reduced with compression factor 2
720 * 4 - Reduced with compression factor 3
721 * 5 - Reduced with compression factor 4
722 * 6 - Imploded
723 * 7 - Reserved for Tokenizing compression algorithm
724 * 9 - Deflate64
725 * 10 - PKWARE Data Compression Library Imploding
726 * 11 - Reserved by PKWARE
727 * 12 - BZIP2
728 */
729 (unsigned)zip_header.formatted.cmpsize,
730 (unsigned)percents,
731 dtbuf,
732 zip_header.formatted.crc32,
733 dst_fn);
734 total_size += zip_header.formatted.cmpsize;
735 } 768 }
736 total_usize += zip_header.formatted.ucmpsize; 769 percents = zip.fmt.ucmpsize - zip.fmt.cmpsize;
737 i = 'n'; 770 if ((int32_t)percents < 0)
738 } else if (dst_fd == STDOUT_FILENO) { 771 percents = 0; /* happens if ucmpsize < cmpsize */
739 /* Extracting to STDOUT */ 772 percents = percents * 100;
740 i = -1; 773 if (zip.fmt.ucmpsize)
741 } else if (last_char_is(dst_fn, '/')) { 774 percents /= zip.fmt.ucmpsize;
742 /* Extract directory */ 775 // " Length Method Size Cmpr Date Time CRC-32 Name\n"
743 if (stat(dst_fn, &stat_buf) == -1) { 776 // "-------- ------ ------- ---- ---------- ----- -------- ----"
744 if (errno != ENOENT) { 777 printf( "%8u %s" "%9u%4u%% " "%s " "%08x " "%s\n",
745 bb_perror_msg_and_die("can't stat '%s'", dst_fn); 778 (unsigned)zip.fmt.ucmpsize,
746 } 779 method6,
747 if (!quiet) { 780 (unsigned)zip.fmt.cmpsize,
748 printf(" creating: %s\n", dst_fn); 781 (unsigned)percents,
749 } 782 dtbuf,
750 unzip_create_leading_dirs(dst_fn); 783 zip.fmt.crc32,
751 if (bb_make_directory(dst_fn, dir_mode, FILEUTILS_IGNORE_CHMOD_ERR)) { 784 dst_fn);
752 xfunc_die(); 785 total_size += zip.fmt.cmpsize;
753 } 786 }
754 } else { 787 total_usize += zip.fmt.ucmpsize;
755 if (!S_ISDIR(stat_buf.st_mode)) { 788 goto skip_cmpsize;
756 bb_error_msg_and_die("'%s' exists but is not a %s", 789 }
757 dst_fn, "directory"); 790
758 } 791 if (dst_fd == STDOUT_FILENO) {
792 /* Extracting to STDOUT */
793 goto do_extract;
794 }
795 if (last_char_is(dst_fn, '/')) {
796 /* Extract directory */
797 if (stat(dst_fn, &stat_buf) == -1) {
798 if (errno != ENOENT) {
799 bb_perror_msg_and_die("can't stat '%s'", dst_fn);
800 }
801 if (!quiet) {
802 printf(" creating: %s\n", dst_fn);
803 }
804 unzip_create_leading_dirs(dst_fn);
805 if (bb_make_directory(dst_fn, dir_mode, FILEUTILS_IGNORE_CHMOD_ERR)) {
806 xfunc_die();
759 } 807 }
760 i = 'n';
761 } else { 808 } else {
762 /* Extract file */ 809 if (!S_ISDIR(stat_buf.st_mode)) {
763 check_file: 810 bb_error_msg_and_die("'%s' exists but is not a %s",
764 if (stat(dst_fn, &stat_buf) == -1) { 811 dst_fn, "directory");
765 /* File does not exist */
766 if (errno != ENOENT) {
767 bb_perror_msg_and_die("can't stat '%s'", dst_fn);
768 }
769 i = 'y';
770 } else {
771 /* File already exists */
772 if (overwrite == O_NEVER) {
773 i = 'n';
774 } else if (S_ISREG(stat_buf.st_mode)) {
775 /* File is regular file */
776 if (overwrite == O_ALWAYS) {
777 i = 'y';
778 } else {
779 printf("replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: ", dst_fn);
780 my_fgets80(key_buf);
781 i = key_buf[0];
782 }
783 } else {
784 /* File is not regular file */
785 bb_error_msg_and_die("'%s' exists but is not a %s",
786 dst_fn, "regular file");
787 }
788 } 812 }
789 } 813 }
814 goto skip_cmpsize;
815 }
816 check_file:
817 /* Extract file */
818 if (stat(dst_fn, &stat_buf) == -1) {
819 /* File does not exist */
820 if (errno != ENOENT) {
821 bb_perror_msg_and_die("can't stat '%s'", dst_fn);
822 }
823 goto do_open_and_extract;
824 }
825 /* File already exists */
826 if (overwrite == O_NEVER) {
827 goto skip_cmpsize;
828 }
829 if (!S_ISREG(stat_buf.st_mode)) {
830 /* File is not regular file */
831 bb_error_msg_and_die("'%s' exists but is not a %s",
832 dst_fn, "regular file");
790 } 833 }
834 /* File is regular file */
835 if (overwrite == O_ALWAYS)
836 goto do_open_and_extract;
837 printf("replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: ", dst_fn);
838 my_fgets80(key_buf);
791 839
792 switch (i) { 840 switch (key_buf[0]) {
793 case 'A': 841 case 'A':
794 overwrite = O_ALWAYS; 842 overwrite = O_ALWAYS;
795 case 'y': /* Open file and fall into unzip */ 843 case 'y': /* Open file and fall into unzip */
844 do_open_and_extract:
796 unzip_create_leading_dirs(dst_fn); 845 unzip_create_leading_dirs(dst_fn);
797#if ENABLE_FEATURE_UNZIP_CDF 846#if ENABLE_FEATURE_UNZIP_CDF
798 dst_fd = xopen3(dst_fn, O_WRONLY | O_CREAT | O_TRUNC, file_mode); 847 dst_fd = xopen3(dst_fn, O_WRONLY | O_CREAT | O_TRUNC, file_mode);
799#else 848#else
800 dst_fd = xopen(dst_fn, O_WRONLY | O_CREAT | O_TRUNC); 849 dst_fd = xopen(dst_fn, O_WRONLY | O_CREAT | O_TRUNC);
801#endif 850#endif
802 case -1: /* Unzip */ 851 do_extract:
803 if (!quiet) { 852 if (!quiet) {
804 printf(" inflating: %s\n", dst_fn); 853 printf(/* zip.fmt.method == 0
854 ? " extracting: %s\n"
855 : */ " inflating: %s\n", dst_fn);
805 } 856 }
806 unzip_extract(&zip_header, dst_fd); 857 unzip_extract(&zip, dst_fd);
807 if (dst_fd != STDOUT_FILENO) { 858 if (dst_fd != STDOUT_FILENO) {
808 /* closing STDOUT is potentially bad for future business */ 859 /* closing STDOUT is potentially bad for future business */
809 close(dst_fd); 860 close(dst_fd);
@@ -812,9 +863,9 @@ int unzip_main(int argc, char **argv)
812 863
813 case 'N': 864 case 'N':
814 overwrite = O_NEVER; 865 overwrite = O_NEVER;
815 case 'n': 866 case 'n': /* Skip entry data */
816 /* Skip entry data */ 867 skip_cmpsize:
817 unzip_skip(zip_header.formatted.cmpsize); 868 unzip_skip(zip.fmt.cmpsize);
818 break; 869 break;
819 870
820 case 'r': 871 case 'r':
@@ -827,7 +878,7 @@ int unzip_main(int argc, char **argv)
827 goto check_file; 878 goto check_file;
828 879
829 default: 880 default:
830 printf("error: invalid response [%c]\n", (char)i); 881 printf("error: invalid response [%c]\n", (char)key_buf[0]);
831 goto check_file; 882 goto check_file;
832 } 883 }
833 884
diff --git a/configs/TEST_nommu_defconfig b/configs/TEST_nommu_defconfig
index 08351a294..7fbbbecc7 100644
--- a/configs/TEST_nommu_defconfig
+++ b/configs/TEST_nommu_defconfig
@@ -266,11 +266,6 @@ CONFIG_YES=y
266CONFIG_FEATURE_PRESERVE_HARDLINKS=y 266CONFIG_FEATURE_PRESERVE_HARDLINKS=y
267 267
268# 268#
269# Common options for ls, more and telnet
270#
271CONFIG_FEATURE_AUTOWIDTH=y
272
273#
274# Common options for df, du, ls 269# Common options for df, du, ls
275# 270#
276CONFIG_FEATURE_HUMAN_READABLE=y 271CONFIG_FEATURE_HUMAN_READABLE=y
@@ -387,7 +382,7 @@ CONFIG_FEATURE_KILL_REMOVED=y
387CONFIG_FEATURE_KILL_DELAY=1 382CONFIG_FEATURE_KILL_DELAY=1
388CONFIG_FEATURE_INIT_SCTTY=y 383CONFIG_FEATURE_INIT_SCTTY=y
389CONFIG_FEATURE_INIT_SYSLOG=y 384CONFIG_FEATURE_INIT_SYSLOG=y
390CONFIG_FEATURE_EXTRA_QUIET=y 385CONFIG_FEATURE_INIT_QUIET=y
391CONFIG_FEATURE_INIT_COREDUMPS=y 386CONFIG_FEATURE_INIT_COREDUMPS=y
392CONFIG_LINUXRC=y 387CONFIG_LINUXRC=y
393CONFIG_HALT=y 388CONFIG_HALT=y
@@ -457,15 +452,12 @@ CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED=y
457# Options common to multiple modutils 452# Options common to multiple modutils
458# 453#
459# CONFIG_FEATURE_2_4_MODULES is not set 454# CONFIG_FEATURE_2_4_MODULES is not set
460CONFIG_FEATURE_INSMOD_TRY_MMAP=y
461# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set 455# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set
462# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set 456# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set
463# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set 457# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set
464# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set 458# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set
465# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set 459# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set
466# CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set 460# CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set
467# CONFIG_FEATURE_MODUTILS_ALIAS is not set
468# CONFIG_FEATURE_MODUTILS_SYMBOLS is not set
469CONFIG_DEFAULT_MODULES_DIR="/lib/modules" 461CONFIG_DEFAULT_MODULES_DIR="/lib/modules"
470CONFIG_DEFAULT_DEPMOD_FILE="modules.dep" 462CONFIG_DEFAULT_DEPMOD_FILE="modules.dep"
471 463
@@ -524,7 +516,6 @@ CONFIG_FEATURE_MDEV_LOAD_FIRMWARE=y
524CONFIG_MKSWAP=y 516CONFIG_MKSWAP=y
525CONFIG_FEATURE_MKSWAP_UUID=y 517CONFIG_FEATURE_MKSWAP_UUID=y
526CONFIG_MORE=y 518CONFIG_MORE=y
527CONFIG_FEATURE_USE_TERMIOS=y
528CONFIG_VOLUMEID=y 519CONFIG_VOLUMEID=y
529CONFIG_FEATURE_VOLUMEID_EXT=y 520CONFIG_FEATURE_VOLUMEID_EXT=y
530CONFIG_FEATURE_VOLUMEID_BTRFS=y 521CONFIG_FEATURE_VOLUMEID_BTRFS=y
@@ -879,9 +870,9 @@ CONFIG_FEATURE_SH_IS_HUSH=y
879# CONFIG_ASH_JOB_CONTROL is not set 870# CONFIG_ASH_JOB_CONTROL is not set
880# CONFIG_ASH_ALIAS is not set 871# CONFIG_ASH_ALIAS is not set
881# CONFIG_ASH_GETOPTS is not set 872# CONFIG_ASH_GETOPTS is not set
882# CONFIG_ASH_BUILTIN_ECHO is not set 873# CONFIG_ASH_ECHO is not set
883# CONFIG_ASH_BUILTIN_PRINTF is not set 874# CONFIG_ASH_PRINTF is not set
884# CONFIG_ASH_BUILTIN_TEST is not set 875# CONFIG_ASH_TEST is not set
885# CONFIG_ASH_CMDCMD is not set 876# CONFIG_ASH_CMDCMD is not set
886# CONFIG_ASH_MAIL is not set 877# CONFIG_ASH_MAIL is not set
887# CONFIG_ASH_OPTIMIZE_FOR_SIZE is not set 878# CONFIG_ASH_OPTIMIZE_FOR_SIZE is not set
diff --git a/configs/TEST_noprintf_defconfig b/configs/TEST_noprintf_defconfig
index 70dacece0..3f85ee1df 100644
--- a/configs/TEST_noprintf_defconfig
+++ b/configs/TEST_noprintf_defconfig
@@ -277,7 +277,6 @@ CONFIG_TRUE=y
277# CONFIG_WHOAMI is not set 277# CONFIG_WHOAMI is not set
278# CONFIG_YES is not set 278# CONFIG_YES is not set
279# CONFIG_FEATURE_PRESERVE_HARDLINKS is not set 279# CONFIG_FEATURE_PRESERVE_HARDLINKS is not set
280# CONFIG_FEATURE_AUTOWIDTH is not set
281# CONFIG_FEATURE_HUMAN_READABLE is not set 280# CONFIG_FEATURE_HUMAN_READABLE is not set
282# CONFIG_FEATURE_MD5_SHA1_SUM_CHECK is not set 281# CONFIG_FEATURE_MD5_SHA1_SUM_CHECK is not set
283 282
@@ -392,7 +391,7 @@ CONFIG_FEATURE_VI_MAX_LEN=0
392CONFIG_FEATURE_KILL_DELAY=0 391CONFIG_FEATURE_KILL_DELAY=0
393# CONFIG_FEATURE_INIT_SCTTY is not set 392# CONFIG_FEATURE_INIT_SCTTY is not set
394# CONFIG_FEATURE_INIT_SYSLOG is not set 393# CONFIG_FEATURE_INIT_SYSLOG is not set
395# CONFIG_FEATURE_EXTRA_QUIET is not set 394# CONFIG_FEATURE_INIT_QUIET is not set
396# CONFIG_FEATURE_INIT_COREDUMPS is not set 395# CONFIG_FEATURE_INIT_COREDUMPS is not set
397# CONFIG_LINUXRC is not set 396# CONFIG_LINUXRC is not set
398# CONFIG_HALT is not set 397# CONFIG_HALT is not set
@@ -527,7 +526,6 @@ CONFIG_FDISK_SUPPORT_LARGE_DISKS=y
527# CONFIG_MKSWAP is not set 526# CONFIG_MKSWAP is not set
528# CONFIG_FEATURE_MKSWAP_UUID is not set 527# CONFIG_FEATURE_MKSWAP_UUID is not set
529# CONFIG_MORE is not set 528# CONFIG_MORE is not set
530# CONFIG_FEATURE_USE_TERMIOS is not set
531CONFIG_VOLUMEID=y 529CONFIG_VOLUMEID=y
532# CONFIG_FEATURE_VOLUMEID_EXT is not set 530# CONFIG_FEATURE_VOLUMEID_EXT is not set
533# CONFIG_FEATURE_VOLUMEID_BTRFS is not set 531# CONFIG_FEATURE_VOLUMEID_BTRFS is not set
@@ -873,9 +871,9 @@ CONFIG_SV_DEFAULT_SERVICE_DIR=""
873# CONFIG_ASH_JOB_CONTROL is not set 871# CONFIG_ASH_JOB_CONTROL is not set
874# CONFIG_ASH_ALIAS is not set 872# CONFIG_ASH_ALIAS is not set
875# CONFIG_ASH_GETOPTS is not set 873# CONFIG_ASH_GETOPTS is not set
876# CONFIG_ASH_BUILTIN_ECHO is not set 874# CONFIG_ASH_ECHO is not set
877# CONFIG_ASH_BUILTIN_PRINTF is not set 875# CONFIG_ASH_PRINTF is not set
878# CONFIG_ASH_BUILTIN_TEST is not set 876# CONFIG_ASH_TEST is not set
879# CONFIG_ASH_CMDCMD is not set 877# CONFIG_ASH_CMDCMD is not set
880# CONFIG_ASH_MAIL is not set 878# CONFIG_ASH_MAIL is not set
881# CONFIG_ASH_OPTIMIZE_FOR_SIZE is not set 879# CONFIG_ASH_OPTIMIZE_FOR_SIZE is not set
diff --git a/configs/TEST_rh9_defconfig b/configs/TEST_rh9_defconfig
index 4a5fad324..34d8e31e2 100644
--- a/configs/TEST_rh9_defconfig
+++ b/configs/TEST_rh9_defconfig
@@ -277,11 +277,6 @@ CONFIG_YES=y
277CONFIG_FEATURE_PRESERVE_HARDLINKS=y 277CONFIG_FEATURE_PRESERVE_HARDLINKS=y
278 278
279# 279#
280# Common options for ls, more and telnet
281#
282CONFIG_FEATURE_AUTOWIDTH=y
283
284#
285# Common options for df, du, ls 280# Common options for df, du, ls
286# 281#
287CONFIG_FEATURE_HUMAN_READABLE=y 282CONFIG_FEATURE_HUMAN_READABLE=y
@@ -404,7 +399,7 @@ CONFIG_FEATURE_USE_INITTAB=y
404CONFIG_FEATURE_KILL_DELAY=0 399CONFIG_FEATURE_KILL_DELAY=0
405CONFIG_FEATURE_INIT_SCTTY=y 400CONFIG_FEATURE_INIT_SCTTY=y
406CONFIG_FEATURE_INIT_SYSLOG=y 401CONFIG_FEATURE_INIT_SYSLOG=y
407CONFIG_FEATURE_EXTRA_QUIET=y 402CONFIG_FEATURE_INIT_QUIET=y
408CONFIG_FEATURE_INIT_COREDUMPS=y 403CONFIG_FEATURE_INIT_COREDUMPS=y
409CONFIG_LINUXRC=y 404CONFIG_LINUXRC=y
410CONFIG_HALT=y 405CONFIG_HALT=y
@@ -472,15 +467,12 @@ CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED=y
472# Options common to multiple modutils 467# Options common to multiple modutils
473# 468#
474# CONFIG_FEATURE_2_4_MODULES is not set 469# CONFIG_FEATURE_2_4_MODULES is not set
475# CONFIG_FEATURE_INSMOD_TRY_MMAP is not set
476# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set 470# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set
477# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set 471# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set
478# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set 472# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set
479# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set 473# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set
480# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set 474# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set
481# CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set 475# CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set
482# CONFIG_FEATURE_MODUTILS_ALIAS is not set
483# CONFIG_FEATURE_MODUTILS_SYMBOLS is not set
484CONFIG_DEFAULT_MODULES_DIR="/lib/modules" 476CONFIG_DEFAULT_MODULES_DIR="/lib/modules"
485CONFIG_DEFAULT_DEPMOD_FILE="modules.dep" 477CONFIG_DEFAULT_DEPMOD_FILE="modules.dep"
486 478
@@ -540,7 +532,6 @@ CONFIG_FEATURE_MDEV_LOAD_FIRMWARE=y
540CONFIG_MKSWAP=y 532CONFIG_MKSWAP=y
541CONFIG_FEATURE_MKSWAP_UUID=y 533CONFIG_FEATURE_MKSWAP_UUID=y
542CONFIG_MORE=y 534CONFIG_MORE=y
543CONFIG_FEATURE_USE_TERMIOS=y
544CONFIG_VOLUMEID=y 535CONFIG_VOLUMEID=y
545CONFIG_FEATURE_VOLUMEID_EXT=y 536CONFIG_FEATURE_VOLUMEID_EXT=y
546CONFIG_FEATURE_VOLUMEID_BTRFS=y 537CONFIG_FEATURE_VOLUMEID_BTRFS=y
@@ -893,9 +884,9 @@ CONFIG_ASH_BASH_COMPAT=y
893CONFIG_ASH_JOB_CONTROL=y 884CONFIG_ASH_JOB_CONTROL=y
894CONFIG_ASH_ALIAS=y 885CONFIG_ASH_ALIAS=y
895CONFIG_ASH_GETOPTS=y 886CONFIG_ASH_GETOPTS=y
896CONFIG_ASH_BUILTIN_ECHO=y 887CONFIG_ASH_ECHO=y
897CONFIG_ASH_BUILTIN_PRINTF=y 888CONFIG_ASH_PRINTF=y
898CONFIG_ASH_BUILTIN_TEST=y 889CONFIG_ASH_TEST=y
899CONFIG_ASH_CMDCMD=y 890CONFIG_ASH_CMDCMD=y
900# CONFIG_ASH_MAIL is not set 891# CONFIG_ASH_MAIL is not set
901CONFIG_ASH_OPTIMIZE_FOR_SIZE=y 892CONFIG_ASH_OPTIMIZE_FOR_SIZE=y
diff --git a/configs/android2_defconfig b/configs/android2_defconfig
index 754f612c6..20866c32b 100644
--- a/configs/android2_defconfig
+++ b/configs/android2_defconfig
@@ -94,7 +94,6 @@ CONFIG_PASSWORD_MINLEN=6
94CONFIG_MD5_SMALL=1 94CONFIG_MD5_SMALL=1
95# CONFIG_FEATURE_FAST_TOP is not set 95# CONFIG_FEATURE_FAST_TOP is not set
96# CONFIG_FEATURE_ETC_NETWORKS is not set 96# CONFIG_FEATURE_ETC_NETWORKS is not set
97CONFIG_FEATURE_USE_TERMIOS=y
98# CONFIG_FEATURE_EDITING is not set 97# CONFIG_FEATURE_EDITING is not set
99CONFIG_FEATURE_EDITING_MAX_LEN=0 98CONFIG_FEATURE_EDITING_MAX_LEN=0
100# CONFIG_FEATURE_EDITING_VI is not set 99# CONFIG_FEATURE_EDITING_VI is not set
@@ -290,11 +289,6 @@ CONFIG_YES=y
290CONFIG_FEATURE_PRESERVE_HARDLINKS=y 289CONFIG_FEATURE_PRESERVE_HARDLINKS=y
291 290
292# 291#
293# Common options for ls, more and telnet
294#
295CONFIG_FEATURE_AUTOWIDTH=y
296
297#
298# Common options for df, du, ls 292# Common options for df, du, ls
299# 293#
300CONFIG_FEATURE_HUMAN_READABLE=y 294CONFIG_FEATURE_HUMAN_READABLE=y
@@ -422,7 +416,7 @@ CONFIG_FEATURE_USE_INITTAB=y
422CONFIG_FEATURE_KILL_DELAY=0 416CONFIG_FEATURE_KILL_DELAY=0
423CONFIG_FEATURE_INIT_SCTTY=y 417CONFIG_FEATURE_INIT_SCTTY=y
424CONFIG_FEATURE_INIT_SYSLOG=y 418CONFIG_FEATURE_INIT_SYSLOG=y
425CONFIG_FEATURE_EXTRA_QUIET=y 419CONFIG_FEATURE_INIT_QUIET=y
426CONFIG_FEATURE_INIT_COREDUMPS=y 420CONFIG_FEATURE_INIT_COREDUMPS=y
427CONFIG_LINUXRC=y 421CONFIG_LINUXRC=y
428CONFIG_INIT_TERMINAL_TYPE="linux" 422CONFIG_INIT_TERMINAL_TYPE="linux"
@@ -493,15 +487,12 @@ CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED=y
493# Options common to multiple modutils 487# Options common to multiple modutils
494# 488#
495# CONFIG_FEATURE_2_4_MODULES is not set 489# CONFIG_FEATURE_2_4_MODULES is not set
496# CONFIG_FEATURE_INSMOD_TRY_MMAP is not set
497# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set 490# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set
498# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set 491# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set
499# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set 492# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set
500# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set 493# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set
501# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set 494# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set
502# CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set 495# CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set
503# CONFIG_FEATURE_MODUTILS_ALIAS is not set
504# CONFIG_FEATURE_MODUTILS_SYMBOLS is not set
505CONFIG_DEFAULT_MODULES_DIR="/lib/modules" 496CONFIG_DEFAULT_MODULES_DIR="/lib/modules"
506CONFIG_DEFAULT_DEPMOD_FILE="modules.dep" 497CONFIG_DEFAULT_DEPMOD_FILE="modules.dep"
507 498
@@ -936,9 +927,9 @@ CONFIG_SOFTLIMIT=y
936# CONFIG_ASH_JOB_CONTROL is not set 927# CONFIG_ASH_JOB_CONTROL is not set
937# CONFIG_ASH_ALIAS is not set 928# CONFIG_ASH_ALIAS is not set
938# CONFIG_ASH_GETOPTS is not set 929# CONFIG_ASH_GETOPTS is not set
939# CONFIG_ASH_BUILTIN_ECHO is not set 930# CONFIG_ASH_ECHO is not set
940# CONFIG_ASH_BUILTIN_PRINTF is not set 931# CONFIG_ASH_PRINTF is not set
941# CONFIG_ASH_BUILTIN_TEST is not set 932# CONFIG_ASH_TEST is not set
942# CONFIG_ASH_CMDCMD is not set 933# CONFIG_ASH_CMDCMD is not set
943# CONFIG_ASH_MAIL is not set 934# CONFIG_ASH_MAIL is not set
944# CONFIG_ASH_OPTIMIZE_FOR_SIZE is not set 935# CONFIG_ASH_OPTIMIZE_FOR_SIZE is not set
diff --git a/configs/android_502_defconfig b/configs/android_502_defconfig
index 8ea6c295d..bdca9eebb 100644
--- a/configs/android_502_defconfig
+++ b/configs/android_502_defconfig
@@ -174,7 +174,6 @@ CONFIG_MD5_SMALL=1
174CONFIG_SHA3_SMALL=1 174CONFIG_SHA3_SMALL=1
175# CONFIG_FEATURE_FAST_TOP is not set 175# CONFIG_FEATURE_FAST_TOP is not set
176# CONFIG_FEATURE_ETC_NETWORKS is not set 176# CONFIG_FEATURE_ETC_NETWORKS is not set
177CONFIG_FEATURE_USE_TERMIOS=y
178CONFIG_FEATURE_EDITING=y 177CONFIG_FEATURE_EDITING=y
179CONFIG_FEATURE_EDITING_MAX_LEN=1024 178CONFIG_FEATURE_EDITING_MAX_LEN=1024
180# CONFIG_FEATURE_EDITING_VI is not set 179# CONFIG_FEATURE_EDITING_VI is not set
@@ -391,11 +390,6 @@ CONFIG_FEATURE_VERBOSE=y
391CONFIG_FEATURE_PRESERVE_HARDLINKS=y 390CONFIG_FEATURE_PRESERVE_HARDLINKS=y
392 391
393# 392#
394# Common options for ls, more and telnet
395#
396CONFIG_FEATURE_AUTOWIDTH=y
397
398#
399# Common options for df, du, ls 393# Common options for df, du, ls
400# 394#
401CONFIG_FEATURE_HUMAN_READABLE=y 395CONFIG_FEATURE_HUMAN_READABLE=y
@@ -529,7 +523,7 @@ CONFIG_FEATURE_USE_INITTAB=y
529CONFIG_FEATURE_KILL_DELAY=0 523CONFIG_FEATURE_KILL_DELAY=0
530CONFIG_FEATURE_INIT_SCTTY=y 524CONFIG_FEATURE_INIT_SCTTY=y
531CONFIG_FEATURE_INIT_SYSLOG=y 525CONFIG_FEATURE_INIT_SYSLOG=y
532CONFIG_FEATURE_EXTRA_QUIET=y 526CONFIG_FEATURE_INIT_QUIET=y
533CONFIG_FEATURE_INIT_COREDUMPS=y 527CONFIG_FEATURE_INIT_COREDUMPS=y
534CONFIG_LINUXRC=y 528CONFIG_LINUXRC=y
535CONFIG_INIT_TERMINAL_TYPE="linux" 529CONFIG_INIT_TERMINAL_TYPE="linux"
@@ -603,15 +597,12 @@ CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED=y
603# Options common to multiple modutils 597# Options common to multiple modutils
604# 598#
605# CONFIG_FEATURE_2_4_MODULES is not set 599# CONFIG_FEATURE_2_4_MODULES is not set
606# CONFIG_FEATURE_INSMOD_TRY_MMAP is not set
607# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set 600# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set
608# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set 601# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set
609# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set 602# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set
610# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set 603# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set
611# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set 604# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set
612# CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set 605# CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set
613# CONFIG_FEATURE_MODUTILS_ALIAS is not set
614# CONFIG_FEATURE_MODUTILS_SYMBOLS is not set
615CONFIG_DEFAULT_MODULES_DIR="/lib/modules" 606CONFIG_DEFAULT_MODULES_DIR="/lib/modules"
616CONFIG_DEFAULT_DEPMOD_FILE="modules.dep" 607CONFIG_DEFAULT_DEPMOD_FILE="modules.dep"
617 608
@@ -1081,9 +1072,9 @@ CONFIG_ASH_BASH_COMPAT=y
1081CONFIG_ASH_JOB_CONTROL=y 1072CONFIG_ASH_JOB_CONTROL=y
1082CONFIG_ASH_ALIAS=y 1073CONFIG_ASH_ALIAS=y
1083CONFIG_ASH_GETOPTS=y 1074CONFIG_ASH_GETOPTS=y
1084CONFIG_ASH_BUILTIN_ECHO=y 1075CONFIG_ASH_ECHO=y
1085CONFIG_ASH_BUILTIN_PRINTF=y 1076CONFIG_ASH_PRINTF=y
1086CONFIG_ASH_BUILTIN_TEST=y 1077CONFIG_ASH_TEST=y
1087CONFIG_ASH_HELP=y 1078CONFIG_ASH_HELP=y
1088CONFIG_ASH_CMDCMD=y 1079CONFIG_ASH_CMDCMD=y
1089# CONFIG_ASH_MAIL is not set 1080# CONFIG_ASH_MAIL is not set
diff --git a/configs/android_defconfig b/configs/android_defconfig
index 30e888ac7..6ef81750e 100644
--- a/configs/android_defconfig
+++ b/configs/android_defconfig
@@ -112,7 +112,6 @@ CONFIG_PASSWORD_MINLEN=6
112CONFIG_MD5_SMALL=1 112CONFIG_MD5_SMALL=1
113# CONFIG_FEATURE_FAST_TOP is not set 113# CONFIG_FEATURE_FAST_TOP is not set
114# CONFIG_FEATURE_ETC_NETWORKS is not set 114# CONFIG_FEATURE_ETC_NETWORKS is not set
115CONFIG_FEATURE_USE_TERMIOS=y
116# CONFIG_FEATURE_EDITING is not set 115# CONFIG_FEATURE_EDITING is not set
117CONFIG_FEATURE_EDITING_MAX_LEN=0 116CONFIG_FEATURE_EDITING_MAX_LEN=0
118# CONFIG_FEATURE_EDITING_VI is not set 117# CONFIG_FEATURE_EDITING_VI is not set
@@ -313,11 +312,6 @@ CONFIG_YES=y
313CONFIG_FEATURE_PRESERVE_HARDLINKS=y 312CONFIG_FEATURE_PRESERVE_HARDLINKS=y
314 313
315# 314#
316# Common options for ls, more and telnet
317#
318CONFIG_FEATURE_AUTOWIDTH=y
319
320#
321# Common options for df, du, ls 315# Common options for df, du, ls
322# 316#
323CONFIG_FEATURE_HUMAN_READABLE=y 317CONFIG_FEATURE_HUMAN_READABLE=y
@@ -445,7 +439,7 @@ CONFIG_FEATURE_USE_INITTAB=y
445CONFIG_FEATURE_KILL_DELAY=0 439CONFIG_FEATURE_KILL_DELAY=0
446CONFIG_FEATURE_INIT_SCTTY=y 440CONFIG_FEATURE_INIT_SCTTY=y
447CONFIG_FEATURE_INIT_SYSLOG=y 441CONFIG_FEATURE_INIT_SYSLOG=y
448CONFIG_FEATURE_EXTRA_QUIET=y 442CONFIG_FEATURE_INIT_QUIET=y
449CONFIG_FEATURE_INIT_COREDUMPS=y 443CONFIG_FEATURE_INIT_COREDUMPS=y
450CONFIG_LINUXRC=y 444CONFIG_LINUXRC=y
451CONFIG_INIT_TERMINAL_TYPE="linux" 445CONFIG_INIT_TERMINAL_TYPE="linux"
@@ -517,15 +511,12 @@ CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED=y
517# Options common to multiple modutils 511# Options common to multiple modutils
518# 512#
519# CONFIG_FEATURE_2_4_MODULES is not set 513# CONFIG_FEATURE_2_4_MODULES is not set
520# CONFIG_FEATURE_INSMOD_TRY_MMAP is not set
521# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set 514# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set
522# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set 515# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set
523# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set 516# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set
524# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set 517# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set
525# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set 518# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set
526# CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set 519# CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set
527# CONFIG_FEATURE_MODUTILS_ALIAS is not set
528# CONFIG_FEATURE_MODUTILS_SYMBOLS is not set
529CONFIG_DEFAULT_MODULES_DIR="/lib/modules" 520CONFIG_DEFAULT_MODULES_DIR="/lib/modules"
530CONFIG_DEFAULT_DEPMOD_FILE="modules.dep" 521CONFIG_DEFAULT_DEPMOD_FILE="modules.dep"
531 522
@@ -968,9 +959,9 @@ CONFIG_SOFTLIMIT=y
968# CONFIG_ASH_JOB_CONTROL is not set 959# CONFIG_ASH_JOB_CONTROL is not set
969# CONFIG_ASH_ALIAS is not set 960# CONFIG_ASH_ALIAS is not set
970# CONFIG_ASH_GETOPTS is not set 961# CONFIG_ASH_GETOPTS is not set
971# CONFIG_ASH_BUILTIN_ECHO is not set 962# CONFIG_ASH_ECHO is not set
972# CONFIG_ASH_BUILTIN_PRINTF is not set 963# CONFIG_ASH_PRINTF is not set
973# CONFIG_ASH_BUILTIN_TEST is not set 964# CONFIG_ASH_TEST is not set
974# CONFIG_ASH_CMDCMD is not set 965# CONFIG_ASH_CMDCMD is not set
975# CONFIG_ASH_MAIL is not set 966# CONFIG_ASH_MAIL is not set
976# CONFIG_ASH_OPTIMIZE_FOR_SIZE is not set 967# CONFIG_ASH_OPTIMIZE_FOR_SIZE is not set
diff --git a/configs/android_ndk_defconfig b/configs/android_ndk_defconfig
index 716ec9a5d..35d03b42e 100644
--- a/configs/android_ndk_defconfig
+++ b/configs/android_ndk_defconfig
@@ -102,7 +102,6 @@ CONFIG_MD5_SMALL=1
102CONFIG_SHA3_SMALL=1 102CONFIG_SHA3_SMALL=1
103# CONFIG_FEATURE_FAST_TOP is not set 103# CONFIG_FEATURE_FAST_TOP is not set
104# CONFIG_FEATURE_ETC_NETWORKS is not set 104# CONFIG_FEATURE_ETC_NETWORKS is not set
105CONFIG_FEATURE_USE_TERMIOS=y
106# CONFIG_FEATURE_EDITING is not set 105# CONFIG_FEATURE_EDITING is not set
107CONFIG_FEATURE_EDITING_MAX_LEN=0 106CONFIG_FEATURE_EDITING_MAX_LEN=0
108# CONFIG_FEATURE_EDITING_VI is not set 107# CONFIG_FEATURE_EDITING_VI is not set
@@ -317,11 +316,6 @@ CONFIG_FEATURE_VERBOSE=y
317CONFIG_FEATURE_PRESERVE_HARDLINKS=y 316CONFIG_FEATURE_PRESERVE_HARDLINKS=y
318 317
319# 318#
320# Common options for ls, more and telnet
321#
322CONFIG_FEATURE_AUTOWIDTH=y
323
324#
325# Common options for df, du, ls 319# Common options for df, du, ls
326# 320#
327CONFIG_FEATURE_HUMAN_READABLE=y 321CONFIG_FEATURE_HUMAN_READABLE=y
@@ -455,7 +449,7 @@ CONFIG_FEATURE_USE_INITTAB=y
455CONFIG_FEATURE_KILL_DELAY=0 449CONFIG_FEATURE_KILL_DELAY=0
456CONFIG_FEATURE_INIT_SCTTY=y 450CONFIG_FEATURE_INIT_SCTTY=y
457CONFIG_FEATURE_INIT_SYSLOG=y 451CONFIG_FEATURE_INIT_SYSLOG=y
458CONFIG_FEATURE_EXTRA_QUIET=y 452CONFIG_FEATURE_INIT_QUIET=y
459CONFIG_FEATURE_INIT_COREDUMPS=y 453CONFIG_FEATURE_INIT_COREDUMPS=y
460CONFIG_LINUXRC=y 454CONFIG_LINUXRC=y
461CONFIG_INIT_TERMINAL_TYPE="linux" 455CONFIG_INIT_TERMINAL_TYPE="linux"
@@ -528,15 +522,12 @@ CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED=y
528# Options common to multiple modutils 522# Options common to multiple modutils
529# 523#
530# CONFIG_FEATURE_2_4_MODULES is not set 524# CONFIG_FEATURE_2_4_MODULES is not set
531# CONFIG_FEATURE_INSMOD_TRY_MMAP is not set
532# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set 525# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set
533# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set 526# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set
534# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set 527# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set
535# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set 528# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set
536# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set 529# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set
537# CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set 530# CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set
538# CONFIG_FEATURE_MODUTILS_ALIAS is not set
539# CONFIG_FEATURE_MODUTILS_SYMBOLS is not set
540CONFIG_DEFAULT_MODULES_DIR="/system/lib/modules" 531CONFIG_DEFAULT_MODULES_DIR="/system/lib/modules"
541CONFIG_DEFAULT_DEPMOD_FILE="modules.dep" 532CONFIG_DEFAULT_DEPMOD_FILE="modules.dep"
542 533
@@ -996,9 +987,9 @@ CONFIG_SOFTLIMIT=y
996# CONFIG_ASH_JOB_CONTROL is not set 987# CONFIG_ASH_JOB_CONTROL is not set
997# CONFIG_ASH_ALIAS is not set 988# CONFIG_ASH_ALIAS is not set
998# CONFIG_ASH_GETOPTS is not set 989# CONFIG_ASH_GETOPTS is not set
999# CONFIG_ASH_BUILTIN_ECHO is not set 990# CONFIG_ASH_ECHO is not set
1000# CONFIG_ASH_BUILTIN_PRINTF is not set 991# CONFIG_ASH_PRINTF is not set
1001# CONFIG_ASH_BUILTIN_TEST is not set 992# CONFIG_ASH_TEST is not set
1002# CONFIG_ASH_HELP is not set 993# CONFIG_ASH_HELP is not set
1003# CONFIG_ASH_CMDCMD is not set 994# CONFIG_ASH_CMDCMD is not set
1004# CONFIG_ASH_MAIL is not set 995# CONFIG_ASH_MAIL is not set
diff --git a/configs/cygwin_defconfig b/configs/cygwin_defconfig
index b856482f6..6bfc973ef 100644
--- a/configs/cygwin_defconfig
+++ b/configs/cygwin_defconfig
@@ -94,7 +94,6 @@ CONFIG_PASSWORD_MINLEN=6
94CONFIG_MD5_SMALL=1 94CONFIG_MD5_SMALL=1
95CONFIG_FEATURE_FAST_TOP=y 95CONFIG_FEATURE_FAST_TOP=y
96# CONFIG_FEATURE_ETC_NETWORKS is not set 96# CONFIG_FEATURE_ETC_NETWORKS is not set
97CONFIG_FEATURE_USE_TERMIOS=y
98CONFIG_FEATURE_EDITING=y 97CONFIG_FEATURE_EDITING=y
99CONFIG_FEATURE_EDITING_MAX_LEN=1024 98CONFIG_FEATURE_EDITING_MAX_LEN=1024
100# CONFIG_FEATURE_EDITING_VI is not set 99# CONFIG_FEATURE_EDITING_VI is not set
@@ -290,11 +289,6 @@ CONFIG_YES=y
290CONFIG_FEATURE_PRESERVE_HARDLINKS=y 289CONFIG_FEATURE_PRESERVE_HARDLINKS=y
291 290
292# 291#
293# Common options for ls, more and telnet
294#
295CONFIG_FEATURE_AUTOWIDTH=y
296
297#
298# Common options for df, du, ls 292# Common options for df, du, ls
299# 293#
300CONFIG_FEATURE_HUMAN_READABLE=y 294CONFIG_FEATURE_HUMAN_READABLE=y
@@ -422,7 +416,7 @@ CONFIG_TELINIT_PATH=""
422CONFIG_FEATURE_KILL_DELAY=0 416CONFIG_FEATURE_KILL_DELAY=0
423# CONFIG_FEATURE_INIT_SCTTY is not set 417# CONFIG_FEATURE_INIT_SCTTY is not set
424# CONFIG_FEATURE_INIT_SYSLOG is not set 418# CONFIG_FEATURE_INIT_SYSLOG is not set
425# CONFIG_FEATURE_EXTRA_QUIET is not set 419# CONFIG_FEATURE_INIT_QUIET is not set
426# CONFIG_FEATURE_INIT_COREDUMPS is not set 420# CONFIG_FEATURE_INIT_COREDUMPS is not set
427# CONFIG_LINUXRC is not set 421# CONFIG_LINUXRC is not set
428CONFIG_INIT_TERMINAL_TYPE="" 422CONFIG_INIT_TERMINAL_TYPE=""
@@ -936,9 +930,9 @@ CONFIG_ASH_BASH_COMPAT=y
936CONFIG_ASH_JOB_CONTROL=y 930CONFIG_ASH_JOB_CONTROL=y
937CONFIG_ASH_ALIAS=y 931CONFIG_ASH_ALIAS=y
938CONFIG_ASH_GETOPTS=y 932CONFIG_ASH_GETOPTS=y
939CONFIG_ASH_BUILTIN_ECHO=y 933CONFIG_ASH_ECHO=y
940CONFIG_ASH_BUILTIN_PRINTF=y 934CONFIG_ASH_PRINTF=y
941CONFIG_ASH_BUILTIN_TEST=y 935CONFIG_ASH_TEST=y
942CONFIG_ASH_CMDCMD=y 936CONFIG_ASH_CMDCMD=y
943# CONFIG_ASH_MAIL is not set 937# CONFIG_ASH_MAIL is not set
944CONFIG_ASH_OPTIMIZE_FOR_SIZE=y 938CONFIG_ASH_OPTIMIZE_FOR_SIZE=y
diff --git a/configs/freebsd_defconfig b/configs/freebsd_defconfig
index 4f14d3be9..e3d04aedc 100644
--- a/configs/freebsd_defconfig
+++ b/configs/freebsd_defconfig
@@ -93,7 +93,6 @@ CONFIG_PASSWORD_MINLEN=6
93CONFIG_MD5_SMALL=1 93CONFIG_MD5_SMALL=1
94CONFIG_FEATURE_FAST_TOP=y 94CONFIG_FEATURE_FAST_TOP=y
95# CONFIG_FEATURE_ETC_NETWORKS is not set 95# CONFIG_FEATURE_ETC_NETWORKS is not set
96CONFIG_FEATURE_USE_TERMIOS=y
97CONFIG_FEATURE_EDITING=y 96CONFIG_FEATURE_EDITING=y
98CONFIG_FEATURE_EDITING_MAX_LEN=1024 97CONFIG_FEATURE_EDITING_MAX_LEN=1024
99# CONFIG_FEATURE_EDITING_VI is not set 98# CONFIG_FEATURE_EDITING_VI is not set
@@ -288,11 +287,6 @@ CONFIG_YES=y
288CONFIG_FEATURE_PRESERVE_HARDLINKS=y 287CONFIG_FEATURE_PRESERVE_HARDLINKS=y
289 288
290# 289#
291# Common options for ls, more and telnet
292#
293CONFIG_FEATURE_AUTOWIDTH=y
294
295#
296# Common options for df, du, ls 290# Common options for df, du, ls
297# 291#
298CONFIG_FEATURE_HUMAN_READABLE=y 292CONFIG_FEATURE_HUMAN_READABLE=y
@@ -419,7 +413,7 @@ CONFIG_TELINIT_PATH=""
419CONFIG_FEATURE_KILL_DELAY=0 413CONFIG_FEATURE_KILL_DELAY=0
420# CONFIG_FEATURE_INIT_SCTTY is not set 414# CONFIG_FEATURE_INIT_SCTTY is not set
421# CONFIG_FEATURE_INIT_SYSLOG is not set 415# CONFIG_FEATURE_INIT_SYSLOG is not set
422# CONFIG_FEATURE_EXTRA_QUIET is not set 416# CONFIG_FEATURE_INIT_QUIET is not set
423# CONFIG_FEATURE_INIT_COREDUMPS is not set 417# CONFIG_FEATURE_INIT_COREDUMPS is not set
424# CONFIG_LINUXRC is not set 418# CONFIG_LINUXRC is not set
425CONFIG_INIT_TERMINAL_TYPE="" 419CONFIG_INIT_TERMINAL_TYPE=""
@@ -912,9 +906,9 @@ CONFIG_ASH=y
912# CONFIG_ASH_JOB_CONTROL is not set 906# CONFIG_ASH_JOB_CONTROL is not set
913# CONFIG_ASH_ALIAS is not set 907# CONFIG_ASH_ALIAS is not set
914# CONFIG_ASH_GETOPTS is not set 908# CONFIG_ASH_GETOPTS is not set
915# CONFIG_ASH_BUILTIN_ECHO is not set 909# CONFIG_ASH_ECHO is not set
916# CONFIG_ASH_BUILTIN_PRINTF is not set 910# CONFIG_ASH_PRINTF is not set
917# CONFIG_ASH_BUILTIN_TEST is not set 911# CONFIG_ASH_TEST is not set
918# CONFIG_ASH_CMDCMD is not set 912# CONFIG_ASH_CMDCMD is not set
919# CONFIG_ASH_MAIL is not set 913# CONFIG_ASH_MAIL is not set
920# CONFIG_ASH_OPTIMIZE_FOR_SIZE is not set 914# CONFIG_ASH_OPTIMIZE_FOR_SIZE is not set
diff --git a/console-tools/loadfont.c b/console-tools/loadfont.c
index 52605baa1..29f723ec0 100644
--- a/console-tools/loadfont.c
+++ b/console-tools/loadfont.c
@@ -42,18 +42,14 @@
42//config: depends on LOADFONT || SETFONT 42//config: depends on LOADFONT || SETFONT
43//config: 43//config:
44//config:config FEATURE_LOADFONT_PSF2 44//config:config FEATURE_LOADFONT_PSF2
45//config: bool "Support for PSF2 console fonts" 45//config: bool "Support PSF2 console fonts"
46//config: default y 46//config: default y
47//config: depends on LOADFONT || SETFONT 47//config: depends on LOADFONT || SETFONT
48//config: help
49//config: Support PSF2 console fonts.
50//config: 48//config:
51//config:config FEATURE_LOADFONT_RAW 49//config:config FEATURE_LOADFONT_RAW
52//config: bool "Support for old (raw) console fonts" 50//config: bool "Support old (raw) console fonts"
53//config: default y 51//config: default y
54//config: depends on LOADFONT || SETFONT 52//config: depends on LOADFONT || SETFONT
55//config: help
56//config: Support old (raw) console fonts.
57 53
58//applet:IF_LOADFONT(APPLET(loadfont, BB_DIR_USR_SBIN, BB_SUID_DROP)) 54//applet:IF_LOADFONT(APPLET(loadfont, BB_DIR_USR_SBIN, BB_SUID_DROP))
59//applet:IF_SETFONT(APPLET(setfont, BB_DIR_USR_SBIN, BB_SUID_DROP)) 55//applet:IF_SETFONT(APPLET(setfont, BB_DIR_USR_SBIN, BB_SUID_DROP))
diff --git a/console-tools/setconsole.c b/console-tools/setconsole.c
index 58057268d..d47a33d59 100644
--- a/console-tools/setconsole.c
+++ b/console-tools/setconsole.c
@@ -19,8 +19,6 @@
19//config: bool "Enable long options" 19//config: bool "Enable long options"
20//config: default y 20//config: default y
21//config: depends on SETCONSOLE && LONG_OPTS 21//config: depends on SETCONSOLE && LONG_OPTS
22//config: help
23//config: Support long options for the setconsole applet.
24 22
25//applet:IF_SETCONSOLE(APPLET(setconsole, BB_DIR_SBIN, BB_SUID_DROP)) 23//applet:IF_SETCONSOLE(APPLET(setconsole, BB_DIR_SBIN, BB_SUID_DROP))
26 24
diff --git a/coreutils/Config.src b/coreutils/Config.src
index c056320f8..1d2fea1fb 100644
--- a/coreutils/Config.src
+++ b/coreutils/Config.src
@@ -27,25 +27,11 @@ config FEATURE_PRESERVE_HARDLINKS
27 help 27 help
28 Allow cp and mv to preserve hard links. 28 Allow cp and mv to preserve hard links.
29 29
30comment "Common options for ls, more and telnet"
31 depends on LS || MORE || TELNET
32
33config FEATURE_AUTOWIDTH
34 bool "Calculate terminal & column widths"
35 default y
36 depends on LS || MORE || TELNET
37 help
38 This option allows utilities such as 'ls', 'more' and 'telnet'
39 to determine the width of the screen, which can allow them to
40 display additional text or avoid wrapping text onto the next line.
41 If you leave this disabled, your utilities will be especially
42 primitive and will be unable to determine the current screen width.
43
44comment "Common options for df, du, ls" 30comment "Common options for df, du, ls"
45 depends on DF || DU || LS 31 depends on DF || DU || LS
46 32
47config FEATURE_HUMAN_READABLE 33config FEATURE_HUMAN_READABLE
48 bool "Support for human readable output (example 13k, 23M, 235G)" 34 bool "Support human readable output (example 13k, 23M, 235G)"
49 default y 35 default y
50 depends on DF || DU || LS 36 depends on DF || DU || LS
51 help 37 help
diff --git a/coreutils/Kbuild.src b/coreutils/Kbuild.src
index d9a448781..a805b64fe 100644
--- a/coreutils/Kbuild.src
+++ b/coreutils/Kbuild.src
@@ -14,12 +14,5 @@ lib-$(CONFIG_MORE) += cat.o # more uses it if stdout isn't a tty
14lib-$(CONFIG_LESS) += cat.o # less too 14lib-$(CONFIG_LESS) += cat.o # less too
15lib-$(CONFIG_CRONTAB) += cat.o # crontab -l 15lib-$(CONFIG_CRONTAB) += cat.o # crontab -l
16lib-$(CONFIG_ADDUSER) += chown.o # used by adduser 16lib-$(CONFIG_ADDUSER) += chown.o # used by adduser
17lib-$(CONFIG_ADDGROUP) += chown.o # used by adduser 17lib-$(CONFIG_ADDGROUP) += chown.o # used by addgroup
18lib-$(CONFIG_ASH) += echo.o # used by ash
19lib-$(CONFIG_SH_IS_ASH) += echo.o # used by ash
20lib-$(CONFIG_BASH_IS_ASH) += echo.o # used by ash
21lib-$(CONFIG_HUSH) += echo.o # used by hush
22lib-$(CONFIG_SH_IS_HUSH) += echo.o # used by hush
23lib-$(CONFIG_BASH_IS_HUSH) += echo.o # used by hush
24lib-$(CONFIG_FTPD) += ls.o # used by ftpd 18lib-$(CONFIG_FTPD) += ls.o # used by ftpd
25lib-$(CONFIG_ASH_BUILTIN_PRINTF) += printf.o
diff --git a/coreutils/chown.c b/coreutils/chown.c
index 50b06d73a..12cd0eacc 100644
--- a/coreutils/chown.c
+++ b/coreutils/chown.c
@@ -17,8 +17,6 @@
17//config: bool "Enable long options" 17//config: bool "Enable long options"
18//config: default y 18//config: default y
19//config: depends on CHOWN && LONG_OPTS 19//config: depends on CHOWN && LONG_OPTS
20//config: help
21//config: Enable use of long options
22 20
23//applet:IF_CHOWN(APPLET_NOEXEC(chown, chown, BB_DIR_BIN, BB_SUID_DROP, chown)) 21//applet:IF_CHOWN(APPLET_NOEXEC(chown, chown, BB_DIR_BIN, BB_SUID_DROP, chown))
24 22
diff --git a/coreutils/cp.c b/coreutils/cp.c
index 4ecdaafda..1e5f36d10 100644
--- a/coreutils/cp.c
+++ b/coreutils/cp.c
@@ -18,11 +18,11 @@
18//config: cp is used to copy files and directories. 18//config: cp is used to copy files and directories.
19//config: 19//config:
20//config:config FEATURE_CP_LONG_OPTIONS 20//config:config FEATURE_CP_LONG_OPTIONS
21//config: bool "Enable long options for cp" 21//config: bool "Enable long options"
22//config: default y 22//config: default y
23//config: depends on CP && LONG_OPTS 23//config: depends on CP && LONG_OPTS
24//config: help 24//config: help
25//config: Enable long options for cp. 25//config: Enable long options.
26//config: Also add support for --parents option. 26//config: Also add support for --parents option.
27 27
28//applet:IF_CP(APPLET_NOEXEC(cp, cp, BB_DIR_BIN, BB_SUID_DROP, cp)) 28//applet:IF_CP(APPLET_NOEXEC(cp, cp, BB_DIR_BIN, BB_SUID_DROP, cp))
diff --git a/coreutils/dd.c b/coreutils/dd.c
index 8c144cfd2..85152d8ce 100644
--- a/coreutils/dd.c
+++ b/coreutils/dd.c
@@ -41,7 +41,7 @@
41//config: default y 41//config: default y
42//config: depends on DD 42//config: depends on DD
43//config: help 43//config: help
44//config: Enables support for writing a certain number of bytes in and out, 44//config: Enable support for writing a certain number of bytes in and out,
45//config: at a time, and performing conversions on the data stream. 45//config: at a time, and performing conversions on the data stream.
46//config: 46//config:
47//config:config FEATURE_DD_STATUS 47//config:config FEATURE_DD_STATUS
@@ -49,7 +49,7 @@
49//config: default y 49//config: default y
50//config: depends on DD 50//config: depends on DD
51//config: help 51//config: help
52//config: Enables support for status=noxfer/none option. 52//config: Enable support for status=noxfer/none option.
53 53
54//applet:IF_DD(APPLET_NOEXEC(dd, dd, BB_DIR_BIN, BB_SUID_DROP, dd)) 54//applet:IF_DD(APPLET_NOEXEC(dd, dd, BB_DIR_BIN, BB_SUID_DROP, dd))
55 55
diff --git a/coreutils/df.c b/coreutils/df.c
index 79e4c4670..cf367161a 100644
--- a/coreutils/df.c
+++ b/coreutils/df.c
@@ -29,11 +29,9 @@
29//config: default y 29//config: default y
30//config: depends on DF 30//config: depends on DF
31//config: help 31//config: help
32//config: This option enables -a, -i and -B. 32//config: -a Show all filesystems
33//config: 33//config: -i Inodes
34//config: -a Show all filesystems 34//config: -B <SIZE> Blocksize
35//config: -i Inodes
36//config: -B <SIZE> Blocksize
37 35
38//applet:IF_DF(APPLET(df, BB_DIR_BIN, BB_SUID_DROP)) 36//applet:IF_DF(APPLET(df, BB_DIR_BIN, BB_SUID_DROP))
39 37
diff --git a/coreutils/echo.c b/coreutils/echo.c
index fd0d9b780..a7e4ca9ac 100644
--- a/coreutils/echo.c
+++ b/coreutils/echo.c
@@ -26,16 +26,17 @@
26//config: 26//config:
27//config:# this entry also appears in shell/Config.in, next to the echo builtin 27//config:# this entry also appears in shell/Config.in, next to the echo builtin
28//config:config FEATURE_FANCY_ECHO 28//config:config FEATURE_FANCY_ECHO
29//config: bool "Enable echo options (-n and -e)" 29//config: bool "Enable -n and -e options"
30//config: default y 30//config: default y
31//config: depends on ECHO || ASH_BUILTIN_ECHO || HUSH 31//config: depends on ECHO || ASH_ECHO || HUSH_ECHO
32//config: help
33//config: This adds options (-n and -e) to echo.
34 32
35//applet:IF_ECHO(APPLET_NOFORK(echo, echo, BB_DIR_BIN, BB_SUID_DROP, echo)) 33//applet:IF_ECHO(APPLET_NOFORK(echo, echo, BB_DIR_BIN, BB_SUID_DROP, echo))
36 34
37//kbuild:lib-$(CONFIG_ECHO) += echo.o 35//kbuild:lib-$(CONFIG_ECHO) += echo.o
38 36
37//kbuild:lib-$(CONFIG_ASH_ECHO) += echo.o
38//kbuild:lib-$(CONFIG_HUSH_ECHO) += echo.o
39
39/* BB_AUDIT SUSv3 compliant -- unless configured as fancy echo. */ 40/* BB_AUDIT SUSv3 compliant -- unless configured as fancy echo. */
40/* http://www.opengroup.org/onlinepubs/007904975/utilities/echo.html */ 41/* http://www.opengroup.org/onlinepubs/007904975/utilities/echo.html */
41 42
diff --git a/coreutils/env.c b/coreutils/env.c
index e91eddb5c..2bd5f41d0 100644
--- a/coreutils/env.c
+++ b/coreutils/env.c
@@ -35,8 +35,6 @@
35//config: bool "Enable long options" 35//config: bool "Enable long options"
36//config: default y 36//config: default y
37//config: depends on ENV && LONG_OPTS 37//config: depends on ENV && LONG_OPTS
38//config: help
39//config: Support long options for the env applet.
40 38
41//applet:IF_ENV(APPLET_NOEXEC(env, env, BB_DIR_USR_BIN, BB_SUID_DROP, env)) 39//applet:IF_ENV(APPLET_NOEXEC(env, env, BB_DIR_USR_BIN, BB_SUID_DROP, env))
42 40
diff --git a/coreutils/expand.c b/coreutils/expand.c
index bb59af46d..9ce86ebff 100644
--- a/coreutils/expand.c
+++ b/coreutils/expand.c
@@ -8,13 +8,13 @@
8 * David MacKenzie <djm@gnu.ai.mit.edu> 8 * David MacKenzie <djm@gnu.ai.mit.edu>
9 * 9 *
10 * Options for expand: 10 * Options for expand:
11 * -t num --tabs=NUM Convert tabs to num spaces (default 8 spaces). 11 * -t num --tabs NUM Convert tabs to num spaces (default 8 spaces).
12 * -i --initial Only convert initial tabs on each line to spaces. 12 * -i --initial Only convert initial tabs on each line to spaces.
13 * 13 *
14 * Options for unexpand: 14 * Options for unexpand:
15 * -a --all Convert all blanks, instead of just initial blanks. 15 * -a --all Convert all blanks, instead of just initial blanks.
16 * -f --first-only Convert only leading sequences of blanks (default). 16 * -f --first-only Convert only leading sequences of blanks (default).
17 * -t num --tabs=NUM Have tabs num characters apart instead of 8. 17 * -t num --tabs NUM Have tabs num characters apart instead of 8.
18 * 18 *
19 * Busybox version (C) 2007 by Tito Ragusa <farmatito@tiscali.it> 19 * Busybox version (C) 2007 by Tito Ragusa <farmatito@tiscali.it>
20 * 20 *
@@ -30,8 +30,6 @@
30//config: bool "Enable long options" 30//config: bool "Enable long options"
31//config: default y 31//config: default y
32//config: depends on EXPAND && LONG_OPTS 32//config: depends on EXPAND && LONG_OPTS
33//config: help
34//config: Support long options for the expand applet.
35//config: 33//config:
36//config:config UNEXPAND 34//config:config UNEXPAND
37//config: bool "unexpand" 35//config: bool "unexpand"
@@ -43,10 +41,9 @@
43//config: bool "Enable long options" 41//config: bool "Enable long options"
44//config: default y 42//config: default y
45//config: depends on UNEXPAND && LONG_OPTS 43//config: depends on UNEXPAND && LONG_OPTS
46//config: help
47//config: Support long options for the unexpand applet.
48 44
49//applet:IF_EXPAND(APPLET(expand, BB_DIR_USR_BIN, BB_SUID_DROP)) 45//applet:IF_EXPAND(APPLET(expand, BB_DIR_USR_BIN, BB_SUID_DROP))
46// APPLET_ODDNAME:name main location suid_type help
50//applet:IF_UNEXPAND(APPLET_ODDNAME(unexpand, expand, BB_DIR_USR_BIN, BB_SUID_DROP, unexpand)) 47//applet:IF_UNEXPAND(APPLET_ODDNAME(unexpand, expand, BB_DIR_USR_BIN, BB_SUID_DROP, unexpand))
51 48
52//kbuild:lib-$(CONFIG_EXPAND) += expand.o 49//kbuild:lib-$(CONFIG_EXPAND) += expand.o
@@ -58,7 +55,7 @@
58//usage: "Convert tabs to spaces, writing to stdout\n" 55//usage: "Convert tabs to spaces, writing to stdout\n"
59//usage: IF_FEATURE_EXPAND_LONG_OPTIONS( 56//usage: IF_FEATURE_EXPAND_LONG_OPTIONS(
60//usage: "\n -i,--initial Don't convert tabs after non blanks" 57//usage: "\n -i,--initial Don't convert tabs after non blanks"
61//usage: "\n -t,--tabs=N Tabstops every N chars" 58//usage: "\n -t,--tabs N Tabstops every N chars"
62//usage: ) 59//usage: )
63//usage: IF_NOT_FEATURE_EXPAND_LONG_OPTIONS( 60//usage: IF_NOT_FEATURE_EXPAND_LONG_OPTIONS(
64//usage: "\n -i Don't convert tabs after non blanks" 61//usage: "\n -i Don't convert tabs after non blanks"
@@ -72,7 +69,7 @@
72//usage: IF_FEATURE_UNEXPAND_LONG_OPTIONS( 69//usage: IF_FEATURE_UNEXPAND_LONG_OPTIONS(
73//usage: "\n -a,--all Convert all blanks" 70//usage: "\n -a,--all Convert all blanks"
74//usage: "\n -f,--first-only Convert only leading blanks" 71//usage: "\n -f,--first-only Convert only leading blanks"
75//usage: "\n -t,--tabs=N Tabstops every N chars" 72//usage: "\n -t,--tabs N Tabstops every N chars"
76//usage: ) 73//usage: )
77//usage: IF_NOT_FEATURE_UNEXPAND_LONG_OPTIONS( 74//usage: IF_NOT_FEATURE_UNEXPAND_LONG_OPTIONS(
78//usage: "\n -a Convert all blanks" 75//usage: "\n -a Convert all blanks"
diff --git a/coreutils/head.c b/coreutils/head.c
index 176e91e3a..d49113e7f 100644
--- a/coreutils/head.c
+++ b/coreutils/head.c
@@ -14,11 +14,9 @@
14//config: from files. 14//config: from files.
15//config: 15//config:
16//config:config FEATURE_FANCY_HEAD 16//config:config FEATURE_FANCY_HEAD
17//config: bool "Enable head options (-c, -q, and -v)" 17//config: bool "Enable -c, -q, and -v"
18//config: default y 18//config: default y
19//config: depends on HEAD 19//config: depends on HEAD
20//config: help
21//config: This enables the head options (-c, -q, and -v).
22 20
23//applet:IF_HEAD(APPLET_NOEXEC(head, head, BB_DIR_USR_BIN, BB_SUID_DROP, head)) 21//applet:IF_HEAD(APPLET_NOEXEC(head, head, BB_DIR_USR_BIN, BB_SUID_DROP, head))
24 22
diff --git a/coreutils/install.c b/coreutils/install.c
index 831f9b802..2a642bdb6 100644
--- a/coreutils/install.c
+++ b/coreutils/install.c
@@ -15,8 +15,6 @@
15//config: bool "Enable long options" 15//config: bool "Enable long options"
16//config: default y 16//config: default y
17//config: depends on INSTALL && LONG_OPTS 17//config: depends on INSTALL && LONG_OPTS
18//config: help
19//config: Support long options for the install applet.
20 18
21//applet:IF_INSTALL(APPLET(install, BB_DIR_USR_BIN, BB_SUID_DROP)) 19//applet:IF_INSTALL(APPLET(install, BB_DIR_USR_BIN, BB_SUID_DROP))
22 20
diff --git a/coreutils/link.c b/coreutils/link.c
new file mode 100644
index 000000000..ac3ef85d9
--- /dev/null
+++ b/coreutils/link.c
@@ -0,0 +1,41 @@
1/*
2 * link implementation for busybox
3 *
4 * Copyright (C) 2017 Denys Vlasenko <vda.linux@googlemail.com>
5 *
6 * Licensed under GPLv2, see file LICENSE in this source tree.
7 */
8//config:config LINK
9//config: bool "link"
10//config: default y
11//config: help
12//config: link creates hard links between files.
13
14//applet:IF_LINK(APPLET_NOFORK(link, link, BB_DIR_BIN, BB_SUID_DROP, link))
15
16//kbuild:lib-$(CONFIG_LINK) += link.o
17
18//usage:#define link_trivial_usage
19//usage: "FILE LINK"
20//usage:#define link_full_usage "\n\n"
21//usage: "Create hard LINK to FILE"
22
23#include "libbb.h"
24
25/* This is a NOFORK applet. Be very careful! */
26
27int link_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
28int link_main(int argc UNUSED_PARAM, char **argv)
29{
30 opt_complementary = "=2"; /* exactly 2 params */
31 getopt32(argv, "");
32 argv += optind;
33 if (link(argv[0], argv[1]) != 0) {
34 /* shared message */
35 bb_perror_msg_and_die("can't create %slink "
36 "%s to %s", "hard",
37 argv[1], argv[0]
38 );
39 }
40 return EXIT_SUCCESS;
41}
diff --git a/coreutils/ls.c b/coreutils/ls.c
index 0f35c70d5..6e0a52d75 100644
--- a/coreutils/ls.c
+++ b/coreutils/ls.c
@@ -37,22 +37,21 @@
37//config: bool "Enable filetyping options (-p and -F)" 37//config: bool "Enable filetyping options (-p and -F)"
38//config: default y 38//config: default y
39//config: depends on LS 39//config: depends on LS
40//config: help
41//config: Enable the ls options (-p and -F).
42//config: 40//config:
43//config:config FEATURE_LS_FOLLOWLINKS 41//config:config FEATURE_LS_FOLLOWLINKS
44//config: bool "Enable symlinks dereferencing (-L)" 42//config: bool "Enable symlinks dereferencing (-L)"
45//config: default y 43//config: default y
46//config: depends on LS 44//config: depends on LS
47//config: help
48//config: Enable the ls option (-L).
49//config: 45//config:
50//config:config FEATURE_LS_RECURSIVE 46//config:config FEATURE_LS_RECURSIVE
51//config: bool "Enable recursion (-R)" 47//config: bool "Enable recursion (-R)"
52//config: default y 48//config: default y
53//config: depends on LS 49//config: depends on LS
54//config: help 50//config:
55//config: Enable the ls option (-R). 51//config:config FEATURE_LS_WIDTH
52//config: bool "Enable -w WIDTH and window size autodetection"
53//config: default y
54//config: depends on LS
56//config: 55//config:
57//config:config FEATURE_LS_SORTFILES 56//config:config FEATURE_LS_SORTFILES
58//config: bool "Sort the file names" 57//config: bool "Sort the file names"
@@ -102,18 +101,17 @@
102//usage: IF_FEATURE_LS_FOLLOWLINKS("LH") 101//usage: IF_FEATURE_LS_FOLLOWLINKS("LH")
103//usage: IF_FEATURE_LS_RECURSIVE("R") 102//usage: IF_FEATURE_LS_RECURSIVE("R")
104//usage: IF_FEATURE_LS_FILETYPES("Fp") "lins" 103//usage: IF_FEATURE_LS_FILETYPES("Fp") "lins"
105//usage: IF_FEATURE_LS_TIMESTAMPS("e")
106//usage: IF_FEATURE_HUMAN_READABLE("h") 104//usage: IF_FEATURE_HUMAN_READABLE("h")
107//usage: IF_FEATURE_LS_SORTFILES("rSXv") 105//usage: IF_FEATURE_LS_SORTFILES("rSXv")
108//usage: IF_FEATURE_LS_TIMESTAMPS("ctu") 106//usage: IF_FEATURE_LS_TIMESTAMPS("ctu")
109//usage: IF_SELINUX("kKZ") "]" 107//usage: IF_SELINUX("kZ") "]"
110//usage: IF_FEATURE_AUTOWIDTH(" [-w WIDTH]") " [FILE]..." 108//usage: IF_FEATURE_LS_WIDTH(" [-w WIDTH]") " [FILE]..."
111//usage:#define ls_full_usage "\n\n" 109//usage:#define ls_full_usage "\n\n"
112//usage: "List directory contents\n" 110//usage: "List directory contents\n"
113//usage: "\n -1 One column output" 111//usage: "\n -1 One column output"
114//usage: "\n -a Include entries which start with ." 112//usage: "\n -a Include entries which start with ."
115//usage: "\n -A Like -a, but exclude . and .." 113//usage: "\n -A Like -a, but exclude . and .."
116//usage: "\n -C List by columns" 114////usage: "\n -C List by columns" - don't show, this is a default anyway
117//usage: "\n -x List by lines" 115//usage: "\n -x List by lines"
118//usage: "\n -d List directory entries instead of contents" 116//usage: "\n -d List directory entries instead of contents"
119//usage: IF_FEATURE_LS_FOLLOWLINKS( 117//usage: IF_FEATURE_LS_FOLLOWLINKS(
@@ -132,29 +130,34 @@
132//usage: "\n -n List numeric UIDs and GIDs instead of names" 130//usage: "\n -n List numeric UIDs and GIDs instead of names"
133//usage: "\n -s List allocated blocks" 131//usage: "\n -s List allocated blocks"
134//usage: IF_FEATURE_LS_TIMESTAMPS( 132//usage: IF_FEATURE_LS_TIMESTAMPS(
135//usage: "\n -e List full date and time" 133//usage: "\n -lc List ctime"
134//usage: "\n -lu List atime"
136//usage: ) 135//usage: )
136//usage: IF_FEATURE_LS_TIMESTAMPS(IF_LONG_OPTS(
137//usage: "\n --full-time List full date and time"
138//usage: ))
137//usage: IF_FEATURE_HUMAN_READABLE( 139//usage: IF_FEATURE_HUMAN_READABLE(
138//usage: "\n -h List sizes in human readable format (1K 243M 2G)" 140//usage: "\n -h Human readable sizes (1K 243M 2G)"
139//usage: ) 141//usage: )
140//usage: IF_FEATURE_LS_SORTFILES( 142//usage: IF_FEATURE_LS_SORTFILES(
141//usage: "\n -r Sort in reverse order" 143//usage: IF_LONG_OPTS(
144//usage: "\n --group-directories-first"
145//usage: )
142//usage: "\n -S Sort by size" 146//usage: "\n -S Sort by size"
143//usage: "\n -X Sort by extension" 147//usage: "\n -X Sort by extension"
144//usage: "\n -v Sort by version" 148//usage: "\n -v Sort by version"
145//usage: ) 149//usage: )
146//usage: IF_FEATURE_LS_TIMESTAMPS( 150//usage: IF_FEATURE_LS_TIMESTAMPS(
147//usage: "\n -c With -l: sort by ctime" 151//usage: "\n -t Sort by mtime"
148//usage: "\n -t With -l: sort by mtime" 152//usage: "\n -tc Sort by ctime"
149//usage: "\n -u With -l: sort by atime" 153//usage: "\n -tu Sort by atime"
150//usage: ) 154//usage: )
155//usage: "\n -r Reverse sort order"
151//usage: IF_SELINUX( 156//usage: IF_SELINUX(
152//usage: "\n -k List security context"
153//usage: "\n -K List security context in long format"
154//usage: "\n -Z List security context and permission" 157//usage: "\n -Z List security context and permission"
155//usage: ) 158//usage: )
156//usage: IF_FEATURE_AUTOWIDTH( 159//usage: IF_FEATURE_LS_WIDTH(
157//usage: "\n -w N Assume the terminal is N columns wide" 160//usage: "\n -w N Format N columns wide"
158//usage: ) 161//usage: )
159//usage: IF_FEATURE_LS_COLOR( 162//usage: IF_FEATURE_LS_COLOR(
160//usage: "\n --color[={always,never,auto}] Control coloring" 163//usage: "\n --color[={always,never,auto}] Control coloring"
@@ -189,187 +192,90 @@ TERMINAL_WIDTH = 80, /* use 79 if terminal has linefold bug */
189SPLIT_FILE = 0, 192SPLIT_FILE = 0,
190SPLIT_DIR = 1, 193SPLIT_DIR = 1,
191SPLIT_SUBDIR = 2, 194SPLIT_SUBDIR = 2,
192
193/* Bits in G.all_fmt: */
194
195/* 51306 lrwxrwxrwx 1 root root 2 May 11 01:43 /bin/view -> vi* */
196/* what file information will be listed */
197LIST_INO = 1 << 0,
198LIST_BLOCKS = 1 << 1,
199LIST_MODEBITS = 1 << 2,
200LIST_NLINKS = 1 << 3,
201LIST_ID_NAME = 1 << 4,
202LIST_ID_NUMERIC = 1 << 5,
203LIST_CONTEXT = 1 << 6,
204LIST_SIZE = 1 << 7,
205LIST_DATE_TIME = 1 << 8,
206LIST_FULLTIME = 1 << 9,
207LIST_SYMLINK = 1 << 10,
208LIST_FILETYPE = 1 << 11, /* show / suffix for dirs */
209LIST_CLASSIFY = 1 << 12, /* requires LIST_FILETYPE, also show *,|,@,= suffixes */
210LIST_MASK = (LIST_CLASSIFY << 1) - 1,
211
212/* what files will be displayed */
213DISP_DIRNAME = 1 << 13, /* 2 or more items? label directories */
214DISP_HIDDEN = 1 << 14, /* show filenames starting with . */
215DISP_DOT = 1 << 15, /* show . and .. */
216DISP_NOLIST = 1 << 16, /* show directory as itself, not contents */
217DISP_RECURSIVE = 1 << 17, /* show directory and everything below it */
218DISP_ROWS = 1 << 18, /* print across rows */
219DISP_MASK = ((DISP_ROWS << 1) - 1) & ~(DISP_DIRNAME - 1),
220
221/* what is the overall style of the listing */
222STYLE_COLUMNAR = 1 << 19, /* many records per line */
223STYLE_LONG = 2 << 19, /* one record per line, extended info */
224STYLE_SINGLE = 3 << 19, /* one record per line */
225STYLE_MASK = STYLE_SINGLE,
226
227/* which of the three times will be used */
228TIME_CHANGE = (1 << 21) * ENABLE_FEATURE_LS_TIMESTAMPS,
229TIME_ACCESS = (2 << 21) * ENABLE_FEATURE_LS_TIMESTAMPS,
230TIME_MASK = (3 << 21) * ENABLE_FEATURE_LS_TIMESTAMPS,
231
232/* how will the files be sorted (CONFIG_FEATURE_LS_SORTFILES) */
233SORT_REVERSE = 1 << 23,
234
235SORT_NAME = 0, /* sort by file name */
236SORT_SIZE = 1 << 24, /* sort by file size */
237SORT_ATIME = 2 << 24, /* sort by last access time */
238SORT_CTIME = 3 << 24, /* sort by last change time */
239SORT_MTIME = 4 << 24, /* sort by last modification time */
240SORT_VERSION = 5 << 24, /* sort by version */
241SORT_EXT = 6 << 24, /* sort by file name extension */
242SORT_DIR = 7 << 24, /* sort by file or directory */
243SORT_MASK = (7 << 24) * ENABLE_FEATURE_LS_SORTFILES,
244
245LIST_LONG = LIST_MODEBITS | LIST_NLINKS | LIST_ID_NAME | LIST_SIZE | \
246 LIST_DATE_TIME | LIST_SYMLINK,
247}; 195};
248 196
249/* -Cadil1 Std options, busybox always supports */ 197/* -Cadi1l Std options, busybox always supports */
250/* -gnsxA Std options, busybox always supports */ 198/* -gnsxA Std options, busybox always supports */
251/* -Q GNU option, busybox always supports */ 199/* -Q GNU option, busybox always supports */
252/* -k SELinux option, busybox always supports (ignores if !SELinux) */ 200/* -k Std option, busybox always supports (by ignoring) */
253/* Std has -k which means "show sizes in kbytes" */ 201/* It means "for -s, show sizes in kbytes" */
202/* Seems to only affect "POSIXLY_CORRECT=1 ls -sk" */
203/* since otherwise -s shows kbytes anyway */
254/* -LHRctur Std options, busybox optionally supports */ 204/* -LHRctur Std options, busybox optionally supports */
255/* -Fp Std options, busybox optionally supports */ 205/* -Fp Std options, busybox optionally supports */
256/* -SXvhTw GNU options, busybox optionally supports */ 206/* -SXvhTw GNU options, busybox optionally supports */
257/* -T WIDTH Ignored (we don't use tabs on output) */ 207/* -T WIDTH Ignored (we don't use tabs on output) */
258/* -KZ SELinux mandated options, busybox optionally supports */ 208/* -Z SELinux mandated option, busybox optionally supports */
259/* (coreutils 8.4 has no -K, remove it?) */
260/* -e I think we made this one up (looks similar to GNU --full-time) */
261/* We already used up all 32 bits, if we need to add more, candidates for removal: */
262/* -K, -T, -e (add --full-time instead) */
263static const char ls_options[] ALIGN1 = 209static const char ls_options[] ALIGN1 =
264 "Cadil1gnsxQAk" /* 13 opts, total 13 */ 210 "Cadi1lgnsxAk" /* 12 opts, total 12 */
265 IF_FEATURE_LS_TIMESTAMPS("cetu") /* 4, 17 */ 211 IF_FEATURE_LS_FILETYPES("Fp") /* 2, 14 */
266 IF_FEATURE_LS_SORTFILES("SXrv") /* 4, 21 */ 212 IF_FEATURE_LS_RECURSIVE("R") /* 1, 15 */
267 IF_FEATURE_LS_FILETYPES("Fp") /* 2, 23 */ 213 IF_SELINUX("Z") /* 1, 16 */
268 IF_FEATURE_LS_RECURSIVE("R") /* 1, 24 */ 214 "Q" /* 1, 17 */
269 IF_SELINUX("KZ") /* 2, 26 */ 215 IF_FEATURE_LS_TIMESTAMPS("ctu") /* 3, 20 */
270 IF_FEATURE_LS_FOLLOWLINKS("LH") /* 2, 28 */ 216 IF_FEATURE_LS_SORTFILES("SXrv") /* 4, 24 */
271 IF_FEATURE_HUMAN_READABLE("h") /* 1, 29 */ 217 IF_FEATURE_LS_FOLLOWLINKS("LH") /* 2, 26 */
272 IF_FEATURE_AUTOWIDTH("T:w:") /* 2, 31 */ 218 IF_FEATURE_HUMAN_READABLE("h") /* 1, 27 */
273 /* with --color, we use all 32 bits */; 219 IF_FEATURE_LS_WIDTH("T:w:") /* 2, 29 */
220;
274enum { 221enum {
275 //OPT_C = (1 << 0), 222 OPT_C = (1 << 0),
276 //OPT_a = (1 << 1), 223 OPT_a = (1 << 1),
277 //OPT_d = (1 << 2), 224 OPT_d = (1 << 2),
278 //OPT_i = (1 << 3), 225 OPT_i = (1 << 3),
279 //OPT_l = (1 << 4), 226 OPT_1 = (1 << 4),
280 //OPT_1 = (1 << 5), 227 OPT_l = (1 << 5),
281 OPT_g = (1 << 6), 228 OPT_g = (1 << 6),
282 //OPT_n = (1 << 7), 229 OPT_n = (1 << 7),
283 //OPT_s = (1 << 8), 230 OPT_s = (1 << 8),
284 //OPT_x = (1 << 9), 231 OPT_x = (1 << 9),
285 OPT_Q = (1 << 10), 232 OPT_A = (1 << 10),
286 //OPT_A = (1 << 11), 233 //OPT_k = (1 << 11),
287 //OPT_k = (1 << 12), 234
288 235 OPTBIT_F = 12,
289 OPTBIT_c = 13, 236 OPTBIT_p, /* 13 */
290 OPTBIT_e,
291 OPTBIT_t,
292 OPTBIT_u,
293 OPTBIT_S = OPTBIT_c + 4 * ENABLE_FEATURE_LS_TIMESTAMPS,
294 OPTBIT_X, /* 18 */
295 OPTBIT_r,
296 OPTBIT_v,
297 OPTBIT_F = OPTBIT_S + 4 * ENABLE_FEATURE_LS_SORTFILES,
298 OPTBIT_p, /* 22 */
299 OPTBIT_R = OPTBIT_F + 2 * ENABLE_FEATURE_LS_FILETYPES, 237 OPTBIT_R = OPTBIT_F + 2 * ENABLE_FEATURE_LS_FILETYPES,
300 OPTBIT_K = OPTBIT_R + 1 * ENABLE_FEATURE_LS_RECURSIVE, 238 OPTBIT_Z = OPTBIT_R + 1 * ENABLE_FEATURE_LS_RECURSIVE,
301 OPTBIT_Z, /* 25 */ 239 OPTBIT_Q = OPTBIT_Z + 1 * ENABLE_SELINUX,
302 OPTBIT_L = OPTBIT_K + 2 * ENABLE_SELINUX, 240 OPTBIT_c, /* 17 */
303 OPTBIT_H, /* 27 */ 241 OPTBIT_t, /* 18 */
242 OPTBIT_u, /* 19 */
243 OPTBIT_S = OPTBIT_c + 3 * ENABLE_FEATURE_LS_TIMESTAMPS,
244 OPTBIT_X, /* 21 */
245 OPTBIT_r, /* 22 */
246 OPTBIT_v, /* 23 */
247 OPTBIT_L = OPTBIT_S + 4 * ENABLE_FEATURE_LS_SORTFILES,
248 OPTBIT_H, /* 25 */
304 OPTBIT_h = OPTBIT_L + 2 * ENABLE_FEATURE_LS_FOLLOWLINKS, 249 OPTBIT_h = OPTBIT_L + 2 * ENABLE_FEATURE_LS_FOLLOWLINKS,
305 OPTBIT_T = OPTBIT_h + 1 * ENABLE_FEATURE_HUMAN_READABLE, 250 OPTBIT_T = OPTBIT_h + 1 * ENABLE_FEATURE_HUMAN_READABLE,
306 OPTBIT_w, /* 30 */ 251 OPTBIT_w, /* 28 */
307 OPTBIT_color = OPTBIT_T + 2 * ENABLE_FEATURE_AUTOWIDTH, 252 OPTBIT_full_time = OPTBIT_T + 2 * ENABLE_FEATURE_LS_WIDTH,
253 OPTBIT_dirs_first,
254 OPTBIT_color, /* 31 */
255 /* with long opts, we use all 32 bits */
308 256
257 OPT_F = (1 << OPTBIT_F) * ENABLE_FEATURE_LS_FILETYPES,
258 OPT_p = (1 << OPTBIT_p) * ENABLE_FEATURE_LS_FILETYPES,
259 OPT_R = (1 << OPTBIT_R) * ENABLE_FEATURE_LS_RECURSIVE,
260 OPT_Z = (1 << OPTBIT_Z) * ENABLE_SELINUX,
261 OPT_Q = (1 << OPTBIT_Q),
309 OPT_c = (1 << OPTBIT_c) * ENABLE_FEATURE_LS_TIMESTAMPS, 262 OPT_c = (1 << OPTBIT_c) * ENABLE_FEATURE_LS_TIMESTAMPS,
310 OPT_e = (1 << OPTBIT_e) * ENABLE_FEATURE_LS_TIMESTAMPS,
311 OPT_t = (1 << OPTBIT_t) * ENABLE_FEATURE_LS_TIMESTAMPS, 263 OPT_t = (1 << OPTBIT_t) * ENABLE_FEATURE_LS_TIMESTAMPS,
312 OPT_u = (1 << OPTBIT_u) * ENABLE_FEATURE_LS_TIMESTAMPS, 264 OPT_u = (1 << OPTBIT_u) * ENABLE_FEATURE_LS_TIMESTAMPS,
313 OPT_S = (1 << OPTBIT_S) * ENABLE_FEATURE_LS_SORTFILES, 265 OPT_S = (1 << OPTBIT_S) * ENABLE_FEATURE_LS_SORTFILES,
314 OPT_X = (1 << OPTBIT_X) * ENABLE_FEATURE_LS_SORTFILES, 266 OPT_X = (1 << OPTBIT_X) * ENABLE_FEATURE_LS_SORTFILES,
315 OPT_r = (1 << OPTBIT_r) * ENABLE_FEATURE_LS_SORTFILES, 267 OPT_r = (1 << OPTBIT_r) * ENABLE_FEATURE_LS_SORTFILES,
316 OPT_v = (1 << OPTBIT_v) * ENABLE_FEATURE_LS_SORTFILES, 268 OPT_v = (1 << OPTBIT_v) * ENABLE_FEATURE_LS_SORTFILES,
317 OPT_F = (1 << OPTBIT_F) * ENABLE_FEATURE_LS_FILETYPES,
318 OPT_p = (1 << OPTBIT_p) * ENABLE_FEATURE_LS_FILETYPES,
319 OPT_R = (1 << OPTBIT_R) * ENABLE_FEATURE_LS_RECURSIVE,
320 OPT_K = (1 << OPTBIT_K) * ENABLE_SELINUX,
321 OPT_Z = (1 << OPTBIT_Z) * ENABLE_SELINUX,
322 OPT_L = (1 << OPTBIT_L) * ENABLE_FEATURE_LS_FOLLOWLINKS, 269 OPT_L = (1 << OPTBIT_L) * ENABLE_FEATURE_LS_FOLLOWLINKS,
323 OPT_H = (1 << OPTBIT_H) * ENABLE_FEATURE_LS_FOLLOWLINKS, 270 OPT_H = (1 << OPTBIT_H) * ENABLE_FEATURE_LS_FOLLOWLINKS,
324 OPT_h = (1 << OPTBIT_h) * ENABLE_FEATURE_HUMAN_READABLE, 271 OPT_h = (1 << OPTBIT_h) * ENABLE_FEATURE_HUMAN_READABLE,
325 OPT_T = (1 << OPTBIT_T) * ENABLE_FEATURE_AUTOWIDTH, 272 OPT_T = (1 << OPTBIT_T) * ENABLE_FEATURE_LS_WIDTH,
326 OPT_w = (1 << OPTBIT_w) * ENABLE_FEATURE_AUTOWIDTH, 273 OPT_w = (1 << OPTBIT_w) * ENABLE_FEATURE_LS_WIDTH,
327 OPT_color = (1 << OPTBIT_color) * ENABLE_FEATURE_LS_COLOR, 274 OPT_full_time = (1 << OPTBIT_full_time ) * ENABLE_LONG_OPTS,
328}; 275 OPT_dirs_first = (1 << OPTBIT_dirs_first) * ENABLE_LONG_OPTS,
329 276 OPT_color = (1 << OPTBIT_color ) * ENABLE_FEATURE_LS_COLOR,
330/* TODO: simple toggles may be stored as OPT_xxx bits instead */
331static const uint32_t opt_flags[] = {
332 STYLE_COLUMNAR, /* C */
333 DISP_HIDDEN | DISP_DOT, /* a */
334 DISP_NOLIST, /* d */
335 LIST_INO, /* i */
336 LIST_LONG | STYLE_LONG, /* l */
337 STYLE_SINGLE, /* 1 */
338 LIST_LONG | STYLE_LONG, /* g (don't show owner) - handled via OPT_g. assumes l */
339 LIST_ID_NUMERIC | LIST_LONG | STYLE_LONG, /* n (assumes l) */
340 LIST_BLOCKS, /* s */
341 DISP_ROWS | STYLE_COLUMNAR, /* x */
342 0, /* Q (quote filename) - handled via OPT_Q */
343 DISP_HIDDEN, /* A */
344 ENABLE_SELINUX * (LIST_CONTEXT|STYLE_SINGLE), /* k (ignored if !SELINUX) */
345#if ENABLE_FEATURE_LS_TIMESTAMPS
346 TIME_CHANGE | (ENABLE_FEATURE_LS_SORTFILES * SORT_CTIME), /* c */
347 LIST_FULLTIME, /* e */
348 ENABLE_FEATURE_LS_SORTFILES * SORT_MTIME, /* t */
349 TIME_ACCESS | (ENABLE_FEATURE_LS_SORTFILES * SORT_ATIME), /* u */
350#endif
351#if ENABLE_FEATURE_LS_SORTFILES
352 SORT_SIZE, /* S */
353 SORT_EXT, /* X */
354 SORT_REVERSE, /* r */
355 SORT_VERSION, /* v */
356#endif
357#if ENABLE_FEATURE_LS_FILETYPES
358 LIST_FILETYPE | LIST_CLASSIFY, /* F */
359 LIST_FILETYPE, /* p */
360#endif
361#if ENABLE_FEATURE_LS_RECURSIVE
362 DISP_RECURSIVE, /* R */
363#endif
364#if ENABLE_SELINUX
365 LIST_MODEBITS|LIST_NLINKS|LIST_CONTEXT|LIST_SIZE|LIST_DATE_TIME|STYLE_SINGLE, /* K */
366 LIST_MODEBITS|LIST_ID_NAME|LIST_CONTEXT|STYLE_SINGLE, /* Z */
367#endif
368 (1U << 31)
369 /* options after Z are not processed through opt_flags */
370}; 277};
371 278
372
373/* 279/*
374 * a directory entry and its stat info 280 * a directory entry and its stat info
375 */ 281 */
@@ -399,9 +305,7 @@ struct dnode {
399 mode_t dn_mode; /* obtained with lstat OR stat, depending on -L etc */ 305 mode_t dn_mode; /* obtained with lstat OR stat, depending on -L etc */
400 off_t dn_size; 306 off_t dn_size;
401#if ENABLE_FEATURE_LS_TIMESTAMPS || ENABLE_FEATURE_LS_SORTFILES 307#if ENABLE_FEATURE_LS_TIMESTAMPS || ENABLE_FEATURE_LS_SORTFILES
402 time_t dn_atime; 308 time_t dn_time;
403 time_t dn_mtime;
404 time_t dn_ctime;
405#endif 309#endif
406 ino_t dn_ino; 310 ino_t dn_ino;
407 blkcnt_t dn_blocks; 311 blkcnt_t dn_blocks;
@@ -422,8 +326,8 @@ struct globals {
422# define G_show_color 0 326# define G_show_color 0
423#endif 327#endif
424 smallint exit_code; 328 smallint exit_code;
425 unsigned all_fmt; 329 smallint show_dirname;
426#if ENABLE_FEATURE_AUTOWIDTH 330#if ENABLE_FEATURE_LS_WIDTH
427 unsigned terminal_width; 331 unsigned terminal_width;
428# define G_terminal_width (G.terminal_width) 332# define G_terminal_width (G.terminal_width)
429#else 333#else
@@ -439,7 +343,7 @@ struct globals {
439 setup_common_bufsiz(); \ 343 setup_common_bufsiz(); \
440 /* we have to zero it out because of NOEXEC */ \ 344 /* we have to zero it out because of NOEXEC */ \
441 memset(&G, 0, sizeof(G)); \ 345 memset(&G, 0, sizeof(G)); \
442 IF_FEATURE_AUTOWIDTH(G_terminal_width = TERMINAL_WIDTH;) \ 346 IF_FEATURE_LS_WIDTH(G_terminal_width = TERMINAL_WIDTH;) \
443 IF_FEATURE_LS_TIMESTAMPS(time(&G.current_time_t);) \ 347 IF_FEATURE_LS_TIMESTAMPS(time(&G.current_time_t);) \
444} while (0) 348} while (0)
445 349
@@ -496,11 +400,12 @@ static char bold(mode_t mode)
496#if ENABLE_FEATURE_LS_FILETYPES 400#if ENABLE_FEATURE_LS_FILETYPES
497static char append_char(mode_t mode) 401static char append_char(mode_t mode)
498{ 402{
499 if (!(G.all_fmt & LIST_FILETYPE)) 403 if (!(option_mask32 & (OPT_F|OPT_p)))
500 return '\0'; 404 return '\0';
405
501 if (S_ISDIR(mode)) 406 if (S_ISDIR(mode))
502 return '/'; 407 return '/';
503 if (!(G.all_fmt & LIST_CLASSIFY)) 408 if (!(option_mask32 & OPT_F))
504 return '\0'; 409 return '\0';
505 if (S_ISREG(mode) && (mode & (S_IXUSR | S_IXGRP | S_IXOTH))) 410 if (S_ISREG(mode) && (mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
506 return '*'; 411 return '*';
@@ -531,8 +436,8 @@ static unsigned calc_name_len(const char *name)
531} 436}
532 437
533/* Return the number of used columns. 438/* Return the number of used columns.
534 * Note that only STYLE_COLUMNAR uses return value. 439 * Note that only columnar output uses return value.
535 * STYLE_SINGLE and STYLE_LONG don't care. 440 * -l and -1 modes don't care.
536 * coreutils 7.2 also supports: 441 * coreutils 7.2 also supports:
537 * ls -b (--escape) = octal escapes (although it doesn't look like working) 442 * ls -b (--escape) = octal escapes (although it doesn't look like working)
538 * ls -N (--literal) = not escape at all 443 * ls -N (--literal) = not escape at all
@@ -565,13 +470,14 @@ static unsigned print_name(const char *name)
565} 470}
566 471
567/* Return the number of used columns. 472/* Return the number of used columns.
568 * Note that only STYLE_COLUMNAR uses return value, 473 * Note that only columnar output uses return value,
569 * STYLE_SINGLE and STYLE_LONG don't care. 474 * -l and -1 modes don't care.
570 */ 475 */
571static NOINLINE unsigned display_single(const struct dnode *dn) 476static NOINLINE unsigned display_single(const struct dnode *dn)
572{ 477{
573 unsigned column = 0; 478 unsigned column = 0;
574 char *lpath; 479 char *lpath;
480 int opt;
575#if ENABLE_FEATURE_LS_FILETYPES || ENABLE_FEATURE_LS_COLOR 481#if ENABLE_FEATURE_LS_FILETYPES || ENABLE_FEATURE_LS_COLOR
576 struct stat statbuf; 482 struct stat statbuf;
577 char append; 483 char append;
@@ -580,50 +486,61 @@ static NOINLINE unsigned display_single(const struct dnode *dn)
580#if ENABLE_FEATURE_LS_FILETYPES 486#if ENABLE_FEATURE_LS_FILETYPES
581 append = append_char(dn->dn_mode); 487 append = append_char(dn->dn_mode);
582#endif 488#endif
489 opt = option_mask32;
583 490
584 /* Do readlink early, so that if it fails, error message 491 /* Do readlink early, so that if it fails, error message
585 * does not appear *inside* the "ls -l" line */ 492 * does not appear *inside* the "ls -l" line */
586 lpath = NULL; 493 lpath = NULL;
587 if (G.all_fmt & LIST_SYMLINK) 494 if (opt & OPT_l)
588 if (S_ISLNK(dn->dn_mode)) 495 if (S_ISLNK(dn->dn_mode))
589 lpath = xmalloc_readlink_or_warn(dn->fullname); 496 lpath = xmalloc_readlink_or_warn(dn->fullname);
590 497
591 if (G.all_fmt & LIST_INO) 498 if (opt & OPT_i) /* show inode# */
592 column += printf("%7llu ", (long long) dn->dn_ino); 499 column += printf("%7llu ", (long long) dn->dn_ino);
593//TODO: -h should affect -s too: 500//TODO: -h should affect -s too:
594 if (G.all_fmt & LIST_BLOCKS) 501 if (opt & OPT_s) /* show allocated blocks */
595 column += printf("%6"OFF_FMT"u ", (off_t) (dn->dn_blocks >> 1)); 502 column += printf("%6"OFF_FMT"u ", (off_t) (dn->dn_blocks >> 1));
596 if (G.all_fmt & LIST_MODEBITS) 503 if (opt & OPT_l) {
504 /* long listing: show mode */
597 column += printf("%-10s ", (char *) bb_mode_string(dn->dn_mode)); 505 column += printf("%-10s ", (char *) bb_mode_string(dn->dn_mode));
598 if (G.all_fmt & LIST_NLINKS) 506 /* long listing: show number of links */
599 column += printf("%4lu ", (long) dn->dn_nlink); 507 column += printf("%4lu ", (long) dn->dn_nlink);
600 if (G.all_fmt & LIST_ID_NUMERIC) { 508 /* long listing: show user/group */
601 if (option_mask32 & OPT_g) 509 if (opt & OPT_n) {
602 column += printf("%-8u ", (int) dn->dn_gid); 510 if (opt & OPT_g)
603 else 511 column += printf("%-8u ", (int) dn->dn_gid);
604 column += printf("%-8u %-8u ", 512 else
605 (int) dn->dn_uid, 513 column += printf("%-8u %-8u ",
606 (int) dn->dn_gid); 514 (int) dn->dn_uid,
607 } 515 (int) dn->dn_gid);
516 }
608#if ENABLE_FEATURE_LS_USERNAME 517#if ENABLE_FEATURE_LS_USERNAME
609 else if (G.all_fmt & LIST_ID_NAME) { 518 else {
610 if (option_mask32 & OPT_g) { 519 if (opt & OPT_g) {
611 column += printf("%-8.8s ", 520 column += printf("%-8.8s ",
612 get_cached_groupname(dn->dn_gid)); 521 get_cached_groupname(dn->dn_gid));
613 } else { 522 } else {
614 column += printf("%-8.8s %-8.8s ", 523 column += printf("%-8.8s %-8.8s ",
615 get_cached_username(dn->dn_uid), 524 get_cached_username(dn->dn_uid),
616 get_cached_groupname(dn->dn_gid)); 525 get_cached_groupname(dn->dn_gid));
526 }
617 } 527 }
528#endif
529#if ENABLE_SELINUX
530 }
531 if (opt & OPT_Z) {
532 column += printf("%-32s ", dn->sid ? dn->sid : "?");
533 freecon(dn->sid);
618 } 534 }
535 if (opt & OPT_l) {
619#endif 536#endif
620 if (G.all_fmt & LIST_SIZE) { 537 /* long listing: show size */
621 if (S_ISBLK(dn->dn_mode) || S_ISCHR(dn->dn_mode)) { 538 if (S_ISBLK(dn->dn_mode) || S_ISCHR(dn->dn_mode)) {
622 column += printf("%4u, %3u ", 539 column += printf("%4u, %3u ",
623 dn->dn_rdev_maj, 540 dn->dn_rdev_maj,
624 dn->dn_rdev_min); 541 dn->dn_rdev_min);
625 } else { 542 } else {
626 if (option_mask32 & OPT_h) { 543 if (opt & OPT_h) {
627 column += printf("%"HUMAN_READABLE_MAX_WIDTH_STR"s ", 544 column += printf("%"HUMAN_READABLE_MAX_WIDTH_STR"s ",
628 /* print size, show one fractional, use suffixes */ 545 /* print size, show one fractional, use suffixes */
629 make_human_readable_str(dn->dn_size, 1, 0) 546 make_human_readable_str(dn->dn_size, 1, 0)
@@ -632,25 +549,22 @@ static NOINLINE unsigned display_single(const struct dnode *dn)
632 column += printf("%9"OFF_FMT"u ", dn->dn_size); 549 column += printf("%9"OFF_FMT"u ", dn->dn_size);
633 } 550 }
634 } 551 }
635 }
636#if ENABLE_FEATURE_LS_TIMESTAMPS 552#if ENABLE_FEATURE_LS_TIMESTAMPS
637 if (G.all_fmt & (LIST_FULLTIME|LIST_DATE_TIME)) { 553 /* long listing: show {m,c,a}time */
638 char *filetime; 554 if (opt & OPT_full_time) { /* --full-time */
639 const time_t *ttime = &dn->dn_mtime; 555 /* coreutils 8.4 ls --full-time prints:
640 if (G.all_fmt & TIME_ACCESS)
641 ttime = &dn->dn_atime;
642 if (G.all_fmt & TIME_CHANGE)
643 ttime = &dn->dn_ctime;
644 filetime = ctime(ttime);
645 /* filetime's format: "Wed Jun 30 21:49:08 1993\n" */
646 if (G.all_fmt & LIST_FULLTIME) { /* -e */
647 /* Note: coreutils 8.4 ls --full-time prints:
648 * 2009-07-13 17:49:27.000000000 +0200 556 * 2009-07-13 17:49:27.000000000 +0200
557 * we don't show fractional seconds.
649 */ 558 */
650 column += printf("%.24s ", filetime); 559 char buf[sizeof("YYYY-mm-dd HH:MM:SS TIMEZONE")];
651 } else { /* LIST_DATE_TIME */ 560 strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %z",
652 /* G.current_time_t ~== time(NULL) */ 561 localtime(&dn->dn_time));
653 time_t age = G.current_time_t - *ttime; 562 column += printf("%s ", buf);
563 } else { /* ordinary time format */
564 /* G.current_time_t is ~== time(NULL) */
565 char *filetime = ctime(&dn->dn_time);
566 /* filetime's format: "Wed Jun 30 21:49:08 1993\n" */
567 time_t age = G.current_time_t - dn->dn_time;
654 if (age < 3600L * 24 * 365 / 2 && age > -15 * 60) { 568 if (age < 3600L * 24 * 365 / 2 && age > -15 * 60) {
655 /* less than 6 months old */ 569 /* less than 6 months old */
656 /* "mmm dd hh:mm " */ 570 /* "mmm dd hh:mm " */
@@ -663,14 +577,8 @@ static NOINLINE unsigned display_single(const struct dnode *dn)
663 } 577 }
664 column += 13; 578 column += 13;
665 } 579 }
666 }
667#endif 580#endif
668#if ENABLE_SELINUX
669 if (G.all_fmt & LIST_CONTEXT) {
670 column += printf("%-32s ", dn->sid ? dn->sid : "unknown");
671 freecon(dn->sid);
672 } 581 }
673#endif
674 582
675#if ENABLE_FEATURE_LS_COLOR 583#if ENABLE_FEATURE_LS_COLOR
676 if (G_show_color) { 584 if (G_show_color) {
@@ -689,7 +597,9 @@ static NOINLINE unsigned display_single(const struct dnode *dn)
689 if (lpath) { 597 if (lpath) {
690 printf(" -> "); 598 printf(" -> ");
691#if ENABLE_FEATURE_LS_FILETYPES || ENABLE_FEATURE_LS_COLOR 599#if ENABLE_FEATURE_LS_FILETYPES || ENABLE_FEATURE_LS_COLOR
692 if ((G.all_fmt & LIST_FILETYPE) || G_show_color) { 600 if ((opt & (OPT_F|OPT_p))
601 || G_show_color
602 ) {
693 mode_t mode = dn->dn_mode_stat; 603 mode_t mode = dn->dn_mode_stat;
694 if (!mode) 604 if (!mode)
695 if (stat(dn->fullname, &statbuf) == 0) 605 if (stat(dn->fullname, &statbuf) == 0)
@@ -711,7 +621,7 @@ static NOINLINE unsigned display_single(const struct dnode *dn)
711 } 621 }
712 } 622 }
713#if ENABLE_FEATURE_LS_FILETYPES 623#if ENABLE_FEATURE_LS_FILETYPES
714 if (G.all_fmt & LIST_FILETYPE) { 624 if (opt & (OPT_F|OPT_p)) {
715 if (append) { 625 if (append) {
716 putchar(append); 626 putchar(append);
717 column++; 627 column++;
@@ -727,9 +637,9 @@ static void display_files(struct dnode **dn, unsigned nfiles)
727 unsigned i, ncols, nrows, row, nc; 637 unsigned i, ncols, nrows, row, nc;
728 unsigned column; 638 unsigned column;
729 unsigned nexttab; 639 unsigned nexttab;
730 unsigned column_width = 0; /* used only by STYLE_COLUMNAR */ 640 unsigned column_width = 0; /* used only by coulmnal output */
731 641
732 if (G.all_fmt & STYLE_LONG) { /* STYLE_LONG or STYLE_SINGLE */ 642 if (option_mask32 & (OPT_l|OPT_1)) {
733 ncols = 1; 643 ncols = 1;
734 } else { 644 } else {
735 /* find the longest file name, use that as the column width */ 645 /* find the longest file name, use that as the column width */
@@ -738,10 +648,11 @@ static void display_files(struct dnode **dn, unsigned nfiles)
738 if (column_width < len) 648 if (column_width < len)
739 column_width = len; 649 column_width = len;
740 } 650 }
741 column_width += 2 + 651 column_width += 2
742 IF_SELINUX( ((G.all_fmt & LIST_CONTEXT) ? 33 : 0) + ) 652 + ((option_mask32 & OPT_Z) ? 33 : 0) /* context width */
743 ((G.all_fmt & LIST_INO) ? 8 : 0) + 653 + ((option_mask32 & OPT_i) ? 8 : 0) /* inode# width */
744 ((G.all_fmt & LIST_BLOCKS) ? 5 : 0); 654 + ((option_mask32 & OPT_s) ? 5 : 0) /* "alloc block" width */
655 ;
745 ncols = (unsigned)G_terminal_width / column_width; 656 ncols = (unsigned)G_terminal_width / column_width;
746 } 657 }
747 658
@@ -759,7 +670,7 @@ static void display_files(struct dnode **dn, unsigned nfiles)
759 for (row = 0; row < nrows; row++) { 670 for (row = 0; row < nrows; row++) {
760 for (nc = 0; nc < ncols; nc++) { 671 for (nc = 0; nc < ncols; nc++) {
761 /* reach into the array based on the column and row */ 672 /* reach into the array based on the column and row */
762 if (G.all_fmt & DISP_ROWS) 673 if (option_mask32 & OPT_x)
763 i = (row * ncols) + nc; /* display across row */ 674 i = (row * ncols) + nc; /* display across row */
764 else 675 else
765 i = (nc * nrows) + row; /* display by column */ 676 i = (nc * nrows) + row; /* display by column */
@@ -792,7 +703,7 @@ static struct dnode *my_stat(const char *fullname, const char *name, int force_f
792 703
793 if ((option_mask32 & OPT_L) || force_follow) { 704 if ((option_mask32 & OPT_L) || force_follow) {
794#if ENABLE_SELINUX 705#if ENABLE_SELINUX
795 if (is_selinux_enabled()) { 706 if (option_mask32 & OPT_Z) {
796 getfilecon(fullname, &cur->sid); 707 getfilecon(fullname, &cur->sid);
797 } 708 }
798#endif 709#endif
@@ -805,7 +716,7 @@ static struct dnode *my_stat(const char *fullname, const char *name, int force_f
805 cur->dn_mode_stat = statbuf.st_mode; 716 cur->dn_mode_stat = statbuf.st_mode;
806 } else { 717 } else {
807#if ENABLE_SELINUX 718#if ENABLE_SELINUX
808 if (is_selinux_enabled()) { 719 if (option_mask32 & OPT_Z) {
809 lgetfilecon(fullname, &cur->sid); 720 lgetfilecon(fullname, &cur->sid);
810 } 721 }
811#endif 722#endif
@@ -822,9 +733,11 @@ static struct dnode *my_stat(const char *fullname, const char *name, int force_f
822 cur->dn_mode = statbuf.st_mode ; 733 cur->dn_mode = statbuf.st_mode ;
823 cur->dn_size = statbuf.st_size ; 734 cur->dn_size = statbuf.st_size ;
824#if ENABLE_FEATURE_LS_TIMESTAMPS || ENABLE_FEATURE_LS_SORTFILES 735#if ENABLE_FEATURE_LS_TIMESTAMPS || ENABLE_FEATURE_LS_SORTFILES
825 cur->dn_atime = statbuf.st_atime ; 736 cur->dn_time = statbuf.st_mtime ;
826 cur->dn_mtime = statbuf.st_mtime ; 737 if (option_mask32 & OPT_u)
827 cur->dn_ctime = statbuf.st_ctime ; 738 cur->dn_time = statbuf.st_atime;
739 if (option_mask32 & OPT_c)
740 cur->dn_time = statbuf.st_ctime;
828#endif 741#endif
829 cur->dn_ino = statbuf.st_ino ; 742 cur->dn_ino = statbuf.st_ino ;
830 cur->dn_blocks = statbuf.st_blocks; 743 cur->dn_blocks = statbuf.st_blocks;
@@ -938,33 +851,30 @@ static int sortcmp(const void *a, const void *b)
938{ 851{
939 struct dnode *d1 = *(struct dnode **)a; 852 struct dnode *d1 = *(struct dnode **)a;
940 struct dnode *d2 = *(struct dnode **)b; 853 struct dnode *d2 = *(struct dnode **)b;
941 unsigned sort_opts = G.all_fmt & SORT_MASK; 854 unsigned opt = option_mask32;
942 off_t dif; 855 off_t dif;
943 856
944 dif = 0; /* assume SORT_NAME */ 857 dif = 0; /* assume sort by name */
945 // TODO: use pre-initialized function pointer 858 // TODO: use pre-initialized function pointer
946 // instead of branch forest 859 // instead of branch forest
947 if (sort_opts == SORT_SIZE) { 860 if (opt & OPT_dirs_first) {
861 dif = S_ISDIR(d2->dn_mode) - S_ISDIR(d1->dn_mode);
862 if (dif != 0)
863 goto maybe_invert_and_ret;
864 }
865
866 if (opt & OPT_S) { /* sort by size */
948 dif = (d2->dn_size - d1->dn_size); 867 dif = (d2->dn_size - d1->dn_size);
949 } else 868 } else
950 if (sort_opts == SORT_ATIME) { 869 if (opt & OPT_t) { /* sort by time */
951 dif = (d2->dn_atime - d1->dn_atime); 870 dif = (d2->dn_time - d1->dn_time);
952 } else
953 if (sort_opts == SORT_CTIME) {
954 dif = (d2->dn_ctime - d1->dn_ctime);
955 } else
956 if (sort_opts == SORT_MTIME) {
957 dif = (d2->dn_mtime - d1->dn_mtime);
958 } else
959 if (sort_opts == SORT_DIR) {
960 dif = S_ISDIR(d2->dn_mode) - S_ISDIR(d1->dn_mode);
961 } else 871 } else
962#if defined(HAVE_STRVERSCMP) && HAVE_STRVERSCMP == 1 872#if defined(HAVE_STRVERSCMP) && HAVE_STRVERSCMP == 1
963 if (sort_opts == SORT_VERSION) { 873 if (opt & OPT_v) { /* sort by version */
964 dif = strverscmp(d1->name, d2->name); 874 dif = strverscmp(d1->name, d2->name);
965 } else 875 } else
966#endif 876#endif
967 if (sort_opts == SORT_EXT) { 877 if (opt & OPT_X) { /* sort by extension */
968 dif = strcmp(strchrnul(d1->name, '.'), strchrnul(d2->name, '.')); 878 dif = strcmp(strchrnul(d1->name, '.'), strchrnul(d2->name, '.'));
969 } 879 }
970 if (dif == 0) { 880 if (dif == 0) {
@@ -973,18 +883,17 @@ static int sortcmp(const void *a, const void *b)
973 dif = strcoll(d1->name, d2->name); 883 dif = strcoll(d1->name, d2->name);
974 else 884 else
975 dif = strcmp(d1->name, d2->name); 885 dif = strcmp(d1->name, d2->name);
976 } 886 } else {
977 887 /* Make dif fit into an int */
978 /* Make dif fit into an int */ 888 if (sizeof(dif) > sizeof(int)) {
979 if (sizeof(dif) > sizeof(int)) { 889 enum { BITS_TO_SHIFT = 8 * (sizeof(dif) - sizeof(int)) };
980 enum { BITS_TO_SHIFT = 8 * (sizeof(dif) - sizeof(int)) }; 890 /* shift leaving only "int" worth of bits */
981 /* shift leaving only "int" worth of bits */ 891 /* (this requires dif != 0, and here it is nonzero) */
982 if (dif != 0) {
983 dif = 1 | (int)((uoff_t)dif >> BITS_TO_SHIFT); 892 dif = 1 | (int)((uoff_t)dif >> BITS_TO_SHIFT);
984 } 893 }
985 } 894 }
986 895 maybe_invert_and_ret:
987 return (G.all_fmt & SORT_REVERSE) ? -(int)dif : (int)dif; 896 return (opt & OPT_r) ? -(int)dif : (int)dif;
988} 897}
989 898
990static void dnsort(struct dnode **dn, int size) 899static void dnsort(struct dnode **dn, int size)
@@ -1023,13 +932,13 @@ static struct dnode **scan_one_dir(const char *path, unsigned *nfiles_p)
1023 932
1024 /* are we going to list the file- it may be . or .. or a hidden file */ 933 /* are we going to list the file- it may be . or .. or a hidden file */
1025 if (entry->d_name[0] == '.') { 934 if (entry->d_name[0] == '.') {
1026 if ((!entry->d_name[1] || (entry->d_name[1] == '.' && !entry->d_name[2])) 935 if (!(option_mask32 & (OPT_a|OPT_A)))
1027 && !(G.all_fmt & DISP_DOT) 936 continue; /* skip all dotfiles if no -a/-A */
937 if (!(option_mask32 & OPT_a)
938 && (!entry->d_name[1] || (entry->d_name[1] == '.' && !entry->d_name[2]))
1028 ) { 939 ) {
1029 continue; 940 continue; /* if only -A, skip . and .. but show other dotfiles */
1030 } 941 }
1031 if (!(G.all_fmt & DISP_HIDDEN))
1032 continue;
1033 } 942 }
1034 fullname = concat_path_file(path, entry->d_name); 943 fullname = concat_path_file(path, entry->d_name);
1035 cur = my_stat(fullname, bb_basename(fullname), 0); 944 cur = my_stat(fullname, bb_basename(fullname), 0);
@@ -1097,7 +1006,7 @@ static void scan_and_display_dirs_recur(struct dnode **dn, int first)
1097 struct dnode **subdnp; 1006 struct dnode **subdnp;
1098 1007
1099 for (; *dn; dn++) { 1008 for (; *dn; dn++) {
1100 if (G.all_fmt & (DISP_DIRNAME | DISP_RECURSIVE)) { 1009 if (G.show_dirname || (option_mask32 & OPT_R)) {
1101 if (!first) 1010 if (!first)
1102 bb_putchar('\n'); 1011 bb_putchar('\n');
1103 first = 0; 1012 first = 0;
@@ -1105,15 +1014,16 @@ static void scan_and_display_dirs_recur(struct dnode **dn, int first)
1105 } 1014 }
1106 subdnp = scan_one_dir((*dn)->fullname, &nfiles); 1015 subdnp = scan_one_dir((*dn)->fullname, &nfiles);
1107#if ENABLE_DESKTOP 1016#if ENABLE_DESKTOP
1108 if ((G.all_fmt & STYLE_MASK) == STYLE_LONG || (G.all_fmt & LIST_BLOCKS)) 1017 if (option_mask32 & (OPT_s|OPT_l)) {
1109 printf("total %"OFF_FMT"u\n", calculate_blocks(subdnp)); 1018 printf("total %"OFF_FMT"u\n", calculate_blocks(subdnp));
1019 }
1110#endif 1020#endif
1111 if (nfiles > 0) { 1021 if (nfiles > 0) {
1112 /* list all files at this level */ 1022 /* list all files at this level */
1113 sort_and_display_files(subdnp, nfiles); 1023 sort_and_display_files(subdnp, nfiles);
1114 1024
1115 if (ENABLE_FEATURE_LS_RECURSIVE 1025 if (ENABLE_FEATURE_LS_RECURSIVE
1116 && (G.all_fmt & DISP_RECURSIVE) 1026 && (option_mask32 & OPT_R)
1117 ) { 1027 ) {
1118 struct dnode **dnd; 1028 struct dnode **dnd;
1119 unsigned dndirs; 1029 unsigned dndirs;
@@ -1135,7 +1045,7 @@ static void scan_and_display_dirs_recur(struct dnode **dn, int first)
1135 1045
1136 1046
1137int ls_main(int argc UNUSED_PARAM, char **argv) 1047int ls_main(int argc UNUSED_PARAM, char **argv)
1138{ 1048{ /* ^^^^^^^^^^^^^^^^^ note: if FTPD, argc can be wrong, see ftpd.c */
1139 struct dnode **dnd; 1049 struct dnode **dnd;
1140 struct dnode **dnf; 1050 struct dnode **dnf;
1141 struct dnode **dnp; 1051 struct dnode **dnp;
@@ -1158,7 +1068,10 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1158 * (and substrings: "--color=alwa" work too) 1068 * (and substrings: "--color=alwa" work too)
1159 */ 1069 */
1160 static const char ls_longopts[] ALIGN1 = 1070 static const char ls_longopts[] ALIGN1 =
1161 "color\0" Optional_argument "\xff"; /* no short equivalent */ 1071 "full-time\0" No_argument "\xff"
1072 "group-directories-first\0" No_argument "\xfe"
1073 "color\0" Optional_argument "\xfd"
1074 ;
1162 static const char color_str[] ALIGN1 = 1075 static const char color_str[] ALIGN1 =
1163 "always\0""yes\0""force\0" 1076 "always\0""yes\0""force\0"
1164 "auto\0""tty\0""if-tty\0"; 1077 "auto\0""tty\0""if-tty\0";
@@ -1170,10 +1083,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1170 1083
1171 init_unicode(); 1084 init_unicode();
1172 1085
1173 if (ENABLE_FEATURE_LS_SORTFILES) 1086#if ENABLE_FEATURE_LS_WIDTH
1174 G.all_fmt = SORT_NAME;
1175
1176#if ENABLE_FEATURE_AUTOWIDTH
1177 /* obtain the terminal width */ 1087 /* obtain the terminal width */
1178 G_terminal_width = get_terminal_width(STDIN_FILENO); 1088 G_terminal_width = get_terminal_width(STDIN_FILENO);
1179 /* go one less... */ 1089 /* go one less... */
@@ -1183,8 +1093,10 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1183 /* process options */ 1093 /* process options */
1184 IF_FEATURE_LS_COLOR(applet_long_options = ls_longopts;) 1094 IF_FEATURE_LS_COLOR(applet_long_options = ls_longopts;)
1185 opt_complementary = 1095 opt_complementary =
1186 /* -e implies -l */ 1096 /* -n and -g imply -l */
1187 IF_FEATURE_LS_TIMESTAMPS("el") 1097 "nl:gl"
1098 /* --full-time implies -l */
1099 IF_FEATURE_LS_TIMESTAMPS(IF_LONG_OPTS(":\xff""l"))
1188 /* http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html: 1100 /* http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html:
1189 * in some pairs of opts, only last one takes effect: 1101 * in some pairs of opts, only last one takes effect:
1190 */ 1102 */
@@ -1196,25 +1108,28 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1196 ":x-1:1-x" /* bylines/oneline (not in SuS, but in GNU coreutils 8.4) */ 1108 ":x-1:1-x" /* bylines/oneline (not in SuS, but in GNU coreutils 8.4) */
1197 IF_FEATURE_LS_TIMESTAMPS(":c-u:u-c") /* mtime/atime */ 1109 IF_FEATURE_LS_TIMESTAMPS(":c-u:u-c") /* mtime/atime */
1198 /* -w NUM: */ 1110 /* -w NUM: */
1199 IF_FEATURE_AUTOWIDTH(":w+"); 1111 IF_FEATURE_LS_WIDTH(":w+");
1200 opt = getopt32(argv, ls_options 1112 opt = getopt32(argv, ls_options
1201 IF_FEATURE_AUTOWIDTH(, NULL, &G_terminal_width) 1113 IF_FEATURE_LS_WIDTH(, /*-T*/ NULL, /*-w*/ &G_terminal_width)
1202 IF_FEATURE_LS_COLOR(, &color_opt) 1114 IF_FEATURE_LS_COLOR(, &color_opt)
1203 ); 1115 );
1204 for (i = 0; opt_flags[i] != (1U << 31); i++) { 1116#if 0 /* option bits debug */
1205 if (opt & (1 << i)) { 1117 bb_error_msg("opt:0x%08x l:%x H:%x color:%x dirs:%x", opt, OPT_l, OPT_H, OPT_color, OPT_dirs_first);
1206 uint32_t flags = opt_flags[i]; 1118 if (opt & OPT_c ) bb_error_msg("-c");
1207 1119 if (opt & OPT_l ) bb_error_msg("-l");
1208 if (flags & STYLE_MASK) 1120 if (opt & OPT_H ) bb_error_msg("-H");
1209 G.all_fmt &= ~STYLE_MASK; 1121 if (opt & OPT_color ) bb_error_msg("--color");
1210 if (flags & SORT_MASK) 1122 if (opt & OPT_dirs_first) bb_error_msg("--group-directories-first");
1211 G.all_fmt &= ~SORT_MASK; 1123 if (opt & OPT_full_time ) bb_error_msg("--full-time");
1212 if (flags & TIME_MASK) 1124 exit(0);
1213 G.all_fmt &= ~TIME_MASK; 1125#endif
1214 1126
1215 G.all_fmt |= flags; 1127#if ENABLE_SELINUX
1216 } 1128 if (opt & OPT_Z) {
1129 if (!is_selinux_enabled())
1130 option_mask32 &= ~OPT_Z;
1217 } 1131 }
1132#endif
1218 1133
1219#if ENABLE_FEATURE_LS_COLOR 1134#if ENABLE_FEATURE_LS_COLOR
1220 /* set G_show_color = 1/0 */ 1135 /* set G_show_color = 1/0 */
@@ -1242,27 +1157,35 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1242#endif 1157#endif
1243 1158
1244 /* sort out which command line options take precedence */ 1159 /* sort out which command line options take precedence */
1245 if (ENABLE_FEATURE_LS_RECURSIVE && (G.all_fmt & DISP_NOLIST)) 1160 if (ENABLE_FEATURE_LS_RECURSIVE && (opt & OPT_d))
1246 G.all_fmt &= ~DISP_RECURSIVE; /* no recurse if listing only dir */ 1161 option_mask32 &= ~OPT_R; /* no recurse if listing only dir */
1247 if (ENABLE_FEATURE_LS_TIMESTAMPS && ENABLE_FEATURE_LS_SORTFILES) { 1162 if (!(opt & OPT_l)) { /* not -l? */
1248 if (G.all_fmt & TIME_CHANGE) 1163 if (ENABLE_FEATURE_LS_TIMESTAMPS && ENABLE_FEATURE_LS_SORTFILES) {
1249 G.all_fmt = (G.all_fmt & ~SORT_MASK) | SORT_CTIME; 1164 /* when to sort by time? -t[cu] sorts by time even with -l */
1250 if (G.all_fmt & TIME_ACCESS) 1165 /* (this is achieved by opt_flags[] element for -t) */
1251 G.all_fmt = (G.all_fmt & ~SORT_MASK) | SORT_ATIME; 1166 /* without -l, bare -c or -u enable sort too */
1167 /* (with -l, bare -c or -u just select which time to show) */
1168 if (opt & (OPT_c|OPT_u)) {
1169 option_mask32 |= OPT_t;
1170 }
1171 }
1252 } 1172 }
1253 if ((G.all_fmt & STYLE_MASK) != STYLE_LONG) /* not -l? */
1254 G.all_fmt &= ~(LIST_ID_NUMERIC|LIST_ID_NAME|LIST_FULLTIME);
1255 1173
1256 /* choose a display format if one was not already specified by an option */ 1174 /* choose a display format if one was not already specified by an option */
1257 if (!(G.all_fmt & STYLE_MASK)) 1175 if (!(option_mask32 & (OPT_l|OPT_1|OPT_x|OPT_C)))
1258 G.all_fmt |= (isatty(STDOUT_FILENO) ? STYLE_COLUMNAR : STYLE_SINGLE); 1176 option_mask32 |= (isatty(STDOUT_FILENO) ? OPT_C : OPT_1);
1177
1178 if (ENABLE_FTPD && applet_name[0] == 'f') {
1179 /* ftpd secret backdoor. dirs first are much nicer */
1180 option_mask32 |= OPT_dirs_first;
1181 }
1259 1182
1260 argv += optind; 1183 argv += optind;
1261 if (!argv[0]) 1184 if (!argv[0])
1262 *--argv = (char*)"."; 1185 *--argv = (char*)".";
1263 1186
1264 if (argv[1]) 1187 if (argv[1])
1265 G.all_fmt |= DISP_DIRNAME; /* 2 or more items? label directories */ 1188 G.show_dirname = 1; /* 2 or more items? label directories */
1266 1189
1267 /* stuff the command line file names into a dnode array */ 1190 /* stuff the command line file names into a dnode array */
1268 dn = NULL; 1191 dn = NULL;
@@ -1270,10 +1193,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1270 do { 1193 do {
1271 cur = my_stat(*argv, *argv, 1194 cur = my_stat(*argv, *argv,
1272 /* follow links on command line unless -l, -s or -F: */ 1195 /* follow links on command line unless -l, -s or -F: */
1273 !((G.all_fmt & STYLE_MASK) == STYLE_LONG 1196 !(option_mask32 & (OPT_l|OPT_s|OPT_F))
1274 || (G.all_fmt & LIST_BLOCKS)
1275 || (option_mask32 & OPT_F)
1276 )
1277 /* ... or if -H: */ 1197 /* ... or if -H: */
1278 || (option_mask32 & OPT_H) 1198 || (option_mask32 & OPT_H)
1279 /* ... or if -L, but my_stat always follows links if -L */ 1199 /* ... or if -L, but my_stat always follows links if -L */
@@ -1302,7 +1222,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1302 break; 1222 break;
1303 } 1223 }
1304 1224
1305 if (G.all_fmt & DISP_NOLIST) { 1225 if (option_mask32 & OPT_d) {
1306 sort_and_display_files(dnp, nfiles); 1226 sort_and_display_files(dnp, nfiles);
1307 } else { 1227 } else {
1308 dnd = splitdnarray(dnp, SPLIT_DIR); 1228 dnd = splitdnarray(dnp, SPLIT_DIR);
diff --git a/coreutils/md5_sha1_sum.c b/coreutils/md5_sha1_sum.c
index 783f44027..50111bd26 100644
--- a/coreutils/md5_sha1_sum.c
+++ b/coreutils/md5_sha1_sum.c
@@ -45,7 +45,6 @@
45//config: help 45//config: help
46//config: Enabling the -c options allows files to be checked 46//config: Enabling the -c options allows files to be checked
47//config: against pre-calculated hash values. 47//config: against pre-calculated hash values.
48//config:
49//config: -s and -w are useful options when verifying checksums. 48//config: -s and -w are useful options when verifying checksums.
50 49
51//applet:IF_MD5SUM(APPLET_NOEXEC(md5sum, md5_sha1_sum, BB_DIR_USR_BIN, BB_SUID_DROP, md5sum)) 50//applet:IF_MD5SUM(APPLET_NOEXEC(md5sum, md5_sha1_sum, BB_DIR_USR_BIN, BB_SUID_DROP, md5sum))
@@ -167,7 +166,7 @@ static uint8_t *hash_file(const char *filename, unsigned sha3_width)
167 } context; 166 } context;
168 uint8_t *hash_value; 167 uint8_t *hash_value;
169 void FAST_FUNC (*update)(void*, const void*, size_t); 168 void FAST_FUNC (*update)(void*, const void*, size_t);
170 void FAST_FUNC (*final)(void*, void*); 169 unsigned FAST_FUNC (*final)(void*, void*);
171 char hash_algo; 170 char hash_algo;
172 171
173 src_fd = open_or_warn_stdin(filename); 172 src_fd = open_or_warn_stdin(filename);
diff --git a/coreutils/mkdir.c b/coreutils/mkdir.c
index 3afe76c28..fcc34f1ad 100644
--- a/coreutils/mkdir.c
+++ b/coreutils/mkdir.c
@@ -23,8 +23,6 @@
23//config: bool "Enable long options" 23//config: bool "Enable long options"
24//config: default y 24//config: default y
25//config: depends on MKDIR && LONG_OPTS 25//config: depends on MKDIR && LONG_OPTS
26//config: help
27//config: Support long options for the mkdir applet.
28 26
29//applet:IF_MKDIR(APPLET_NOFORK(mkdir, mkdir, BB_DIR_BIN, BB_SUID_DROP, mkdir)) 27//applet:IF_MKDIR(APPLET_NOFORK(mkdir, mkdir, BB_DIR_BIN, BB_SUID_DROP, mkdir))
30 28
diff --git a/coreutils/mv.c b/coreutils/mv.c
index 1cc318fd1..df2ef0a52 100644
--- a/coreutils/mv.c
+++ b/coreutils/mv.c
@@ -21,8 +21,6 @@
21//config: bool "Enable long options" 21//config: bool "Enable long options"
22//config: default y 22//config: default y
23//config: depends on MV && LONG_OPTS 23//config: depends on MV && LONG_OPTS
24//config: help
25//config: Support long options for the mv applet.
26 24
27//applet:IF_MV(APPLET(mv, BB_DIR_BIN, BB_SUID_DROP)) 25//applet:IF_MV(APPLET(mv, BB_DIR_BIN, BB_SUID_DROP))
28 26
diff --git a/coreutils/printf.c b/coreutils/printf.c
index 6c8e115d8..bc22e0ee7 100644
--- a/coreutils/printf.c
+++ b/coreutils/printf.c
@@ -49,6 +49,9 @@
49 49
50//kbuild:lib-$(CONFIG_PRINTF) += printf.o 50//kbuild:lib-$(CONFIG_PRINTF) += printf.o
51 51
52//kbuild:lib-$(CONFIG_ASH_PRINTF) += printf.o
53//kbuild:lib-$(CONFIG_HUSH_PRINTF) += printf.o
54
52//usage:#define printf_trivial_usage 55//usage:#define printf_trivial_usage
53//usage: "FORMAT [ARG]..." 56//usage: "FORMAT [ARG]..."
54//usage:#define printf_full_usage "\n\n" 57//usage:#define printf_full_usage "\n\n"
@@ -417,7 +420,7 @@ int printf_main(int argc UNUSED_PARAM, char **argv)
417 if (argv[1] && argv[1][0] == '-' && argv[1][1] == '-' && !argv[1][2]) 420 if (argv[1] && argv[1][0] == '-' && argv[1][1] == '-' && !argv[1][2])
418 argv++; 421 argv++;
419 if (!argv[1]) { 422 if (!argv[1]) {
420 if (ENABLE_ASH_BUILTIN_PRINTF 423 if (ENABLE_ASH_PRINTF
421 && applet_name[0] != 'p' 424 && applet_name[0] != 'p'
422 ) { 425 ) {
423 bb_error_msg("usage: printf FORMAT [ARGUMENT...]"); 426 bb_error_msg("usage: printf FORMAT [ARGUMENT...]");
diff --git a/coreutils/split.c b/coreutils/split.c
index 50918a1ce..7af359d0e 100644
--- a/coreutils/split.c
+++ b/coreutils/split.c
@@ -9,7 +9,7 @@
9//config: bool "split" 9//config: bool "split"
10//config: default y 10//config: default y
11//config: help 11//config: help
12//config: split a file into pieces. 12//config: Split a file into pieces.
13//config: 13//config:
14//config:config FEATURE_SPLIT_FANCY 14//config:config FEATURE_SPLIT_FANCY
15//config: bool "Fancy extensions" 15//config: bool "Fancy extensions"
diff --git a/coreutils/tail.c b/coreutils/tail.c
index 99f58ddd8..e7a24a7a8 100644
--- a/coreutils/tail.c
+++ b/coreutils/tail.c
@@ -26,13 +26,12 @@
26//config: from files. 26//config: from files.
27//config: 27//config:
28//config:config FEATURE_FANCY_TAIL 28//config:config FEATURE_FANCY_TAIL
29//config: bool "Enable extra tail options (-q, -s, -v, and -F)" 29//config: bool "Enable -q, -s, -v, and -F options"
30//config: default y 30//config: default y
31//config: depends on TAIL 31//config: depends on TAIL
32//config: help 32//config: help
33//config: The options (-q, -s, -v and -F) are provided by GNU tail, but 33//config: These options are provided by GNU tail, but
34//config: are not specific in the SUSv3 standard. 34//config: are not specific in the SUSv3 standard:
35//config:
36//config: -q Never output headers giving file names 35//config: -q Never output headers giving file names
37//config: -s SEC Wait SEC seconds between reads with -f 36//config: -s SEC Wait SEC seconds between reads with -f
38//config: -v Always output headers giving file names 37//config: -v Always output headers giving file names
diff --git a/coreutils/test.c b/coreutils/test.c
index 67fdfde4f..c949a3cc9 100644
--- a/coreutils/test.c
+++ b/coreutils/test.c
@@ -42,21 +42,20 @@
42//config:config FEATURE_TEST_64 42//config:config FEATURE_TEST_64
43//config: bool "Extend test to 64 bit" 43//config: bool "Extend test to 64 bit"
44//config: default y 44//config: default y
45//config: depends on TEST || TEST1 || TEST2 || ASH_BUILTIN_TEST || HUSH 45//config: depends on TEST || TEST1 || TEST2 || ASH_TEST || HUSH_TEST
46//config: help 46//config: help
47//config: Enable 64-bit support in test. 47//config: Enable 64-bit support in test.
48 48
49//applet:IF_TEST(APPLET_NOFORK(test, test, BB_DIR_USR_BIN, BB_SUID_DROP, test)) 49//applet:IF_TEST(APPLET_NOFORK(test, test, BB_DIR_USR_BIN, BB_SUID_DROP, test))
50//applet:IF_TEST1(APPLET_NOFORK([, test, BB_DIR_USR_BIN, BB_SUID_DROP, test)) 50//applet:IF_TEST1(APPLET_NOFORK([, test, BB_DIR_USR_BIN, BB_SUID_DROP, test))
51//applet:IF_TEST2(APPLET_NOFORK([[, test, BB_DIR_USR_BIN, BB_SUID_DROP, test)) 51//applet:IF_TEST2(APPLET_NOFORK([[, test, BB_DIR_USR_BIN, BB_SUID_DROP, test))
52 52
53//kbuild:lib-$(CONFIG_TEST) += test.o test_ptr_hack.o 53//kbuild:lib-$(CONFIG_TEST) += test.o test_ptr_hack.o
54//kbuild:lib-$(CONFIG_TEST1) += test.o test_ptr_hack.o 54//kbuild:lib-$(CONFIG_TEST1) += test.o test_ptr_hack.o
55//kbuild:lib-$(CONFIG_TEST2) += test.o test_ptr_hack.o 55//kbuild:lib-$(CONFIG_TEST2) += test.o test_ptr_hack.o
56//kbuild:lib-$(CONFIG_ASH_BUILTIN_TEST) += test.o test_ptr_hack.o 56
57//kbuild:lib-$(CONFIG_HUSH) += test.o test_ptr_hack.o 57//kbuild:lib-$(CONFIG_ASH_TEST) += test.o test_ptr_hack.o
58//kbuild:lib-$(CONFIG_SH_IS_HUSH) += test.o test_ptr_hack.o 58//kbuild:lib-$(CONFIG_HUSH_TEST) += test.o test_ptr_hack.o
59//kbuild:lib-$(CONFIG_BASH_IS_HUSH) += test.o test_ptr_hack.o
60 59
61/* "test --help" is special-cased to ignore --help */ 60/* "test --help" is special-cased to ignore --help */
62//usage:#define test_trivial_usage NOUSAGE_STR 61//usage:#define test_trivial_usage NOUSAGE_STR
@@ -858,7 +857,7 @@ int test_main(int argc, char **argv)
858 const char *arg0; 857 const char *arg0;
859 858
860 arg0 = bb_basename(argv[0]); 859 arg0 = bb_basename(argv[0]);
861 if ((ENABLE_TEST1 || ENABLE_TEST2 || ENABLE_ASH_BUILTIN_TEST || ENABLE_HUSH) 860 if ((ENABLE_TEST1 || ENABLE_TEST2 || ENABLE_ASH_TEST || ENABLE_HUSH_TEST)
862 && (arg0[0] == '[') 861 && (arg0[0] == '[')
863 ) { 862 ) {
864 --argc; 863 --argc;
diff --git a/coreutils/wc.c b/coreutils/wc.c
index 73837141e..4c53049b0 100644
--- a/coreutils/wc.c
+++ b/coreutils/wc.c
@@ -40,11 +40,11 @@
40//config: in specified files. 40//config: in specified files.
41//config: 41//config:
42//config:config FEATURE_WC_LARGE 42//config:config FEATURE_WC_LARGE
43//config: bool "Support very large files in wc" 43//config: bool "Support very large counts"
44//config: default y 44//config: default y
45//config: depends on WC 45//config: depends on WC
46//config: help 46//config: help
47//config: Use "unsigned long long" in wc for counter variables. 47//config: Use "unsigned long long" for counter variables.
48 48
49//applet:IF_WC(APPLET(wc, BB_DIR_USR_BIN, BB_SUID_DROP)) 49//applet:IF_WC(APPLET(wc, BB_DIR_USR_BIN, BB_SUID_DROP))
50 50
diff --git a/coreutils/who.c b/coreutils/who.c
index ac19dc720..e6179bb00 100644
--- a/coreutils/who.c
+++ b/coreutils/who.c
@@ -30,6 +30,7 @@
30//config: help 30//config: help
31//config: Print users currently logged on. 31//config: Print users currently logged on.
32 32
33// APPLET_ODDNAME:name main location suid_type help
33//applet:IF_USERS(APPLET_ODDNAME(users, who, BB_DIR_USR_BIN, BB_SUID_DROP, users)) 34//applet:IF_USERS(APPLET_ODDNAME(users, who, BB_DIR_USR_BIN, BB_SUID_DROP, users))
34//applet:IF_WHO(APPLET(who, BB_DIR_USR_BIN, BB_SUID_DROP)) 35//applet:IF_WHO(APPLET(who, BB_DIR_USR_BIN, BB_SUID_DROP))
35 36
diff --git a/debianutils/run_parts.c b/debianutils/run_parts.c
index 0bb666abc..3ef28f1d4 100644
--- a/debianutils/run_parts.c
+++ b/debianutils/run_parts.c
@@ -41,8 +41,6 @@
41//config: bool "Enable long options" 41//config: bool "Enable long options"
42//config: default y 42//config: default y
43//config: depends on RUN_PARTS && LONG_OPTS 43//config: depends on RUN_PARTS && LONG_OPTS
44//config: help
45//config: Support long options for the run-parts applet.
46//config: 44//config:
47//config:config FEATURE_RUN_PARTS_FANCY 45//config:config FEATURE_RUN_PARTS_FANCY
48//config: bool "Support additional arguments" 46//config: bool "Support additional arguments"
diff --git a/debianutils/start_stop_daemon.c b/debianutils/start_stop_daemon.c
index 3625ffee8..4a9e0653e 100644
--- a/debianutils/start_stop_daemon.c
+++ b/debianutils/start_stop_daemon.c
@@ -64,22 +64,19 @@ Misc options:
64//config: termination of system-level processes, usually the ones 64//config: termination of system-level processes, usually the ones
65//config: started during the startup of the system. 65//config: started during the startup of the system.
66//config: 66//config:
67//config:config FEATURE_START_STOP_DAEMON_LONG_OPTIONS
68//config: bool "Enable long options"
69//config: default y
70//config: depends on START_STOP_DAEMON && LONG_OPTS
71//config:
67//config:config FEATURE_START_STOP_DAEMON_FANCY 72//config:config FEATURE_START_STOP_DAEMON_FANCY
68//config: bool "Support additional arguments" 73//config: bool "Support additional arguments"
69//config: default y 74//config: default y
70//config: depends on START_STOP_DAEMON 75//config: depends on START_STOP_DAEMON
71//config: help 76//config: help
72//config: Support additional arguments.
73//config: -o|--oknodo ignored since we exit with 0 anyway 77//config: -o|--oknodo ignored since we exit with 0 anyway
74//config: -v|--verbose 78//config: -v|--verbose
75//config: -N|--nicelevel N 79//config: -N|--nicelevel N
76//config:
77//config:config FEATURE_START_STOP_DAEMON_LONG_OPTIONS
78//config: bool "Enable long options"
79//config: default y
80//config: depends on START_STOP_DAEMON && LONG_OPTS
81//config: help
82//config: Support long options for the start-stop-daemon applet.
83 80
84//applet:IF_START_STOP_DAEMON(APPLET_ODDNAME(start-stop-daemon, start_stop_daemon, BB_DIR_SBIN, BB_SUID_DROP, start_stop_daemon)) 81//applet:IF_START_STOP_DAEMON(APPLET_ODDNAME(start-stop-daemon, start_stop_daemon, BB_DIR_SBIN, BB_SUID_DROP, start_stop_daemon))
85 82
diff --git a/docs/nofork_noexec.txt b/docs/nofork_noexec.txt
index c58f5a83f..a24dd9c27 100644
--- a/docs/nofork_noexec.txt
+++ b/docs/nofork_noexec.txt
@@ -33,6 +33,7 @@ roughly are:
33* do not expect shared global variables/buffers to be in their 33* do not expect shared global variables/buffers to be in their
34 "initialized" state. Examples: xfunc_error_retval can be != 1, 34 "initialized" state. Examples: xfunc_error_retval can be != 1,
35 bb_common_bufsiz1 can be scribbled over, ... 35 bb_common_bufsiz1 can be scribbled over, ...
36 (although usually xfunc_error_retval's state is not a problem).
36* do not expect that stdio wasn't used before. Calling set[v]buf() 37* do not expect that stdio wasn't used before. Calling set[v]buf()
37 can be disastrous. 38 can be disastrous.
38* ... 39* ...
@@ -81,18 +82,44 @@ are probably not worth the effort.
81Any NOFORK applet is also a NOEXEC applet. 82Any NOFORK applet is also a NOEXEC applet.
82 83
83 84
85 Calling NOFORK applets
86
87API to call NOFORK applets is two functions:
88
89 run_nofork_applet(appno, argv)
90 spawn_and_wait(argv) // only if FEATURE_PREFER_APPLETS=y
91
92First one is directly used by shells if FEATURE_SH_NOFORK=y.
93Second one is used by many applets, but main users are xargs and find.
94It itself calls run_nofork_applet(), if argv[0] turned out to be a name
95of a NOFORK applet.
96
97run_nofork_applet() saves/inits/restores option parsing, xfunc_error_retval,
98applet_name. Thus, for example, caller does not need to worry about
99option_mask32 getting trashed.
100
101
102 Calling NOEXEC applets
103
104It's the same trusty spawn_and_wait(argv). If FEATURE_PREFER_APPLETS=y,
105it does NOEXEC trick. It resets xfunc_error_retval = 1 and
106logmode = LOGMODE_STDIO in the child.
107
108
84 Relevant CONFIG options 109 Relevant CONFIG options
85 110
86FEATURE_PREFER_APPLETS 111FEATURE_PREFER_APPLETS
87 BB_EXECVP(cmd, argv) will try to exec /proc/self/exe 112 BB_EXECVP(cmd, argv) will try to exec /proc/self/exe
88 if command's name matches some applet name 113 if command's name matches some applet name;
89 applet tables will contain NOFORK/NOEXEC bits
90 spawn_and_wait(argv) will do NOFORK/NOEXEC tricks 114 spawn_and_wait(argv) will do NOFORK/NOEXEC tricks
91 115
92FEATURE_SH_STANDALONE (needs FEATURE_PREFER_APPLETS=y) 116//TODO: the above two things probably should have separate options?
117
118FEATURE_SH_STANDALONE
93 shells will try to exec /proc/self/exe if command's name matches 119 shells will try to exec /proc/self/exe if command's name matches
94 some applet name 120 some applet name; shells will do NOEXEC trick on NOEXEC applets
95 shells will do NOEXEC trick on NOEXEC applets 121
122//TODO: split (same as for PREFER_APPLETS)
96 123
97FEATURE_SH_NOFORK (needs FEATURE_PREFER_APPLETS=y) 124FEATURE_SH_NOFORK
98 shells will do NOFORK trick on NOFORK applets 125 shells will do NOFORK trick on NOFORK applets
diff --git a/e2fsprogs/fsck.c b/e2fsprogs/fsck.c
index 6414988b4..eb53002b1 100644
--- a/e2fsprogs/fsck.c
+++ b/e2fsprogs/fsck.c
@@ -1071,7 +1071,7 @@ int fsck_main(int argc UNUSED_PARAM, char **argv)
1071 new_args(); /* G.args[G.num_args - 1] is the last, NULL element */ 1071 new_args(); /* G.args[G.num_args - 1] is the last, NULL element */
1072 1072
1073 if (!notitle) 1073 if (!notitle)
1074 puts("fsck (busybox "BB_VER", "BB_BT")"); 1074 puts("fsck (busybox "BB_VER")");
1075 1075
1076 /* Even plain "fsck /dev/hda1" needs fstab to get fs type, 1076 /* Even plain "fsck /dev/hda1" needs fstab to get fs type,
1077 * so we are scanning it anyway */ 1077 * so we are scanning it anyway */
diff --git a/editors/Config.src b/editors/Config.src
index c6e9d92af..8f2b265bd 100644
--- a/editors/Config.src
+++ b/editors/Config.src
@@ -12,7 +12,7 @@ config FEATURE_ALLOW_EXEC
12 default y 12 default y
13 depends on VI || AWK 13 depends on VI || AWK
14 help 14 help
15 Enables vi and awk features which allows user to execute 15 Enables vi and awk features which allow user to execute
16 shell commands (using system() C call). 16 shell commands (using system() C call).
17 17
18endmenu 18endmenu
diff --git a/editors/diff.c b/editors/diff.c
index 0ae7e20b3..f2eeb8257 100644
--- a/editors/diff.c
+++ b/editors/diff.c
@@ -88,8 +88,6 @@
88//config: bool "Enable long options" 88//config: bool "Enable long options"
89//config: default y 89//config: default y
90//config: depends on DIFF && LONG_OPTS 90//config: depends on DIFF && LONG_OPTS
91//config: help
92//config: Enable use of long options.
93//config: 91//config:
94//config:config FEATURE_DIFF_DIR 92//config:config FEATURE_DIFF_DIR
95//config: bool "Enable directory support" 93//config: bool "Enable directory support"
diff --git a/editors/vi.c b/editors/vi.c
index b81f2b92d..e5ca3adfa 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -30,7 +30,7 @@
30//config: you may wish to use something else. 30//config: you may wish to use something else.
31//config: 31//config:
32//config:config FEATURE_VI_MAX_LEN 32//config:config FEATURE_VI_MAX_LEN
33//config: int "Maximum screen width in vi" 33//config: int "Maximum screen width"
34//config: range 256 16384 34//config: range 256 16384
35//config: default 4096 35//config: default 4096
36//config: depends on VI 36//config: depends on VI
@@ -39,7 +39,7 @@
39//config: Make it smaller than 4k only if you are very limited on memory. 39//config: Make it smaller than 4k only if you are very limited on memory.
40//config: 40//config:
41//config:config FEATURE_VI_8BIT 41//config:config FEATURE_VI_8BIT
42//config: bool "Allow vi to display 8-bit chars (otherwise shows dots)" 42//config: bool "Allow to display 8-bit chars (otherwise shows dots)"
43//config: default n 43//config: default n
44//config: depends on VI 44//config: depends on VI
45//config: help 45//config: help
@@ -53,7 +53,7 @@
53//config: default y 53//config: default y
54//config: depends on VI 54//config: depends on VI
55//config: help 55//config: help
56//config: Enable a limited set of colon commands for vi. This does not 56//config: Enable a limited set of colon commands. This does not
57//config: provide an "ex" mode. 57//config: provide an "ex" mode.
58//config: 58//config:
59//config:config FEATURE_VI_YANKMARK 59//config:config FEATURE_VI_YANKMARK
@@ -61,16 +61,14 @@
61//config: default y 61//config: default y
62//config: depends on VI 62//config: depends on VI
63//config: help 63//config: help
64//config: This will enable you to use yank and put, as well as mark in 64//config: This will enable you to use yank and put, as well as mark.
65//config: busybox vi.
66//config: 65//config:
67//config:config FEATURE_VI_SEARCH 66//config:config FEATURE_VI_SEARCH
68//config: bool "Enable search and replace cmds" 67//config: bool "Enable search and replace cmds"
69//config: default y 68//config: default y
70//config: depends on VI 69//config: depends on VI
71//config: help 70//config: help
72//config: Select this if you wish to be able to do search and replace in 71//config: Select this if you wish to be able to do search and replace.
73//config: busybox vi.
74//config: 72//config:
75//config:config FEATURE_VI_REGEX_SEARCH 73//config:config FEATURE_VI_REGEX_SEARCH
76//config: bool "Enable regex in search and replace" 74//config: bool "Enable regex in search and replace"
@@ -84,16 +82,15 @@
84//config: default y 82//config: default y
85//config: depends on VI 83//config: depends on VI
86//config: help 84//config: help
87//config: Selecting this option will make busybox vi signal aware. This will 85//config: Selecting this option will make vi signal aware. This will support
88//config: make busybox vi support SIGWINCH to deal with Window Changes, catch 86//config: SIGWINCH to deal with Window Changes, catch ^Z and ^C and alarms.
89//config: Ctrl-Z and Ctrl-C and alarms.
90//config: 87//config:
91//config:config FEATURE_VI_DOT_CMD 88//config:config FEATURE_VI_DOT_CMD
92//config: bool "Remember previous cmd and \".\" cmd" 89//config: bool "Remember previous cmd and \".\" cmd"
93//config: default y 90//config: default y
94//config: depends on VI 91//config: depends on VI
95//config: help 92//config: help
96//config: Make busybox vi remember the last command and be able to repeat it. 93//config: Make vi remember the last command and be able to repeat it.
97//config: 94//config:
98//config:config FEATURE_VI_READONLY 95//config:config FEATURE_VI_READONLY
99//config: bool "Enable -R option and \"view\" mode" 96//config: bool "Enable -R option and \"view\" mode"
@@ -104,25 +101,23 @@
104//config: open a file in read-only mode. 101//config: open a file in read-only mode.
105//config: 102//config:
106//config:config FEATURE_VI_SETOPTS 103//config:config FEATURE_VI_SETOPTS
107//config: bool "Enable set-able options, ai ic showmatch" 104//config: bool "Enable settable options, ai ic showmatch"
108//config: default y 105//config: default y
109//config: depends on VI 106//config: depends on VI
110//config: help 107//config: help
111//config: Enable the editor to set some (ai, ic, showmatch) options. 108//config: Enable the editor to set some (ai, ic, showmatch) options.
112//config: 109//config:
113//config:config FEATURE_VI_SET 110//config:config FEATURE_VI_SET
114//config: bool "Support for :set" 111//config: bool "Support :set"
115//config: default y 112//config: default y
116//config: depends on VI 113//config: depends on VI
117//config: help
118//config: Support for ":set".
119//config: 114//config:
120//config:config FEATURE_VI_WIN_RESIZE 115//config:config FEATURE_VI_WIN_RESIZE
121//config: bool "Handle window resize" 116//config: bool "Handle window resize"
122//config: default y 117//config: default y
123//config: depends on VI 118//config: depends on VI
124//config: help 119//config: help
125//config: Make busybox vi behave nicely with terminals that get resized. 120//config: Behave nicely with terminals that get resized.
126//config: 121//config:
127//config:config FEATURE_VI_ASK_TERMINAL 122//config:config FEATURE_VI_ASK_TERMINAL
128//config: bool "Use 'tell me cursor position' ESC sequence to measure window" 123//config: bool "Use 'tell me cursor position' ESC sequence to measure window"
@@ -133,15 +128,16 @@
133//config: this option makes vi perform a last-ditch effort to find it: 128//config: this option makes vi perform a last-ditch effort to find it:
134//config: position cursor to 999,999 and ask terminal to report real 129//config: position cursor to 999,999 and ask terminal to report real
135//config: cursor position using "ESC [ 6 n" escape sequence, then read stdin. 130//config: cursor position using "ESC [ 6 n" escape sequence, then read stdin.
136//config:
137//config: This is not clean but helps a lot on serial lines and such. 131//config: This is not clean but helps a lot on serial lines and such.
132//config:
138//config:config FEATURE_VI_UNDO 133//config:config FEATURE_VI_UNDO
139//config: bool "Support undo command 'u'" 134//config: bool "Support undo command \"u\""
140//config: default y 135//config: default y
141//config: depends on VI 136//config: depends on VI
142//config: help 137//config: help
143//config: Support the 'u' command to undo insertion, deletion, and replacement 138//config: Support the 'u' command to undo insertion, deletion, and replacement
144//config: of text. 139//config: of text.
140//config:
145//config:config FEATURE_VI_UNDO_QUEUE 141//config:config FEATURE_VI_UNDO_QUEUE
146//config: bool "Enable undo operation queuing" 142//config: bool "Enable undo operation queuing"
147//config: default y 143//config: default y
@@ -152,6 +148,7 @@
152//config: reached, the contents of the queue are committed to the undo stack. 148//config: reached, the contents of the queue are committed to the undo stack.
153//config: This increases the size of the undo code and allows some undo 149//config: This increases the size of the undo code and allows some undo
154//config: operations (especially un-typing/backspacing) to be far more useful. 150//config: operations (especially un-typing/backspacing) to be far more useful.
151//config:
155//config:config FEATURE_VI_UNDO_QUEUE_MAX 152//config:config FEATURE_VI_UNDO_QUEUE_MAX
156//config: int "Maximum undo character queue size" 153//config: int "Maximum undo character queue size"
157//config: default 256 154//config: default 256
@@ -357,7 +354,7 @@ struct globals {
357#if ENABLE_FEATURE_VI_USE_SIGNALS 354#if ENABLE_FEATURE_VI_USE_SIGNALS
358 sigjmp_buf restart; // catch_sig() 355 sigjmp_buf restart; // catch_sig()
359#endif 356#endif
360 struct termios term_orig, term_vi; // remember what the cooked mode was 357 struct termios term_orig; // remember what the cooked mode was
361#if ENABLE_FEATURE_VI_COLON 358#if ENABLE_FEATURE_VI_COLON
362 char *initial_cmds[3]; // currently 2 entries, NULL terminated 359 char *initial_cmds[3]; // currently 2 entries, NULL terminated
363#endif 360#endif
@@ -465,7 +462,6 @@ struct globals {
465#define context_end (G.context_end ) 462#define context_end (G.context_end )
466#define restart (G.restart ) 463#define restart (G.restart )
467#define term_orig (G.term_orig ) 464#define term_orig (G.term_orig )
468#define term_vi (G.term_vi )
469#define initial_cmds (G.initial_cmds ) 465#define initial_cmds (G.initial_cmds )
470#define readbuffer (G.readbuffer ) 466#define readbuffer (G.readbuffer )
471#define scr_out_buf (G.scr_out_buf ) 467#define scr_out_buf (G.scr_out_buf )
@@ -1461,7 +1457,7 @@ static void colon(char *buf)
1461 } 1457 }
1462#endif /* FEATURE_VI_SEARCH */ 1458#endif /* FEATURE_VI_SEARCH */
1463 } else if (strncmp(cmd, "version", i) == 0) { // show software version 1459 } else if (strncmp(cmd, "version", i) == 0) { // show software version
1464 status_line(BB_VER " " BB_BT); 1460 status_line(BB_VER);
1465 } else if (strncmp(cmd, "write", i) == 0 // write text to file 1461 } else if (strncmp(cmd, "write", i) == 0 // write text to file
1466 || strncmp(cmd, "wq", i) == 0 1462 || strncmp(cmd, "wq", i) == 0
1467 || strncmp(cmd, "wn", i) == 0 1463 || strncmp(cmd, "wn", i) == 0
@@ -2734,15 +2730,9 @@ static char *swap_context(char *p) // goto new context for '' command make this
2734//----- Set terminal attributes -------------------------------- 2730//----- Set terminal attributes --------------------------------
2735static void rawmode(void) 2731static void rawmode(void)
2736{ 2732{
2737 tcgetattr(0, &term_orig); 2733 // no TERMIOS_CLEAR_ISIG: leave ISIG on - allow signals
2738 term_vi = term_orig; 2734 set_termios_to_raw(STDIN_FILENO, &term_orig, TERMIOS_RAW_CRNL);
2739 term_vi.c_lflag &= (~ICANON & ~ECHO); // leave ISIG on - allow intr's 2735 erase_char = term_orig.c_cc[VERASE];
2740 term_vi.c_iflag &= (~IXON & ~ICRNL);
2741 term_vi.c_oflag &= (~ONLCR);
2742 term_vi.c_cc[VMIN] = 1;
2743 term_vi.c_cc[VTIME] = 0;
2744 erase_char = term_vi.c_cc[VERASE];
2745 tcsetattr_stdin_TCSANOW(&term_vi);
2746} 2736}
2747 2737
2748static void cookmode(void) 2738static void cookmode(void)
diff --git a/examples/depmod b/examples/depmod
index d769590d0..8d421c6ab 100755
--- a/examples/depmod
+++ b/examples/depmod
@@ -7,7 +7,7 @@
7# Licensed under GPLv2, see file LICENSE in this source tree. 7# Licensed under GPLv2, see file LICENSE in this source tree.
8# 8#
9 9
10local BASE="${1:-/usr/lib/modules}" 10BASE="${1:-/usr/lib/modules}"
11 11
12find "$BASE" -name '*.ko.gz' | while read I ; do 12find "$BASE" -name '*.ko.gz' | while read I ; do
13 N=`basename "$I" '.ko.gz'` 13 N=`basename "$I" '.ko.gz'`
diff --git a/findutils/find.c b/findutils/find.c
index 27698e537..67aa40b21 100644
--- a/findutils/find.c
+++ b/findutils/find.c
@@ -89,8 +89,6 @@
89//config: bool "Enable -perm: permissions matching" 89//config: bool "Enable -perm: permissions matching"
90//config: default y 90//config: default y
91//config: depends on FIND 91//config: depends on FIND
92//config: help
93//config: Enable searching based on file permissions.
94//config: 92//config:
95//config:config FEATURE_FIND_TYPE 93//config:config FEATURE_FIND_TYPE
96//config: bool "Enable -type: file type matching (file/dir/link/...)" 94//config: bool "Enable -type: file type matching (file/dir/link/...)"
@@ -104,15 +102,11 @@
104//config: bool "Enable -xdev: 'stay in filesystem'" 102//config: bool "Enable -xdev: 'stay in filesystem'"
105//config: default y 103//config: default y
106//config: depends on FIND 104//config: depends on FIND
107//config: help
108//config: This option allows find to restrict searches to a single filesystem.
109//config: 105//config:
110//config:config FEATURE_FIND_MAXDEPTH 106//config:config FEATURE_FIND_MAXDEPTH
111//config: bool "Enable -mindepth N and -maxdepth N" 107//config: bool "Enable -mindepth N and -maxdepth N"
112//config: default y 108//config: default y
113//config: depends on FIND 109//config: depends on FIND
114//config: help
115//config: This option enables -mindepth N and -maxdepth N option.
116//config: 110//config:
117//config:config FEATURE_FIND_NEWER 111//config:config FEATURE_FIND_NEWER
118//config: bool "Enable -newer: compare file modification times" 112//config: bool "Enable -newer: compare file modification times"
@@ -126,8 +120,6 @@
126//config: bool "Enable -inum: inode number matching" 120//config: bool "Enable -inum: inode number matching"
127//config: default y 121//config: default y
128//config: depends on FIND 122//config: depends on FIND
129//config: help
130//config: Support the 'find -inum' option for searching by inode number.
131//config: 123//config:
132//config:config FEATURE_FIND_EXEC 124//config:config FEATURE_FIND_EXEC
133//config: bool "Enable -exec: execute commands" 125//config: bool "Enable -exec: execute commands"
@@ -151,15 +143,11 @@
151//config: bool "Enable -user: username/uid matching" 143//config: bool "Enable -user: username/uid matching"
152//config: default y 144//config: default y
153//config: depends on FIND 145//config: depends on FIND
154//config: help
155//config: Support the 'find -user' option for searching by username or uid.
156//config: 146//config:
157//config:config FEATURE_FIND_GROUP 147//config:config FEATURE_FIND_GROUP
158//config: bool "Enable -group: group/gid matching" 148//config: bool "Enable -group: group/gid matching"
159//config: default y 149//config: default y
160//config: depends on FIND 150//config: depends on FIND
161//config: help
162//config: Support the 'find -group' option for searching by group name or gid.
163//config: 151//config:
164//config:config FEATURE_FIND_NOT 152//config:config FEATURE_FIND_NOT
165//config: bool "Enable the 'not' (!) operator" 153//config: bool "Enable the 'not' (!) operator"
@@ -188,8 +176,6 @@
188//config: bool "Enable -size: file size matching" 176//config: bool "Enable -size: file size matching"
189//config: default y 177//config: default y
190//config: depends on FIND 178//config: depends on FIND
191//config: help
192//config: Support the 'find -size' option for searching by file size.
193//config: 179//config:
194//config:config FEATURE_FIND_PRUNE 180//config:config FEATURE_FIND_PRUNE
195//config: bool "Enable -prune: exclude subdirectories" 181//config: bool "Enable -prune: exclude subdirectories"
diff --git a/findutils/grep.c b/findutils/grep.c
index 9f84d529b..8b6e29874 100644
--- a/findutils/grep.c
+++ b/findutils/grep.c
@@ -46,6 +46,7 @@
46//config: Print the specified number of context lines (-C). 46//config: Print the specified number of context lines (-C).
47 47
48//applet:IF_GREP(APPLET(grep, BB_DIR_BIN, BB_SUID_DROP)) 48//applet:IF_GREP(APPLET(grep, BB_DIR_BIN, BB_SUID_DROP))
49// APPLET_ODDNAME:name main location suid_type help
49//applet:IF_EGREP(APPLET_ODDNAME(egrep, grep, BB_DIR_BIN, BB_SUID_DROP, egrep)) 50//applet:IF_EGREP(APPLET_ODDNAME(egrep, grep, BB_DIR_BIN, BB_SUID_DROP, egrep))
50//applet:IF_FGREP(APPLET_ODDNAME(fgrep, grep, BB_DIR_BIN, BB_SUID_DROP, fgrep)) 51//applet:IF_FGREP(APPLET_ODDNAME(fgrep, grep, BB_DIR_BIN, BB_SUID_DROP, fgrep))
51 52
diff --git a/include/libbb.h b/include/libbb.h
index 0b9cfb585..1f5b211c1 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -366,6 +366,27 @@ extern char *skip_dev_pfx(const char *tty_name) FAST_FUNC;
366 366
367extern char *strrstr(const char *haystack, const char *needle) FAST_FUNC; 367extern char *strrstr(const char *haystack, const char *needle) FAST_FUNC;
368 368
369/* dmalloc will redefine these to it's own implementation. It is safe
370 * to have the prototypes here unconditionally. */
371void *malloc_or_warn(size_t size) FAST_FUNC RETURNS_MALLOC;
372void *xmalloc(size_t size) FAST_FUNC RETURNS_MALLOC;
373void *xzalloc(size_t size) FAST_FUNC RETURNS_MALLOC;
374void *xrealloc(void *old, size_t size) FAST_FUNC;
375/* After v = xrealloc_vector(v, SHIFT, idx) it's ok to use
376 * at least v[idx] and v[idx+1], for all idx values.
377 * SHIFT specifies how many new elements are added (1:2, 2:4, ..., 8:256...)
378 * when all elements are used up. New elements are zeroed out.
379 * xrealloc_vector(v, SHIFT, idx) *MUST* be called with consecutive IDXs -
380 * skipping an index is a bad bug - it may miss a realloc!
381 */
382#define xrealloc_vector(vector, shift, idx) \
383 xrealloc_vector_helper((vector), (sizeof((vector)[0]) << 8) + (shift), (idx))
384void* xrealloc_vector_helper(void *vector, unsigned sizeof_and_shift, int idx) FAST_FUNC;
385char *xstrdup(const char *s) FAST_FUNC RETURNS_MALLOC;
386char *xstrndup(const char *s, int n) FAST_FUNC RETURNS_MALLOC;
387void *xmemdup(const void *s, int n) FAST_FUNC RETURNS_MALLOC;
388
389
369//TODO: supply a pointer to char[11] buffer (avoid statics)? 390//TODO: supply a pointer to char[11] buffer (avoid statics)?
370extern const char *bb_mode_string(mode_t mode) FAST_FUNC; 391extern const char *bb_mode_string(mode_t mode) FAST_FUNC;
371extern int is_directory(const char *name, int followLinks) FAST_FUNC; 392extern int is_directory(const char *name, int followLinks) FAST_FUNC;
@@ -709,6 +730,56 @@ struct hostent *xgethostbyname(const char *name) FAST_FUNC;
709// + inet_common.c has additional IPv4-only stuff 730// + inet_common.c has additional IPv4-only stuff
710 731
711 732
733#define TLS_MAX_MAC_SIZE 32
734#define TLS_MAX_KEY_SIZE 32
735struct tls_handshake_data; /* opaque */
736typedef struct tls_state {
737 int ofd;
738 int ifd;
739
740 unsigned min_encrypted_len_on_read;
741 uint16_t cipher_id;
742 uint8_t encrypt_on_write;
743 unsigned MAC_size;
744 unsigned key_size;
745
746 uint8_t *outbuf;
747 int outbuf_size;
748
749 int inbuf_size;
750 int ofs_to_buffered;
751 int buffered_size;
752 uint8_t *inbuf;
753
754 struct tls_handshake_data *hsd;
755
756 // RFC 5246
757 // sequence number
758 // Each connection state contains a sequence number, which is
759 // maintained separately for read and write states. The sequence
760 // number MUST be set to zero whenever a connection state is made the
761 // active state. Sequence numbers are of type uint64 and may not
762 // exceed 2^64-1.
763 /*uint64_t read_seq64_be;*/
764 uint64_t write_seq64_be;
765
766 uint8_t *client_write_key;
767 uint8_t *server_write_key;
768 uint8_t client_write_MAC_key[TLS_MAX_MAC_SIZE];
769 uint8_t server_write_MAC_k__[TLS_MAX_MAC_SIZE];
770 uint8_t client_write_k__[TLS_MAX_KEY_SIZE];
771 uint8_t server_write_k__[TLS_MAX_KEY_SIZE];
772} tls_state_t;
773
774static inline tls_state_t *new_tls_state(void)
775{
776 tls_state_t *tls = xzalloc(sizeof(*tls));
777 return tls;
778}
779void tls_handshake(tls_state_t *tls, const char *sni) FAST_FUNC;
780void tls_run_copy_loop(tls_state_t *tls) FAST_FUNC;
781
782
712void socket_want_pktinfo(int fd) FAST_FUNC; 783void socket_want_pktinfo(int fd) FAST_FUNC;
713ssize_t send_to_from(int fd, void *buf, size_t len, int flags, 784ssize_t send_to_from(int fd, void *buf, size_t len, int flags,
714 const struct sockaddr *to, 785 const struct sockaddr *to,
@@ -721,9 +792,6 @@ ssize_t recv_from_to(int fd, void *buf, size_t len, int flags,
721 792
722uint16_t inet_cksum(uint16_t *addr, int len) FAST_FUNC; 793uint16_t inet_cksum(uint16_t *addr, int len) FAST_FUNC;
723 794
724char *xstrdup(const char *s) FAST_FUNC RETURNS_MALLOC;
725char *xstrndup(const char *s, int n) FAST_FUNC RETURNS_MALLOC;
726void *xmemdup(const void *s, int n) FAST_FUNC RETURNS_MALLOC;
727void overlapping_strcpy(char *dst, const char *src) FAST_FUNC; 795void overlapping_strcpy(char *dst, const char *src) FAST_FUNC;
728char *safe_strncpy(char *dst, const char *src, size_t size) FAST_FUNC; 796char *safe_strncpy(char *dst, const char *src, size_t size) FAST_FUNC;
729char *strncpy_IFNAMSIZ(char *dst, const char *src) FAST_FUNC; 797char *strncpy_IFNAMSIZ(char *dst, const char *src) FAST_FUNC;
@@ -769,24 +837,6 @@ enum {
769}; 837};
770void visible(unsigned ch, char *buf, int flags) FAST_FUNC; 838void visible(unsigned ch, char *buf, int flags) FAST_FUNC;
771 839
772/* dmalloc will redefine these to it's own implementation. It is safe
773 * to have the prototypes here unconditionally. */
774void *malloc_or_warn(size_t size) FAST_FUNC RETURNS_MALLOC;
775void *xmalloc(size_t size) FAST_FUNC RETURNS_MALLOC;
776void *xzalloc(size_t size) FAST_FUNC RETURNS_MALLOC;
777void *xrealloc(void *old, size_t size) FAST_FUNC;
778/* After v = xrealloc_vector(v, SHIFT, idx) it's ok to use
779 * at least v[idx] and v[idx+1], for all idx values.
780 * SHIFT specifies how many new elements are added (1:2, 2:4, ..., 8:256...)
781 * when all elements are used up. New elements are zeroed out.
782 * xrealloc_vector(v, SHIFT, idx) *MUST* be called with consecutive IDXs -
783 * skipping an index is a bad bug - it may miss a realloc!
784 */
785#define xrealloc_vector(vector, shift, idx) \
786 xrealloc_vector_helper((vector), (sizeof((vector)[0]) << 8) + (shift), (idx))
787void* xrealloc_vector_helper(void *vector, unsigned sizeof_and_shift, int idx) FAST_FUNC;
788
789
790extern ssize_t safe_read(int fd, void *buf, size_t count) FAST_FUNC; 840extern ssize_t safe_read(int fd, void *buf, size_t count) FAST_FUNC;
791extern ssize_t nonblock_immune_read(int fd, void *buf, size_t count) FAST_FUNC; 841extern ssize_t nonblock_immune_read(int fd, void *buf, size_t count) FAST_FUNC;
792// NB: will return short read on error, not -1, 842// NB: will return short read on error, not -1,
@@ -1062,10 +1112,19 @@ pid_t wait_any_nohang(int *wstat) FAST_FUNC;
1062 */ 1112 */
1063int wait4pid(pid_t pid) FAST_FUNC; 1113int wait4pid(pid_t pid) FAST_FUNC;
1064int wait_for_exitstatus(pid_t pid) FAST_FUNC; 1114int wait_for_exitstatus(pid_t pid) FAST_FUNC;
1115/************************************************************************/
1116/* spawn_and_wait/run_nofork_applet/run_applet_no_and_exit need to work */
1117/* carefully together to reinit some global state while not disturbing */
1118/* other. Be careful if you change them. Consult docs/nofork_noexec.txt */
1119/************************************************************************/
1065/* Same as wait4pid(spawn(argv)), but with NOFORK/NOEXEC if configured: */ 1120/* Same as wait4pid(spawn(argv)), but with NOFORK/NOEXEC if configured: */
1066int spawn_and_wait(char **argv) FAST_FUNC; 1121int spawn_and_wait(char **argv) FAST_FUNC;
1067/* Does NOT check that applet is NOFORK, just blindly runs it */ 1122/* Does NOT check that applet is NOFORK, just blindly runs it */
1068int run_nofork_applet(int applet_no, char **argv) FAST_FUNC; 1123int run_nofork_applet(int applet_no, char **argv) FAST_FUNC;
1124#ifndef BUILD_INDIVIDUAL
1125extern int find_applet_by_name(const char *name) FAST_FUNC;
1126extern void run_applet_no_and_exit(int a, char **argv) NORETURN FAST_FUNC;
1127#endif
1069 1128
1070/* Helpers for daemonization. 1129/* Helpers for daemonization.
1071 * 1130 *
@@ -1272,13 +1331,8 @@ const struct hwtype *get_hwtype(const char *name) FAST_FUNC;
1272const struct hwtype *get_hwntype(int type) FAST_FUNC; 1331const struct hwtype *get_hwntype(int type) FAST_FUNC;
1273 1332
1274 1333
1275#ifndef BUILD_INDIVIDUAL 1334extern int fstype_matches(const char *fstype, const char *comma_list) FAST_FUNC;
1276extern int find_applet_by_name(const char *name) FAST_FUNC;
1277extern void run_applet_no_and_exit(int a, char **argv) NORETURN FAST_FUNC;
1278#endif
1279
1280#ifdef HAVE_MNTENT_H 1335#ifdef HAVE_MNTENT_H
1281extern int match_fstype(const struct mntent *mt, const char *fstypes) FAST_FUNC;
1282extern struct mntent *find_mount_point(const char *name, int subdir_too) FAST_FUNC; 1336extern struct mntent *find_mount_point(const char *name, int subdir_too) FAST_FUNC;
1283#endif 1337#endif
1284extern void erase_mtab(const char * name) FAST_FUNC; 1338extern void erase_mtab(const char * name) FAST_FUNC;
@@ -1457,6 +1511,10 @@ int get_terminal_width_height(int fd, unsigned *width, unsigned *height) FAST_FU
1457int get_terminal_width(int fd) FAST_FUNC; 1511int get_terminal_width(int fd) FAST_FUNC;
1458 1512
1459int tcsetattr_stdin_TCSANOW(const struct termios *tp) FAST_FUNC; 1513int tcsetattr_stdin_TCSANOW(const struct termios *tp) FAST_FUNC;
1514#define TERMIOS_CLEAR_ISIG (1 << 0)
1515#define TERMIOS_RAW_CRNL (1 << 1)
1516#define TERMIOS_RAW_INPUT (1 << 2)
1517int set_termios_to_raw(int fd, struct termios *oldterm, int flags) FAST_FUNC;
1460 1518
1461/* NB: "unsigned request" is crucial! "int request" will break some arches! */ 1519/* NB: "unsigned request" is crucial! "int request" will break some arches! */
1462int ioctl_or_perror(int fd, unsigned request, void *argp, const char *fmt,...) __attribute__ ((format (printf, 4, 5))) FAST_FUNC; 1520int ioctl_or_perror(int fd, unsigned request, void *argp, const char *fmt,...) __attribute__ ((format (printf, 4, 5))) FAST_FUNC;
@@ -1775,19 +1833,23 @@ typedef struct sha3_ctx_t {
1775} sha3_ctx_t; 1833} sha3_ctx_t;
1776void md5_begin(md5_ctx_t *ctx) FAST_FUNC; 1834void md5_begin(md5_ctx_t *ctx) FAST_FUNC;
1777void md5_hash(md5_ctx_t *ctx, const void *buffer, size_t len) FAST_FUNC; 1835void md5_hash(md5_ctx_t *ctx, const void *buffer, size_t len) FAST_FUNC;
1778void md5_end(md5_ctx_t *ctx, void *resbuf) FAST_FUNC; 1836unsigned md5_end(md5_ctx_t *ctx, void *resbuf) FAST_FUNC;
1779void sha1_begin(sha1_ctx_t *ctx) FAST_FUNC; 1837void sha1_begin(sha1_ctx_t *ctx) FAST_FUNC;
1780#define sha1_hash md5_hash 1838#define sha1_hash md5_hash
1781void sha1_end(sha1_ctx_t *ctx, void *resbuf) FAST_FUNC; 1839unsigned sha1_end(sha1_ctx_t *ctx, void *resbuf) FAST_FUNC;
1782void sha256_begin(sha256_ctx_t *ctx) FAST_FUNC; 1840void sha256_begin(sha256_ctx_t *ctx) FAST_FUNC;
1783#define sha256_hash md5_hash 1841#define sha256_hash md5_hash
1784#define sha256_end sha1_end 1842#define sha256_end sha1_end
1785void sha512_begin(sha512_ctx_t *ctx) FAST_FUNC; 1843void sha512_begin(sha512_ctx_t *ctx) FAST_FUNC;
1786void sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len) FAST_FUNC; 1844void sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len) FAST_FUNC;
1787void sha512_end(sha512_ctx_t *ctx, void *resbuf) FAST_FUNC; 1845unsigned sha512_end(sha512_ctx_t *ctx, void *resbuf) FAST_FUNC;
1788void sha3_begin(sha3_ctx_t *ctx) FAST_FUNC; 1846void sha3_begin(sha3_ctx_t *ctx) FAST_FUNC;
1789void sha3_hash(sha3_ctx_t *ctx, const void *buffer, size_t len) FAST_FUNC; 1847void sha3_hash(sha3_ctx_t *ctx, const void *buffer, size_t len) FAST_FUNC;
1790void sha3_end(sha3_ctx_t *ctx, void *resbuf) FAST_FUNC; 1848unsigned sha3_end(sha3_ctx_t *ctx, void *resbuf) FAST_FUNC;
1849/* TLS benefits from knowing that sha1 and sha256 share these. Give them "agnostic" names too */
1850typedef struct md5_ctx_t md5sha_ctx_t;
1851#define md5sha_hash md5_hash
1852#define sha_end sha1_end
1791 1853
1792extern uint32_t *global_crc32_table; 1854extern uint32_t *global_crc32_table;
1793uint32_t *crc32_filltable(uint32_t *tbl256, int endian) FAST_FUNC; 1855uint32_t *crc32_filltable(uint32_t *tbl256, int endian) FAST_FUNC;
diff --git a/include/platform.h b/include/platform.h
index 94368539e..13f818202 100644
--- a/include/platform.h
+++ b/include/platform.h
@@ -117,13 +117,18 @@
117 * and/or smaller by using modified ABI. It is usually only needed 117 * and/or smaller by using modified ABI. It is usually only needed
118 * on non-static, busybox internal functions. Recent versions of gcc 118 * on non-static, busybox internal functions. Recent versions of gcc
119 * optimize statics automatically. FAST_FUNC on static is required 119 * optimize statics automatically. FAST_FUNC on static is required
120 * only if you need to match a function pointer's type */ 120 * only if you need to match a function pointer's type.
121#if __GNUC_PREREQ(3,0) && defined(i386) /* || defined(__x86_64__)? */ 121 * FAST_FUNC may not work well with -flto so allow user to disable this.
122 * (-DFAST_FUNC= )
123 */
124#ifndef FAST_FUNC
125# if __GNUC_PREREQ(3,0) && defined(i386)
122/* stdcall makes callee to pop arguments from stack, not caller */ 126/* stdcall makes callee to pop arguments from stack, not caller */
123# define FAST_FUNC __attribute__((regparm(3),stdcall)) 127# define FAST_FUNC __attribute__((regparm(3),stdcall))
124/* #elif ... - add your favorite arch today! */ 128/* #elif ... - add your favorite arch today! */
125#else 129# else
126# define FAST_FUNC 130# define FAST_FUNC
131# endif
127#endif 132#endif
128 133
129/* Make all declarations hidden (-fvisibility flag only affects definitions) */ 134/* Make all declarations hidden (-fvisibility flag only affects definitions) */
diff --git a/include/usage.src.h b/include/usage.src.h
index 78beccf4d..00369dfb3 100644
--- a/include/usage.src.h
+++ b/include/usage.src.h
@@ -14,6 +14,14 @@
14 14
15#define NOUSAGE_STR "\b" 15#define NOUSAGE_STR "\b"
16 16
17#if !ENABLE_USE_BB_CRYPT || ENABLE_USE_BB_CRYPT_SHA
18# define CRYPT_METHODS_HELP_STR "des,md5,sha256/512" \
19 " (default "CONFIG_FEATURE_DEFAULT_PASSWD_ALGO")"
20#else
21# define CRYPT_METHODS_HELP_STR "des,md5" \
22 " (default "CONFIG_FEATURE_DEFAULT_PASSWD_ALGO")"
23#endif
24
17INSERT 25INSERT
18 26
19#define busybox_notes_usage \ 27#define busybox_notes_usage \
diff --git a/init/halt.c b/init/halt.c
index b7fb10869..f69b89772 100644
--- a/init/halt.c
+++ b/init/halt.c
@@ -46,8 +46,9 @@
46//config: locating telinit executable. 46//config: locating telinit executable.
47 47
48//applet:IF_HALT(APPLET(halt, BB_DIR_SBIN, BB_SUID_DROP)) 48//applet:IF_HALT(APPLET(halt, BB_DIR_SBIN, BB_SUID_DROP))
49// APPLET_ODDNAME:name main location suid_type help
49//applet:IF_POWEROFF(APPLET_ODDNAME(poweroff, halt, BB_DIR_SBIN, BB_SUID_DROP, poweroff)) 50//applet:IF_POWEROFF(APPLET_ODDNAME(poweroff, halt, BB_DIR_SBIN, BB_SUID_DROP, poweroff))
50//applet:IF_REBOOT(APPLET_ODDNAME(reboot, halt, BB_DIR_SBIN, BB_SUID_DROP, reboot)) 51//applet:IF_REBOOT( APPLET_ODDNAME(reboot, halt, BB_DIR_SBIN, BB_SUID_DROP, reboot))
51 52
52//kbuild:lib-$(CONFIG_HALT) += halt.o 53//kbuild:lib-$(CONFIG_HALT) += halt.o
53//kbuild:lib-$(CONFIG_POWEROFF) += halt.o 54//kbuild:lib-$(CONFIG_POWEROFF) += halt.o
diff --git a/init/init.c b/init/init.c
index 08cfa2f8c..833759341 100644
--- a/init/init.c
+++ b/init/init.c
@@ -17,7 +17,7 @@
17//config: init is the first program run when the system boots. 17//config: init is the first program run when the system boots.
18//config: 18//config:
19//config:config LINUXRC 19//config:config LINUXRC
20//config: bool "Support running init from within an initrd (not initramfs)" 20//config: bool "linuxrc: support running init from initrd (not initramfs)"
21//config: default y 21//config: default y
22//config: select FEATURE_SYSLOG 22//config: select FEATURE_SYSLOG
23//config: help 23//config: help
@@ -74,12 +74,10 @@
74//config: default y 74//config: default y
75//config: depends on INIT || LINUXRC 75//config: depends on INIT || LINUXRC
76//config: 76//config:
77//config:config FEATURE_EXTRA_QUIET 77//config:config FEATURE_INIT_QUIET
78//config: bool "Be _extra_ quiet on boot" 78//config: bool "Be quiet on boot (no 'init started:' message)"
79//config: default y 79//config: default y
80//config: depends on INIT || LINUXRC 80//config: depends on INIT || LINUXRC
81//config: help
82//config: Prevent init from logging some messages to the console during boot.
83//config: 81//config:
84//config:config FEATURE_INIT_COREDUMPS 82//config:config FEATURE_INIT_COREDUMPS
85//config: bool "Support dumping core for child processes (debugging only)" 83//config: bool "Support dumping core for child processes (debugging only)"
@@ -104,13 +102,13 @@
104//config: sets TERM to "vt102" if one is found. 102//config: sets TERM to "vt102" if one is found.
105//config: 103//config:
106//config:config FEATURE_INIT_MODIFY_CMDLINE 104//config:config FEATURE_INIT_MODIFY_CMDLINE
107//config: bool "Modify the command-line to \"init\"" 105//config: bool "Clear init's command line"
108//config: default y 106//config: default y
109//config: depends on INIT || LINUXRC 107//config: depends on INIT || LINUXRC
110//config: help 108//config: help
111//config: When launched as PID 1 and after parsing its arguments, init 109//config: When launched as PID 1 and after parsing its arguments, init
112//config: wipes all the arguments but argv[0] and rewrites argv[0] to 110//config: wipes all the arguments but argv[0] and rewrites argv[0] to
113//config: contain only "init", so that its command-line appears solely as 111//config: contain only "init", so that its command line appears solely as
114//config: "init" in tools such as ps. 112//config: "init" in tools such as ps.
115//config: If this option is set to Y, init will keep its original behavior, 113//config: If this option is set to Y, init will keep its original behavior,
116//config: otherwise, all the arguments including argv[0] will be preserved, 114//config: otherwise, all the arguments including argv[0] will be preserved,
@@ -1098,7 +1096,7 @@ int init_main(int argc UNUSED_PARAM, char **argv)
1098 if (argv[1]) 1096 if (argv[1])
1099 xsetenv("RUNLEVEL", argv[1]); 1097 xsetenv("RUNLEVEL", argv[1]);
1100 1098
1101#if !ENABLE_FEATURE_EXTRA_QUIET 1099#if !ENABLE_FEATURE_INIT_QUIET
1102 /* Hello world */ 1100 /* Hello world */
1103 message(L_CONSOLE | L_LOG, "init started: %s", bb_banner); 1101 message(L_CONSOLE | L_LOG, "init started: %s", bb_banner);
1104#endif 1102#endif
diff --git a/libbb/Config.src b/libbb/Config.src
index 172fbcc0e..c51640305 100644
--- a/libbb/Config.src
+++ b/libbb/Config.src
@@ -70,24 +70,13 @@ config FEATURE_FAST_TOP
70 but code size is slightly bigger. 70 but code size is slightly bigger.
71 71
72config FEATURE_ETC_NETWORKS 72config FEATURE_ETC_NETWORKS
73 bool "Support for /etc/networks" 73 bool "Support /etc/networks"
74 default n 74 default n
75 help 75 help
76 Enable support for network names in /etc/networks. This is 76 Enable support for network names in /etc/networks. This is
77 a rarely used feature which allows you to use names 77 a rarely used feature which allows you to use names
78 instead of IP/mask pairs in route command. 78 instead of IP/mask pairs in route command.
79 79
80config FEATURE_USE_TERMIOS
81 bool "Use termios to manipulate the screen"
82 default y
83 depends on MORE || TOP || POWERTOP
84 help
85 This option allows utilities such as 'more' and 'top' to determine
86 the size of the screen. If you leave this disabled, your utilities
87 that display things on the screen will be especially primitive and
88 will be unable to determine the current screen size, and will be
89 unable to move the cursor.
90
91config FEATURE_EDITING 80config FEATURE_EDITING
92 bool "Command line editing" 81 bool "Command line editing"
93 default y 82 default y
@@ -147,15 +136,11 @@ config FEATURE_TAB_COMPLETION
147 bool "Tab completion" 136 bool "Tab completion"
148 default y 137 default y
149 depends on FEATURE_EDITING 138 depends on FEATURE_EDITING
150 help
151 Enable tab completion.
152 139
153config FEATURE_USERNAME_COMPLETION 140config FEATURE_USERNAME_COMPLETION
154 bool "Username completion" 141 bool "Username completion"
155 default y 142 default y
156 depends on FEATURE_TAB_COMPLETION 143 depends on FEATURE_TAB_COMPLETION
157 help
158 Enable username completion.
159 144
160config FEATURE_EDITING_FANCY_PROMPT 145config FEATURE_EDITING_FANCY_PROMPT
161 bool "Fancy shell prompts" 146 bool "Fancy shell prompts"
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index 6732f89a9..a31a73e90 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -777,11 +777,7 @@ static int busybox_main(char **argv)
777 int col; 777 int col;
778 unsigned output_width; 778 unsigned output_width;
779 help: 779 help:
780 output_width = 80; 780 output_width = get_terminal_width(2);
781 if (ENABLE_FEATURE_AUTOWIDTH) {
782 /* Obtain the terminal width */
783 output_width = get_terminal_width(2);
784 }
785 781
786 dup2(1, 2); 782 dup2(1, 2);
787 full_write2_str(bb_banner); /* reuse const string */ 783 full_write2_str(bb_banner); /* reuse const string */
diff --git a/libbb/crc32.c b/libbb/crc32.c
index ac9836cc9..0711ca84e 100644
--- a/libbb/crc32.c
+++ b/libbb/crc32.c
@@ -24,7 +24,7 @@ uint32_t* FAST_FUNC crc32_filltable(uint32_t *crc_table, int endian)
24{ 24{
25 uint32_t polynomial = endian ? 0x04c11db7 : 0xedb88320; 25 uint32_t polynomial = endian ? 0x04c11db7 : 0xedb88320;
26 uint32_t c; 26 uint32_t c;
27 int i, j; 27 unsigned i, j;
28 28
29 if (!crc_table) 29 if (!crc_table)
30 crc_table = xmalloc(256 * sizeof(uint32_t)); 30 crc_table = xmalloc(256 * sizeof(uint32_t));
diff --git a/libbb/dump.c b/libbb/dump.c
index 154be5d80..87c1dce13 100644
--- a/libbb/dump.c
+++ b/libbb/dump.c
@@ -14,12 +14,12 @@
14#include "libbb.h" 14#include "libbb.h"
15#include "dump.h" 15#include "dump.h"
16 16
17static const char index_str[] ALIGN1 = ".#-+ 0123456789"; 17static const char dot_flags_width_chars[] ALIGN1 = ".#-+ 0123456789";
18 18
19static const char size_conv_str[] ALIGN1 = 19static const char size_conv_str[] ALIGN1 =
20"\x1\x4\x4\x4\x4\x4\x4\x8\x8\x8\x8\010cdiouxXeEfgG"; 20"\x1\x4\x4\x4\x4\x4\x4\x8\x8\x8\x8\010cdiouxXeEfgG";
21 21
22static const char lcc[] ALIGN1 = "diouxX"; 22static const char int_convs[] ALIGN1 = "diouxX";
23 23
24 24
25typedef struct priv_dumper_t { 25typedef struct priv_dumper_t {
@@ -71,7 +71,7 @@ static NOINLINE int bb_dump_size(FS *fs)
71 * skip any special chars -- save precision in 71 * skip any special chars -- save precision in
72 * case it's a %s format. 72 * case it's a %s format.
73 */ 73 */
74 while (strchr(index_str + 1, *++fmt)) 74 while (strchr(dot_flags_width_chars + 1, *++fmt))
75 continue; 75 continue;
76 if (*fmt == '.' && isdigit(*++fmt)) { 76 if (*fmt == '.' && isdigit(*++fmt)) {
77 prec = atoi(fmt); 77 prec = atoi(fmt);
@@ -82,14 +82,15 @@ static NOINLINE int bb_dump_size(FS *fs)
82 if (!p) { 82 if (!p) {
83 if (*fmt == 's') { 83 if (*fmt == 's') {
84 bcnt += prec; 84 bcnt += prec;
85 } else if (*fmt == '_') { 85 }
86 if (*fmt == '_') {
86 ++fmt; 87 ++fmt;
87 if ((*fmt == 'c') || (*fmt == 'p') || (*fmt == 'u')) { 88 if ((*fmt == 'c') || (*fmt == 'p') || (*fmt == 'u')) {
88 bcnt += 1; 89 bcnt += 1;
89 } 90 }
90 } 91 }
91 } else { 92 } else {
92 bcnt += size_conv_str[p - (size_conv_str + 12)]; 93 bcnt += p[-12];
93 } 94 }
94 } 95 }
95 cur_size += bcnt * fu->reps; 96 cur_size += bcnt * fu->reps;
@@ -99,32 +100,30 @@ static NOINLINE int bb_dump_size(FS *fs)
99 100
100static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs) 101static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs)
101{ 102{
102 enum { NOTOKAY, USEBCNT, USEPREC } sokay;
103 FU *fu; 103 FU *fu;
104 PR *pr;
105 char *p1, *p2, *p3;
106 char savech, *fmtp;
107 const char *byte_count_str;
108 int nconv, prec = 0;
109 104
110 for (fu = fs->nextfu; fu; fu = fu->nextfu) { 105 for (fu = fs->nextfu; fu; fu = fu->nextfu) {
106 PR *pr;
107 char *p1, *p2, *p3;
108 char *fmtp;
109 int nconv = 0;
111 /* 110 /*
112 * break each format unit into print units; each 111 * break each format unit into print units; each
113 * conversion character gets its own. 112 * conversion character gets its own.
114 */ 113 */
115 for (nconv = 0, fmtp = fu->fmt; *fmtp; ) { 114 for (fmtp = fu->fmt; *fmtp; ) {
116 /* NOSTRICT */ 115 unsigned len;
117 /* DBU:[dvae@cray.com] zalloc so that forward ptrs start out NULL*/ 116 const char *prec;
118 pr = xzalloc(sizeof(PR)); 117 const char *byte_count_str;
118
119 /* DBU:[dvae@cray.com] zalloc so that forward ptrs start out NULL */
120 pr = xzalloc(sizeof(*pr));
119 if (!fu->nextpr) 121 if (!fu->nextpr)
120 fu->nextpr = pr; 122 fu->nextpr = pr;
121 123
122 /* skip preceding text and up to the next % sign */ 124 /* skip preceding text and up to the next % sign */
123 for (p1 = fmtp; *p1 && *p1 != '%'; ++p1) 125 p1 = strchr(fmtp, '%');
124 continue; 126 if (!p1) { /* only text in the string */
125
126 /* only text in the string */
127 if (!*p1) {
128 pr->fmt = fmtp; 127 pr->fmt = fmtp;
129 pr->flags = F_TEXT; 128 pr->flags = F_TEXT;
130 break; 129 break;
@@ -134,22 +133,20 @@ static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs)
134 * get precision for %s -- if have a byte count, don't 133 * get precision for %s -- if have a byte count, don't
135 * need it. 134 * need it.
136 */ 135 */
136 prec = NULL;
137 if (fu->bcnt) { 137 if (fu->bcnt) {
138 sokay = USEBCNT;
139 /* skip to conversion character */ 138 /* skip to conversion character */
140 for (++p1; strchr(index_str, *p1); ++p1) 139 while (strchr(dot_flags_width_chars, *++p1))
141 continue; 140 continue;
142 } else { 141 } else {
143 /* skip any special chars, field width */ 142 /* skip any special chars, field width */
144 while (strchr(index_str + 1, *++p1)) 143 while (strchr(dot_flags_width_chars + 1, *++p1))
145 continue; 144 continue;
146 if (*p1 == '.' && isdigit(*++p1)) { 145 if (*p1 == '.' && isdigit(*++p1)) {
147 sokay = USEPREC; 146 prec = p1;
148 prec = atoi(p1);
149 while (isdigit(*++p1)) 147 while (isdigit(*++p1))
150 continue; 148 continue;
151 } else 149 }
152 sokay = NOTOKAY;
153 } 150 }
154 151
155 p2 = p1 + 1; /* set end pointer */ 152 p2 = p1 + 1; /* set end pointer */
@@ -165,74 +162,72 @@ static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs)
165 byte_count_str = "\001"; 162 byte_count_str = "\001";
166 DO_BYTE_COUNT: 163 DO_BYTE_COUNT:
167 if (fu->bcnt) { 164 if (fu->bcnt) {
168 do { 165 for (;;) {
169 if (fu->bcnt == *byte_count_str) { 166 if (fu->bcnt == *byte_count_str)
170 break; 167 break;
171 } 168 if (*++byte_count_str == 0)
172 } while (*++byte_count_str); 169 bb_error_msg_and_die("bad byte count for conversion character %s", p1);
170 }
173 } 171 }
174 /* Unlike the original, output the remainder of the format string. */ 172 /* Unlike the original, output the remainder of the format string. */
175 if (!*byte_count_str) {
176 bb_error_msg_and_die("bad byte count for conversion character %s", p1);
177 }
178 pr->bcnt = *byte_count_str; 173 pr->bcnt = *byte_count_str;
179 } else if (*p1 == 'l') { 174 } else
175 if (*p1 == 'l') { /* %ld etc */
176 const char *e;
177
180 ++p2; 178 ++p2;
181 ++p1; 179 ++p1;
182 DO_INT_CONV: 180 DO_INT_CONV:
183 { 181 e = strchr(int_convs, *p1); /* "diouxX"? */
184 const char *e; 182 if (!e)
185 e = strchr(lcc, *p1); 183 goto DO_BAD_CONV_CHAR;
186 if (!e) { 184 pr->flags = F_INT;
187 goto DO_BAD_CONV_CHAR; 185 if (e > int_convs + 1) /* not d or i? */
188 } 186 pr->flags = F_UINT;
189 pr->flags = F_INT; 187 byte_count_str = "\004\002\001";
190 if (e > lcc + 1) { 188 goto DO_BYTE_COUNT;
191 pr->flags = F_UINT; 189 } else
192 } 190 if (strchr(int_convs, *p1)) { /* %d etc */
193 byte_count_str = "\004\002\001";
194 goto DO_BYTE_COUNT;
195 }
196 /* NOTREACHED */
197 } else if (strchr(lcc, *p1)) {
198 goto DO_INT_CONV; 191 goto DO_INT_CONV;
199 } else if (strchr("eEfgG", *p1)) { 192 } else
193 if (strchr("eEfgG", *p1)) { /* floating point */
200 pr->flags = F_DBL; 194 pr->flags = F_DBL;
201 byte_count_str = "\010\004"; 195 byte_count_str = "\010\004";
202 goto DO_BYTE_COUNT; 196 goto DO_BYTE_COUNT;
203 } else if (*p1 == 's') { 197 } else
198 if (*p1 == 's') {
204 pr->flags = F_STR; 199 pr->flags = F_STR;
205 if (sokay == USEBCNT) { 200 pr->bcnt = fu->bcnt;
206 pr->bcnt = fu->bcnt; 201 if (fu->bcnt == 0) {
207 } else if (sokay == USEPREC) { 202 if (!prec)
208 pr->bcnt = prec; 203 bb_error_msg_and_die("%%s needs precision or byte count");
209 } else { /* NOTOKAY */ 204 pr->bcnt = atoi(prec);
210 bb_error_msg_and_die("%%s requires a precision or a byte count");
211 } 205 }
212 } else if (*p1 == '_') { 206 } else
213 ++p2; 207 if (*p1 == '_') {
208 p2++; /* move past a in "%_a" */
214 switch (p1[1]) { 209 switch (p1[1]) {
215 case 'A': 210 case 'A': /* %_A[dox]: print address and the end */
216 dumper->endfu = fu; 211 dumper->endfu = fu;
217 fu->flags |= F_IGNORE; 212 fu->flags |= F_IGNORE;
218 /* FALLTHROUGH */ 213 /* FALLTHROUGH */
219 case 'a': 214 case 'a': /* %_a[dox]: current address */
220 pr->flags = F_ADDRESS; 215 pr->flags = F_ADDRESS;
221 ++p2; 216 p2++; /* move past x in "%_ax" */
222 if ((p1[2] != 'd') && (p1[2] != 'o') && (p1[2] != 'x')) { 217 if ((p1[2] != 'd') && (p1[2] != 'o') && (p1[2] != 'x')) {
223 goto DO_BAD_CONV_CHAR; 218 goto DO_BAD_CONV_CHAR;
224 } 219 }
225 *p1 = p1[2]; 220 *p1 = p1[2];
226 break; 221 break;
227 case 'c': 222 case 'c': /* %_c: chars, \ooo, \n \r \t etc */
228 pr->flags = F_C; 223 pr->flags = F_C;
229 /* *p1 = 'c'; set in conv_c */ 224 /* *p1 = 'c'; set in conv_c */
230 goto DO_BYTE_COUNT_1; 225 goto DO_BYTE_COUNT_1;
231 case 'p': 226 case 'p': /* %_p: chars, dots for nonprintable */
232 pr->flags = F_P; 227 pr->flags = F_P;
233 *p1 = 'c'; 228 *p1 = 'c';
234 goto DO_BYTE_COUNT_1; 229 goto DO_BYTE_COUNT_1;
235 case 'u': 230 case 'u': /* %_p: chars, 'nul', 'esc' etc for nonprintable */
236 pr->flags = F_U; 231 pr->flags = F_U;
237 /* *p1 = 'c'; set in conv_u */ 232 /* *p1 = 'c'; set in conv_u */
238 goto DO_BYTE_COUNT_1; 233 goto DO_BYTE_COUNT_1;
@@ -248,13 +243,8 @@ static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs)
248 * copy to PR format string, set conversion character 243 * copy to PR format string, set conversion character
249 * pointer, update original. 244 * pointer, update original.
250 */ 245 */
251 savech = *p2; 246 len = (p1 - fmtp) + 1;
252 p1[1] = '\0'; 247 pr->fmt = xstrndup(fmtp, len);
253 pr->fmt = xstrdup(fmtp);
254 *p2 = savech;
255 //Too early! xrealloc can move pr->fmt!
256 //pr->cchar = pr->fmt + (p1 - fmtp);
257
258 /* DBU:[dave@cray.com] w/o this, trailing fmt text, space is lost. 248 /* DBU:[dave@cray.com] w/o this, trailing fmt text, space is lost.
259 * Skip subsequent text and up to the next % sign and tack the 249 * Skip subsequent text and up to the next % sign and tack the
260 * additional text onto fmt: eg. if fmt is "%x is a HEX number", 250 * additional text onto fmt: eg. if fmt is "%x is a HEX number",
@@ -262,16 +252,17 @@ static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs)
262 */ 252 */
263 for (p3 = p2; *p3 && *p3 != '%'; p3++) 253 for (p3 = p2; *p3 && *p3 != '%'; p3++)
264 continue; 254 continue;
265 if (p3 > p2) { 255 if ((p3 - p2) != 0) {
266 savech = *p3; 256 char *d;
267 *p3 = '\0'; 257 pr->fmt = d = xrealloc(pr->fmt, len + (p3 - p2) + 1);
268 pr->fmt = xrealloc(pr->fmt, strlen(pr->fmt) + (p3-p2) + 1); 258 d += len;
269 strcat(pr->fmt, p2); 259 do {
270 *p3 = savech; 260 *d++ = *p2++;
271 p2 = p3; 261 } while (p2 != p3);
262 *d = '\0';
263 /* now p2 = p3 */
272 } 264 }
273 265 pr->cchar = pr->fmt + len - 1; /* must be after realloc! */
274 pr->cchar = pr->fmt + (p1 - fmtp);
275 fmtp = p2; 266 fmtp = p2;
276 267
277 /* only one conversion character if byte count */ 268 /* only one conversion character if byte count */
@@ -283,7 +274,7 @@ static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs)
283 * if format unit byte count not specified, figure it out 274 * if format unit byte count not specified, figure it out
284 * so can adjust rep count later. 275 * so can adjust rep count later.
285 */ 276 */
286 if (!fu->bcnt) 277 if (fu->bcnt == 0)
287 for (pr = fu->nextpr; pr; pr = pr->nextpr) 278 for (pr = fu->nextpr; pr; pr = pr->nextpr)
288 fu->bcnt += pr->bcnt; 279 fu->bcnt += pr->bcnt;
289 } 280 }
@@ -305,16 +296,18 @@ static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs)
305 fu->reps += (dumper->blocksize - fs->bcnt) / fu->bcnt; 296 fu->reps += (dumper->blocksize - fs->bcnt) / fu->bcnt;
306 } 297 }
307 if (fu->reps > 1 && fu->nextpr) { 298 if (fu->reps > 1 && fu->nextpr) {
299 PR *pr;
300 char *p1, *p2;
301
308 for (pr = fu->nextpr;; pr = pr->nextpr) 302 for (pr = fu->nextpr;; pr = pr->nextpr)
309 if (!pr->nextpr) 303 if (!pr->nextpr)
310 break; 304 break;
311 for (p1 = pr->fmt, p2 = NULL; *p1; ++p1) 305 p2 = NULL;
306 for (p1 = pr->fmt; *p1; ++p1)
312 p2 = isspace(*p1) ? p1 : NULL; 307 p2 = isspace(*p1) ? p1 : NULL;
313 if (p2) 308 if (p2)
314 pr->nospace = p2; 309 pr->nospace = p2;
315 } 310 }
316 if (!fu->nextfu)
317 break;
318 } 311 }
319} 312}
320 313
@@ -358,6 +351,7 @@ static NOINLINE int next(priv_dumper_t *dumper)
358 if (dumper->next__done) 351 if (dumper->next__done)
359 return 0; /* no next file */ 352 return 0; /* no next file */
360 dumper->next__done = 1; 353 dumper->next__done = 1;
354//why stat of stdin is specially prohibited?
361 statok = 0; 355 statok = 0;
362 } 356 }
363 if (dumper->pub.dump_skip) 357 if (dumper->pub.dump_skip)
@@ -762,6 +756,11 @@ void FAST_FUNC bb_dump_add(dumper_t* pub_dumper, const char *fmt)
762 if (!isspace(*p)) { 756 if (!isspace(*p)) {
763 bb_error_msg_and_die("bad format {%s}", fmt); 757 bb_error_msg_and_die("bad format {%s}", fmt);
764 } 758 }
759// Above check prohibits formats such as '/1"%02x"' - it requires space after 1.
760// Other than this, formats can be pretty much jammed together:
761// "%07_ax:"8/2 "%04x|""\n"
762// but this space is required. The check *can* be removed, but
763// keeping it to stay compat with util-linux hexdump.
765 tfu->bcnt = atoi(savep); 764 tfu->bcnt = atoi(savep);
766 /* skip trailing white space */ 765 /* skip trailing white space */
767 p = skip_whitespace(p + 1); 766 p = skip_whitespace(p + 1);
diff --git a/libbb/getopt32.c b/libbb/getopt32.c
index ed9352191..03fca3493 100644
--- a/libbb/getopt32.c
+++ b/libbb/getopt32.c
@@ -404,7 +404,7 @@ getopt32(char **argv, const char *applet_opts, ...)
404 if (c >= 32) 404 if (c >= 32)
405 break; 405 break;
406 on_off->opt_char = *s; 406 on_off->opt_char = *s;
407 on_off->switch_on = (1 << c); 407 on_off->switch_on = (1U << c);
408 if (*++s == ':') { 408 if (*++s == ':') {
409 on_off->optarg = va_arg(p, void **); 409 on_off->optarg = va_arg(p, void **);
410 if (s[1] == '+' || s[1] == '*') { 410 if (s[1] == '+' || s[1] == '*') {
@@ -454,7 +454,7 @@ getopt32(char **argv, const char *applet_opts, ...)
454 if (c >= 32) 454 if (c >= 32)
455 break; 455 break;
456 on_off->opt_char = l_o->val; 456 on_off->opt_char = l_o->val;
457 on_off->switch_on = (1 << c); 457 on_off->switch_on = (1U << c);
458 if (l_o->has_arg != no_argument) 458 if (l_o->has_arg != no_argument)
459 on_off->optarg = va_arg(p, void **); 459 on_off->optarg = va_arg(p, void **);
460 c++; 460 c++;
diff --git a/libbb/hash_md5_sha.c b/libbb/hash_md5_sha.c
index 7e7d8da2f..2a7247430 100644
--- a/libbb/hash_md5_sha.c
+++ b/libbb/hash_md5_sha.c
@@ -9,6 +9,8 @@
9 9
10#include "libbb.h" 10#include "libbb.h"
11 11
12#define NEED_SHA512 (ENABLE_SHA512SUM || ENABLE_USE_BB_CRYPT_SHA)
13
12/* gcc 4.2.1 optimizes rotr64 better with inline than with macro 14/* gcc 4.2.1 optimizes rotr64 better with inline than with macro
13 * (for rotX32, there is no difference). Why? My guess is that 15 * (for rotX32, there is no difference). Why? My guess is that
14 * macro requires clever common subexpression elimination heuristics 16 * macro requires clever common subexpression elimination heuristics
@@ -456,7 +458,7 @@ void FAST_FUNC md5_hash(md5_ctx_t *ctx, const void *buffer, size_t len)
456 * endian byte order, so that a byte-wise output yields to the wanted 458 * endian byte order, so that a byte-wise output yields to the wanted
457 * ASCII representation of the message digest. 459 * ASCII representation of the message digest.
458 */ 460 */
459void FAST_FUNC md5_end(md5_ctx_t *ctx, void *resbuf) 461unsigned FAST_FUNC md5_end(md5_ctx_t *ctx, void *resbuf)
460{ 462{
461 /* MD5 stores total in LE, need to swap on BE arches: */ 463 /* MD5 stores total in LE, need to swap on BE arches: */
462 common64_end(ctx, /*swap_needed:*/ BB_BIG_ENDIAN); 464 common64_end(ctx, /*swap_needed:*/ BB_BIG_ENDIAN);
@@ -470,6 +472,7 @@ void FAST_FUNC md5_end(md5_ctx_t *ctx, void *resbuf)
470 } 472 }
471 473
472 memcpy(resbuf, ctx->hash, sizeof(ctx->hash[0]) * 4); 474 memcpy(resbuf, ctx->hash, sizeof(ctx->hash[0]) * 4);
475 return sizeof(ctx->hash[0]) * 4;
473} 476}
474 477
475 478
@@ -564,48 +567,59 @@ static void FAST_FUNC sha1_process_block64(sha1_ctx_t *ctx)
564 * are the most significant half of first 64 elements 567 * are the most significant half of first 64 elements
565 * of the same array. 568 * of the same array.
566 */ 569 */
567static const uint64_t sha_K[80] = { 570#undef K
568 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 571#if NEED_SHA512
569 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, 572typedef uint64_t sha_K_int;
570 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 573# define K(v) v
571 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 574#else
572 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, 575typedef uint32_t sha_K_int;
573 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, 576# define K(v) (uint32_t)(v >> 32)
574 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 577#endif
575 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, 578static const sha_K_int sha_K[] = {
576 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 579 K(0x428a2f98d728ae22ULL), K(0x7137449123ef65cdULL),
577 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 580 K(0xb5c0fbcfec4d3b2fULL), K(0xe9b5dba58189dbbcULL),
578 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 581 K(0x3956c25bf348b538ULL), K(0x59f111f1b605d019ULL),
579 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, 582 K(0x923f82a4af194f9bULL), K(0xab1c5ed5da6d8118ULL),
580 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 583 K(0xd807aa98a3030242ULL), K(0x12835b0145706fbeULL),
581 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, 584 K(0x243185be4ee4b28cULL), K(0x550c7dc3d5ffb4e2ULL),
582 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, 585 K(0x72be5d74f27b896fULL), K(0x80deb1fe3b1696b1ULL),
583 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 586 K(0x9bdc06a725c71235ULL), K(0xc19bf174cf692694ULL),
584 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 587 K(0xe49b69c19ef14ad2ULL), K(0xefbe4786384f25e3ULL),
585 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, 588 K(0x0fc19dc68b8cd5b5ULL), K(0x240ca1cc77ac9c65ULL),
586 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 589 K(0x2de92c6f592b0275ULL), K(0x4a7484aa6ea6e483ULL),
587 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, 590 K(0x5cb0a9dcbd41fbd4ULL), K(0x76f988da831153b5ULL),
588 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 591 K(0x983e5152ee66dfabULL), K(0xa831c66d2db43210ULL),
589 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 592 K(0xb00327c898fb213fULL), K(0xbf597fc7beef0ee4ULL),
590 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, 593 K(0xc6e00bf33da88fc2ULL), K(0xd5a79147930aa725ULL),
591 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, 594 K(0x06ca6351e003826fULL), K(0x142929670a0e6e70ULL),
592 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 595 K(0x27b70a8546d22ffcULL), K(0x2e1b21385c26c926ULL),
593 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, 596 K(0x4d2c6dfc5ac42aedULL), K(0x53380d139d95b3dfULL),
594 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 597 K(0x650a73548baf63deULL), K(0x766a0abb3c77b2a8ULL),
595 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 598 K(0x81c2c92e47edaee6ULL), K(0x92722c851482353bULL),
596 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 599 K(0xa2bfe8a14cf10364ULL), K(0xa81a664bbc423001ULL),
597 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, 600 K(0xc24b8b70d0f89791ULL), K(0xc76c51a30654be30ULL),
598 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 601 K(0xd192e819d6ef5218ULL), K(0xd69906245565a910ULL),
599 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, 602 K(0xf40e35855771202aULL), K(0x106aa07032bbd1b8ULL),
600 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, /* [64]+ are used for sha512 only */ 603 K(0x19a4c116b8d2d0c8ULL), K(0x1e376c085141ab53ULL),
601 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 604 K(0x2748774cdf8eeb99ULL), K(0x34b0bcb5e19b48a8ULL),
602 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, 605 K(0x391c0cb3c5c95a63ULL), K(0x4ed8aa4ae3418acbULL),
603 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, 606 K(0x5b9cca4f7763e373ULL), K(0x682e6ff3d6b2b8a3ULL),
604 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 607 K(0x748f82ee5defb2fcULL), K(0x78a5636f43172f60ULL),
605 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, 608 K(0x84c87814a1f0ab72ULL), K(0x8cc702081a6439ecULL),
606 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 609 K(0x90befffa23631e28ULL), K(0xa4506cebde82bde9ULL),
607 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL 610 K(0xbef9a3f7b2c67915ULL), K(0xc67178f2e372532bULL),
611#if NEED_SHA512 /* [64]+ are used for sha512 only */
612 K(0xca273eceea26619cULL), K(0xd186b8c721c0c207ULL),
613 K(0xeada7dd6cde0eb1eULL), K(0xf57d4f7fee6ed178ULL),
614 K(0x06f067aa72176fbaULL), K(0x0a637dc5a2c898a6ULL),
615 K(0x113f9804bef90daeULL), K(0x1b710b35131c471bULL),
616 K(0x28db77f523047d84ULL), K(0x32caab7b40c72493ULL),
617 K(0x3c9ebe0a15c9bebcULL), K(0x431d67c49c100d4cULL),
618 K(0x4cc5d4becb3e42b6ULL), K(0x597f299cfc657e2aULL),
619 K(0x5fcb6fab3ad6faecULL), K(0x6c44198c4a475817ULL),
620#endif
608}; 621};
622#undef K
609 623
610#undef Ch 624#undef Ch
611#undef Maj 625#undef Maj
@@ -649,7 +663,7 @@ static void FAST_FUNC sha256_process_block64(sha256_ctx_t *ctx)
649 * (I hope compiler is clever enough to just fetch 663 * (I hope compiler is clever enough to just fetch
650 * upper half) 664 * upper half)
651 */ 665 */
652 uint32_t K_t = sha_K[t] >> 32; 666 uint32_t K_t = NEED_SHA512 ? (sha_K[t] >> 32) : sha_K[t];
653 uint32_t T1 = h + S1(e) + Ch(e, f, g) + K_t + W[t]; 667 uint32_t T1 = h + S1(e) + Ch(e, f, g) + K_t + W[t];
654 uint32_t T2 = S0(a) + Maj(a, b, c); 668 uint32_t T2 = S0(a) + Maj(a, b, c);
655 h = g; 669 h = g;
@@ -679,6 +693,7 @@ static void FAST_FUNC sha256_process_block64(sha256_ctx_t *ctx)
679 ctx->hash[7] += h; 693 ctx->hash[7] += h;
680} 694}
681 695
696#if NEED_SHA512
682static void FAST_FUNC sha512_process_block128(sha512_ctx_t *ctx) 697static void FAST_FUNC sha512_process_block128(sha512_ctx_t *ctx)
683{ 698{
684 unsigned t; 699 unsigned t;
@@ -740,7 +755,7 @@ static void FAST_FUNC sha512_process_block128(sha512_ctx_t *ctx)
740 ctx->hash[6] += g; 755 ctx->hash[6] += g;
741 ctx->hash[7] += h; 756 ctx->hash[7] += h;
742} 757}
743 758#endif /* NEED_SHA512 */
744 759
745void FAST_FUNC sha1_begin(sha1_ctx_t *ctx) 760void FAST_FUNC sha1_begin(sha1_ctx_t *ctx)
746{ 761{
@@ -765,6 +780,7 @@ static const uint32_t init256[] = {
765 0x1f83d9ab, 780 0x1f83d9ab,
766 0x5be0cd19, 781 0x5be0cd19,
767}; 782};
783#if NEED_SHA512
768static const uint32_t init512_lo[] = { 784static const uint32_t init512_lo[] = {
769 0, 785 0,
770 0, 786 0,
@@ -777,6 +793,7 @@ static const uint32_t init512_lo[] = {
777 0xfb41bd6b, 793 0xfb41bd6b,
778 0x137e2179, 794 0x137e2179,
779}; 795};
796#endif /* NEED_SHA512 */
780 797
781/* Initialize structure containing state of computation. 798/* Initialize structure containing state of computation.
782 (FIPS 180-2:5.3.2) */ 799 (FIPS 180-2:5.3.2) */
@@ -787,6 +804,7 @@ void FAST_FUNC sha256_begin(sha256_ctx_t *ctx)
787 ctx->process_block = sha256_process_block64; 804 ctx->process_block = sha256_process_block64;
788} 805}
789 806
807#if NEED_SHA512
790/* Initialize structure containing state of computation. 808/* Initialize structure containing state of computation.
791 (FIPS 180-2:5.3.3) */ 809 (FIPS 180-2:5.3.3) */
792void FAST_FUNC sha512_begin(sha512_ctx_t *ctx) 810void FAST_FUNC sha512_begin(sha512_ctx_t *ctx)
@@ -810,7 +828,7 @@ void FAST_FUNC sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len)
810 ctx->total64[0] += len; 828 ctx->total64[0] += len;
811 if (ctx->total64[0] < len) 829 if (ctx->total64[0] < len)
812 ctx->total64[1]++; 830 ctx->total64[1]++;
813#if 0 831# if 0
814 remaining = 128 - bufpos; 832 remaining = 128 - bufpos;
815 833
816 /* Hash whole blocks */ 834 /* Hash whole blocks */
@@ -825,7 +843,7 @@ void FAST_FUNC sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len)
825 843
826 /* Save last, partial blosk */ 844 /* Save last, partial blosk */
827 memcpy(ctx->wbuffer + bufpos, buffer, len); 845 memcpy(ctx->wbuffer + bufpos, buffer, len);
828#else 846# else
829 while (1) { 847 while (1) {
830 remaining = 128 - bufpos; 848 remaining = 128 - bufpos;
831 if (remaining > len) 849 if (remaining > len)
@@ -843,11 +861,12 @@ void FAST_FUNC sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len)
843 sha512_process_block128(ctx); 861 sha512_process_block128(ctx);
844 /*bufpos = 0; - already is */ 862 /*bufpos = 0; - already is */
845 } 863 }
846#endif 864# endif
847} 865}
866#endif /* NEED_SHA512 */
848 867
849/* Used also for sha256 */ 868/* Used also for sha256 */
850void FAST_FUNC sha1_end(sha1_ctx_t *ctx, void *resbuf) 869unsigned FAST_FUNC sha1_end(sha1_ctx_t *ctx, void *resbuf)
851{ 870{
852 unsigned hash_size; 871 unsigned hash_size;
853 872
@@ -861,10 +880,13 @@ void FAST_FUNC sha1_end(sha1_ctx_t *ctx, void *resbuf)
861 for (i = 0; i < hash_size; ++i) 880 for (i = 0; i < hash_size; ++i)
862 ctx->hash[i] = SWAP_BE32(ctx->hash[i]); 881 ctx->hash[i] = SWAP_BE32(ctx->hash[i]);
863 } 882 }
864 memcpy(resbuf, ctx->hash, sizeof(ctx->hash[0]) * hash_size); 883 hash_size *= sizeof(ctx->hash[0]);
884 memcpy(resbuf, ctx->hash, hash_size);
885 return hash_size;
865} 886}
866 887
867void FAST_FUNC sha512_end(sha512_ctx_t *ctx, void *resbuf) 888#if NEED_SHA512
889unsigned FAST_FUNC sha512_end(sha512_ctx_t *ctx, void *resbuf)
868{ 890{
869 unsigned bufpos = ctx->total64[0] & 127; 891 unsigned bufpos = ctx->total64[0] & 127;
870 892
@@ -896,7 +918,9 @@ void FAST_FUNC sha512_end(sha512_ctx_t *ctx, void *resbuf)
896 ctx->hash[i] = SWAP_BE64(ctx->hash[i]); 918 ctx->hash[i] = SWAP_BE64(ctx->hash[i]);
897 } 919 }
898 memcpy(resbuf, ctx->hash, sizeof(ctx->hash)); 920 memcpy(resbuf, ctx->hash, sizeof(ctx->hash));
921 return sizeof(ctx->hash);
899} 922}
923#endif /* NEED_SHA512 */
900 924
901 925
902/* 926/*
@@ -1430,7 +1454,7 @@ void FAST_FUNC sha3_hash(sha3_ctx_t *ctx, const void *buffer, size_t len)
1430#endif 1454#endif
1431} 1455}
1432 1456
1433void FAST_FUNC sha3_end(sha3_ctx_t *ctx, void *resbuf) 1457unsigned FAST_FUNC sha3_end(sha3_ctx_t *ctx, void *resbuf)
1434{ 1458{
1435 /* Padding */ 1459 /* Padding */
1436 uint8_t *buf = (uint8_t*)ctx->state; 1460 uint8_t *buf = (uint8_t*)ctx->state;
@@ -1455,4 +1479,5 @@ void FAST_FUNC sha3_end(sha3_ctx_t *ctx, void *resbuf)
1455 1479
1456 /* Output */ 1480 /* Output */
1457 memcpy(resbuf, ctx->state, 64); 1481 memcpy(resbuf, ctx->state, 64);
1482 return 64;
1458} 1483}
diff --git a/libbb/hash_md5prime.c b/libbb/hash_md5prime.c
index e089a15f5..4b58d37ff 100644
--- a/libbb/hash_md5prime.c
+++ b/libbb/hash_md5prime.c
@@ -437,7 +437,7 @@ void FAST_FUNC md5_hash(const void *buffer, size_t inputLen, md5_ctx_t *context)
437 * MD5 finalization. Ends an MD5 message-digest operation, 437 * MD5 finalization. Ends an MD5 message-digest operation,
438 * writing the message digest. 438 * writing the message digest.
439 */ 439 */
440void FAST_FUNC md5_end(void *digest, md5_ctx_t *context) 440unsigned FAST_FUNC md5_end(void *digest, md5_ctx_t *context)
441{ 441{
442 unsigned idx, padLen; 442 unsigned idx, padLen;
443 unsigned char bits[8]; 443 unsigned char bits[8];
@@ -457,4 +457,5 @@ void FAST_FUNC md5_end(void *digest, md5_ctx_t *context)
457 457
458 /* Store state in digest */ 458 /* Store state in digest */
459 memcpy32_cpu2le(digest, context->state, 16); 459 memcpy32_cpu2le(digest, context->state, 16);
460 return 16;
460} 461}
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 5d9080131..670a1b194 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -2402,7 +2402,7 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
2402 /* ~ECHO, ~ECHONL: turn off echoing, including newline echoing */ 2402 /* ~ECHO, ~ECHONL: turn off echoing, including newline echoing */
2403 /* ~ISIG: turn off INTR (ctrl-C), QUIT, SUSP */ 2403 /* ~ISIG: turn off INTR (ctrl-C), QUIT, SUSP */
2404 new_settings.c_lflag &= ~(ICANON | ECHO | ECHONL | ISIG); 2404 new_settings.c_lflag &= ~(ICANON | ECHO | ECHONL | ISIG);
2405 /* reads would block only if < 1 char is available */ 2405 /* reads will block only if < 1 char is available */
2406 new_settings.c_cc[VMIN] = 1; 2406 new_settings.c_cc[VMIN] = 1;
2407 /* no timeout (reads block forever) */ 2407 /* no timeout (reads block forever) */
2408 new_settings.c_cc[VTIME] = 0; 2408 new_settings.c_cc[VTIME] = 0;
diff --git a/libbb/match_fstype.c b/libbb/match_fstype.c
index b066b4211..6046bc6db 100644
--- a/libbb/match_fstype.c
+++ b/libbb/match_fstype.c
@@ -12,34 +12,30 @@
12 12
13#include "libbb.h" 13#include "libbb.h"
14 14
15#ifdef HAVE_MNTENT_H 15int FAST_FUNC fstype_matches(const char *fstype, const char *comma_list)
16
17int FAST_FUNC match_fstype(const struct mntent *mt, const char *t_fstype)
18{ 16{
19 int match = 1; 17 int match = 1;
20 18
21 if (!t_fstype) 19 if (!comma_list)
22 return match; 20 return match;
23 21
24 if (t_fstype[0] == 'n' && t_fstype[1] == 'o') { 22 if (comma_list[0] == 'n' && comma_list[1] == 'o') {
25 match--; 23 match--;
26 t_fstype += 2; 24 comma_list += 2;
27 } 25 }
28 26
29 while (1) { 27 while (1) {
30 char *after_mnt_type = is_prefixed_with(t_fstype, mt->mnt_type); 28 char *after_mnt_type = is_prefixed_with(comma_list, fstype);
31 if (after_mnt_type 29 if (after_mnt_type
32 && (*after_mnt_type == '\0' || *after_mnt_type == ',') 30 && (*after_mnt_type == '\0' || *after_mnt_type == ',')
33 ) { 31 ) {
34 return match; 32 return match;
35 } 33 }
36 t_fstype = strchr(t_fstype, ','); 34 comma_list = strchr(comma_list, ',');
37 if (!t_fstype) 35 if (!comma_list)
38 break; 36 break;
39 t_fstype++; 37 comma_list++;
40 } 38 }
41 39
42 return !match; 40 return !match;
43} 41}
44
45#endif /* HAVE_MNTENT_H */
diff --git a/libbb/procps.c b/libbb/procps.c
index 452b50b82..6f971a116 100644
--- a/libbb/procps.c
+++ b/libbb/procps.c
@@ -371,6 +371,7 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
371 | PSSCAN_TTY | PSSCAN_NICE 371 | PSSCAN_TTY | PSSCAN_NICE
372 | PSSCAN_CPU) 372 | PSSCAN_CPU)
373 ) { 373 ) {
374 int s_idx;
374 char *cp, *comm1; 375 char *cp, *comm1;
375 int tty; 376 int tty;
376#if !ENABLE_FEATURE_FAST_TOP 377#if !ENABLE_FEATURE_FAST_TOP
@@ -469,17 +470,20 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
469#if ENABLE_FEATURE_PS_ADDITIONAL_COLUMNS 470#if ENABLE_FEATURE_PS_ADDITIONAL_COLUMNS
470 sp->niceness = tasknice; 471 sp->niceness = tasknice;
471#endif 472#endif
472 473 sp->state[1] = ' ';
473 if (sp->vsz == 0 && sp->state[0] != 'Z') 474 sp->state[2] = ' ';
475 s_idx = 1;
476 if (sp->vsz == 0 && sp->state[0] != 'Z') {
477 /* not sure what the purpose of this flag */
474 sp->state[1] = 'W'; 478 sp->state[1] = 'W';
475 else 479 s_idx = 2;
476 sp->state[1] = ' '; 480 }
477 if (tasknice < 0) 481 if (tasknice != 0) {
478 sp->state[2] = '<'; 482 if (tasknice < 0)
479 else if (tasknice) /* > 0 */ 483 sp->state[s_idx] = '<';
480 sp->state[2] = 'N'; 484 else /* > 0 */
481 else 485 sp->state[s_idx] = 'N';
482 sp->state[2] = ' '; 486 }
483 } 487 }
484 488
485#if ENABLE_FEATURE_TOPMEM 489#if ENABLE_FEATURE_TOPMEM
diff --git a/libbb/pw_encrypt.c b/libbb/pw_encrypt.c
index 4cdc2de76..fe06a8fe6 100644
--- a/libbb/pw_encrypt.c
+++ b/libbb/pw_encrypt.c
@@ -30,7 +30,7 @@ static int i64c(int i)
30int FAST_FUNC crypt_make_salt(char *p, int cnt /*, int x */) 30int FAST_FUNC crypt_make_salt(char *p, int cnt /*, int x */)
31{ 31{
32 /* was: x += ... */ 32 /* was: x += ... */
33 int x = getpid() + monotonic_us(); 33 unsigned x = getpid() + monotonic_us();
34 do { 34 do {
35 /* x = (x*1664525 + 1013904223) % 2^32 generator is lame 35 /* x = (x*1664525 + 1013904223) % 2^32 generator is lame
36 * (low-order bit is not "random", etc...), 36 * (low-order bit is not "random", etc...),
diff --git a/libbb/pw_encrypt_sha.c b/libbb/pw_encrypt_sha.c
index 8aeaacad6..5457d7ab6 100644
--- a/libbb/pw_encrypt_sha.c
+++ b/libbb/pw_encrypt_sha.c
@@ -18,9 +18,10 @@ static char *
18NOINLINE 18NOINLINE
19sha_crypt(/*const*/ char *key_data, /*const*/ char *salt_data) 19sha_crypt(/*const*/ char *key_data, /*const*/ char *salt_data)
20{ 20{
21#undef sha_end
21 void (*sha_begin)(void *ctx) FAST_FUNC; 22 void (*sha_begin)(void *ctx) FAST_FUNC;
22 void (*sha_hash)(void *ctx, const void *buffer, size_t len) FAST_FUNC; 23 void (*sha_hash)(void *ctx, const void *buffer, size_t len) FAST_FUNC;
23 void (*sha_end)(void *ctx, void *resbuf) FAST_FUNC; 24 unsigned (*sha_end)(void *ctx, void *resbuf) FAST_FUNC;
24 int _32or64; 25 int _32or64;
25 26
26 char *result, *resptr; 27 char *result, *resptr;
@@ -47,16 +48,17 @@ sha_crypt(/*const*/ char *key_data, /*const*/ char *salt_data)
47 unsigned cnt; 48 unsigned cnt;
48 unsigned rounds; 49 unsigned rounds;
49 char *cp; 50 char *cp;
50 char is_sha512;
51 51
52 /* Analyze salt, construct already known part of result */ 52 /* Analyze salt, construct already known part of result */
53 cnt = strlen(salt_data) + 1 + 43 + 1; 53 cnt = strlen(salt_data) + 1 + 43 + 1;
54 is_sha512 = salt_data[1]; 54 _32or64 = 32;
55 if (is_sha512 == '6') 55 if (salt_data[1] == '6') { /* sha512 */
56 _32or64 *= 2; /*64*/
56 cnt += 43; 57 cnt += 43;
58 }
57 result = resptr = xzalloc(cnt); /* will provide NUL terminator */ 59 result = resptr = xzalloc(cnt); /* will provide NUL terminator */
58 *resptr++ = '$'; 60 *resptr++ = '$';
59 *resptr++ = is_sha512; 61 *resptr++ = salt_data[1];
60 *resptr++ = '$'; 62 *resptr++ = '$';
61 rounds = ROUNDS_DEFAULT; 63 rounds = ROUNDS_DEFAULT;
62 salt_data += 3; 64 salt_data += 3;
@@ -93,12 +95,10 @@ sha_crypt(/*const*/ char *key_data, /*const*/ char *salt_data)
93 sha_begin = (void*)sha256_begin; 95 sha_begin = (void*)sha256_begin;
94 sha_hash = (void*)sha256_hash; 96 sha_hash = (void*)sha256_hash;
95 sha_end = (void*)sha256_end; 97 sha_end = (void*)sha256_end;
96 _32or64 = 32; 98 if (_32or64 != 32) {
97 if (is_sha512 == '6') {
98 sha_begin = (void*)sha512_begin; 99 sha_begin = (void*)sha512_begin;
99 sha_hash = (void*)sha512_hash; 100 sha_hash = (void*)sha512_hash;
100 sha_end = (void*)sha512_end; 101 sha_end = (void*)sha512_end;
101 _32or64 = 64;
102 } 102 }
103 103
104 /* Add KEY, SALT. */ 104 /* Add KEY, SALT. */
@@ -200,7 +200,7 @@ do { \
200 unsigned w = ((B2) << 16) | ((B1) << 8) | (B0); \ 200 unsigned w = ((B2) << 16) | ((B1) << 8) | (B0); \
201 resptr = to64(resptr, w, N); \ 201 resptr = to64(resptr, w, N); \
202} while (0) 202} while (0)
203 if (is_sha512 == '5') { 203 if (_32or64 == 32) { /* sha256 */
204 unsigned i = 0; 204 unsigned i = 0;
205 while (1) { 205 while (1) {
206 unsigned j = i + 10; 206 unsigned j = i + 10;
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c
index 766a89e5f..a6d260a40 100644
--- a/libbb/vfork_daemon_rexec.c
+++ b/libbb/vfork_daemon_rexec.c
@@ -185,26 +185,30 @@ int FAST_FUNC spawn_and_wait(char **argv)
185#if ENABLE_FEATURE_PREFER_APPLETS 185#if ENABLE_FEATURE_PREFER_APPLETS
186 int a = find_applet_by_name(argv[0]); 186 int a = find_applet_by_name(argv[0]);
187 187
188 if (a >= 0 && (APPLET_IS_NOFORK(a) 188 if (a >= 0) {
189# if BB_MMU
190 || APPLET_IS_NOEXEC(a) /* NOEXEC trick needs fork() */
191# endif
192 )) {
193# if BB_MMU
194 if (APPLET_IS_NOFORK(a)) 189 if (APPLET_IS_NOFORK(a))
195# endif
196 {
197 return run_nofork_applet(a, argv); 190 return run_nofork_applet(a, argv);
191# if BB_MMU /* NOEXEC needs fork(), thus this is done only on MMU machines: */
192# if !ENABLE_PLATFORM_MINGW32 /* and then only if not on Microsoft Windows */
193 if (APPLET_IS_NOEXEC(a)) {
194 fflush_all();
195 rc = fork();
196 if (rc) /* parent or error */
197 return wait4pid(rc);
198
199 /* child */
200 /* reset some state and run without execing */
201
202 /* msg_eol = "\n"; - no caller needs this reinited yet */
203 logmode = LOGMODE_STDIO;
204 /* die_func = NULL; - needed if the caller is a shell,
205 * init, or a NOFORK applet. But none of those call us
206 * as of yet (and that should probably always stay true).
207 */
208 /* xfunc_error_retval and applet_name are init by: */
209 run_applet_no_and_exit(a, argv);
198 } 210 }
199# if BB_MMU && !ENABLE_PLATFORM_MINGW32 211# endif
200 /* MMU only */
201 /* a->noexec is true */
202 rc = fork();
203 if (rc) /* parent or error */
204 return wait4pid(rc);
205 /* child */
206 xfunc_error_retval = EXIT_FAILURE;
207 run_applet_no_and_exit(a, argv);
208# endif 212# endif
209 } 213 }
210#endif /* FEATURE_PREFER_APPLETS */ 214#endif /* FEATURE_PREFER_APPLETS */
diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c
index 45650edba..98d3531d6 100644
--- a/libbb/xfuncs.c
+++ b/libbb/xfuncs.c
@@ -311,6 +311,43 @@ int FAST_FUNC tcsetattr_stdin_TCSANOW(const struct termios *tp)
311 return tcsetattr(STDIN_FILENO, TCSANOW, tp); 311 return tcsetattr(STDIN_FILENO, TCSANOW, tp);
312} 312}
313 313
314int FAST_FUNC set_termios_to_raw(int fd, struct termios *oldterm, int flags)
315{
316//TODO: lineedit, microcom and less might be adapted to use this too:
317// grep for "tcsetattr"
318
319 struct termios newterm;
320
321 tcgetattr(fd, oldterm);
322 newterm = *oldterm;
323
324 /* Turn off buffered input (ICANON)
325 * Turn off echoing (ECHO)
326 * and separate echoing of newline (ECHONL, normally off anyway)
327 */
328 newterm.c_lflag &= ~(ICANON | ECHO | ECHONL);
329 if (flags & TERMIOS_CLEAR_ISIG) {
330 /* dont recognize INT/QUIT/SUSP chars */
331 newterm.c_lflag &= ~ISIG;
332 }
333 /* reads will block only if < 1 char is available */
334 newterm.c_cc[VMIN] = 1;
335 /* no timeout (reads block forever) */
336 newterm.c_cc[VTIME] = 0;
337 if (flags & TERMIOS_RAW_CRNL) {
338 /* dont convert CR to NL on input */
339 newterm.c_iflag &= ~(IXON | ICRNL);
340 /* dont convert NL to CR on output */
341 newterm.c_oflag &= ~(ONLCR);
342 }
343 if (flags & TERMIOS_RAW_INPUT) {
344 /* dont convert anything on input */
345 newterm.c_iflag &= ~(BRKINT|INLCR|ICRNL|IXON|IXOFF|IUCLC|IXANY|IMAXBEL);
346 }
347
348 return tcsetattr(fd, TCSANOW, &newterm);
349}
350
314pid_t FAST_FUNC safe_waitpid(pid_t pid, int *wstat, int options) 351pid_t FAST_FUNC safe_waitpid(pid_t pid, int *wstat, int options)
315{ 352{
316 pid_t r; 353 pid_t r;
diff --git a/loginutils/Config.src b/loginutils/Config.src
index efb954b6c..beb4eb855 100644
--- a/loginutils/Config.src
+++ b/loginutils/Config.src
@@ -6,7 +6,7 @@
6menu "Login/Password Management Utilities" 6menu "Login/Password Management Utilities"
7 7
8config FEATURE_SHADOWPASSWDS 8config FEATURE_SHADOWPASSWDS
9 bool "Support for shadow passwords" 9 bool "Support shadow passwords"
10 default y 10 default y
11 help 11 help
12 Build support for shadow password in /etc/shadow. This file is only 12 Build support for shadow password in /etc/shadow. This file is only
diff --git a/loginutils/add-remove-shell.c b/loginutils/add-remove-shell.c
index ce4a7bbd2..af7c31779 100644
--- a/loginutils/add-remove-shell.c
+++ b/loginutils/add-remove-shell.c
@@ -19,6 +19,7 @@
19//config: help 19//config: help
20//config: Remove shells from /etc/shells. 20//config: Remove shells from /etc/shells.
21 21
22// APPLET_ODDNAME:name main location suid_type help
22//applet:IF_ADD_SHELL( APPLET_ODDNAME(add-shell , add_remove_shell, BB_DIR_USR_SBIN, BB_SUID_DROP, add_shell )) 23//applet:IF_ADD_SHELL( APPLET_ODDNAME(add-shell , add_remove_shell, BB_DIR_USR_SBIN, BB_SUID_DROP, add_shell ))
23//applet:IF_REMOVE_SHELL(APPLET_ODDNAME(remove-shell, add_remove_shell, BB_DIR_USR_SBIN, BB_SUID_DROP, remove_shell)) 24//applet:IF_REMOVE_SHELL(APPLET_ODDNAME(remove-shell, add_remove_shell, BB_DIR_USR_SBIN, BB_SUID_DROP, remove_shell))
24 25
diff --git a/loginutils/addgroup.c b/loginutils/addgroup.c
index 6b2fd7ba9..94da4efbb 100644
--- a/loginutils/addgroup.c
+++ b/loginutils/addgroup.c
@@ -19,15 +19,13 @@
19//config: bool "Enable long options" 19//config: bool "Enable long options"
20//config: default y 20//config: default y
21//config: depends on ADDGROUP && LONG_OPTS 21//config: depends on ADDGROUP && LONG_OPTS
22//config: help
23//config: Support long options for the addgroup applet.
24//config: 22//config:
25//config:config FEATURE_ADDUSER_TO_GROUP 23//config:config FEATURE_ADDUSER_TO_GROUP
26//config: bool "Support for adding users to groups" 24//config: bool "Support adding users to groups"
27//config: default y 25//config: default y
28//config: depends on ADDGROUP 26//config: depends on ADDGROUP
29//config: help 27//config: help
30//config: If called with two non-option arguments, 28//config: If called with two non-option arguments,
31//config: addgroup will add an existing user to an 29//config: addgroup will add an existing user to an
32//config: existing group. 30//config: existing group.
33 31
diff --git a/loginutils/adduser.c b/loginutils/adduser.c
index 608fb8437..40bc816a1 100644
--- a/loginutils/adduser.c
+++ b/loginutils/adduser.c
@@ -17,8 +17,6 @@
17//config: bool "Enable long options" 17//config: bool "Enable long options"
18//config: default y 18//config: default y
19//config: depends on ADDUSER && LONG_OPTS 19//config: depends on ADDUSER && LONG_OPTS
20//config: help
21//config: Support long options for the adduser applet.
22//config: 20//config:
23//config:config FEATURE_CHECK_NAMES 21//config:config FEATURE_CHECK_NAMES
24//config: bool "Enable sanity check on user/group names in adduser and addgroup" 22//config: bool "Enable sanity check on user/group names in adduser and addgroup"
@@ -66,7 +64,7 @@
66//usage: "\n -h DIR Home directory" 64//usage: "\n -h DIR Home directory"
67//usage: "\n -g GECOS GECOS field" 65//usage: "\n -g GECOS GECOS field"
68//usage: "\n -s SHELL Login shell" 66//usage: "\n -s SHELL Login shell"
69//usage: "\n -G GRP Add user to existing group" 67//usage: "\n -G GRP Group"
70//usage: "\n -S Create a system user" 68//usage: "\n -S Create a system user"
71//usage: "\n -D Don't assign a password" 69//usage: "\n -D Don't assign a password"
72//usage: "\n -H Don't create home directory" 70//usage: "\n -H Don't create home directory"
diff --git a/loginutils/chpasswd.c b/loginutils/chpasswd.c
index 2d268be67..baafd35c8 100644
--- a/loginutils/chpasswd.c
+++ b/loginutils/chpasswd.c
@@ -13,9 +13,9 @@
13//config: and uses this information to update a group of existing users. 13//config: and uses this information to update a group of existing users.
14//config: 14//config:
15//config:config FEATURE_DEFAULT_PASSWD_ALGO 15//config:config FEATURE_DEFAULT_PASSWD_ALGO
16//config: string "Default password encryption method (passwd -a, cryptpw -m parameter)" 16//config: string "Default encryption method (passwd -a, cryptpw -m, chpasswd -c ALG)"
17//config: default "des" 17//config: default "des"
18//config: depends on PASSWD || CRYPTPW 18//config: depends on PASSWD || CRYPTPW || CHPASSWD
19//config: help 19//config: help
20//config: Possible choices are "d[es]", "m[d5]", "s[ha256]" or "sha512". 20//config: Possible choices are "d[es]", "m[d5]", "s[ha256]" or "sha512".
21 21
@@ -29,13 +29,13 @@
29//usage: "Read user:password from stdin and update /etc/passwd\n" 29//usage: "Read user:password from stdin and update /etc/passwd\n"
30//usage: IF_LONG_OPTS( 30//usage: IF_LONG_OPTS(
31//usage: "\n -e,--encrypted Supplied passwords are in encrypted form" 31//usage: "\n -e,--encrypted Supplied passwords are in encrypted form"
32//usage: "\n -m,--md5 Use MD5 encryption instead of DES" 32//usage: "\n -m,--md5 Eencrypt using md5, not des"
33//usage: "\n -c,--crypt-method Use the specified method to encrypt the passwords" 33//usage: "\n -c,--crypt-method ALG "CRYPT_METHODS_HELP_STR
34//usage: ) 34//usage: )
35//usage: IF_NOT_LONG_OPTS( 35//usage: IF_NOT_LONG_OPTS(
36//usage: "\n -e Supplied passwords are in encrypted form" 36//usage: "\n -e Supplied passwords are in encrypted form"
37//usage: "\n -m Use MD5 encryption instead of DES" 37//usage: "\n -m Eencrypt using md5, not des"
38//usage: "\n -c Use the specified method to encrypt the passwords" 38//usage: "\n -c ALG "CRYPT_METHODS_HELP_STR
39//usage: ) 39//usage: )
40 40
41#include "libbb.h" 41#include "libbb.h"
diff --git a/loginutils/cryptpw.c b/loginutils/cryptpw.c
index 9f5f40686..696e169fc 100644
--- a/loginutils/cryptpw.c
+++ b/loginutils/cryptpw.c
@@ -35,17 +35,17 @@
35//usage: "[OPTIONS] [PASSWORD] [SALT]" 35//usage: "[OPTIONS] [PASSWORD] [SALT]"
36/* We do support -s, we just don't mention it */ 36/* We do support -s, we just don't mention it */
37//usage:#define cryptpw_full_usage "\n\n" 37//usage:#define cryptpw_full_usage "\n\n"
38//usage: "Crypt PASSWORD using crypt(3)\n" 38//usage: "Print crypt(3) hashed PASSWORD\n"
39//usage: IF_LONG_OPTS( 39//usage: IF_LONG_OPTS(
40//usage: "\n -P,--password-fd=N Read password from fd N" 40//usage: "\n -P,--password-fd N Read password from fd N"
41/* //usage: "\n -s,--stdin Use stdin; like -P0" */ 41/* //usage: "\n -s,--stdin Use stdin; like -P0" */
42//usage: "\n -m,--method=TYPE Encryption method" 42//usage: "\n -m,--method TYPE "CRYPT_METHODS_HELP_STR
43//usage: "\n -S,--salt=SALT" 43//usage: "\n -S,--salt SALT"
44//usage: ) 44//usage: )
45//usage: IF_NOT_LONG_OPTS( 45//usage: IF_NOT_LONG_OPTS(
46//usage: "\n -P N Read password from fd N" 46//usage: "\n -P N Read password from fd N"
47/* //usage: "\n -s Use stdin; like -P0" */ 47/* //usage: "\n -s Use stdin; like -P0" */
48//usage: "\n -m TYPE Encryption method TYPE" 48//usage: "\n -m TYPE "CRYPT_METHODS_HELP_STR
49//usage: "\n -S SALT" 49//usage: "\n -S SALT"
50//usage: ) 50//usage: )
51 51
@@ -92,7 +92,8 @@ to cryptpw. -a option (alias for -m) came from cryptpw.
92int cryptpw_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 92int cryptpw_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
93int cryptpw_main(int argc UNUSED_PARAM, char **argv) 93int cryptpw_main(int argc UNUSED_PARAM, char **argv)
94{ 94{
95 char salt[MAX_PW_SALT_LEN]; 95 /* Supports: cryptpw -m sha256 PASS 'rounds=999999999$SALT' */
96 char salt[MAX_PW_SALT_LEN + sizeof("rounds=999999999$")];
96 char *salt_ptr; 97 char *salt_ptr;
97 char *password; 98 char *password;
98 const char *opt_m, *opt_S; 99 const char *opt_m, *opt_S;
@@ -122,6 +123,7 @@ int cryptpw_main(int argc UNUSED_PARAM, char **argv)
122 123
123 salt_ptr = crypt_make_pw_salt(salt, opt_m); 124 salt_ptr = crypt_make_pw_salt(salt, opt_m);
124 if (opt_S) 125 if (opt_S)
126 /* put user's data after the "$N$" prefix */
125 safe_strncpy(salt_ptr, opt_S, sizeof(salt) - (sizeof("$N$")-1)); 127 safe_strncpy(salt_ptr, opt_S, sizeof(salt) - (sizeof("$N$")-1));
126 128
127 xmove_fd(fd, STDIN_FILENO); 129 xmove_fd(fd, STDIN_FILENO);
diff --git a/loginutils/deluser.c b/loginutils/deluser.c
index 7c3caf9e3..fbb1614fb 100644
--- a/loginutils/deluser.c
+++ b/loginutils/deluser.c
@@ -21,7 +21,7 @@
21//config: Utility for deleting a group account. 21//config: Utility for deleting a group account.
22//config: 22//config:
23//config:config FEATURE_DEL_USER_FROM_GROUP 23//config:config FEATURE_DEL_USER_FROM_GROUP
24//config: bool "Support for removing users from groups" 24//config: bool "Support removing users from groups"
25//config: default y 25//config: default y
26//config: depends on DELGROUP 26//config: depends on DELGROUP
27//config: help 27//config: help
diff --git a/loginutils/getty.c b/loginutils/getty.c
index 162c1697e..ba6c784a3 100644
--- a/loginutils/getty.c
+++ b/loginutils/getty.c
@@ -316,7 +316,7 @@ static void init_tty_attrs(int speed)
316 /* non-raw output; add CR to each NL */ 316 /* non-raw output; add CR to each NL */
317 G.tty_attrs.c_oflag = OPOST | ONLCR; 317 G.tty_attrs.c_oflag = OPOST | ONLCR;
318 318
319 /* reads would block only if < 1 char is available */ 319 /* reads will block only if < 1 char is available */
320 G.tty_attrs.c_cc[VMIN] = 1; 320 G.tty_attrs.c_cc[VMIN] = 1;
321 /* no timeout (reads block forever) */ 321 /* no timeout (reads block forever) */
322 G.tty_attrs.c_cc[VTIME] = 0; 322 G.tty_attrs.c_cc[VTIME] = 0;
diff --git a/loginutils/login.c b/loginutils/login.c
index 3ca8213bb..d1757a65d 100644
--- a/loginutils/login.c
+++ b/loginutils/login.c
@@ -24,7 +24,7 @@
24//config: will not be cleaned up. 24//config: will not be cleaned up.
25//config: 25//config:
26//config:config LOGIN_SCRIPTS 26//config:config LOGIN_SCRIPTS
27//config: bool "Support for login scripts" 27//config: bool "Support login scripts"
28//config: depends on LOGIN 28//config: depends on LOGIN
29//config: default y 29//config: default y
30//config: help 30//config: help
@@ -32,7 +32,7 @@
32//config: just prior to switching from root to logged-in user. 32//config: just prior to switching from root to logged-in user.
33//config: 33//config:
34//config:config FEATURE_NOLOGIN 34//config:config FEATURE_NOLOGIN
35//config: bool "Support for /etc/nologin" 35//config: bool "Support /etc/nologin"
36//config: default y 36//config: default y
37//config: depends on LOGIN 37//config: depends on LOGIN
38//config: help 38//config: help
@@ -40,7 +40,7 @@
40//config: If it exists, non-root logins are prohibited. 40//config: If it exists, non-root logins are prohibited.
41//config: 41//config:
42//config:config FEATURE_SECURETTY 42//config:config FEATURE_SECURETTY
43//config: bool "Support for /etc/securetty" 43//config: bool "Support /etc/securetty"
44//config: default y 44//config: default y
45//config: depends on LOGIN 45//config: depends on LOGIN
46//config: help 46//config: help
diff --git a/loginutils/passwd.c b/loginutils/passwd.c
index 52b66ca50..b7b7423fd 100644
--- a/loginutils/passwd.c
+++ b/loginutils/passwd.c
@@ -32,7 +32,7 @@
32//usage:#define passwd_full_usage "\n\n" 32//usage:#define passwd_full_usage "\n\n"
33//usage: "Change USER's password (default: current user)" 33//usage: "Change USER's password (default: current user)"
34//usage: "\n" 34//usage: "\n"
35//usage: "\n -a ALG Encryption method" 35//usage: "\n -a ALG "CRYPT_METHODS_HELP_STR
36//usage: "\n -d Set password to ''" 36//usage: "\n -d Set password to ''"
37//usage: "\n -l Lock (disable) account" 37//usage: "\n -l Lock (disable) account"
38//usage: "\n -u Unlock (enable) account" 38//usage: "\n -u Unlock (enable) account"
diff --git a/loginutils/su.c b/loginutils/su.c
index 24ffbde86..d04b85fb1 100644
--- a/loginutils/su.c
+++ b/loginutils/su.c
@@ -11,19 +11,18 @@
11//config: help 11//config: help
12//config: su is used to become another user during a login session. 12//config: su is used to become another user during a login session.
13//config: Invoked without a username, su defaults to becoming the super user. 13//config: Invoked without a username, su defaults to becoming the super user.
14//config: 14//config: Note that busybox binary must be setuid root for this applet to
15//config: Note that Busybox binary must be setuid root for this applet to
16//config: work properly. 15//config: work properly.
17//config: 16//config:
18//config:config FEATURE_SU_SYSLOG 17//config:config FEATURE_SU_SYSLOG
19//config: bool "Enable su to write to syslog" 18//config: bool "Log to syslog all attempts to use su"
20//config: default y 19//config: default y
21//config: depends on SU 20//config: depends on SU
22//config: 21//config:
23//config:config FEATURE_SU_CHECKS_SHELLS 22//config:config FEATURE_SU_CHECKS_SHELLS
24//config: bool "Enable su to check user's shell to be listed in /etc/shells" 23//config: bool "If user's shell is not in /etc/shells, disallow -s PROG"
25//config: depends on SU
26//config: default y 24//config: default y
25//config: depends on SU
27 26
28//applet:/* Needs to be run by root or be suid root - needs to change uid and gid: */ 27//applet:/* Needs to be run by root or be suid root - needs to change uid and gid: */
29//applet:IF_SU(APPLET(su, BB_DIR_BIN, BB_SUID_REQUIRE)) 28//applet:IF_SU(APPLET(su, BB_DIR_BIN, BB_SUID_REQUIRE))
diff --git a/loginutils/vlock.c b/loginutils/vlock.c
index 52ae607c9..5ba6a8780 100644
--- a/loginutils/vlock.c
+++ b/loginutils/vlock.c
@@ -105,12 +105,12 @@ int vlock_main(int argc UNUSED_PARAM, char **argv)
105 ioctl(STDIN_FILENO, VT_SETMODE, &vtm); 105 ioctl(STDIN_FILENO, VT_SETMODE, &vtm);
106#endif 106#endif
107 107
108//TODO: use set_termios_to_raw()
108 tcgetattr(STDIN_FILENO, &oterm); 109 tcgetattr(STDIN_FILENO, &oterm);
109 term = oterm; 110 term = oterm;
110 term.c_iflag &= ~BRKINT; 111 term.c_iflag |= IGNBRK; /* ignore serial break (why? VTs don't have breaks, right?) */
111 term.c_iflag |= IGNBRK; 112 term.c_iflag &= ~BRKINT; /* redundant? "dont translate break to SIGINT" */
112 term.c_lflag &= ~ISIG; 113 term.c_lflag &= ~(ISIG | ECHO | ECHOCTL); /* ignore ^C ^Z, echo off */
113 term.c_lflag &= ~(ECHO | ECHOCTL);
114 tcsetattr_stdin_TCSANOW(&term); 114 tcsetattr_stdin_TCSANOW(&term);
115 115
116 while (1) { 116 while (1) {
diff --git a/make_single_applets.sh b/make_single_applets.sh
index 00f502eda..8ad7a7406 100755
--- a/make_single_applets.sh
+++ b/make_single_applets.sh
@@ -28,9 +28,14 @@ for app in $apps; do
28done 28done
29#echo "$allno" >.config_allno 29#echo "$allno" >.config_allno
30 30
31trap 'test -f .config.SV && mv .config.SV .config && touch .config' EXIT
32
33
31# Turn on each applet individually and build single-applet executable 34# Turn on each applet individually and build single-applet executable
35# (give config names on command line to build only those)
36test $# = 0 && set -- $apps
32fail=0 37fail=0
33for app in $apps; do 38for app; do
34 # Only if it was indeed originally enabled... 39 # Only if it was indeed originally enabled...
35 { echo "$cfg" | grep -q "^CONFIG_${app}=y\$"; } || continue 40 { echo "$cfg" | grep -q "^CONFIG_${app}=y\$"; } || continue
36 41
@@ -54,16 +59,20 @@ for app in $apps; do
54 mv .config busybox_config_${app} 59 mv .config busybox_config_${app}
55 elif ! make $makeopts >>busybox_make_${app}.log 2>&1; then 60 elif ! make $makeopts >>busybox_make_${app}.log 2>&1; then
56 : $((fail++)) 61 : $((fail++))
62 grep -i -e error: -e warning: busybox_make_${app}.log
57 echo "Build error for ${app}" 63 echo "Build error for ${app}"
58 mv .config busybox_config_${app} 64 mv .config busybox_config_${app}
59 elif ! grep -q '^#define NUM_APPLETS 1$' include/NUM_APPLETS.h; then 65 elif ! grep -q '^#define NUM_APPLETS 1$' include/NUM_APPLETS.h; then
66 grep -i -e error: -e warning: busybox_make_${app}.log
60 mv busybox busybox_${app} 67 mv busybox busybox_${app}
61 : $((fail++)) 68 : $((fail++))
62 echo "NUM_APPLETS != 1 for ${app}: `cat include/NUM_APPLETS.h`" 69 echo "NUM_APPLETS != 1 for ${app}: `cat include/NUM_APPLETS.h`"
63 mv .config busybox_config_${app} 70 mv .config busybox_config_${app}
64 else 71 else
72 grep -i -e error: -e warning: busybox_make_${app}.log \
73 || rm busybox_make_${app}.log
65 mv busybox busybox_${app} 74 mv busybox busybox_${app}
66 rm busybox_make_${app}.log 75 #mv .config busybox_config_${app}
67 fi 76 fi
68 mv .config.SV .config 77 mv .config.SV .config
69 #exit 78 #exit
diff --git a/miscutils/chat.c b/miscutils/chat.c
index dc85f82fb..8df194534 100644
--- a/miscutils/chat.c
+++ b/miscutils/chat.c
@@ -213,6 +213,7 @@ int chat_main(int argc UNUSED_PARAM, char **argv)
213 , signal_handler); 213 , signal_handler);
214 214
215#if ENABLE_FEATURE_CHAT_TTY_HIFI 215#if ENABLE_FEATURE_CHAT_TTY_HIFI
216//TODO: use set_termios_to_raw()
216 tcgetattr(STDIN_FILENO, &tio); 217 tcgetattr(STDIN_FILENO, &tio);
217 tio0 = tio; 218 tio0 = tio;
218 cfmakeraw(&tio); 219 cfmakeraw(&tio);
diff --git a/miscutils/conspy.c b/miscutils/conspy.c
index d9d09d482..1f0278b47 100644
--- a/miscutils/conspy.c
+++ b/miscutils/conspy.c
@@ -363,7 +363,6 @@ int conspy_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
363int conspy_main(int argc UNUSED_PARAM, char **argv) 363int conspy_main(int argc UNUSED_PARAM, char **argv)
364{ 364{
365 char tty_name[sizeof(DEV_TTY "NN")]; 365 char tty_name[sizeof(DEV_TTY "NN")];
366 struct termios termbuf;
367 unsigned opts; 366 unsigned opts;
368 unsigned ttynum; 367 unsigned ttynum;
369 int poll_timeout_ms; 368 int poll_timeout_ms;
@@ -414,16 +413,14 @@ int conspy_main(int argc UNUSED_PARAM, char **argv)
414 413
415 bb_signals(BB_FATAL_SIGS, cleanup); 414 bb_signals(BB_FATAL_SIGS, cleanup);
416 415
417 // All characters must be passed through to us unaltered
418 G.kbd_fd = xopen(CURRENT_TTY, O_RDONLY); 416 G.kbd_fd = xopen(CURRENT_TTY, O_RDONLY);
419 tcgetattr(G.kbd_fd, &G.term_orig); 417
420 termbuf = G.term_orig; 418 // All characters must be passed through to us unaltered
421 termbuf.c_iflag &= ~(BRKINT|INLCR|ICRNL|IXON|IXOFF|IUCLC|IXANY|IMAXBEL); 419 set_termios_to_raw(G.kbd_fd, &G.term_orig, 0
422 //termbuf.c_oflag &= ~(OPOST); - no, we still want \n -> \r\n 420 | TERMIOS_CLEAR_ISIG // no signals on ^C ^Z etc
423 termbuf.c_lflag &= ~(ISIG|ICANON|ECHO); 421 | TERMIOS_RAW_INPUT // turn off all input conversions
424 termbuf.c_cc[VMIN] = 1; 422 );
425 termbuf.c_cc[VTIME] = 0; 423 //Note: termios.c_oflag &= ~(OPOST); - no, we still want \n -> \r\n
426 tcsetattr(G.kbd_fd, TCSANOW, &termbuf);
427 424
428 poll_timeout_ms = 250; 425 poll_timeout_ms = 250;
429 while (1) { 426 while (1) {
diff --git a/miscutils/crond.c b/miscutils/crond.c
index f96c96ee7..88e7b47b3 100644
--- a/miscutils/crond.c
+++ b/miscutils/crond.c
@@ -52,7 +52,7 @@
52//usage: " -f Foreground" 52//usage: " -f Foreground"
53//usage: "\n -b Background (default)" 53//usage: "\n -b Background (default)"
54//usage: "\n -S Log to syslog (default)" 54//usage: "\n -S Log to syslog (default)"
55//usage: "\n -l N Set log level. Most verbose:0, default:8" 55//usage: "\n -l N Set log level. Most verbose 0, default 8"
56//usage: IF_FEATURE_CROND_D( 56//usage: IF_FEATURE_CROND_D(
57//usage: "\n -d N Set log level, log to stderr" 57//usage: "\n -d N Set log level, log to stderr"
58//usage: ) 58//usage: )
diff --git a/miscutils/devfsd.c b/miscutils/devfsd.c
index 99bdc72b8..334f1071b 100644
--- a/miscutils/devfsd.c
+++ b/miscutils/devfsd.c
@@ -82,7 +82,7 @@
82//config: the external modutils. 82//config: the external modutils.
83//config: 83//config:
84//config:config DEVFSD_FG_NP 84//config:config DEVFSD_FG_NP
85//config: bool "Enables the -fg and -np options" 85//config: bool "Enable the -fg and -np options"
86//config: default y 86//config: default y
87//config: depends on DEVFSD 87//config: depends on DEVFSD
88//config: help 88//config: help
diff --git a/miscutils/flash_lock_unlock.c b/miscutils/flash_lock_unlock.c
index 2f698641f..003496d5b 100644
--- a/miscutils/flash_lock_unlock.c
+++ b/miscutils/flash_lock_unlock.c
@@ -17,7 +17,8 @@
17//config: The flash_unlock binary from mtd-utils as of git head 5ec0c10d0. This 17//config: The flash_unlock binary from mtd-utils as of git head 5ec0c10d0. This
18//config: utility unlocks part or all of the flash device. 18//config: utility unlocks part or all of the flash device.
19 19
20//applet:IF_FLASH_LOCK(APPLET_ODDNAME(flash_lock, flash_lock_unlock, BB_DIR_USR_SBIN, BB_SUID_DROP, flash_lock)) 20// APPLET_ODDNAME:name main location suid_type help
21//applet:IF_FLASH_LOCK( APPLET_ODDNAME(flash_lock, flash_lock_unlock, BB_DIR_USR_SBIN, BB_SUID_DROP, flash_lock))
21//applet:IF_FLASH_UNLOCK(APPLET_ODDNAME(flash_unlock, flash_lock_unlock, BB_DIR_USR_SBIN, BB_SUID_DROP, flash_unlock)) 22//applet:IF_FLASH_UNLOCK(APPLET_ODDNAME(flash_unlock, flash_lock_unlock, BB_DIR_USR_SBIN, BB_SUID_DROP, flash_unlock))
22 23
23//kbuild:lib-$(CONFIG_FLASH_LOCK) += flash_lock_unlock.o 24//kbuild:lib-$(CONFIG_FLASH_LOCK) += flash_lock_unlock.o
diff --git a/miscutils/hdparm.c b/miscutils/hdparm.c
index e43a0dec2..84675285a 100644
--- a/miscutils/hdparm.c
+++ b/miscutils/hdparm.c
@@ -25,7 +25,7 @@
25//config: default y 25//config: default y
26//config: depends on HDPARM 26//config: depends on HDPARM
27//config: help 27//config: help
28//config: Enables the -I and -i options to obtain detailed information 28//config: Enable the -I and -i options to obtain detailed information
29//config: directly from drives about their capabilities and supported ATA 29//config: directly from drives about their capabilities and supported ATA
30//config: feature set. If no device name is specified, hdparm will read 30//config: feature set. If no device name is specified, hdparm will read
31//config: identify data from stdin. Enabling this option will add about 16k... 31//config: identify data from stdin. Enabling this option will add about 16k...
@@ -35,7 +35,7 @@
35//config: default y 35//config: default y
36//config: depends on HDPARM 36//config: depends on HDPARM
37//config: help 37//config: help
38//config: Enables the 'hdparm -R' option to register an IDE interface. 38//config: Enable the 'hdparm -R' option to register an IDE interface.
39//config: This is dangerous stuff, so you should probably say N. 39//config: This is dangerous stuff, so you should probably say N.
40//config: 40//config:
41//config:config FEATURE_HDPARM_HDIO_UNREGISTER_HWIF 41//config:config FEATURE_HDPARM_HDIO_UNREGISTER_HWIF
@@ -43,7 +43,7 @@
43//config: default y 43//config: default y
44//config: depends on HDPARM 44//config: depends on HDPARM
45//config: help 45//config: help
46//config: Enables the 'hdparm -U' option to un-register an IDE interface. 46//config: Enable the 'hdparm -U' option to un-register an IDE interface.
47//config: This is dangerous stuff, so you should probably say N. 47//config: This is dangerous stuff, so you should probably say N.
48//config: 48//config:
49//config:config FEATURE_HDPARM_HDIO_DRIVE_RESET 49//config:config FEATURE_HDPARM_HDIO_DRIVE_RESET
@@ -51,7 +51,7 @@
51//config: default y 51//config: default y
52//config: depends on HDPARM 52//config: depends on HDPARM
53//config: help 53//config: help
54//config: Enables the 'hdparm -w' option to perform a device reset. 54//config: Enable the 'hdparm -w' option to perform a device reset.
55//config: This is dangerous stuff, so you should probably say N. 55//config: This is dangerous stuff, so you should probably say N.
56//config: 56//config:
57//config:config FEATURE_HDPARM_HDIO_TRISTATE_HWIF 57//config:config FEATURE_HDPARM_HDIO_TRISTATE_HWIF
@@ -59,7 +59,7 @@
59//config: default y 59//config: default y
60//config: depends on HDPARM 60//config: depends on HDPARM
61//config: help 61//config: help
62//config: Enables the 'hdparm -x' option to tristate device for hotswap, 62//config: Enable the 'hdparm -x' option to tristate device for hotswap,
63//config: and the '-b' option to get/set bus state. This is dangerous 63//config: and the '-b' option to get/set bus state. This is dangerous
64//config: stuff, so you should probably say N. 64//config: stuff, so you should probably say N.
65//config: 65//config:
@@ -68,7 +68,7 @@
68//config: default y 68//config: default y
69//config: depends on HDPARM 69//config: depends on HDPARM
70//config: help 70//config: help
71//config: Enables the 'hdparm -d' option to get/set using_dma flag. 71//config: Enable the 'hdparm -d' option to get/set using_dma flag.
72 72
73//applet:IF_HDPARM(APPLET(hdparm, BB_DIR_SBIN, BB_SUID_DROP)) 73//applet:IF_HDPARM(APPLET(hdparm, BB_DIR_SBIN, BB_SUID_DROP))
74 74
diff --git a/miscutils/last.c b/miscutils/last.c
index 67c1343f1..b3f125c3f 100644
--- a/miscutils/last.c
+++ b/miscutils/last.c
@@ -14,7 +14,7 @@
14//config: 'last' displays a list of the last users that logged into the system. 14//config: 'last' displays a list of the last users that logged into the system.
15//config: 15//config:
16//config:config FEATURE_LAST_FANCY 16//config:config FEATURE_LAST_FANCY
17//config: bool "Turn on output of extra information" 17//config: bool "Output extra information"
18//config: default y 18//config: default y
19//config: depends on LAST 19//config: depends on LAST
20//config: help 20//config: help
diff --git a/miscutils/less.c b/miscutils/less.c
index 8f9b329ba..220e2c693 100644
--- a/miscutils/less.c
+++ b/miscutils/less.c
@@ -87,7 +87,6 @@
87//config: this option makes less perform a last-ditch effort to find it: 87//config: this option makes less perform a last-ditch effort to find it:
88//config: position cursor to 999,999 and ask terminal to report real 88//config: position cursor to 999,999 and ask terminal to report real
89//config: cursor position using "ESC [ 6 n" escape sequence, then read stdin. 89//config: cursor position using "ESC [ 6 n" escape sequence, then read stdin.
90//config:
91//config: This is not clean but helps a lot on serial lines and such. 90//config: This is not clean but helps a lot on serial lines and such.
92//config: 91//config:
93//config:config FEATURE_LESS_DASHCMD 92//config:config FEATURE_LESS_DASHCMD
@@ -99,11 +98,9 @@
99//config: less itself ('-' keyboard command). 98//config: less itself ('-' keyboard command).
100//config: 99//config:
101//config:config FEATURE_LESS_LINENUMS 100//config:config FEATURE_LESS_LINENUMS
102//config: bool "Enable dynamic switching of line numbers" 101//config: bool "Enable -N (dynamic switching of line numbers)"
103//config: default y 102//config: default y
104//config: depends on FEATURE_LESS_DASHCMD 103//config: depends on FEATURE_LESS_DASHCMD
105//config: help
106//config: Enables "-N" command.
107 104
108//applet:IF_LESS(APPLET(less, BB_DIR_USR_BIN, BB_SUID_DROP)) 105//applet:IF_LESS(APPLET(less, BB_DIR_USR_BIN, BB_SUID_DROP))
109 106
diff --git a/miscutils/microcom.c b/miscutils/microcom.c
index 04605d883..5a4bbefa9 100644
--- a/miscutils/microcom.c
+++ b/miscutils/microcom.c
@@ -33,6 +33,7 @@
33// set raw tty mode 33// set raw tty mode
34static void xget1(int fd, struct termios *t, struct termios *oldt) 34static void xget1(int fd, struct termios *t, struct termios *oldt)
35{ 35{
36//TODO: use set_termios_to_raw()
36 tcgetattr(fd, oldt); 37 tcgetattr(fd, oldt);
37 *t = *oldt; 38 *t = *oldt;
38 cfmakeraw(t); 39 cfmakeraw(t);
diff --git a/miscutils/nandwrite.c b/miscutils/nandwrite.c
index c95cbb21e..dbe9043f4 100644
--- a/miscutils/nandwrite.c
+++ b/miscutils/nandwrite.c
@@ -37,7 +37,7 @@
37//usage: "\n -s ADDR Start address" 37//usage: "\n -s ADDR Start address"
38 38
39//usage:#define nanddump_trivial_usage 39//usage:#define nanddump_trivial_usage
40//usage: "[-no]" IF_LONG_OPTS(" [--bb=padbad|skipbad]") " [-s ADDR] [-l LEN] [-f FILE] MTD_DEVICE" 40//usage: "[-no]" IF_LONG_OPTS(" [--bb padbad|skipbad]") " [-s ADDR] [-l LEN] [-f FILE] MTD_DEVICE"
41//usage:#define nanddump_full_usage "\n\n" 41//usage:#define nanddump_full_usage "\n\n"
42//usage: "Dump MTD_DEVICE\n" 42//usage: "Dump MTD_DEVICE\n"
43//usage: "\n -n Read without ecc" 43//usage: "\n -n Read without ecc"
@@ -46,7 +46,7 @@
46//usage: "\n -l LEN Length" 46//usage: "\n -l LEN Length"
47//usage: "\n -f FILE Dump to file ('-' for stdout)" 47//usage: "\n -f FILE Dump to file ('-' for stdout)"
48//usage: IF_LONG_OPTS( 48//usage: IF_LONG_OPTS(
49//usage: "\n --bb=METHOD:" 49//usage: "\n --bb METHOD"
50//usage: "\n skipbad: skip bad blocks" 50//usage: "\n skipbad: skip bad blocks"
51//usage: "\n padbad: substitute bad blocks by 0xff (default)" 51//usage: "\n padbad: substitute bad blocks by 0xff (default)"
52//usage: ) 52//usage: )
diff --git a/miscutils/rx.c b/miscutils/rx.c
index 660f66a89..1f6f2825c 100644
--- a/miscutils/rx.c
+++ b/miscutils/rx.c
@@ -94,7 +94,7 @@ static int receive(/*int read_fd, */int file_fd)
94 int blockBegin; 94 int blockBegin;
95 int blockNo, blockNoOnesCompl; 95 int blockNo, blockNoOnesCompl;
96 int cksum_or_crc; 96 int cksum_or_crc;
97 int expected; 97 unsigned expected;
98 int i, j; 98 int i, j;
99 99
100 blockBegin = read_byte(timeout); 100 blockBegin = read_byte(timeout);
@@ -263,6 +263,7 @@ int rx_main(int argc UNUSED_PARAM, char **argv)
263 263
264 termios_err = tcgetattr(read_fd, &tty); 264 termios_err = tcgetattr(read_fd, &tty);
265 if (termios_err == 0) { 265 if (termios_err == 0) {
266//TODO: use set_termios_to_raw()
266 orig_tty = tty; 267 orig_tty = tty;
267 cfmakeraw(&tty); 268 cfmakeraw(&tty);
268 tcsetattr(read_fd, TCSAFLUSH, &tty); 269 tcsetattr(read_fd, TCSAFLUSH, &tty);
diff --git a/miscutils/taskset.c b/miscutils/taskset.c
index fb352ab8d..94a07383a 100644
--- a/miscutils/taskset.c
+++ b/miscutils/taskset.c
@@ -8,7 +8,7 @@
8 8
9//config:config TASKSET 9//config:config TASKSET
10//config: bool "taskset" 10//config: bool "taskset"
11//config: default n # doesn't build on some non-x86 targets (m68k) 11//config: default y
12//config: help 12//config: help
13//config: Retrieve or set a processes's CPU affinity. 13//config: Retrieve or set a processes's CPU affinity.
14//config: This requires sched_{g,s}etaffinity support in your libc. 14//config: This requires sched_{g,s}etaffinity support in your libc.
@@ -18,15 +18,15 @@
18//config: default y 18//config: default y
19//config: depends on TASKSET 19//config: depends on TASKSET
20//config: help 20//config: help
21//config: Add code for fancy output. This merely silences a compiler-warning 21//config: Needed for machines with more than 32-64 CPUs:
22//config: and adds about 135 Bytes. May be needed for machines with alot 22//config: affinity parameter 0xHHHHHHHHHHHHHHHHHHHH can be arbitrarily long
23//config: of CPUs. 23//config: in this case. Otherwise, it is limited to sizeof(long).
24 24
25//applet:IF_TASKSET(APPLET(taskset, BB_DIR_USR_BIN, BB_SUID_DROP)) 25//applet:IF_TASKSET(APPLET(taskset, BB_DIR_USR_BIN, BB_SUID_DROP))
26//kbuild:lib-$(CONFIG_TASKSET) += taskset.o 26//kbuild:lib-$(CONFIG_TASKSET) += taskset.o
27 27
28//usage:#define taskset_trivial_usage 28//usage:#define taskset_trivial_usage
29//usage: "[-p] [MASK] [PID | PROG ARGS]" 29//usage: "[-p] [HEXMASK] PID | PROG ARGS"
30//usage:#define taskset_full_usage "\n\n" 30//usage:#define taskset_full_usage "\n\n"
31//usage: "Set or get CPU affinity\n" 31//usage: "Set or get CPU affinity\n"
32//usage: "\n -p Operate on an existing PID" 32//usage: "\n -p Operate on an existing PID"
@@ -42,72 +42,81 @@
42//usage: "$ taskset -p 1\n" 42//usage: "$ taskset -p 1\n"
43//usage: "pid 1's current affinity mask: 3\n" 43//usage: "pid 1's current affinity mask: 3\n"
44/* 44/*
45 Not yet implemented: 45 * Not yet implemented:
46 * -a/--all-tasks (affect all threads) 46 * -a/--all-tasks (affect all threads)
47 * needs to get TIDs from /proc/PID/task/ and use _them_ as "pid" in sched_setaffinity(pid)
47 * -c/--cpu-list (specify CPUs via "1,3,5-7") 48 * -c/--cpu-list (specify CPUs via "1,3,5-7")
48 */ 49 */
49 50
50#include <sched.h> 51#include <sched.h>
51#include "libbb.h" 52#include "libbb.h"
52 53
54typedef unsigned long ul;
55#define SZOF_UL (unsigned)(sizeof(ul))
56#define BITS_UL (unsigned)(sizeof(ul)*8)
57#define MASK_UL (unsigned)(sizeof(ul)*8 - 1)
58
53#if ENABLE_FEATURE_TASKSET_FANCY 59#if ENABLE_FEATURE_TASKSET_FANCY
54#define TASKSET_PRINTF_MASK "%s" 60#define TASKSET_PRINTF_MASK "%s"
55/* craft a string from the mask */ 61/* craft a string from the mask */
56static char *from_cpuset(cpu_set_t *mask) 62static char *from_mask(const ul *mask, unsigned sz_in_bytes)
57{ 63{
58 int i; 64 char *str = xzalloc((sz_in_bytes+1) * 2); /* we will leak it */
59 char *ret = NULL; 65 char *p = str;
60 char *str = xzalloc((CPU_SETSIZE / 4) + 1); /* we will leak it */ 66 for (;;) {
61 67 ul v = *mask++;
62 for (i = CPU_SETSIZE - 4; i >= 0; i -= 4) { 68 if (SZOF_UL == 4)
63 int val = 0; 69 p += sprintf(p, "%08lx", v);
64 int off; 70 if (SZOF_UL == 8)
65 for (off = 0; off <= 3; ++off) 71 p += sprintf(p, "%016lx", v);
66 if (CPU_ISSET(i + off, mask)) 72 if (SZOF_UL == 16)
67 val |= 1 << off; 73 p += sprintf(p, "%032lx", v); /* :) */
68 if (!ret && val) 74 sz_in_bytes -= SZOF_UL;
69 ret = str; 75 if ((int)sz_in_bytes <= 0)
70 *str++ = bb_hexdigits_upcase[val] | 0x20; 76 break;
71 } 77 }
72 return ret; 78 while (str[0] == '0' && str[1])
79 str++;
80 return str;
73} 81}
74#else 82#else
75#define TASKSET_PRINTF_MASK "%llx" 83#define TASKSET_PRINTF_MASK "%lx"
76static unsigned long long from_cpuset(cpu_set_t *mask) 84static unsigned long long from_mask(ul *mask, unsigned sz_in_bytes UNUSED_PARAM)
77{ 85{
78 BUILD_BUG_ON(CPU_SETSIZE < 8*sizeof(int)); 86 return *mask;
79
80 /* Take the least significant bits. Assume cpu_set_t is
81 * implemented as an array of unsigned long or unsigned
82 * int.
83 */
84 if (CPU_SETSIZE < 8*sizeof(long))
85 return *(unsigned*)mask;
86 if (CPU_SETSIZE < 8*sizeof(long long))
87 return *(unsigned long*)mask;
88# if BB_BIG_ENDIAN
89 if (sizeof(long long) > sizeof(long)) {
90 /* We can put two long in the long long, but they have to
91 * be swapped: the least significant word comes first in the
92 * array */
93 unsigned long *p = (void*)mask;
94 return p[0] + ((unsigned long long)p[1] << (8*sizeof(long)));
95 }
96# endif
97 return *(unsigned long long*)mask;
98} 87}
99#endif 88#endif
100 89
90static unsigned long *get_aff(int pid, unsigned *sz)
91{
92 int r;
93 unsigned long *mask = NULL;
94 unsigned sz_in_bytes = *sz;
95
96 for (;;) {
97 mask = xrealloc(mask, sz_in_bytes);
98 r = sched_getaffinity(pid, sz_in_bytes, (void*)mask);
99 if (r == 0)
100 break;
101 sz_in_bytes *= 2;
102 if (errno == EINVAL && (int)sz_in_bytes > 0)
103 continue;
104 bb_perror_msg_and_die("can't %cet pid %d's affinity", 'g', pid);
105 }
106 //bb_error_msg("get mask[0]:%lx sz_in_bytes:%d", mask[0], sz_in_bytes);
107 *sz = sz_in_bytes;
108 return mask;
109}
101 110
102int taskset_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 111int taskset_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
103int taskset_main(int argc UNUSED_PARAM, char **argv) 112int taskset_main(int argc UNUSED_PARAM, char **argv)
104{ 113{
105 cpu_set_t mask; 114 ul *mask;
115 unsigned mask_size_in_bytes;
106 pid_t pid = 0; 116 pid_t pid = 0;
107 unsigned opt_p; 117 unsigned opt_p;
108 const char *current_new; 118 const char *current_new;
109 char *pid_str; 119 char *aff;
110 char *aff = aff; /* for compiler */
111 120
112 /* NB: we mimic util-linux's taskset: -p does not take 121 /* NB: we mimic util-linux's taskset: -p does not take
113 * an argument, i.e., "-pN" is NOT valid, only "-p N"! 122 * an argument, i.e., "-pN" is NOT valid, only "-p N"!
@@ -118,102 +127,92 @@ int taskset_main(int argc UNUSED_PARAM, char **argv)
118 opt_p = getopt32(argv, "+p"); 127 opt_p = getopt32(argv, "+p");
119 argv += optind; 128 argv += optind;
120 129
130 aff = *argv++;
121 if (opt_p) { 131 if (opt_p) {
122 pid_str = *argv++; 132 char *pid_str = aff;
123 if (*argv) { /* "-p <aff> <pid> ...rest.is.ignored..." */ 133 if (*argv) { /* "-p <aff> <pid> ...rest.is.ignored..." */
124 aff = pid_str;
125 pid_str = *argv; /* NB: *argv != NULL in this case */ 134 pid_str = *argv; /* NB: *argv != NULL in this case */
126 } 135 }
127 /* else it was just "-p <pid>", and *argv == NULL */ 136 /* else it was just "-p <pid>", and *argv == NULL */
128 pid = xatoul_range(pid_str, 1, ((unsigned)(pid_t)ULONG_MAX) >> 1); 137 pid = xatoul_range(pid_str, 1, ((unsigned)(pid_t)ULONG_MAX) >> 1);
129 } else { 138 } else {
130 aff = *argv++; /* <aff> <cmd...> */ 139 /* <aff> <cmd...> */
131 if (!*argv) 140 if (!*argv)
132 bb_show_usage(); 141 bb_show_usage();
133 } 142 }
134 143
135 current_new = "current\0new"; 144 mask_size_in_bytes = SZOF_UL;
136 if (opt_p) { 145 current_new = "current";
137 print_aff: 146 print_aff:
138 if (sched_getaffinity(pid, sizeof(mask), &mask) < 0) 147 mask = get_aff(pid, &mask_size_in_bytes);
139 bb_perror_msg_and_die("can't %cet pid %d's affinity", 'g', pid); 148 if (opt_p) {
140 printf("pid %d's %s affinity mask: "TASKSET_PRINTF_MASK"\n", 149 printf("pid %d's %s affinity mask: "TASKSET_PRINTF_MASK"\n",
141 pid, current_new, from_cpuset(&mask)); 150 pid, current_new, from_mask(mask, mask_size_in_bytes));
142 if (!*argv) { 151 if (*argv == NULL) {
143 /* Either it was just "-p <pid>", 152 /* Either it was just "-p <pid>",
144 * or it was "-p <aff> <pid>" and we came here 153 * or it was "-p <aff> <pid>" and we came here
145 * for the second time (see goto below) */ 154 * for the second time (see goto below) */
146 return EXIT_SUCCESS; 155 return EXIT_SUCCESS;
147 } 156 }
148 *argv = NULL; 157 *argv = NULL;
149 current_new += 8; /* "new" */ 158 current_new = "new";
150 } 159 }
160 memset(mask, 0, mask_size_in_bytes);
161
162 /* Affinity was specified, translate it into mask */
163 /* it is always in hex, skip "0x" if it exists */
164 if (aff[0] == '0' && (aff[1]|0x20) == 'x')
165 aff += 2;
151 166
152 /* Affinity was specified, translate it into cpu_set_t */
153 CPU_ZERO(&mask);
154 if (!ENABLE_FEATURE_TASKSET_FANCY) { 167 if (!ENABLE_FEATURE_TASKSET_FANCY) {
155 unsigned i; 168 mask[0] = xstrtoul(aff, 16);
156 unsigned long long m;
157
158 /* Do not allow zero mask: */
159 m = xstrtoull_range(aff, 0, 1, ULLONG_MAX);
160 i = 0;
161 do {
162 if (m & 1)
163 CPU_SET(i, &mask);
164 i++;
165 m >>= 1;
166 } while (m != 0);
167 } else { 169 } else {
168 unsigned i; 170 unsigned i;
169 char *last_byte; 171 char *last_char;
170 char *bin; 172
171 uint8_t bit_in_byte; 173 i = 0; /* bit pos in mask[] */
172 174
173 /* Cheap way to get "long enough" buffer */ 175 /* aff is ASCII hex string, accept very long masks in this form.
174 bin = xstrdup(aff); 176 * Process hex string AABBCCDD... to ulong mask[]
175 177 * from the rightmost nibble, which is least-significant.
176 if (aff[0] != '0' || (aff[1]|0x20) != 'x') { 178 * Bits not fitting into mask[] are ignored: (example: 1234
177/* TODO: decimal/octal masks are still limited to 2^64 */ 179 * in 12340000000000000000000000000000000000000ff)
178 unsigned long long m = xstrtoull_range(aff, 0, 1, ULLONG_MAX); 180 */
179 bin += strlen(bin); 181 last_char = strchrnul(aff, '\0');
180 last_byte = bin - 1; 182 while (last_char > aff) {
181 while (m) { 183 char c;
182 *--bin = m & 0xff; 184 ul val;
183 m >>= 8; 185
184 } 186 last_char--;
185 } else { 187 c = *last_char;
186 /* aff is "0x.....", we accept very long masks in this form */ 188 if (isdigit(c))
187 last_byte = hex2bin(bin, aff + 2, INT_MAX); 189 val = c - '0';
188 if (!last_byte) { 190 else if ((c|0x20) >= 'a' && (c|0x20) <= 'f')
189 bad_aff: 191 val = (c|0x20) - ('a' - 10);
192 else
190 bb_error_msg_and_die("bad affinity '%s'", aff); 193 bb_error_msg_and_die("bad affinity '%s'", aff);
191 }
192 last_byte--; /* now points to the last byte */
193 }
194 194
195 i = 0; 195 if (i < mask_size_in_bytes * 8) {
196 bit_in_byte = 1; 196 mask[i / BITS_UL] |= val << (i & MASK_UL);
197 while (last_byte >= bin) {
198 if (bit_in_byte & *last_byte) {
199 if (i >= CPU_SETSIZE)
200 goto bad_aff;
201 CPU_SET(i, &mask);
202 //bb_error_msg("bit %d set", i); 197 //bb_error_msg("bit %d set", i);
203 } 198 }
204 i++; 199 /* else:
205 /* bit_in_byte is uint8_t! & 0xff is implied */ 200 * We can error out here, but we don't.
206 bit_in_byte = (bit_in_byte << 1); 201 * For one, kernel itself ignores bits in mask[]
207 if (!bit_in_byte) { 202 * which do not map to any CPUs:
208 bit_in_byte = 1; 203 * if mask[] has one 32-bit long element,
209 last_byte--; 204 * but you have only 8 CPUs, all bits beyond first 8
210 } 205 * are ignored, silently.
206 * No point in making bits past 31th to be errors.
207 */
208 i += 4;
211 } 209 }
212 } 210 }
213 211
214 /* Set pid's or our own (pid==0) affinity */ 212 /* Set pid's or our own (pid==0) affinity */
215 if (sched_setaffinity(pid, sizeof(mask), &mask)) 213 if (sched_setaffinity(pid, mask_size_in_bytes, (void*)mask))
216 bb_perror_msg_and_die("can't %cet pid %d's affinity", 's', pid); 214 bb_perror_msg_and_die("can't %cet pid %d's affinity", 's', pid);
215 //bb_error_msg("set mask[0]:%lx", mask[0]);
217 216
218 if (!argv[0]) /* "-p <aff> <pid> [...ignored...]" */ 217 if (!argv[0]) /* "-p <aff> <pid> [...ignored...]" */
219 goto print_aff; /* print new affinity and exit */ 218 goto print_aff; /* print new affinity and exit */
diff --git a/miscutils/ubi_tools.c b/miscutils/ubi_tools.c
index 8e55e9577..982e3e52a 100644
--- a/miscutils/ubi_tools.c
+++ b/miscutils/ubi_tools.c
@@ -45,11 +45,12 @@
45//config: help 45//config: help
46//config: Update a UBI volume. 46//config: Update a UBI volume.
47 47
48//applet:IF_UBIATTACH(APPLET_ODDNAME(ubiattach, ubi_tools, BB_DIR_USR_SBIN, BB_SUID_DROP, ubiattach)) 48// APPLET_ODDNAME:name main location suid_type help
49//applet:IF_UBIDETACH(APPLET_ODDNAME(ubidetach, ubi_tools, BB_DIR_USR_SBIN, BB_SUID_DROP, ubidetach)) 49//applet:IF_UBIATTACH( APPLET_ODDNAME(ubiattach, ubi_tools, BB_DIR_USR_SBIN, BB_SUID_DROP, ubiattach))
50//applet:IF_UBIMKVOL(APPLET_ODDNAME(ubimkvol, ubi_tools, BB_DIR_USR_SBIN, BB_SUID_DROP, ubimkvol)) 50//applet:IF_UBIDETACH( APPLET_ODDNAME(ubidetach, ubi_tools, BB_DIR_USR_SBIN, BB_SUID_DROP, ubidetach))
51//applet:IF_UBIRMVOL(APPLET_ODDNAME(ubirmvol, ubi_tools, BB_DIR_USR_SBIN, BB_SUID_DROP, ubirmvol)) 51//applet:IF_UBIMKVOL( APPLET_ODDNAME(ubimkvol, ubi_tools, BB_DIR_USR_SBIN, BB_SUID_DROP, ubimkvol))
52//applet:IF_UBIRSVOL(APPLET_ODDNAME(ubirsvol, ubi_tools, BB_DIR_USR_SBIN, BB_SUID_DROP, ubirsvol)) 52//applet:IF_UBIRMVOL( APPLET_ODDNAME(ubirmvol, ubi_tools, BB_DIR_USR_SBIN, BB_SUID_DROP, ubirmvol))
53//applet:IF_UBIRSVOL( APPLET_ODDNAME(ubirsvol, ubi_tools, BB_DIR_USR_SBIN, BB_SUID_DROP, ubirsvol))
53//applet:IF_UBIUPDATEVOL(APPLET_ODDNAME(ubiupdatevol, ubi_tools, BB_DIR_USR_SBIN, BB_SUID_DROP, ubiupdatevol)) 54//applet:IF_UBIUPDATEVOL(APPLET_ODDNAME(ubiupdatevol, ubi_tools, BB_DIR_USR_SBIN, BB_SUID_DROP, ubiupdatevol))
54 55
55//kbuild:lib-$(CONFIG_UBIATTACH) += ubi_tools.o 56//kbuild:lib-$(CONFIG_UBIATTACH) += ubi_tools.o
diff --git a/modutils/Config.src b/modutils/Config.src
index 84ff34a08..5f0b0cec4 100644
--- a/modutils/Config.src
+++ b/modutils/Config.src
@@ -8,9 +8,11 @@ menu "Linux Module Utilities"
8config MODPROBE_SMALL 8config MODPROBE_SMALL
9 bool "Simplified modutils" 9 bool "Simplified modutils"
10 default y 10 default y
11 select PLATFORM_LINUX
12 help 11 help
13 Simplified modutils. 12 Build smaller (~1.5 kbytes), simplified module tools.
13
14 This option by itself does not enable any applets -
15 you need to select applets individually below.
14 16
15 With this option modprobe does not require modules.dep file 17 With this option modprobe does not require modules.dep file
16 and does not use /etc/modules.conf file. 18 and does not use /etc/modules.conf file.
@@ -31,47 +33,38 @@ config MODPROBE_SMALL
31 Additional module parameters can be stored in 33 Additional module parameters can be stored in
32 /etc/modules/$module_name files. 34 /etc/modules/$module_name files.
33 35
34 Apart from modprobe, other utilities are also provided:
35 - insmod is an alias to modprobe
36 - rmmod is an alias to modprobe -r
37 - depmod generates modules.dep.bb
38
39INSERT 36INSERT
40 37
41comment "Options common to multiple modutils" 38comment "Options common to multiple modutils"
42 39
40config FEATURE_CMDLINE_MODULE_OPTIONS
41 bool "Accept module options on modprobe command line"
42 default y
43 depends on INSMOD || MODPROBE
44 help
45 Allow insmod and modprobe take module options from the applets'
46 command line.
47
48config FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED
49 bool "Skip loading of already loaded modules"
50 default y
51 depends on MODPROBE_SMALL && (DEPMOD || INSMOD || MODPROBE)
52 help
53 Check if the module is already loaded.
54
43config FEATURE_2_4_MODULES 55config FEATURE_2_4_MODULES
44 bool "Support version 2.2/2.4 Linux kernels" 56 bool "Support version 2.2/2.4 Linux kernels"
45 default n 57 default n
46 depends on INSMOD || RMMOD || LSMOD 58 depends on (INSMOD || LSMOD || MODPROBE || RMMOD) && !MODPROBE_SMALL
47 select PLATFORM_LINUX
48 help 59 help
49 Support module loading for 2.2.x and 2.4.x Linux kernels. 60 Support module loading for 2.2.x and 2.4.x Linux kernels.
50 This increases size considerably. Say N unless you plan 61 This increases size considerably. Say N unless you plan
51 to run ancient kernels. 62 to run ancient kernels.
52 63
53config FEATURE_INSMOD_TRY_MMAP
54 bool "Try to load module from a mmap'ed area"
55 default n
56 depends on INSMOD || MODPROBE_SMALL
57 select PLATFORM_LINUX
58 help
59 This option causes module loading code to try to mmap
60 module first. If it does not work (for example,
61 it does not work for compressed modules), module will be read
62 (and unpacked if needed) into a memory block allocated by malloc.
63
64 The only case when mmap works but malloc does not is when
65 you are trying to load a big module on a very memory-constrained
66 machine. Malloc will momentarily need 2x as much memory as mmap.
67
68 Choosing N saves about 250 bytes of code (on 32-bit x86).
69
70config FEATURE_INSMOD_VERSION_CHECKING 64config FEATURE_INSMOD_VERSION_CHECKING
71 bool "Enable module version checking" 65 bool "Enable module version checking"
72 default n 66 default n
73 depends on FEATURE_2_4_MODULES && (INSMOD || MODPROBE) 67 depends on FEATURE_2_4_MODULES && (INSMOD || MODPROBE)
74 select PLATFORM_LINUX
75 help 68 help
76 Support checking of versions for modules. This is used to 69 Support checking of versions for modules. This is used to
77 ensure that the kernel and module are made for each other. 70 ensure that the kernel and module are made for each other.
@@ -80,7 +73,6 @@ config FEATURE_INSMOD_KSYMOOPS_SYMBOLS
80 bool "Add module symbols to kernel symbol table" 73 bool "Add module symbols to kernel symbol table"
81 default n 74 default n
82 depends on FEATURE_2_4_MODULES && (INSMOD || MODPROBE) 75 depends on FEATURE_2_4_MODULES && (INSMOD || MODPROBE)
83 select PLATFORM_LINUX
84 help 76 help
85 By adding module symbols to the kernel symbol table, Oops messages 77 By adding module symbols to the kernel symbol table, Oops messages
86 occuring within kernel modules can be properly debugged. By enabling 78 occuring within kernel modules can be properly debugged. By enabling
@@ -92,7 +84,6 @@ config FEATURE_INSMOD_LOADINKMEM
92 bool "In kernel memory optimization (uClinux only)" 84 bool "In kernel memory optimization (uClinux only)"
93 default n 85 default n
94 depends on FEATURE_2_4_MODULES && (INSMOD || MODPROBE) 86 depends on FEATURE_2_4_MODULES && (INSMOD || MODPROBE)
95 select PLATFORM_LINUX
96 help 87 help
97 This is a special uClinux only memory optimization that lets insmod 88 This is a special uClinux only memory optimization that lets insmod
98 load the specified kernel module directly into kernel space, reducing 89 load the specified kernel module directly into kernel space, reducing
@@ -103,7 +94,6 @@ config FEATURE_INSMOD_LOAD_MAP
103 bool "Enable insmod load map (-m) option" 94 bool "Enable insmod load map (-m) option"
104 default n 95 default n
105 depends on FEATURE_2_4_MODULES && INSMOD 96 depends on FEATURE_2_4_MODULES && INSMOD
106 select PLATFORM_LINUX
107 help 97 help
108 Enabling this, one would be able to get a load map 98 Enabling this, one would be able to get a load map
109 output on stdout. This makes kernel module debugging 99 output on stdout. This makes kernel module debugging
@@ -114,8 +104,7 @@ config FEATURE_INSMOD_LOAD_MAP
114config FEATURE_INSMOD_LOAD_MAP_FULL 104config FEATURE_INSMOD_LOAD_MAP_FULL
115 bool "Symbols in load map" 105 bool "Symbols in load map"
116 default y 106 default y
117 depends on FEATURE_INSMOD_LOAD_MAP && !MODPROBE_SMALL 107 depends on FEATURE_INSMOD_LOAD_MAP
118 select PLATFORM_LINUX
119 help 108 help
120 Without this option, -m will only output section 109 Without this option, -m will only output section
121 load map. With this option, -m will also output 110 load map. With this option, -m will also output
@@ -125,18 +114,32 @@ config FEATURE_CHECK_TAINTED_MODULE
125 bool "Support tainted module checking with new kernels" 114 bool "Support tainted module checking with new kernels"
126 default y 115 default y
127 depends on (LSMOD || FEATURE_2_4_MODULES) && !MODPROBE_SMALL 116 depends on (LSMOD || FEATURE_2_4_MODULES) && !MODPROBE_SMALL
128 select PLATFORM_LINUX
129 help 117 help
130 Support checking for tainted modules. These are usually binary 118 Support checking for tainted modules. These are usually binary
131 only modules that will make the linux-kernel list ignore your 119 only modules that will make the linux-kernel list ignore your
132 support request. 120 support request.
133 This option is required to support GPLONLY modules. 121 This option is required to support GPLONLY modules.
134 122
123config FEATURE_INSMOD_TRY_MMAP
124 bool "Try to load module from a mmap'ed area"
125 default n
126 depends on (INSMOD || MODPROBE) && !MODPROBE_SMALL
127 help
128 This option causes module loading code to try to mmap
129 module first. If it does not work (for example,
130 it does not work for compressed modules), module will be read
131 (and unpacked if needed) into a memory block allocated by malloc.
132
133 The only case when mmap works but malloc does not is when
134 you are trying to load a big module on a very memory-constrained
135 machine. Malloc will momentarily need 2x as much memory as mmap.
136
137 Choosing N saves about 250 bytes of code (on 32-bit x86).
138
135config FEATURE_MODUTILS_ALIAS 139config FEATURE_MODUTILS_ALIAS
136 bool "Support for module.aliases file" 140 bool "Support module.aliases file"
137 default y 141 default y
138 depends on DEPMOD || MODPROBE 142 depends on (DEPMOD || MODPROBE) && !MODPROBE_SMALL
139 select PLATFORM_LINUX
140 help 143 help
141 Generate and parse modules.alias containing aliases for bus 144 Generate and parse modules.alias containing aliases for bus
142 identifiers: 145 identifiers:
@@ -150,10 +153,9 @@ config FEATURE_MODUTILS_ALIAS
150 Say Y if unsure. 153 Say Y if unsure.
151 154
152config FEATURE_MODUTILS_SYMBOLS 155config FEATURE_MODUTILS_SYMBOLS
153 bool "Support for module.symbols file" 156 bool "Support module.symbols file"
154 default y 157 default y
155 depends on DEPMOD || MODPROBE 158 depends on (DEPMOD || MODPROBE) && !MODPROBE_SMALL
156 select PLATFORM_LINUX
157 help 159 help
158 Generate and parse modules.symbols containing aliases for 160 Generate and parse modules.symbols containing aliases for
159 symbol_request() kernel calls, such as: 161 symbol_request() kernel calls, such as:
@@ -164,7 +166,7 @@ config FEATURE_MODUTILS_SYMBOLS
164config DEFAULT_MODULES_DIR 166config DEFAULT_MODULES_DIR
165 string "Default directory containing modules" 167 string "Default directory containing modules"
166 default "/lib/modules" 168 default "/lib/modules"
167 depends on DEPMOD || MODPROBE || MODPROBE_SMALL || MODINFO 169 depends on DEPMOD || MODPROBE || MODINFO
168 help 170 help
169 Directory that contains kernel modules. 171 Directory that contains kernel modules.
170 Defaults to "/lib/modules" 172 Defaults to "/lib/modules"
@@ -172,9 +174,13 @@ config DEFAULT_MODULES_DIR
172config DEFAULT_DEPMOD_FILE 174config DEFAULT_DEPMOD_FILE
173 string "Default name of modules.dep" 175 string "Default name of modules.dep"
174 default "modules.dep" 176 default "modules.dep"
175 depends on DEPMOD || MODPROBE || MODPROBE_SMALL || MODINFO 177 depends on DEPMOD || MODPROBE || MODINFO
176 help 178 help
177 Filename that contains kernel modules dependencies. 179 Filename that contains kernel modules dependencies.
178 Defaults to "modules.dep" 180 Defaults to "modules.dep".
181 If you configured the "simplified modutils" (MODPROBE_SMALL), a
182 ".bb" suffix will be added after this name. Do not specify ".bb"
183 here unless you intend your depmod or modprobe to work on
184 "modules.dep.bb.bb" or such.
179 185
180endmenu 186endmenu
diff --git a/modutils/insmod.c b/modutils/insmod.c
index f2c70e16f..8526979eb 100644
--- a/modutils/insmod.c
+++ b/modutils/insmod.c
@@ -27,9 +27,9 @@
27 27
28//usage:#if !ENABLE_MODPROBE_SMALL 28//usage:#if !ENABLE_MODPROBE_SMALL
29//usage:#define insmod_trivial_usage 29//usage:#define insmod_trivial_usage
30//usage: IF_FEATURE_2_4_MODULES("[OPTIONS] MODULE ") 30//usage: IF_FEATURE_2_4_MODULES("[OPTIONS] MODULE")
31//usage: IF_NOT_FEATURE_2_4_MODULES("FILE ") 31//usage: IF_NOT_FEATURE_2_4_MODULES("FILE")
32//usage: "[SYMBOL=VALUE]..." 32//usage: IF_FEATURE_CMDLINE_MODULE_OPTIONS(" [SYMBOL=VALUE]...")
33//usage:#define insmod_full_usage "\n\n" 33//usage:#define insmod_full_usage "\n\n"
34//usage: "Load kernel module" 34//usage: "Load kernel module"
35//usage: IF_FEATURE_2_4_MODULES( "\n" 35//usage: IF_FEATURE_2_4_MODULES( "\n"
diff --git a/modutils/lsmod.c b/modutils/lsmod.c
index 24589420a..24e5d35b9 100644
--- a/modutils/lsmod.c
+++ b/modutils/lsmod.c
@@ -18,7 +18,6 @@
18//config: bool "Pretty output" 18//config: bool "Pretty output"
19//config: default y 19//config: default y
20//config: depends on LSMOD && !MODPROBE_SMALL 20//config: depends on LSMOD && !MODPROBE_SMALL
21//config: select PLATFORM_LINUX
22//config: help 21//config: help
23//config: This option makes output format of lsmod adjusted to 22//config: This option makes output format of lsmod adjusted to
24//config: the format of module-init-tools for Linux kernel 2.6. 23//config: the format of module-init-tools for Linux kernel 2.6.
@@ -34,7 +33,7 @@
34//usage:#define lsmod_trivial_usage 33//usage:#define lsmod_trivial_usage
35//usage: "" 34//usage: ""
36//usage:#define lsmod_full_usage "\n\n" 35//usage:#define lsmod_full_usage "\n\n"
37//usage: "List the currently loaded kernel modules" 36//usage: "List loaded kernel modules"
38//usage:#endif 37//usage:#endif
39 38
40#include "libbb.h" 39#include "libbb.h"
diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c
index 0fc9ea454..431b8aeb2 100644
--- a/modutils/modprobe-small.c
+++ b/modutils/modprobe-small.c
@@ -8,28 +8,15 @@
8 * Licensed under GPLv2, see file LICENSE in this source tree. 8 * Licensed under GPLv2, see file LICENSE in this source tree.
9 */ 9 */
10 10
11/* config MODPROBE_SMALL is defined in Config.src to ensure better "make config" order */ 11/* modprobe-small configs are defined in Config.src to ensure better
12 12 * "make config" order */
13//config:config FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE
14//config: bool "Accept module options on modprobe command line"
15//config: default y
16//config: depends on MODPROBE_SMALL
17//config: select PLATFORM_LINUX
18//config: help
19//config: Allow insmod and modprobe take module options from command line.
20//config:
21//config:config FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED
22//config: bool "Skip loading of already loaded modules"
23//config: default y
24//config: depends on MODPROBE_SMALL
25//config: help
26//config: Check if the module is already loaded.
27 13
14//applet:IF_LSMOD( IF_MODPROBE_SMALL(APPLET(lsmod, BB_DIR_SBIN, BB_SUID_DROP)))
28//applet:IF_MODPROBE(IF_MODPROBE_SMALL(APPLET(modprobe, BB_DIR_SBIN, BB_SUID_DROP))) 15//applet:IF_MODPROBE(IF_MODPROBE_SMALL(APPLET(modprobe, BB_DIR_SBIN, BB_SUID_DROP)))
16// APPLET_ODDNAME:name main location suid_type help
29//applet:IF_DEPMOD(IF_MODPROBE_SMALL(APPLET_ODDNAME(depmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, depmod))) 17//applet:IF_DEPMOD(IF_MODPROBE_SMALL(APPLET_ODDNAME(depmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, depmod)))
30//applet:IF_INSMOD(IF_MODPROBE_SMALL(APPLET_ODDNAME(insmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, insmod))) 18//applet:IF_INSMOD(IF_MODPROBE_SMALL(APPLET_ODDNAME(insmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, insmod)))
31//applet:IF_LSMOD(IF_MODPROBE_SMALL(APPLET_ODDNAME(lsmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, lsmod))) 19//applet:IF_RMMOD( IF_MODPROBE_SMALL(APPLET_ODDNAME(rmmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, rmmod)))
32//applet:IF_RMMOD(IF_MODPROBE_SMALL(APPLET_ODDNAME(rmmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, rmmod)))
33 20
34//kbuild:lib-$(CONFIG_MODPROBE_SMALL) += modprobe-small.o 21//kbuild:lib-$(CONFIG_MODPROBE_SMALL) += modprobe-small.o
35 22
@@ -59,6 +46,38 @@
59 46
60#define DEPFILE_BB CONFIG_DEFAULT_DEPMOD_FILE".bb" 47#define DEPFILE_BB CONFIG_DEFAULT_DEPMOD_FILE".bb"
61 48
49//usage:#if ENABLE_MODPROBE_SMALL
50
51//usage:#define lsmod_trivial_usage
52//usage: ""
53//usage:#define lsmod_full_usage "\n\n"
54//usage: "List loaded kernel modules"
55
56//usage:#endif
57
58#if ENABLE_LSMOD
59int lsmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
60int lsmod_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
61{
62 xprint_and_close_file(xfopen_for_read("/proc/modules"));
63 return EXIT_SUCCESS;
64}
65#endif
66
67/* Num of applets that use modprobe_main() entry point. */
68/* lsmod is not here. */
69#define MOD_APPLET_CNT (ENABLE_MODPROBE + ENABLE_DEPMOD + ENABLE_INSMOD + ENABLE_RMMOD)
70
71/* Do not bother if MODPROBE_SMALL=y but no applets selected. */
72/* The rest of the file is in this if block. */
73#if MOD_APPLET_CNT > 0
74
75#define ONLY_APPLET (MOD_APPLET_CNT == 1)
76#define is_modprobe (ENABLE_MODPROBE && (ONLY_APPLET || applet_name[0] == 'm'))
77#define is_depmod (ENABLE_DEPMOD && (ONLY_APPLET || applet_name[0] == 'd'))
78#define is_insmod (ENABLE_INSMOD && (ONLY_APPLET || applet_name[0] == 'i'))
79#define is_rmmod (ENABLE_RMMOD && (ONLY_APPLET || applet_name[0] == 'r'))
80
62enum { 81enum {
63 OPT_q = (1 << 0), /* be quiet */ 82 OPT_q = (1 << 0), /* be quiet */
64 OPT_r = (1 << 1), /* module removal instead of loading */ 83 OPT_r = (1 << 1), /* module removal instead of loading */
@@ -361,6 +380,8 @@ static FAST_FUNC int fileAction(const char *pathname,
361{ 380{
362 int cur; 381 int cur;
363 const char *fname; 382 const char *fname;
383 bool is_remove = (ENABLE_RMMOD && ONLY_APPLET)
384 || ((ENABLE_RMMOD || ENABLE_MODPROBE) && (option_mask32 & OPT_r));
364 385
365 pathname += 2; /* skip "./" */ 386 pathname += 2; /* skip "./" */
366 fname = bb_get_last_path_component_nostrip(pathname); 387 fname = bb_get_last_path_component_nostrip(pathname);
@@ -385,7 +406,7 @@ static FAST_FUNC int fileAction(const char *pathname,
385 if (parse_module(&modinfo[cur], pathname) != 0) 406 if (parse_module(&modinfo[cur], pathname) != 0)
386 return TRUE; /* failed to open/read it, no point in trying loading */ 407 return TRUE; /* failed to open/read it, no point in trying loading */
387 408
388 if (!(option_mask32 & OPT_r)) { 409 if (!is_remove) {
389 if (load_module(pathname, module_load_options) == 0) { 410 if (load_module(pathname, module_load_options) == 0) {
390 /* Load was successful, there is nothing else to do. 411 /* Load was successful, there is nothing else to do.
391 * This can happen ONLY for "top-level" module load, 412 * This can happen ONLY for "top-level" module load,
@@ -656,7 +677,7 @@ static int rmmod(const char *filename)
656 * NB: also called by depmod with bogus name "/", 677 * NB: also called by depmod with bogus name "/",
657 * just in order to force modprobe.dep.bb creation. 678 * just in order to force modprobe.dep.bb creation.
658*/ 679*/
659#if !ENABLE_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE 680#if !ENABLE_FEATURE_CMDLINE_MODULE_OPTIONS
660#define process_module(a,b) process_module(a) 681#define process_module(a,b) process_module(a)
661#define cmdline_options "" 682#define cmdline_options ""
662#endif 683#endif
@@ -666,7 +687,8 @@ static int process_module(char *name, const char *cmdline_options)
666 module_info **infovec; 687 module_info **infovec;
667 module_info *info; 688 module_info *info;
668 int infoidx; 689 int infoidx;
669 int is_remove = (option_mask32 & OPT_r) != 0; 690 bool is_remove = (ENABLE_RMMOD && ONLY_APPLET)
691 || ((ENABLE_RMMOD || ENABLE_MODPROBE) && (option_mask32 & OPT_r));
670 int exitcode = EXIT_SUCCESS; 692 int exitcode = EXIT_SUCCESS;
671 693
672 dbg1_error_msg("process_module('%s','%s')", name, cmdline_options); 694 dbg1_error_msg("process_module('%s','%s')", name, cmdline_options);
@@ -675,9 +697,8 @@ static int process_module(char *name, const char *cmdline_options)
675 697
676 dbg1_error_msg("already_loaded:%d is_remove:%d", already_loaded(name), is_remove); 698 dbg1_error_msg("already_loaded:%d is_remove:%d", already_loaded(name), is_remove);
677 699
678 if (applet_name[0] == 'r') { 700 if (is_rmmod) {
679 /* rmmod. 701 /* Does not remove dependencies, no need to scan, just remove.
680 * Does not remove dependencies, no need to scan, just remove.
681 * (compat note: this allows and strips .ko suffix) 702 * (compat note: this allows and strips .ko suffix)
682 */ 703 */
683 rmmod(name); 704 rmmod(name);
@@ -701,7 +722,7 @@ static int process_module(char *name, const char *cmdline_options)
701 options = xmalloc_open_read_close(opt_filename, NULL); 722 options = xmalloc_open_read_close(opt_filename, NULL);
702 if (options) 723 if (options)
703 replace(options, '\n', ' '); 724 replace(options, '\n', ' ');
704#if ENABLE_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE 725#if ENABLE_FEATURE_CMDLINE_MODULE_OPTIONS
705 if (cmdline_options) { 726 if (cmdline_options) {
706 /* NB: cmdline_options always have one leading ' ' 727 /* NB: cmdline_options always have one leading ' '
707 * (see main()), we remove it here */ 728 * (see main()), we remove it here */
@@ -743,7 +764,7 @@ static int process_module(char *name, const char *cmdline_options)
743 764
744 if (!infovec) { 765 if (!infovec) {
745 /* both dirscan and find_alias found nothing */ 766 /* both dirscan and find_alias found nothing */
746 if (!is_remove && applet_name[0] != 'd') /* it wasn't rmmod or depmod */ 767 if (!is_remove && !is_depmod) /* it wasn't rmmod or depmod */
747 bb_error_msg("module '%s' not found", name); 768 bb_error_msg("module '%s' not found", name);
748//TODO: _and_die()? or should we continue (un)loading modules listed on cmdline? 769//TODO: _and_die()? or should we continue (un)loading modules listed on cmdline?
749 goto ret; 770 goto ret;
@@ -875,79 +896,48 @@ The following options are useful for people managing distributions:
875//usage:#define depmod_trivial_usage NOUSAGE_STR 896//usage:#define depmod_trivial_usage NOUSAGE_STR
876//usage:#define depmod_full_usage "" 897//usage:#define depmod_full_usage ""
877 898
878//usage:#define lsmod_trivial_usage
879//usage: ""
880//usage:#define lsmod_full_usage "\n\n"
881//usage: "List the currently loaded kernel modules"
882
883//usage:#define insmod_trivial_usage 899//usage:#define insmod_trivial_usage
884//usage: IF_FEATURE_2_4_MODULES("[OPTIONS] MODULE ") 900//usage: "FILE" IF_FEATURE_CMDLINE_MODULE_OPTIONS(" [SYMBOL=VALUE]...")
885//usage: IF_NOT_FEATURE_2_4_MODULES("FILE ")
886//usage: "[SYMBOL=VALUE]..."
887//usage:#define insmod_full_usage "\n\n" 901//usage:#define insmod_full_usage "\n\n"
888//usage: "Load kernel module" 902//usage: "Load kernel module"
889//usage: IF_FEATURE_2_4_MODULES( "\n"
890//usage: "\n -f Force module to load into the wrong kernel version"
891//usage: "\n -k Make module autoclean-able"
892//usage: "\n -v Verbose"
893//usage: "\n -q Quiet"
894//usage: "\n -L Lock: prevent simultaneous loads"
895//usage: IF_FEATURE_INSMOD_LOAD_MAP(
896//usage: "\n -m Output load map to stdout"
897//usage: )
898//usage: "\n -x Don't export externs"
899//usage: )
900 903
901//usage:#define rmmod_trivial_usage 904//usage:#define rmmod_trivial_usage
902//usage: "[-wfa] [MODULE]..." 905//usage: "MODULE..."
903//usage:#define rmmod_full_usage "\n\n" 906//usage:#define rmmod_full_usage "\n\n"
904//usage: "Unload kernel modules\n" 907//usage: "Unload kernel modules"
905//usage: "\n -w Wait until the module is no longer used"
906//usage: "\n -f Force unload"
907//usage: "\n -a Remove all unused modules (recursively)"
908//usage:
909//usage:#define rmmod_example_usage
910//usage: "$ rmmod tulip\n"
911 908
912//usage:#define modprobe_trivial_usage 909//usage:#define modprobe_trivial_usage
913//usage: "[-qfwrsv] MODULE [SYMBOL=VALUE]..." 910//usage: "[-rq] MODULE" IF_FEATURE_CMDLINE_MODULE_OPTIONS(" [SYMBOL=VALUE]...")
914//usage:#define modprobe_full_usage "\n\n" 911//usage:#define modprobe_full_usage "\n\n"
915//usage: " -r Remove MODULE (stacks) or do autoclean" 912//usage: " -r Remove MODULE"
916//usage: "\n -q Quiet" 913//usage: "\n -q Quiet"
917//usage: "\n -v Verbose"
918//usage: "\n -f Force"
919//usage: "\n -w Wait for unload"
920//usage: "\n -s Report via syslog instead of stderr"
921 914
922//usage:#endif 915//usage:#endif
923 916
924int modprobe_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 917int modprobe_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
925int modprobe_main(int argc UNUSED_PARAM, char **argv) 918int modprobe_main(int argc UNUSED_PARAM, char **argv)
926{ 919{
920#if ENABLE_MODPROBE || ENABLE_INSMOD || ENABLE_RMMOD
927 int exitcode; 921 int exitcode;
922#endif
928 struct utsname uts; 923 struct utsname uts;
929 char applet0 = applet_name[0]; 924 IF_FEATURE_CMDLINE_MODULE_OPTIONS(char *options = NULL;)
930 IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(char *options;)
931
932 /* are we lsmod? -> just dump /proc/modules */
933 if (ENABLE_LSMOD && 'l' == applet0) {
934 xprint_and_close_file(xfopen_for_read("/proc/modules"));
935 return EXIT_SUCCESS;
936 }
937 925
938 INIT_G(); 926 INIT_G();
939 927
940 /* Prevent ugly corner cases with no modules at all */ 928 /* Prevent ugly corner cases with no modules at all */
941 modinfo = xzalloc(sizeof(modinfo[0])); 929 modinfo = xzalloc(sizeof(modinfo[0]));
942 930
943 if (!ENABLE_INSMOD || 'i' != applet0) { /* not insmod */ 931 if ((MOD_APPLET_CNT == 2 && ENABLE_DEPMOD && ENABLE_MODPROBE)
932 || is_depmod || is_modprobe
933 ) {
944 /* Goto modules directory */ 934 /* Goto modules directory */
945 xchdir(CONFIG_DEFAULT_MODULES_DIR); 935 xchdir(CONFIG_DEFAULT_MODULES_DIR);
936 uname(&uts); /* never fails */
946 } 937 }
947 uname(&uts); /* never fails */
948 938
949 /* depmod? */ 939 /* depmod? */
950 if (ENABLE_DEPMOD && 'd' == applet0) { 940 if (is_depmod) {
951 /* Supported: 941 /* Supported:
952 * -n: print result to stdout 942 * -n: print result to stdout
953 * -a: process all modules (default) 943 * -a: process all modules (default)
@@ -978,28 +968,28 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
978 return !wrote_dep_bb_ok; 968 return !wrote_dep_bb_ok;
979 } 969 }
980 970
981 /* insmod, modprobe, rmmod require at least one argument */ 971#if ENABLE_MODPROBE || ENABLE_INSMOD || ENABLE_RMMOD
972 /* modprobe, insmod, rmmod require at least one argument */
982 opt_complementary = "-1"; 973 opt_complementary = "-1";
983 /* only -q (quiet) and -r (rmmod), 974 /* only -q (quiet) and -r (rmmod),
984 * the rest are accepted and ignored (compat) */ 975 * the rest are accepted and ignored (compat) */
985 getopt32(argv, "qrfsvwb"); 976 getopt32(argv, "qrfsvwb");
986 argv += optind; 977 argv += optind;
987 978
988 /* are we rmmod? -> simulate modprobe -r */ 979 if (is_modprobe) {
989 if (ENABLE_RMMOD && 'r' == applet0) {
990 option_mask32 |= OPT_r;
991 }
992
993 if (!ENABLE_INSMOD || 'i' != applet0) { /* not insmod */
994 /* Goto $VERSION directory */ 980 /* Goto $VERSION directory */
995 xchdir(uts.release); 981 xchdir(uts.release);
996 } 982 }
997 983
998#if ENABLE_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE 984 /* are we rmmod? -> simulate modprobe -r, but don't bother the flag if
985 * there're no other applets here */
986 if (is_rmmod) {
987 if (!ONLY_APPLET)
988 option_mask32 |= OPT_r;
989 } else if (!ENABLE_MODPROBE || !(option_mask32 & OPT_r)) {
990# if ENABLE_FEATURE_CMDLINE_MODULE_OPTIONS
999 /* If not rmmod/-r, parse possible module options given on command line. 991 /* If not rmmod/-r, parse possible module options given on command line.
1000 * insmod/modprobe takes one module name, the rest are parameters. */ 992 * insmod/modprobe takes one module name, the rest are parameters. */
1001 options = NULL;
1002 if (!(option_mask32 & OPT_r)) {
1003 char **arg = argv; 993 char **arg = argv;
1004 while (*++arg) { 994 while (*++arg) {
1005 /* Enclose options in quotes */ 995 /* Enclose options in quotes */
@@ -1008,13 +998,12 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
1008 free(s); 998 free(s);
1009 *arg = NULL; 999 *arg = NULL;
1010 } 1000 }
1011 } 1001# else
1012#else
1013 if (!(option_mask32 & OPT_r))
1014 argv[1] = NULL; 1002 argv[1] = NULL;
1015#endif 1003# endif
1004 }
1016 1005
1017 if (ENABLE_INSMOD && 'i' == applet0) { /* insmod */ 1006 if (is_insmod) {
1018 size_t len; 1007 size_t len;
1019 void *map; 1008 void *map;
1020 1009
@@ -1023,8 +1012,7 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
1023 if (!map) 1012 if (!map)
1024 bb_perror_msg_and_die("can't read '%s'", *argv); 1013 bb_perror_msg_and_die("can't read '%s'", *argv);
1025 if (init_module(map, len, 1014 if (init_module(map, len,
1026 IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(options ? options : "") 1015 (IF_FEATURE_CMDLINE_MODULE_OPTIONS(options ? options : ) "")
1027 IF_NOT_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE("")
1028 ) != 0 1016 ) != 0
1029 ) { 1017 ) {
1030 bb_error_msg_and_die("can't insert '%s': %s", 1018 bb_error_msg_and_die("can't insert '%s': %s",
@@ -1034,7 +1022,7 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
1034 } 1022 }
1035 1023
1036 /* Try to load modprobe.dep.bb */ 1024 /* Try to load modprobe.dep.bb */
1037 if (!ENABLE_RMMOD || 'r' != applet0) { /* not rmmod */ 1025 if (!is_rmmod) {
1038 load_dep_bb(); 1026 load_dep_bb();
1039 } 1027 }
1040 1028
@@ -1046,7 +1034,10 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
1046 } while (*++argv); 1034 } while (*++argv);
1047 1035
1048 if (ENABLE_FEATURE_CLEAN_UP) { 1036 if (ENABLE_FEATURE_CLEAN_UP) {
1049 IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(free(options);) 1037 IF_FEATURE_CMDLINE_MODULE_OPTIONS(free(options);)
1050 } 1038 }
1051 return exitcode; 1039 return exitcode;
1040#endif /* MODPROBE || INSMOD || RMMOD */
1052} 1041}
1042
1043#endif /* MOD_APPLET_CNT > 0 */
diff --git a/modutils/modprobe.c b/modutils/modprobe.c
index 09e3de6c3..a6224fa63 100644
--- a/modutils/modprobe.c
+++ b/modutils/modprobe.c
@@ -19,7 +19,6 @@
19//config: bool "Blacklist support" 19//config: bool "Blacklist support"
20//config: default y 20//config: default y
21//config: depends on MODPROBE && !MODPROBE_SMALL 21//config: depends on MODPROBE && !MODPROBE_SMALL
22//config: select PLATFORM_LINUX
23//config: help 22//config: help
24//config: Say 'y' here to enable support for the 'blacklist' command in 23//config: Say 'y' here to enable support for the 'blacklist' command in
25//config: modprobe.conf. This prevents the alias resolver to resolve 24//config: modprobe.conf. This prevents the alias resolver to resolve
@@ -113,7 +112,7 @@
113//usage: 112//usage:
114//usage:#define modprobe_trivial_usage 113//usage:#define modprobe_trivial_usage
115//usage: "[-alrqvsD" IF_FEATURE_MODPROBE_BLACKLIST("b") "]" 114//usage: "[-alrqvsD" IF_FEATURE_MODPROBE_BLACKLIST("b") "]"
116//usage: " MODULE [SYMBOL=VALUE]..." 115//usage: " MODULE" IF_FEATURE_CMDLINE_MODULE_OPTIONS(" [SYMBOL=VALUE]...")
117//usage:#define modprobe_full_usage "\n\n" 116//usage:#define modprobe_full_usage "\n\n"
118//usage: " -a Load multiple MODULEs" 117//usage: " -a Load multiple MODULEs"
119//usage: "\n -l List (MODULE is a pattern)" 118//usage: "\n -l List (MODULE is a pattern)"
@@ -175,7 +174,9 @@ static const char modprobe_longopts[] ALIGN1 =
175 174
176struct globals { 175struct globals {
177 llist_t *probes; /* MEs of module(s) requested on cmdline */ 176 llist_t *probes; /* MEs of module(s) requested on cmdline */
177#if ENABLE_FEATURE_CMDLINE_MODULE_OPTIONS
178 char *cmdline_mopts; /* module options from cmdline */ 178 char *cmdline_mopts; /* module options from cmdline */
179#endif
179 int num_unresolved_deps; 180 int num_unresolved_deps;
180 /* bool. "Did we have 'symbol:FOO' requested on cmdline?" */ 181 /* bool. "Did we have 'symbol:FOO' requested on cmdline?" */
181 smallint need_symbols; 182 smallint need_symbols;
@@ -459,8 +460,10 @@ static int do_modprobe(struct module_entry *m)
459 options = m2->options; 460 options = m2->options;
460 m2->options = NULL; 461 m2->options = NULL;
461 options = parse_and_add_kcmdline_module_options(options, m2->modname); 462 options = parse_and_add_kcmdline_module_options(options, m2->modname);
463#if ENABLE_FEATURE_CMDLINE_MODULE_OPTIONS
462 if (m == m2) 464 if (m == m2)
463 options = gather_options_str(options, G.cmdline_mopts); 465 options = gather_options_str(options, G.cmdline_mopts);
466#endif
464 467
465 if (option_mask32 & OPT_SHOW_DEPS) { 468 if (option_mask32 & OPT_SHOW_DEPS) {
466 printf(options ? "insmod %s/%s/%s %s\n" 469 printf(options ? "insmod %s/%s/%s %s\n"
@@ -627,7 +630,9 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
627 /* First argument is module name, rest are parameters */ 630 /* First argument is module name, rest are parameters */
628 DBG("probing just module %s", *argv); 631 DBG("probing just module %s", *argv);
629 add_probe(argv[0]); 632 add_probe(argv[0]);
633#if ENABLE_FEATURE_CMDLINE_MODULE_OPTIONS
630 G.cmdline_mopts = parse_cmdline_module_options(argv, /*quote_spaces:*/ 1); 634 G.cmdline_mopts = parse_cmdline_module_options(argv, /*quote_spaces:*/ 1);
635#endif
631 } 636 }
632 637
633 /* Happens if all requested modules are already loaded */ 638 /* Happens if all requested modules are already loaded */
diff --git a/modutils/modutils.c b/modutils/modutils.c
index 4204f06fe..dae623ee4 100644
--- a/modutils/modutils.c
+++ b/modutils/modutils.c
@@ -120,6 +120,7 @@ char* FAST_FUNC filename2modname(const char *filename, char *modname)
120 return modname; 120 return modname;
121} 121}
122 122
123#if ENABLE_FEATURE_CMDLINE_MODULE_OPTIONS
123char* FAST_FUNC parse_cmdline_module_options(char **argv, int quote_spaces) 124char* FAST_FUNC parse_cmdline_module_options(char **argv, int quote_spaces)
124{ 125{
125 char *options; 126 char *options;
@@ -155,6 +156,7 @@ char* FAST_FUNC parse_cmdline_module_options(char **argv, int quote_spaces)
155 /* if (optlen != 0) options[optlen-1] = '\0'; */ 156 /* if (optlen != 0) options[optlen-1] = '\0'; */
156 return options; 157 return options;
157} 158}
159#endif
158 160
159#if ENABLE_FEATURE_INSMOD_TRY_MMAP 161#if ENABLE_FEATURE_INSMOD_TRY_MMAP
160void* FAST_FUNC try_to_mmap_module(const char *filename, size_t *image_size_p) 162void* FAST_FUNC try_to_mmap_module(const char *filename, size_t *image_size_p)
diff --git a/modutils/modutils.h b/modutils/modutils.h
index 2cbd1448a..76ce242ba 100644
--- a/modutils/modutils.h
+++ b/modutils/modutils.h
@@ -51,7 +51,11 @@ void replace(char *s, char what, char with) FAST_FUNC;
51char *replace_underscores(char *s) FAST_FUNC; 51char *replace_underscores(char *s) FAST_FUNC;
52int string_to_llist(char *string, llist_t **llist, const char *delim) FAST_FUNC; 52int string_to_llist(char *string, llist_t **llist, const char *delim) FAST_FUNC;
53char *filename2modname(const char *filename, char *modname) FAST_FUNC; 53char *filename2modname(const char *filename, char *modname) FAST_FUNC;
54#if ENABLE_FEATURE_CMDLINE_MODULE_OPTIONS
54char *parse_cmdline_module_options(char **argv, int quote_spaces) FAST_FUNC; 55char *parse_cmdline_module_options(char **argv, int quote_spaces) FAST_FUNC;
56#else
57# define parse_cmdline_module_options(argv, quote_spaces) ""
58#endif
55 59
56/* insmod for 2.4 and modprobe's options (insmod 2.6 has no options at all): */ 60/* insmod for 2.4 and modprobe's options (insmod 2.6 has no options at all): */
57#define INSMOD_OPTS \ 61#define INSMOD_OPTS \
diff --git a/networking/ftpd.c b/networking/ftpd.c
index bcd60a2ad..439608ce6 100644
--- a/networking/ftpd.c
+++ b/networking/ftpd.c
@@ -15,7 +15,7 @@
15//config: bool "ftpd" 15//config: bool "ftpd"
16//config: default y 16//config: default y
17//config: help 17//config: help
18//config: simple FTP daemon. You have to run it via inetd. 18//config: Simple FTP daemon. You have to run it via inetd.
19//config: 19//config:
20//config:config FEATURE_FTPD_WRITE 20//config:config FEATURE_FTPD_WRITE
21//config: bool "Enable upload commands" 21//config: bool "Enable upload commands"
@@ -47,20 +47,26 @@
47//kbuild:lib-$(CONFIG_FTPD) += ftpd.o 47//kbuild:lib-$(CONFIG_FTPD) += ftpd.o
48 48
49//usage:#define ftpd_trivial_usage 49//usage:#define ftpd_trivial_usage
50//usage: "[-wvS] [-t N] [-T N] [DIR]" 50//usage: "[-wvS]"IF_FEATURE_FTPD_AUTHENTICATION(" [-a USER]")" [-t N] [-T N] [DIR]"
51//usage:#define ftpd_full_usage "\n\n" 51//usage:#define ftpd_full_usage "\n\n"
52//usage: "Anonymous FTP server\n" 52//usage: IF_NOT_FEATURE_FTPD_AUTHENTICATION(
53//usage: "\n" 53//usage: "Anonymous FTP server. Accesses by clients occur under ftpd's UID.\n"
54//usage: "ftpd should be used as an inetd service.\n" 54//usage: )
55//usage: "ftpd's line for inetd.conf:\n" 55//usage: IF_FEATURE_FTPD_AUTHENTICATION(
56//usage: "FTP server. "
57//usage: )
58//usage: "Chroots to DIR, if this fails (run by non-root), cds to it.\n"
59//usage: "Should be used as inetd service, inetd.conf line:\n"
56//usage: " 21 stream tcp nowait root ftpd ftpd /files/to/serve\n" 60//usage: " 21 stream tcp nowait root ftpd ftpd /files/to/serve\n"
57//usage: "It also can be ran from tcpsvd:\n" 61//usage: "Can be run from tcpsvd:\n"
58//usage: " tcpsvd -vE 0.0.0.0 21 ftpd /files/to/serve\n" 62//usage: " tcpsvd -vE 0.0.0.0 21 ftpd /files/to/serve\n"
59//usage: "\n -w Allow upload" 63//usage: "\n -w Allow upload"
64//usage: IF_FEATURE_FTPD_AUTHENTICATION(
65//usage: "\n -a USER Enable 'anonymous' login and map it to USER"
66//usage: )
60//usage: "\n -v Log errors to stderr. -vv: verbose log" 67//usage: "\n -v Log errors to stderr. -vv: verbose log"
61//usage: "\n -S Log errors to syslog. -SS: verbose log" 68//usage: "\n -S Log errors to syslog. -SS: verbose log"
62//usage: "\n -t,-T Idle and absolute timeouts" 69//usage: "\n -t,-T N Idle and absolute timeout"
63//usage: "\n DIR Change root to this directory"
64 70
65#include "libbb.h" 71#include "libbb.h"
66#include "common_bufsiz.h" 72#include "common_bufsiz.h"
@@ -695,7 +701,7 @@ popen_ls(const char *opt)
695 dup(STDOUT_FILENO); /* copy will become STDIN_FILENO */ 701 dup(STDOUT_FILENO); /* copy will become STDIN_FILENO */
696#if BB_MMU 702#if BB_MMU
697 /* memset(&G, 0, sizeof(G)); - ls_main does it */ 703 /* memset(&G, 0, sizeof(G)); - ls_main does it */
698 exit(ls_main(ARRAY_SIZE(argv) - 1, (char**) argv)); 704 exit(ls_main(/*argc_unused*/ 0, (char**) argv));
699#else 705#else
700 cur_fd = xopen(".", O_RDONLY | O_DIRECTORY); 706 cur_fd = xopen(".", O_RDONLY | O_DIRECTORY);
701 /* On NOMMU, we want to execute a child - copy of ourself 707 /* On NOMMU, we want to execute a child - copy of ourself
@@ -1146,14 +1152,11 @@ enum {
1146}; 1152};
1147 1153
1148int ftpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 1154int ftpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1149#if !BB_MMU
1150int ftpd_main(int argc, char **argv)
1151#else
1152int ftpd_main(int argc UNUSED_PARAM, char **argv) 1155int ftpd_main(int argc UNUSED_PARAM, char **argv)
1153#endif
1154{ 1156{
1155#if ENABLE_FEATURE_FTPD_AUTHENTICATION 1157#if ENABLE_FEATURE_FTPD_AUTHENTICATION
1156 struct passwd *pw = NULL; 1158 struct passwd *pw = NULL;
1159 char *anon_opt = NULL;
1157#endif 1160#endif
1158 unsigned abs_timeout; 1161 unsigned abs_timeout;
1159 unsigned verbose_S; 1162 unsigned verbose_S;
@@ -1166,16 +1169,21 @@ int ftpd_main(int argc UNUSED_PARAM, char **argv)
1166 G.timeout = 2 * 60; 1169 G.timeout = 2 * 60;
1167 opt_complementary = "vv:SS"; 1170 opt_complementary = "vv:SS";
1168#if BB_MMU 1171#if BB_MMU
1169 opts = getopt32(argv, "vS" IF_FEATURE_FTPD_WRITE("w") "t:+T:+", &G.timeout, &abs_timeout, &G.verbose, &verbose_S); 1172 opts = getopt32(argv, "vS"
1173 IF_FEATURE_FTPD_WRITE("w") "t:+T:+" IF_FEATURE_FTPD_AUTHENTICATION("a:"),
1174 &G.timeout, &abs_timeout, IF_FEATURE_FTPD_AUTHENTICATION(&anon_opt,)
1175 &G.verbose, &verbose_S);
1170#else 1176#else
1171 opts = getopt32(argv, "l1AvS" IF_FEATURE_FTPD_WRITE("w") "t:+T:+", &G.timeout, &abs_timeout, &G.verbose, &verbose_S); 1177 opts = getopt32(argv, "l1AvS"
1178 IF_FEATURE_FTPD_WRITE("w") "t:+T:+" IF_FEATURE_FTPD_AUTHENTICATION("a:"),
1179 &G.timeout, &abs_timeout, IF_FEATURE_FTPD_AUTHENTICATION(&anon_opt,)
1180 &G.verbose, &verbose_S);
1172 if (opts & (OPT_l|OPT_1)) { 1181 if (opts & (OPT_l|OPT_1)) {
1173 /* Our secret backdoor to ls */ 1182 /* Our secret backdoor to ls */
1174/* TODO: pass --group-directories-first? would be nice, but ls doesn't do that yet */
1175 if (fchdir(3) != 0) 1183 if (fchdir(3) != 0)
1176 _exit(127); 1184 _exit(127);
1177 /* memset(&G, 0, sizeof(G)); - ls_main does it */ 1185 /* memset(&G, 0, sizeof(G)); - ls_main does it */
1178 return ls_main(argc, argv); 1186 return ls_main(/*argc_unused*/ 0, argv);
1179 } 1187 }
1180#endif 1188#endif
1181 if (G.verbose < verbose_S) 1189 if (G.verbose < verbose_S)
@@ -1234,7 +1242,12 @@ int ftpd_main(int argc UNUSED_PARAM, char **argv)
1234#if ENABLE_FEATURE_FTPD_AUTHENTICATION 1242#if ENABLE_FEATURE_FTPD_AUTHENTICATION
1235 while (1) { 1243 while (1) {
1236 uint32_t cmdval = cmdio_get_cmd_and_arg(); 1244 uint32_t cmdval = cmdio_get_cmd_and_arg();
1237 if (cmdval == const_USER) { 1245 if (cmdval == const_USER) {
1246 if (anon_opt && strcmp(G.ftp_arg, "anonymous") == 0) {
1247 pw = getpwnam(anon_opt);
1248 if (pw)
1249 break; /* does not even ask for password */
1250 }
1238 pw = getpwnam(G.ftp_arg); 1251 pw = getpwnam(G.ftp_arg);
1239 cmdio_write_raw(STR(FTP_GIVEPWORD)" Please specify password\r\n"); 1252 cmdio_write_raw(STR(FTP_GIVEPWORD)" Please specify password\r\n");
1240 } else if (cmdval == const_PASS) { 1253 } else if (cmdval == const_PASS) {
diff --git a/networking/ftpgetput.c b/networking/ftpgetput.c
index 0b06f85b4..3eadd752d 100644
--- a/networking/ftpgetput.c
+++ b/networking/ftpgetput.c
@@ -28,8 +28,6 @@
28//config: bool "Enable long options in ftpget/ftpput" 28//config: bool "Enable long options in ftpget/ftpput"
29//config: default y 29//config: default y
30//config: depends on LONG_OPTS && (FTPGET || FTPPUT) 30//config: depends on LONG_OPTS && (FTPGET || FTPPUT)
31//config: help
32//config: Support long options for the ftpget/ftpput applet.
33 31
34//applet:IF_FTPGET(APPLET_ODDNAME(ftpget, ftpgetput, BB_DIR_USR_BIN, BB_SUID_DROP, ftpget)) 32//applet:IF_FTPGET(APPLET_ODDNAME(ftpget, ftpgetput, BB_DIR_USR_BIN, BB_SUID_DROP, ftpget))
35//applet:IF_FTPPUT(APPLET_ODDNAME(ftpput, ftpgetput, BB_DIR_USR_BIN, BB_SUID_DROP, ftpput)) 33//applet:IF_FTPPUT(APPLET_ODDNAME(ftpput, ftpgetput, BB_DIR_USR_BIN, BB_SUID_DROP, ftpput))
diff --git a/networking/hostname.c b/networking/hostname.c
index 04a051ede..9f2418422 100644
--- a/networking/hostname.c
+++ b/networking/hostname.c
@@ -22,6 +22,7 @@
22//config: help 22//config: help
23//config: Alias to "hostname -d". 23//config: Alias to "hostname -d".
24 24
25// APPLET_ODDNAME:name main location suid_type help
25//applet:IF_DNSDOMAINNAME(APPLET_ODDNAME(dnsdomainname, hostname, BB_DIR_BIN, BB_SUID_DROP, dnsdomainname)) 26//applet:IF_DNSDOMAINNAME(APPLET_ODDNAME(dnsdomainname, hostname, BB_DIR_BIN, BB_SUID_DROP, dnsdomainname))
26//applet:IF_HOSTNAME(APPLET(hostname, BB_DIR_BIN, BB_SUID_DROP)) 27//applet:IF_HOSTNAME(APPLET(hostname, BB_DIR_BIN, BB_SUID_DROP))
27 28
diff --git a/networking/httpd.c b/networking/httpd.c
index d301d598d..e072f23c7 100644
--- a/networking/httpd.c
+++ b/networking/httpd.c
@@ -102,7 +102,7 @@
102//config: bool "httpd" 102//config: bool "httpd"
103//config: default y 103//config: default y
104//config: help 104//config: help
105//config: Serve web pages via an HTTP server. 105//config: HTTP server.
106//config: 106//config:
107//config:config FEATURE_HTTPD_RANGES 107//config:config FEATURE_HTTPD_RANGES
108//config: bool "Support 'Ranges:' header" 108//config: bool "Support 'Ranges:' header"
@@ -156,7 +156,7 @@
156//config: when specific URLs are requested. 156//config: when specific URLs are requested.
157//config: 157//config:
158//config:config FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR 158//config:config FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
159//config: bool "Support for running scripts through an interpreter" 159//config: bool "Support running scripts through an interpreter"
160//config: default y 160//config: default y
161//config: depends on FEATURE_HTTPD_CGI 161//config: depends on FEATURE_HTTPD_CGI
162//config: help 162//config: help
@@ -185,7 +185,7 @@
185//config: "&#60Hello&#32World&#62". 185//config: "&#60Hello&#32World&#62".
186//config: 186//config:
187//config:config FEATURE_HTTPD_ERROR_PAGES 187//config:config FEATURE_HTTPD_ERROR_PAGES
188//config: bool "Support for custom error pages" 188//config: bool "Support custom error pages"
189//config: default y 189//config: default y
190//config: depends on HTTPD 190//config: depends on HTTPD
191//config: help 191//config: help
@@ -198,7 +198,7 @@
198//config: message. 198//config: message.
199//config: 199//config:
200//config:config FEATURE_HTTPD_PROXY 200//config:config FEATURE_HTTPD_PROXY
201//config: bool "Support for reverse proxy" 201//config: bool "Support reverse proxy"
202//config: default y 202//config: default y
203//config: depends on HTTPD 203//config: depends on HTTPD
204//config: help 204//config: help
@@ -210,7 +210,7 @@
210//config: http://hostname[:port]/new/path/myfile. 210//config: http://hostname[:port]/new/path/myfile.
211//config: 211//config:
212//config:config FEATURE_HTTPD_GZIP 212//config:config FEATURE_HTTPD_GZIP
213//config: bool "Support for GZIP content encoding" 213//config: bool "Support GZIP content encoding"
214//config: default y 214//config: default y
215//config: depends on HTTPD 215//config: depends on HTTPD
216//config: help 216//config: help
@@ -460,11 +460,6 @@ struct globals {
460#define ip_a_d (G.ip_a_d ) 460#define ip_a_d (G.ip_a_d )
461#define g_realm (G.g_realm ) 461#define g_realm (G.g_realm )
462#define remoteuser (G.remoteuser ) 462#define remoteuser (G.remoteuser )
463#define referer (G.referer )
464#define user_agent (G.user_agent )
465#define host (G.host )
466#define http_accept (G.http_accept )
467#define http_accept_language (G.http_accept_language)
468#define file_size (G.file_size ) 463#define file_size (G.file_size )
469#if ENABLE_FEATURE_HTTPD_RANGES 464#if ENABLE_FEATURE_HTTPD_RANGES
470#define range_start (G.range_start ) 465#define range_start (G.range_start )
@@ -1152,7 +1147,7 @@ static void send_headers(int responseNum)
1152 "Last-Modified: %s\r\n" 1147 "Last-Modified: %s\r\n"
1153 "%s %"OFF_FMT"u\r\n", 1148 "%s %"OFF_FMT"u\r\n",
1154 date_str, 1149 date_str,
1155 content_gzip ? "Transfer-length:" : "Content-length:", 1150 content_gzip ? "Transfer-Length:" : "Content-Length:",
1156 file_size 1151 file_size
1157 ); 1152 );
1158 } 1153 }
@@ -1529,11 +1524,11 @@ static void send_cgi_and_exit(
1529#endif 1524#endif
1530 } 1525 }
1531 } 1526 }
1532 setenv1("HTTP_USER_AGENT", user_agent); 1527 setenv1("HTTP_USER_AGENT", G.user_agent);
1533 if (http_accept) 1528 if (G.http_accept)
1534 setenv1("HTTP_ACCEPT", http_accept); 1529 setenv1("HTTP_ACCEPT", G.http_accept);
1535 if (http_accept_language) 1530 if (G.http_accept_language)
1536 setenv1("HTTP_ACCEPT_LANGUAGE", http_accept_language); 1531 setenv1("HTTP_ACCEPT_LANGUAGE", G.http_accept_language);
1537 if (post_len) 1532 if (post_len)
1538 putenv(xasprintf("CONTENT_LENGTH=%d", post_len)); 1533 putenv(xasprintf("CONTENT_LENGTH=%d", post_len));
1539 if (cookie) 1534 if (cookie)
@@ -1546,9 +1541,9 @@ static void send_cgi_and_exit(
1546 putenv((char*)"AUTH_TYPE=Basic"); 1541 putenv((char*)"AUTH_TYPE=Basic");
1547 } 1542 }
1548#endif 1543#endif
1549 if (referer) 1544 if (G.referer)
1550 setenv1("HTTP_REFERER", referer); 1545 setenv1("HTTP_REFERER", G.referer);
1551 setenv1("HTTP_HOST", host); /* set to "" if NULL */ 1546 setenv1("HTTP_HOST", G.host); /* set to "" if NULL */
1552 /* setenv1("SERVER_NAME", safe_gethostname()); - don't do this, 1547 /* setenv1("SERVER_NAME", safe_gethostname()); - don't do this,
1553 * just run "env SERVER_NAME=xyz httpd ..." instead */ 1548 * just run "env SERVER_NAME=xyz httpd ..." instead */
1554 1549
@@ -2269,10 +2264,8 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
2269#if ENABLE_FEATURE_HTTPD_PROXY 2264#if ENABLE_FEATURE_HTTPD_PROXY
2270 /* We need 2 more bytes for yet another "\r\n" - 2265 /* We need 2 more bytes for yet another "\r\n" -
2271 * see near fdprintf(proxy_fd...) further below */ 2266 * see near fdprintf(proxy_fd...) further below */
2272 if (proxy_entry && (header_ptr - header_buf) < IOBUF_SIZE - 2) { 2267 if (proxy_entry && (header_ptr - header_buf) < IOBUF_SIZE - 4) {
2273 int len = strlen(iobuf); 2268 int len = strnlen(iobuf, IOBUF_SIZE - (header_ptr - header_buf) - 4);
2274 if (len > IOBUF_SIZE - (header_ptr - header_buf) - 4)
2275 len = IOBUF_SIZE - (header_ptr - header_buf) - 4;
2276 memcpy(header_ptr, iobuf, len); 2269 memcpy(header_ptr, iobuf, len);
2277 header_ptr += len; 2270 header_ptr += len;
2278 header_ptr[0] = '\r'; 2271 header_ptr[0] = '\r';
@@ -2283,14 +2276,14 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
2283 2276
2284#if ENABLE_FEATURE_HTTPD_CGI || ENABLE_FEATURE_HTTPD_PROXY 2277#if ENABLE_FEATURE_HTTPD_CGI || ENABLE_FEATURE_HTTPD_PROXY
2285 /* Try and do our best to parse more lines */ 2278 /* Try and do our best to parse more lines */
2286 if ((STRNCASECMP(iobuf, "Content-length:") == 0)) { 2279 if ((STRNCASECMP(iobuf, "Content-Length:") == 0)) {
2287 /* extra read only for POST */ 2280 /* extra read only for POST */
2288 if (prequest != request_GET 2281 if (prequest != request_GET
2289# if ENABLE_FEATURE_HTTPD_CGI 2282# if ENABLE_FEATURE_HTTPD_CGI
2290 && prequest != request_HEAD 2283 && prequest != request_HEAD
2291# endif 2284# endif
2292 ) { 2285 ) {
2293 tptr = skip_whitespace(iobuf + sizeof("Content-length:") - 1); 2286 tptr = skip_whitespace(iobuf + sizeof("Content-Length:") - 1);
2294 if (!tptr[0]) 2287 if (!tptr[0])
2295 send_headers_and_exit(HTTP_BAD_REQUEST); 2288 send_headers_and_exit(HTTP_BAD_REQUEST);
2296 /* not using strtoul: it ignores leading minus! */ 2289 /* not using strtoul: it ignores leading minus! */
@@ -2303,19 +2296,26 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
2303#endif 2296#endif
2304#if ENABLE_FEATURE_HTTPD_CGI 2297#if ENABLE_FEATURE_HTTPD_CGI
2305 else if (STRNCASECMP(iobuf, "Cookie:") == 0) { 2298 else if (STRNCASECMP(iobuf, "Cookie:") == 0) {
2306 cookie = xstrdup(skip_whitespace(iobuf + sizeof("Cookie:")-1)); 2299 if (!cookie) /* in case they send millions of these, do not OOM */
2300 cookie = xstrdup(skip_whitespace(iobuf + sizeof("Cookie:")-1));
2307 } else if (STRNCASECMP(iobuf, "Content-Type:") == 0) { 2301 } else if (STRNCASECMP(iobuf, "Content-Type:") == 0) {
2308 content_type = xstrdup(skip_whitespace(iobuf + sizeof("Content-Type:")-1)); 2302 if (!content_type)
2303 content_type = xstrdup(skip_whitespace(iobuf + sizeof("Content-Type:")-1));
2309 } else if (STRNCASECMP(iobuf, "Referer:") == 0) { 2304 } else if (STRNCASECMP(iobuf, "Referer:") == 0) {
2310 referer = xstrdup(skip_whitespace(iobuf + sizeof("Referer:")-1)); 2305 if (!G.referer)
2306 G.referer = xstrdup(skip_whitespace(iobuf + sizeof("Referer:")-1));
2311 } else if (STRNCASECMP(iobuf, "User-Agent:") == 0) { 2307 } else if (STRNCASECMP(iobuf, "User-Agent:") == 0) {
2312 user_agent = xstrdup(skip_whitespace(iobuf + sizeof("User-Agent:")-1)); 2308 if (!G.user_agent)
2309 G.user_agent = xstrdup(skip_whitespace(iobuf + sizeof("User-Agent:")-1));
2313 } else if (STRNCASECMP(iobuf, "Host:") == 0) { 2310 } else if (STRNCASECMP(iobuf, "Host:") == 0) {
2314 host = xstrdup(skip_whitespace(iobuf + sizeof("Host:")-1)); 2311 if (!G.host)
2312 G.host = xstrdup(skip_whitespace(iobuf + sizeof("Host:")-1));
2315 } else if (STRNCASECMP(iobuf, "Accept:") == 0) { 2313 } else if (STRNCASECMP(iobuf, "Accept:") == 0) {
2316 http_accept = xstrdup(skip_whitespace(iobuf + sizeof("Accept:")-1)); 2314 if (!G.http_accept)
2315 G.http_accept = xstrdup(skip_whitespace(iobuf + sizeof("Accept:")-1));
2317 } else if (STRNCASECMP(iobuf, "Accept-Language:") == 0) { 2316 } else if (STRNCASECMP(iobuf, "Accept-Language:") == 0) {
2318 http_accept_language = xstrdup(skip_whitespace(iobuf + sizeof("Accept-Language:")-1)); 2317 if (!G.http_accept_language)
2318 G.http_accept_language = xstrdup(skip_whitespace(iobuf + sizeof("Accept-Language:")-1));
2319 } 2319 }
2320#endif 2320#endif
2321#if ENABLE_FEATURE_HTTPD_BASIC_AUTH 2321#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
@@ -2396,12 +2396,12 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
2396 int proxy_fd; 2396 int proxy_fd;
2397 len_and_sockaddr *lsa; 2397 len_and_sockaddr *lsa;
2398 2398
2399 proxy_fd = socket(AF_INET, SOCK_STREAM, 0);
2400 if (proxy_fd < 0)
2401 send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR);
2402 lsa = host2sockaddr(proxy_entry->host_port, 80); 2399 lsa = host2sockaddr(proxy_entry->host_port, 80);
2403 if (lsa == NULL) 2400 if (lsa == NULL)
2404 send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); 2401 send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR);
2402 proxy_fd = socket(lsa->u.sa.sa_family, SOCK_STREAM, 0);
2403 if (proxy_fd < 0)
2404 send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR);
2405 if (connect(proxy_fd, &lsa->u.sa, lsa->len) < 0) 2405 if (connect(proxy_fd, &lsa->u.sa, lsa->len) < 0)
2406 send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); 2406 send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR);
2407 fdprintf(proxy_fd, "%s %s%s%s%s HTTP/%c.%c\r\n", 2407 fdprintf(proxy_fd, "%s %s%s%s%s HTTP/%c.%c\r\n",
diff --git a/networking/ifupdown.c b/networking/ifupdown.c
index 1806a6ccc..a76fe1021 100644
--- a/networking/ifupdown.c
+++ b/networking/ifupdown.c
@@ -66,14 +66,14 @@
66//config: utilities, or enable these applets in Busybox. 66//config: utilities, or enable these applets in Busybox.
67//config: 67//config:
68//config:config FEATURE_IFUPDOWN_IPV4 68//config:config FEATURE_IFUPDOWN_IPV4
69//config: bool "Support for IPv4" 69//config: bool "Support IPv4"
70//config: default y 70//config: default y
71//config: depends on IFUP || IFDOWN 71//config: depends on IFUP || IFDOWN
72//config: help 72//config: help
73//config: If you want ifup/ifdown to talk IPv4, leave this on. 73//config: If you want ifup/ifdown to talk IPv4, leave this on.
74//config: 74//config:
75//config:config FEATURE_IFUPDOWN_IPV6 75//config:config FEATURE_IFUPDOWN_IPV6
76//config: bool "Support for IPv6" 76//config: bool "Support IPv6"
77//config: default y 77//config: default y
78//config: depends on (IFUP || IFDOWN) && FEATURE_IPV6 78//config: depends on (IFUP || IFDOWN) && FEATURE_IPV6
79//config: help 79//config: help
@@ -81,7 +81,7 @@
81//config: 81//config:
82//UNUSED: 82//UNUSED:
83////////:config FEATURE_IFUPDOWN_IPX 83////////:config FEATURE_IFUPDOWN_IPX
84////////: bool "Support for IPX" 84////////: bool "Support IPX"
85////////: default y 85////////: default y
86////////: depends on IFUP || IFDOWN 86////////: depends on IFUP || IFDOWN
87////////: help 87////////: help
@@ -97,7 +97,7 @@
97//config: a weird network setup you don't need it. 97//config: a weird network setup you don't need it.
98//config: 98//config:
99//config:config FEATURE_IFUPDOWN_EXTERNAL_DHCP 99//config:config FEATURE_IFUPDOWN_EXTERNAL_DHCP
100//config: bool "Support for external dhcp clients" 100//config: bool "Support external DHCP clients"
101//config: default n 101//config: default n
102//config: depends on IFUP || IFDOWN 102//config: depends on IFUP || IFDOWN
103//config: help 103//config: help
@@ -106,7 +106,8 @@
106//config: Otherwise, if udhcpc applet is enabled, it is used. 106//config: Otherwise, if udhcpc applet is enabled, it is used.
107//config: Otherwise, ifup/ifdown will have no support for DHCP. 107//config: Otherwise, ifup/ifdown will have no support for DHCP.
108 108
109//applet:IF_IFUP(APPLET_ODDNAME(ifup, ifupdown, BB_DIR_SBIN, BB_SUID_DROP, ifup)) 109// APPLET_ODDNAME:name main location suid_type help
110//applet:IF_IFUP( APPLET_ODDNAME(ifup, ifupdown, BB_DIR_SBIN, BB_SUID_DROP, ifup))
110//applet:IF_IFDOWN(APPLET_ODDNAME(ifdown, ifupdown, BB_DIR_SBIN, BB_SUID_DROP, ifdown)) 111//applet:IF_IFDOWN(APPLET_ODDNAME(ifdown, ifupdown, BB_DIR_SBIN, BB_SUID_DROP, ifdown))
111 112
112//kbuild:lib-$(CONFIG_IFUP) += ifupdown.o 113//kbuild:lib-$(CONFIG_IFUP) += ifupdown.o
diff --git a/networking/inetd.c b/networking/inetd.c
index 4d0ab2e0d..01e659f13 100644
--- a/networking/inetd.c
+++ b/networking/inetd.c
@@ -213,9 +213,9 @@
213//usage: "Listen for network connections and launch programs\n" 213//usage: "Listen for network connections and launch programs\n"
214//usage: "\n -f Run in foreground" 214//usage: "\n -f Run in foreground"
215//usage: "\n -e Log to stderr" 215//usage: "\n -e Log to stderr"
216//usage: "\n -q N Socket listen queue (default: 128)" 216//usage: "\n -q N Socket listen queue (default 128)"
217//usage: "\n -R N Pause services after N connects/min" 217//usage: "\n -R N Pause services after N connects/min"
218//usage: "\n (default: 0 - disabled)" 218//usage: "\n (default 0 - disabled)"
219 219
220#include <syslog.h> 220#include <syslog.h>
221#include <sys/resource.h> /* setrlimit */ 221#include <sys/resource.h> /* setrlimit */
@@ -1677,7 +1677,7 @@ static uint32_t machtime(void)
1677 struct timeval tv; 1677 struct timeval tv;
1678 1678
1679 gettimeofday(&tv, NULL); 1679 gettimeofday(&tv, NULL);
1680 return htonl((uint32_t)(tv.tv_sec + 2208988800)); 1680 return htonl((uint32_t)(tv.tv_sec + 2208988800U));
1681} 1681}
1682/* ARGSUSED */ 1682/* ARGSUSED */
1683static void FAST_FUNC machtime_stream(int s, servtab_t *sep UNUSED_PARAM) 1683static void FAST_FUNC machtime_stream(int s, servtab_t *sep UNUSED_PARAM)
diff --git a/networking/ip.c b/networking/ip.c
index 939721e46..0f52b19dd 100644
--- a/networking/ip.c
+++ b/networking/ip.c
@@ -140,84 +140,106 @@
140//kbuild:lib-$(CONFIG_IPTUNNEL) += ip.o 140//kbuild:lib-$(CONFIG_IPTUNNEL) += ip.o
141//kbuild:lib-$(CONFIG_IPNEIGH) += ip.o 141//kbuild:lib-$(CONFIG_IPNEIGH) += ip.o
142 142
143/* would need to make the " | " optional depending on more than one selected: */
144//usage:#define ip_trivial_usage
145//usage: "[OPTIONS] {"
146//usage: IF_FEATURE_IP_ADDRESS("address | ")
147//usage: IF_FEATURE_IP_ROUTE("route | ")
148//usage: IF_FEATURE_IP_LINK("link | ")
149//usage: IF_FEATURE_IP_TUNNEL("tunnel | ")
150//usage: IF_FEATURE_IP_NEIGH("neigh | ")
151//usage: IF_FEATURE_IP_RULE("rule")
152//usage: "} {COMMAND}"
153//usage:#define ip_full_usage "\n\n"
154//usage: "ip [OPTIONS] OBJECT {COMMAND}\n"
155//usage: "where OBJECT := {"
156//usage: IF_FEATURE_IP_ADDRESS("address | ")
157//usage: IF_FEATURE_IP_ROUTE("route | ")
158//usage: IF_FEATURE_IP_LINK("link | ")
159//usage: IF_FEATURE_IP_TUNNEL("tunnel | ")
160//usage: IF_FEATURE_IP_NEIGH("neigh | ")
161//usage: IF_FEATURE_IP_RULE("rule")
162//usage: "}\n"
163//usage: "OPTIONS := { -f[amily] { inet | inet6 | link } | -o[neline] }"
164//usage:
165//usage:#define ipaddr_trivial_usage 143//usage:#define ipaddr_trivial_usage
166//usage: "{ {add|del} IFADDR dev STRING | {show|flush}\n" 144//usage: "add|del IFADDR dev IFACE | show|flush [dev IFACE] [to PREFIX]"
167//usage: " [dev STRING] [to PREFIX] }"
168//usage:#define ipaddr_full_usage "\n\n" 145//usage:#define ipaddr_full_usage "\n\n"
169//usage: "ipaddr {add|change|replace|delete} IFADDR dev STRING\n" 146//usage: "ipaddr add|change|replace|delete IFADDR dev IFACE\n"
170//usage: "ipaddr {show|flush} [dev STRING] [scope SCOPE-ID]\n" 147//usage: "ipaddr show|flush [dev IFACE] [scope SCOPE-ID]\n"
171//usage: " [to PREFIX] [label PATTERN]\n" 148//usage: " [to PREFIX] [label PATTERN]\n"
172//usage: " IFADDR := PREFIX | ADDR peer PREFIX\n" 149//usage: " IFADDR := PREFIX | ADDR peer PREFIX\n"
173//usage: " [broadcast ADDR] [anycast ADDR]\n" 150//usage: " [broadcast ADDR] [anycast ADDR]\n"
174//usage: " [label STRING] [scope SCOPE-ID]\n" 151//usage: " [label STRING] [scope SCOPE-ID]\n"
175//usage: " SCOPE-ID := [host | link | global | NUMBER]" 152//usage: " SCOPE-ID := [host|link|global|NUMBER]"
176//usage: 153//usage:
177//usage:#define iplink_trivial_usage 154//usage:#define iplink_trivial_usage
178//usage: "{ set DEVICE { up | down | arp { on | off } | show [DEVICE] }" 155//usage: "set IFACE [up|down] [arp on|off] | show [IFACE]"
179//usage:#define iplink_full_usage "\n\n" 156//usage:#define iplink_full_usage "\n\n"
180//usage: "iplink set DEVICE { up | down | arp | multicast { on | off } |\n" 157//usage: "iplink set IFACE [up|down]\n"
181//usage: " dynamic { on | off } |\n" 158//usage: " [arp on|off]\n"
182//usage: " mtu MTU }\n" 159//usage: " [dynamic on|off]\n"
183//usage: "iplink show [DEVICE]" 160//usage: " [multicast on|off]\n"
161//usage: " [mtu MTU]\n"
162//usage: "iplink show [IFACE]"
184//usage: 163//usage:
185//usage:#define iproute_trivial_usage 164//usage:#define iproute_trivial_usage
186//usage: "{ list | flush | add | del | change | append |\n" 165//usage: "list|flush|add|del|change|append|replace|test ROUTE"
187//usage: " replace | test } ROUTE"
188//usage:#define iproute_full_usage "\n\n" 166//usage:#define iproute_full_usage "\n\n"
189//usage: "iproute { list | flush } SELECTOR\n" 167//usage: "iproute list|flush SELECTOR\n"
190//usage: "iproute get ADDRESS [from ADDRESS iif STRING]\n" 168//usage: "iproute get ADDRESS [from ADDRESS iif STRING]\n"
191//usage: " [oif STRING] [tos TOS]\n" 169//usage: " [oif STRING] [tos TOS]\n"
192//usage: "iproute { add | del | change | append | replace | test } ROUTE\n" 170//usage: "iproute add|del|change|append|replace|test ROUTE\n"
193//usage: " SELECTOR := [root PREFIX] [match PREFIX] [proto RTPROTO]\n" 171//usage: " SELECTOR := [root PREFIX] [match PREFIX] [proto RTPROTO]\n"
194//usage: " ROUTE := [TYPE] PREFIX [tos TOS] [proto RTPROTO] [metric METRIC]" 172//usage: " ROUTE := [TYPE] PREFIX [tos TOS] [proto RTPROTO] [metric METRIC]"
195//usage: 173//usage:
196//usage:#define iprule_trivial_usage 174//usage:#define iprule_trivial_usage
197//usage: "{[list | add | del] RULE}" 175//usage: "[list] | add|del SELECTOR ACTION"
198//usage:#define iprule_full_usage "\n\n" 176//usage:#define iprule_full_usage "\n\n"
199//usage: "iprule [list | add | del] SELECTOR ACTION\n"
200//usage: " SELECTOR := [from PREFIX] [to PREFIX] [tos TOS] [fwmark FWMARK]\n" 177//usage: " SELECTOR := [from PREFIX] [to PREFIX] [tos TOS] [fwmark FWMARK]\n"
201//usage: " [dev STRING] [pref NUMBER]\n" 178//usage: " [dev IFACE] [pref NUMBER]\n"
202//usage: " ACTION := [table TABLE_ID] [nat ADDRESS]\n" 179//usage: " ACTION := [table TABLE_ID] [nat ADDRESS]\n"
203//usage: " [prohibit | reject | unreachable]\n" 180//usage: " [prohibit|reject|unreachable]\n"
204//usage: " [realms [SRCREALM/]DSTREALM]\n" 181//usage: " [realms [SRCREALM/]DSTREALM]\n"
205//usage: " TABLE_ID := [local | main | default | NUMBER]" 182//usage: " TABLE_ID := [local|main|default|NUMBER]"
206//usage: 183//usage:
207//usage:#define iptunnel_trivial_usage 184//usage:#define iptunnel_trivial_usage
208//usage: "{ add | change | del | show } [NAME]\n" 185//usage: "add|change|del|show [NAME]\n"
209//usage: " [mode { ipip | gre | sit }]\n" 186//usage: " [mode ipip|gre|sit]\n"
210//usage: " [remote ADDR] [local ADDR] [ttl TTL]" 187//usage: " [remote ADDR] [local ADDR] [ttl TTL]"
211//usage:#define iptunnel_full_usage "\n\n" 188//usage:#define iptunnel_full_usage "\n\n"
212//usage: "iptunnel { add | change | del | show } [NAME]\n" 189//usage: "iptunnel add|change|del|show [NAME]\n"
213//usage: " [mode { ipip | gre | sit }] [remote ADDR] [local ADDR]\n" 190//usage: " [mode ipip|gre|sit] [remote ADDR] [local ADDR]\n"
214//usage: " [[i|o]seq] [[i|o]key KEY] [[i|o]csum]\n" 191//usage: " [[i|o]seq] [[i|o]key KEY] [[i|o]csum]\n"
215//usage: " [ttl TTL] [tos TOS] [[no]pmtudisc] [dev PHYS_DEV]" 192//usage: " [ttl TTL] [tos TOS] [[no]pmtudisc] [dev PHYS_DEV]"
216//usage: 193//usage:
217//usage:#define ipneigh_trivial_usage 194//usage:#define ipneigh_trivial_usage
218//usage: "{ show | flush} [ to PREFIX ] [ dev DEV ] [ nud STATE ]" 195//usage: "show|flush [to PREFIX] [dev DEV] [nud STATE]"
219//usage:#define ipneigh_full_usage "\n\n" 196//usage:#define ipneigh_full_usage ""
220//usage: "ipneigh { show | flush} [ to PREFIX ] [ dev DEV ] [ nud STATE ]" 197//usage:
198//usage:#if ENABLE_FEATURE_IP_ADDRESS || ENABLE_FEATURE_IP_ROUTE
199//usage:# define IP_BAR_LINK "|"
200//usage:#else
201//usage:# define IP_BAR_LINK ""
202//usage:#endif
203//usage:#if ENABLE_FEATURE_IP_ADDRESS || ENABLE_FEATURE_IP_ROUTE || ENABLE_FEATURE_IP_LINK
204//usage:# define IP_BAR_TUNNEL "|"
205//usage:#else
206//usage:# define IP_BAR_TUNNEL ""
207//usage:#endif
208//usage:#if ENABLE_FEATURE_IP_ADDRESS || ENABLE_FEATURE_IP_ROUTE || ENABLE_FEATURE_IP_LINK || ENABLE_FEATURE_IP_TUNNEL
209//usage:# define IP_BAR_NEIGH "|"
210//usage:#else
211//usage:# define IP_BAR_NEIGH ""
212//usage:#endif
213//usage:#if ENABLE_FEATURE_IP_ADDRESS || ENABLE_FEATURE_IP_ROUTE || ENABLE_FEATURE_IP_LINK || ENABLE_FEATURE_IP_TUNNEL || ENABLE_FEATURE_IP_NEIGH
214//usage:# define IP_BAR_RULE "|"
215//usage:#else
216//usage:# define IP_BAR_RULE ""
217//usage:#endif
218//usage:
219//usage:#define ip_trivial_usage
220//usage: "[OPTIONS] "
221//usage: IF_FEATURE_IP_ADDRESS("address")
222//usage: IF_FEATURE_IP_ROUTE( IF_FEATURE_IP_ADDRESS("|")"route")
223//usage: IF_FEATURE_IP_LINK( IP_BAR_LINK "link")
224//usage: IF_FEATURE_IP_TUNNEL( IP_BAR_TUNNEL"tunnel")
225//usage: IF_FEATURE_IP_NEIGH( IP_BAR_NEIGH "neigh")
226//usage: IF_FEATURE_IP_RULE( IP_BAR_RULE "rule")
227//usage: " [COMMAND]"
228//usage:#define ip_full_usage "\n\n"
229//usage: "OPTIONS := -f[amily] inet|inet6|link | -o[neline]\n"
230//usage: "COMMAND :="
231//usage: IF_FEATURE_IP_ADDRESS("\n"
232//usage: "ip addr "ipaddr_trivial_usage)
233//usage: IF_FEATURE_IP_ROUTE("\n"
234//usage: "ip route "iproute_trivial_usage)
235//usage: IF_FEATURE_IP_LINK("\n"
236//usage: "ip link "iplink_trivial_usage)
237//usage: IF_FEATURE_IP_TUNNEL("\n"
238//usage: "ip tunnel "iptunnel_trivial_usage)
239//usage: IF_FEATURE_IP_NEIGH("\n"
240//usage: "ip neigh "ipneigh_trivial_usage)
241//usage: IF_FEATURE_IP_RULE("\n"
242//usage: "ip rule "iprule_trivial_usage)
221 243
222#include "libbb.h" 244#include "libbb.h"
223 245
diff --git a/networking/ipcalc.c b/networking/ipcalc.c
index 21219424f..9359f9016 100644
--- a/networking/ipcalc.c
+++ b/networking/ipcalc.c
@@ -18,6 +18,11 @@
18//config: ipcalc takes an IP address and netmask and calculates the 18//config: ipcalc takes an IP address and netmask and calculates the
19//config: resulting broadcast, network, and host range. 19//config: resulting broadcast, network, and host range.
20//config: 20//config:
21//config:config FEATURE_IPCALC_LONG_OPTIONS
22//config: bool "Enable long options"
23//config: default y
24//config: depends on IPCALC && LONG_OPTS
25//config:
21//config:config FEATURE_IPCALC_FANCY 26//config:config FEATURE_IPCALC_FANCY
22//config: bool "Fancy IPCALC, more options, adds 1 kbyte" 27//config: bool "Fancy IPCALC, more options, adds 1 kbyte"
23//config: default y 28//config: default y
@@ -25,13 +30,6 @@
25//config: help 30//config: help
26//config: Adds the options hostname, prefix and silent to the output of 31//config: Adds the options hostname, prefix and silent to the output of
27//config: "ipcalc". 32//config: "ipcalc".
28//config:
29//config:config FEATURE_IPCALC_LONG_OPTIONS
30//config: bool "Enable long options"
31//config: default y
32//config: depends on IPCALC && LONG_OPTS
33//config: help
34//config: Support long options for the ipcalc applet.
35 33
36//applet:IF_IPCALC(APPLET(ipcalc, BB_DIR_BIN, BB_SUID_DROP)) 34//applet:IF_IPCALC(APPLET(ipcalc, BB_DIR_BIN, BB_SUID_DROP))
37 35
diff --git a/networking/netstat.c b/networking/netstat.c
index 90da6cdb8..68e0c1a04 100644
--- a/networking/netstat.c
+++ b/networking/netstat.c
@@ -21,7 +21,7 @@
21//config: netstat prints information about the Linux networking subsystem. 21//config: netstat prints information about the Linux networking subsystem.
22//config: 22//config:
23//config:config FEATURE_NETSTAT_WIDE 23//config:config FEATURE_NETSTAT_WIDE
24//config: bool "Enable wide netstat output" 24//config: bool "Enable wide output"
25//config: default y 25//config: default y
26//config: depends on NETSTAT 26//config: depends on NETSTAT
27//config: help 27//config: help
diff --git a/networking/ntpd.c b/networking/ntpd.c
index bfd5705fc..5cc71ca7a 100644
--- a/networking/ntpd.c
+++ b/networking/ntpd.c
@@ -757,7 +757,7 @@ reset_peer_stats(peer_t *p, double offset)
757 * and clear reachable bits, but this proved to be too agressive: 757 * and clear reachable bits, but this proved to be too agressive:
758 * after step (tested with suspending laptop for ~30 secs), 758 * after step (tested with suspending laptop for ~30 secs),
759 * this caused all previous data to be considered invalid, 759 * this caused all previous data to be considered invalid,
760 * making us needing to collect full ~8 datapoins per peer 760 * making us needing to collect full ~8 datapoints per peer
761 * after step in order to start trusting them. 761 * after step in order to start trusting them.
762 * In turn, this was making poll interval decrease even after 762 * In turn, this was making poll interval decrease even after
763 * step was done. (Poll interval decreases already before step 763 * step was done. (Poll interval decreases already before step
@@ -800,6 +800,8 @@ resolve_peer_hostname(peer_t *p)
800 free(p->p_dotted); 800 free(p->p_dotted);
801 p->p_lsa = lsa; 801 p->p_lsa = lsa;
802 p->p_dotted = xmalloc_sockaddr2dotted_noport(&lsa->u.sa); 802 p->p_dotted = xmalloc_sockaddr2dotted_noport(&lsa->u.sa);
803 VERB1 if (strcmp(p->p_hostname, p->p_dotted) != 0)
804 bb_error_msg("'%s' is %s", p->p_hostname, p->p_dotted);
803 } else { 805 } else {
804 /* error message is emitted by host2sockaddr() */ 806 /* error message is emitted by host2sockaddr() */
805 set_next(p, HOSTNAME_INTERVAL); 807 set_next(p, HOSTNAME_INTERVAL);
diff --git a/networking/ping.c b/networking/ping.c
index d0ef7ba62..ef31e000b 100644
--- a/networking/ping.c
+++ b/networking/ping.c
@@ -94,10 +94,10 @@
94//usage: "\n -4,-6 Force IP or IPv6 name resolution" 94//usage: "\n -4,-6 Force IP or IPv6 name resolution"
95//usage: ) 95//usage: )
96//usage: "\n -c CNT Send only CNT pings" 96//usage: "\n -c CNT Send only CNT pings"
97//usage: "\n -s SIZE Send SIZE data bytes in packets (default:56)" 97//usage: "\n -s SIZE Send SIZE data bytes in packets (default 56)"
98//usage: "\n -t TTL Set TTL" 98//usage: "\n -t TTL Set TTL"
99//usage: "\n -I IFACE/IP Use interface or IP address as source" 99//usage: "\n -I IFACE/IP Source interface or IP address"
100//usage: "\n -W SEC Seconds to wait for the first response (default:10)" 100//usage: "\n -W SEC Seconds to wait for the first response (default 10)"
101//usage: "\n (after all -c CNT packets are sent)" 101//usage: "\n (after all -c CNT packets are sent)"
102//usage: "\n -w SEC Seconds until ping exits (default:infinite)" 102//usage: "\n -w SEC Seconds until ping exits (default:infinite)"
103//usage: "\n (can exit earlier with -c CNT)" 103//usage: "\n (can exit earlier with -c CNT)"
@@ -110,8 +110,8 @@
110//usage:# define ping6_full_usage "\n\n" 110//usage:# define ping6_full_usage "\n\n"
111//usage: "Send ICMP ECHO_REQUEST packets to network hosts\n" 111//usage: "Send ICMP ECHO_REQUEST packets to network hosts\n"
112//usage: "\n -c CNT Send only CNT pings" 112//usage: "\n -c CNT Send only CNT pings"
113//usage: "\n -s SIZE Send SIZE data bytes in packets (default:56)" 113//usage: "\n -s SIZE Send SIZE data bytes in packets (default 56)"
114//usage: "\n -I IFACE/IP Use interface or IP address as source" 114//usage: "\n -I IFACE/IP Source interface or IP address"
115//usage: "\n -q Quiet, only display output at start" 115//usage: "\n -q Quiet, only display output at start"
116//usage: "\n and when finished" 116//usage: "\n and when finished"
117//usage: "\n -p Pattern to use for payload" 117//usage: "\n -p Pattern to use for payload"
diff --git a/networking/ssl_client.c b/networking/ssl_client.c
new file mode 100644
index 000000000..cfeae1587
--- /dev/null
+++ b/networking/ssl_client.c
@@ -0,0 +1,55 @@
1/*
2 * Copyright (C) 2017 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6//config:config SSL_CLIENT
7//config: bool "ssl_client"
8//config: default y
9//config: select TLS
10//config: help
11//config: This tool pipes data to/from a socket, TLS-encrypting it.
12
13//applet:IF_SSL_CLIENT(APPLET(ssl_client, BB_DIR_USR_BIN, BB_SUID_DROP))
14
15//kbuild:lib-$(CONFIG_SSL_CLIENT) += ssl_client.o
16
17//usage:#define ssl_client_trivial_usage
18//usage: "-s FD [-r FD] [-n SNI]"
19//usage:#define ssl_client_full_usage ""
20
21#include "libbb.h"
22
23int ssl_client_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
24int ssl_client_main(int argc UNUSED_PARAM, char **argv)
25{
26 tls_state_t *tls;
27 const char *sni = NULL;
28 int opt;
29
30 // INIT_G();
31
32 tls = new_tls_state();
33 opt = getopt32(argv, "s:#r:#n:", &tls->ofd, &tls->ifd, &sni);
34 if (!(opt & 2)) {
35 /* -r N defaults to -s N */
36 tls->ifd = tls->ofd;
37 }
38
39 if (!(opt & 3)) {
40 if (!argv[1])
41 bb_show_usage();
42 /* Undocumented debug feature: without -s and -r, takes HOST arg and connects to it */
43 //
44 // Talk to kernel.org:
45 // printf "GET / HTTP/1.1\r\nHost: kernel.org\r\n\r\n" | ./busybox ssl_client kernel.org
46 if (!sni)
47 sni = argv[1];
48 tls->ifd = tls->ofd = create_and_connect_stream_or_die(argv[1], 443);
49 }
50
51 tls_handshake(tls, sni);
52 tls_run_copy_loop(tls);
53
54 return EXIT_SUCCESS;
55}
diff --git a/networking/tc.c b/networking/tc.c
index 25875aa3e..23abf636c 100644
--- a/networking/tc.c
+++ b/networking/tc.c
@@ -27,22 +27,22 @@
27/* //usage: "[OPTIONS] OBJECT CMD [dev STRING]" */ 27/* //usage: "[OPTIONS] OBJECT CMD [dev STRING]" */
28//usage: "OBJECT CMD [dev STRING]" 28//usage: "OBJECT CMD [dev STRING]"
29//usage:#define tc_full_usage "\n\n" 29//usage:#define tc_full_usage "\n\n"
30//usage: "OBJECT: {qdisc|class|filter}\n" 30//usage: "OBJECT: qdisc|class|filter\n"
31//usage: "CMD: {add|del|change|replace|show}\n" 31//usage: "CMD: add|del|change|replace|show\n"
32//usage: "\n" 32//usage: "\n"
33//usage: "qdisc [ handle QHANDLE ] [ root |"IF_FEATURE_TC_INGRESS(" ingress |")" parent CLASSID ]\n" 33//usage: "qdisc [handle QHANDLE] [root|"IF_FEATURE_TC_INGRESS("ingress|")"parent CLASSID]\n"
34/* //usage: "[ estimator INTERVAL TIME_CONSTANT ]\n" */ 34/* //usage: "[estimator INTERVAL TIME_CONSTANT]\n" */
35//usage: " [ [ QDISC_KIND ] [ help | OPTIONS ] ]\n" 35//usage: " [[QDISC_KIND] [help|OPTIONS]]\n"
36//usage: " QDISC_KIND := { [p|b]fifo | tbf | prio | cbq | red | etc. }\n" 36//usage: " QDISC_KIND := [p|b]fifo|tbf|prio|cbq|red|etc.\n"
37//usage: "qdisc show [ dev STRING ]"IF_FEATURE_TC_INGRESS(" [ingress]")"\n" 37//usage: "qdisc show [dev STRING]"IF_FEATURE_TC_INGRESS(" [ingress]")"\n"
38//usage: "class [ classid CLASSID ] [ root | parent CLASSID ]\n" 38//usage: "class [classid CLASSID] [root|parent CLASSID]\n"
39//usage: " [ [ QDISC_KIND ] [ help | OPTIONS ] ]\n" 39//usage: " [[QDISC_KIND] [help|OPTIONS] ]\n"
40//usage: "class show [ dev STRING ] [ root | parent CLASSID ]\n" 40//usage: "class show [ dev STRING ] [root|parent CLASSID]\n"
41//usage: "filter [ pref PRIO ] [ protocol PROTO ]\n" 41//usage: "filter [pref PRIO] [protocol PROTO]\n"
42/* //usage: "\t[ estimator INTERVAL TIME_CONSTANT ]\n" */ 42/* //usage: "\t[estimator INTERVAL TIME_CONSTANT]\n" */
43//usage: " [ root | classid CLASSID ] [ handle FILTERID ]\n" 43//usage: " [root|classid CLASSID] [handle FILTERID]\n"
44//usage: " [ [ FILTER_TYPE ] [ help | OPTIONS ] ]\n" 44//usage: " [[FILTER_TYPE] [help|OPTIONS]]\n"
45//usage: "filter show [ dev STRING ] [ root | parent CLASSID ]" 45//usage: "filter show [dev STRING] [root|parent CLASSID]"
46 46
47#include "libbb.h" 47#include "libbb.h"
48#include "common_bufsiz.h" 48#include "common_bufsiz.h"
diff --git a/networking/telnet.c b/networking/telnet.c
index f520fe1dd..a70f74762 100644
--- a/networking/telnet.c
+++ b/networking/telnet.c
@@ -45,6 +45,11 @@
45//config: remote host you are connecting to. This is useful when you need to 45//config: remote host you are connecting to. This is useful when you need to
46//config: log into a machine without telling the username (autologin). This 46//config: log into a machine without telling the username (autologin). This
47//config: option enables `-a' and `-l USER' arguments. 47//config: option enables `-a' and `-l USER' arguments.
48//config:
49//config:config FEATURE_TELNET_WIDTH
50//config: bool "Enable window size autodetection"
51//config: default y
52//config: depends on TELNET
48 53
49//applet:IF_TELNET(APPLET(telnet, BB_DIR_USR_BIN, BB_SUID_DROP)) 54//applet:IF_TELNET(APPLET(telnet, BB_DIR_USR_BIN, BB_SUID_DROP))
50 55
@@ -128,7 +133,7 @@ struct globals {
128#if ENABLE_FEATURE_TELNET_AUTOLOGIN 133#if ENABLE_FEATURE_TELNET_AUTOLOGIN
129 const char *autologin; 134 const char *autologin;
130#endif 135#endif
131#if ENABLE_FEATURE_AUTOWIDTH 136#if ENABLE_FEATURE_TELNET_WIDTH
132 unsigned win_width, win_height; 137 unsigned win_width, win_height;
133#endif 138#endif
134 /* same buffer used both for network and console read/write */ 139 /* same buffer used both for network and console read/write */
@@ -401,7 +406,7 @@ static void put_iac_subopt_autologin(void)
401} 406}
402#endif 407#endif
403 408
404#if ENABLE_FEATURE_AUTOWIDTH 409#if ENABLE_FEATURE_TELNET_WIDTH
405static void put_iac_naws(byte c, int x, int y) 410static void put_iac_naws(byte c, int x, int y)
406{ 411{
407 if (G.iaclen + 9 > IACBUFSIZE) 412 if (G.iaclen + 9 > IACBUFSIZE)
@@ -538,7 +543,7 @@ static void to_new_environ(void)
538} 543}
539#endif 544#endif
540 545
541#if ENABLE_FEATURE_AUTOWIDTH 546#if ENABLE_FEATURE_TELNET_WIDTH
542static void to_naws(void) 547static void to_naws(void)
543{ 548{
544 /* Tell server we will do NAWS */ 549 /* Tell server we will do NAWS */
@@ -561,7 +566,7 @@ static void telopt(byte c)
561 case TELOPT_NEW_ENVIRON: 566 case TELOPT_NEW_ENVIRON:
562 to_new_environ(); break; 567 to_new_environ(); break;
563#endif 568#endif
564#if ENABLE_FEATURE_AUTOWIDTH 569#if ENABLE_FEATURE_TELNET_WIDTH
565 case TELOPT_NAWS: 570 case TELOPT_NAWS:
566 to_naws(); 571 to_naws();
567 put_iac_naws(c, G.win_width, G.win_height); 572 put_iac_naws(c, G.win_width, G.win_height);
@@ -623,7 +628,7 @@ int telnet_main(int argc UNUSED_PARAM, char **argv)
623 628
624 INIT_G(); 629 INIT_G();
625 630
626#if ENABLE_FEATURE_AUTOWIDTH 631#if ENABLE_FEATURE_TELNET_WIDTH
627 get_terminal_width_height(0, &G.win_width, &G.win_height); 632 get_terminal_width_height(0, &G.win_width, &G.win_height);
628#endif 633#endif
629 634
diff --git a/networking/tftp.c b/networking/tftp.c
index ed8672025..189364f0c 100644
--- a/networking/tftp.c
+++ b/networking/tftp.c
@@ -69,11 +69,9 @@
69//config: "blksize" and "tsize" options. 69//config: "blksize" and "tsize" options.
70//config: 70//config:
71//config:config FEATURE_TFTP_PROGRESS_BAR 71//config:config FEATURE_TFTP_PROGRESS_BAR
72//config: bool "Enable tftp progress meter" 72//config: bool "Enable progress bar"
73//config: default y 73//config: default y
74//config: depends on TFTP && FEATURE_TFTP_BLOCKSIZE 74//config: depends on TFTP && FEATURE_TFTP_BLOCKSIZE
75//config: help
76//config: Show progress bar.
77//config: 75//config:
78//config:config TFTP_DEBUG 76//config:config TFTP_DEBUG
79//config: bool "Enable debug" 77//config: bool "Enable debug"
diff --git a/networking/tls.c b/networking/tls.c
new file mode 100644
index 000000000..30afd9ea9
--- /dev/null
+++ b/networking/tls.c
@@ -0,0 +1,1815 @@
1/*
2 * Copyright (C) 2017 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6//config:config TLS
7//config: bool #No description makes it a hidden option
8//config: default n
9
10//kbuild:lib-$(CONFIG_TLS) += tls.o
11//kbuild:lib-$(CONFIG_TLS) += tls_pstm.o
12//kbuild:lib-$(CONFIG_TLS) += tls_pstm_montgomery_reduce.o
13//kbuild:lib-$(CONFIG_TLS) += tls_pstm_mul_comba.o
14//kbuild:lib-$(CONFIG_TLS) += tls_pstm_sqr_comba.o
15//kbuild:lib-$(CONFIG_TLS) += tls_rsa.o
16//kbuild:lib-$(CONFIG_TLS) += tls_aes.o
17////kbuild:lib-$(CONFIG_TLS) += tls_aes_gcm.o
18
19#include "tls.h"
20
21//Tested against kernel.org:
22//TLS 1.2
23#define TLS_MAJ 3
24#define TLS_MIN 3
25//#define CIPHER_ID TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA // ok, recvs SERVER_KEY_EXCHANGE *** matrixssl uses this on my box
26//#define CIPHER_ID TLS_RSA_WITH_AES_256_CBC_SHA256 // ok, no SERVER_KEY_EXCHANGE
27//#define CIPHER_ID TLS_DH_anon_WITH_AES_256_CBC_SHA // SSL_ALERT_HANDSHAKE_FAILURE
28//^^^^^^^^^^^^^^^^^^^^^^^ (tested b/c this one doesn't req server certs... no luck, server refuses it)
29//#define CIPHER_ID TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 // SSL_ALERT_HANDSHAKE_FAILURE
30//#define CIPHER_ID TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 // SSL_ALERT_HANDSHAKE_FAILURE
31//#define CIPHER_ID TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 // ok, recvs SERVER_KEY_EXCHANGE
32//#define CIPHER_ID TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
33//#define CIPHER_ID TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
34//#define CIPHER_ID TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 // SSL_ALERT_HANDSHAKE_FAILURE
35//#define CIPHER_ID TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
36//#define CIPHER_ID TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 // SSL_ALERT_HANDSHAKE_FAILURE
37//#define CIPHER_ID TLS_RSA_WITH_AES_256_GCM_SHA384 // ok, no SERVER_KEY_EXCHANGE
38//#define CIPHER_ID TLS_RSA_WITH_AES_128_GCM_SHA256 // ok, no SERVER_KEY_EXCHANGE *** select this?
39
40// works against "openssl s_server -cipher NULL"
41// and against wolfssl-3.9.10-stable/examples/server/server.c:
42//#define CIPHER_ID TLS_RSA_WITH_NULL_SHA256 // for testing (does everything except encrypting)
43
44// works against wolfssl-3.9.10-stable/examples/server/server.c
45// works for kernel.org
46// does not work for cdn.kernel.org (e.g. downloading an actual tarball, not a web page)
47// getting alert 40 "handshake failure" at once
48// with GNU Wget 1.18, they agree on TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xC02F) cipher
49// fail: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES256-SHA256
50// fail: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES256-GCM-SHA384
51// fail: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES128-SHA256
52// ok: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES128-GCM-SHA256
53// ok: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES128-SHA
54// (TLS_RSA_WITH_AES_128_CBC_SHA - in TLS 1.2 it's mandated to be always supported)
55#define CIPHER_ID1 TLS_RSA_WITH_AES_256_CBC_SHA256 // no SERVER_KEY_EXCHANGE from peer
56// Works with "wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.9.5.tar.xz"
57#define CIPHER_ID2 TLS_RSA_WITH_AES_128_CBC_SHA
58
59
60#define TLS_DEBUG 0
61#define TLS_DEBUG_HASH 0
62#define TLS_DEBUG_DER 0
63#define TLS_DEBUG_FIXED_SECRETS 0
64#if 0
65# define dump_raw_out(...) dump_hex(__VA_ARGS__)
66#else
67# define dump_raw_out(...) ((void)0)
68#endif
69#if 0
70# define dump_raw_in(...) dump_hex(__VA_ARGS__)
71#else
72# define dump_raw_in(...) ((void)0)
73#endif
74
75#if TLS_DEBUG
76# define dbg(...) fprintf(stderr, __VA_ARGS__)
77#else
78# define dbg(...) ((void)0)
79#endif
80
81#if TLS_DEBUG_DER
82# define dbg_der(...) fprintf(stderr, __VA_ARGS__)
83#else
84# define dbg_der(...) ((void)0)
85#endif
86
87#define RECORD_TYPE_CHANGE_CIPHER_SPEC 20
88#define RECORD_TYPE_ALERT 21
89#define RECORD_TYPE_HANDSHAKE 22
90#define RECORD_TYPE_APPLICATION_DATA 23
91
92#define HANDSHAKE_HELLO_REQUEST 0
93#define HANDSHAKE_CLIENT_HELLO 1
94#define HANDSHAKE_SERVER_HELLO 2
95#define HANDSHAKE_HELLO_VERIFY_REQUEST 3
96#define HANDSHAKE_NEW_SESSION_TICKET 4
97#define HANDSHAKE_CERTIFICATE 11
98#define HANDSHAKE_SERVER_KEY_EXCHANGE 12
99#define HANDSHAKE_CERTIFICATE_REQUEST 13
100#define HANDSHAKE_SERVER_HELLO_DONE 14
101#define HANDSHAKE_CERTIFICATE_VERIFY 15
102#define HANDSHAKE_CLIENT_KEY_EXCHANGE 16
103#define HANDSHAKE_FINISHED 20
104
105#define SSL_NULL_WITH_NULL_NULL 0x0000
106#define SSL_RSA_WITH_NULL_MD5 0x0001
107#define SSL_RSA_WITH_NULL_SHA 0x0002
108#define SSL_RSA_WITH_RC4_128_MD5 0x0004
109#define SSL_RSA_WITH_RC4_128_SHA 0x0005
110#define SSL_RSA_WITH_3DES_EDE_CBC_SHA 0x000A /* 10 */
111#define TLS_RSA_WITH_AES_128_CBC_SHA 0x002F /* 47 */
112#define TLS_RSA_WITH_AES_256_CBC_SHA 0x0035 /* 53 */
113#define TLS_RSA_WITH_NULL_SHA256 0x003B /* 59 */
114
115#define TLS_EMPTY_RENEGOTIATION_INFO_SCSV 0x00FF
116
117#define TLS_RSA_WITH_IDEA_CBC_SHA 0x0007 /* 7 */
118#define SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x0016 /* 22 */
119#define SSL_DH_anon_WITH_RC4_128_MD5 0x0018 /* 24 */
120#define SSL_DH_anon_WITH_3DES_EDE_CBC_SHA 0x001B /* 27 */
121#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x0033 /* 51 */
122#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x0039 /* 57 */
123#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x0067 /* 103 */
124#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x006B /* 107 */
125#define TLS_DH_anon_WITH_AES_128_CBC_SHA 0x0034 /* 52 */
126#define TLS_DH_anon_WITH_AES_256_CBC_SHA 0x003A /* 58 */
127#define TLS_RSA_WITH_AES_128_CBC_SHA256 0x003C /* 60 */
128#define TLS_RSA_WITH_AES_256_CBC_SHA256 0x003D /* 61 */
129#define TLS_RSA_WITH_SEED_CBC_SHA 0x0096 /* 150 */
130#define TLS_PSK_WITH_AES_128_CBC_SHA 0x008C /* 140 */
131#define TLS_PSK_WITH_AES_128_CBC_SHA256 0x00AE /* 174 */
132#define TLS_PSK_WITH_AES_256_CBC_SHA384 0x00AF /* 175 */
133#define TLS_PSK_WITH_AES_256_CBC_SHA 0x008D /* 141 */
134#define TLS_DHE_PSK_WITH_AES_128_CBC_SHA 0x0090 /* 144 */
135#define TLS_DHE_PSK_WITH_AES_256_CBC_SHA 0x0091 /* 145 */
136#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004 /* 49156 */
137#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005 /* 49157 */
138#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009 /* 49161 */
139#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A /* 49162 */
140#define TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC012 /* 49170 */
141#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 /* 49171 */
142#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 /* 49172 */
143#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E /* 49166 */
144#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F /* 49167 */
145#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023 /* 49187 */
146#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024 /* 49188 */
147#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 0xC025 /* 49189 */
148#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 0xC026 /* 49190 */
149#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027 /* 49191 */
150#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028 /* 49192 */
151#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029 /* 49193 */
152#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A /* 49194 */
153
154/* RFC 5288 "AES Galois Counter Mode (GCM) Cipher Suites for TLS" */
155#define TLS_RSA_WITH_AES_128_GCM_SHA256 0x009C /* 156 */
156#define TLS_RSA_WITH_AES_256_GCM_SHA384 0x009D /* 157 */
157#define TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B /* 49195 */
158#define TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C /* 49196 */
159#define TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D /* 49197 */
160#define TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0xC02E /* 49198 */
161#define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F /* 49199 */
162#define TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030 /* 49200 */
163#define TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031 /* 49201 */
164#define TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032 /* 49202 */
165
166/* Might go to libbb.h */
167#define TLS_MAX_CRYPTBLOCK_SIZE 16
168#define TLS_MAX_OUTBUF (1 << 14)
169
170enum {
171 SHA_INSIZE = 64,
172 SHA1_OUTSIZE = 20,
173 SHA256_OUTSIZE = 32,
174
175 AES_BLOCKSIZE = 16,
176 AES128_KEYSIZE = 16,
177 AES256_KEYSIZE = 32,
178
179 RSA_PREMASTER_SIZE = 48,
180
181 RECHDR_LEN = 5,
182
183 /* 8 = 3+5. 3 extra bytes result in record data being 32-bit aligned */
184 OUTBUF_PFX = 8 + AES_BLOCKSIZE, /* header + IV */
185 OUTBUF_SFX = TLS_MAX_MAC_SIZE + TLS_MAX_CRYPTBLOCK_SIZE, /* MAC + padding */
186
187 // RFC 5246
188 // | 6.2.1. Fragmentation
189 // | The record layer fragments information blocks into TLSPlaintext
190 // | records carrying data in chunks of 2^14 bytes or less. Client
191 // | message boundaries are not preserved in the record layer (i.e.,
192 // | multiple client messages of the same ContentType MAY be coalesced
193 // | into a single TLSPlaintext record, or a single message MAY be
194 // | fragmented across several records)
195 // |...
196 // | length
197 // | The length (in bytes) of the following TLSPlaintext.fragment.
198 // | The length MUST NOT exceed 2^14.
199 // |...
200 // | 6.2.2. Record Compression and Decompression
201 // |...
202 // | Compression must be lossless and may not increase the content length
203 // | by more than 1024 bytes. If the decompression function encounters a
204 // | TLSCompressed.fragment that would decompress to a length in excess of
205 // | 2^14 bytes, it MUST report a fatal decompression failure error.
206 // |...
207 // | length
208 // | The length (in bytes) of the following TLSCompressed.fragment.
209 // | The length MUST NOT exceed 2^14 + 1024.
210 // |...
211 // | 6.2.3. Record Payload Protection
212 // | The encryption and MAC functions translate a TLSCompressed
213 // | structure into a TLSCiphertext. The decryption functions reverse
214 // | the process. The MAC of the record also includes a sequence
215 // | number so that missing, extra, or repeated messages are
216 // | detectable.
217 // |...
218 // | length
219 // | The length (in bytes) of the following TLSCiphertext.fragment.
220 // | The length MUST NOT exceed 2^14 + 2048.
221 MAX_INBUF = RECHDR_LEN + (1 << 14) + 2048,
222};
223
224struct record_hdr {
225 uint8_t type;
226 uint8_t proto_maj, proto_min;
227 uint8_t len16_hi, len16_lo;
228};
229
230struct tls_handshake_data {
231 /* In bbox, md5/sha1/sha256 ctx's are the same structure */
232 md5sha_ctx_t handshake_hash_ctx;
233
234 uint8_t client_and_server_rand32[2 * 32];
235 uint8_t master_secret[48];
236//TODO: store just the DER key here, parse/use/delete it when sending client key
237//this way it will stay key type agnostic here.
238 psRsaKey_t server_rsa_pub_key;
239
240 unsigned saved_client_hello_size;
241 uint8_t saved_client_hello[1];
242};
243
244
245static unsigned get24be(const uint8_t *p)
246{
247 return 0x100*(0x100*p[0] + p[1]) + p[2];
248}
249
250#if TLS_DEBUG
251static void dump_hex(const char *fmt, const void *vp, int len)
252{
253 char hexbuf[32 * 1024 + 4];
254 const uint8_t *p = vp;
255
256 bin2hex(hexbuf, (void*)p, len)[0] = '\0';
257 dbg(fmt, hexbuf);
258}
259
260static void dump_tls_record(const void *vp, int len)
261{
262 const uint8_t *p = vp;
263
264 while (len > 0) {
265 unsigned xhdr_len;
266 if (len < RECHDR_LEN) {
267 dump_hex("< |%s|\n", p, len);
268 return;
269 }
270 xhdr_len = 0x100*p[3] + p[4];
271 dbg("< hdr_type:%u ver:%u.%u len:%u", p[0], p[1], p[2], xhdr_len);
272 p += RECHDR_LEN;
273 len -= RECHDR_LEN;
274 if (len >= 4 && p[-RECHDR_LEN] == RECORD_TYPE_HANDSHAKE) {
275 unsigned len24 = get24be(p + 1);
276 dbg(" type:%u len24:%u", p[0], len24);
277 }
278 if (xhdr_len > len)
279 xhdr_len = len;
280 dump_hex(" |%s|\n", p, xhdr_len);
281 p += xhdr_len;
282 len -= xhdr_len;
283 }
284}
285#else
286# define dump_hex(...) ((void)0)
287# define dump_tls_record(...) ((void)0)
288#endif
289
290void tls_get_random(void *buf, unsigned len)
291{
292 if (len != open_read_close("/dev/urandom", buf, len))
293 xfunc_die();
294}
295
296/* Nondestructively see the current hash value */
297static unsigned sha_peek(md5sha_ctx_t *ctx, void *buffer)
298{
299 md5sha_ctx_t ctx_copy = *ctx; /* struct copy */
300 return sha_end(&ctx_copy, buffer);
301}
302
303static ALWAYS_INLINE unsigned get_handshake_hash(tls_state_t *tls, void *buffer)
304{
305 return sha_peek(&tls->hsd->handshake_hash_ctx, buffer);
306}
307
308#if !TLS_DEBUG_HASH
309# define hash_handshake(tls, fmt, buffer, len) \
310 hash_handshake(tls, buffer, len)
311#endif
312static void hash_handshake(tls_state_t *tls, const char *fmt, const void *buffer, unsigned len)
313{
314 md5sha_hash(&tls->hsd->handshake_hash_ctx, buffer, len);
315#if TLS_DEBUG_HASH
316 {
317 uint8_t h[TLS_MAX_MAC_SIZE];
318 dump_hex(fmt, buffer, len);
319 dbg(" (%u bytes) ", (int)len);
320 len = sha_peek(&tls->hsd->handshake_hash_ctx, h);
321 if (len == SHA1_OUTSIZE)
322 dump_hex("sha1:%s\n", h, len);
323 else
324 if (len == SHA256_OUTSIZE)
325 dump_hex("sha256:%s\n", h, len);
326 else
327 dump_hex("sha???:%s\n", h, len);
328 }
329#endif
330}
331
332// RFC 2104
333// HMAC(key, text) based on a hash H (say, sha256) is:
334// ipad = [0x36 x INSIZE]
335// opad = [0x5c x INSIZE]
336// HMAC(key, text) = H((key XOR opad) + H((key XOR ipad) + text))
337//
338// H(key XOR opad) and H(key XOR ipad) can be precomputed
339// if we often need HMAC hmac with the same key.
340//
341// text is often given in disjoint pieces.
342typedef struct hmac_precomputed {
343 md5sha_ctx_t hashed_key_xor_ipad;
344 md5sha_ctx_t hashed_key_xor_opad;
345} hmac_precomputed_t;
346
347static unsigned hmac_sha_precomputed_v(
348 hmac_precomputed_t *pre,
349 uint8_t *out,
350 va_list va)
351{
352 uint8_t *text;
353 unsigned len;
354
355 /* pre->hashed_key_xor_ipad contains unclosed "H((key XOR ipad) +" state */
356 /* pre->hashed_key_xor_opad contains unclosed "H((key XOR opad) +" state */
357
358 /* calculate out = H((key XOR ipad) + text) */
359 while ((text = va_arg(va, uint8_t*)) != NULL) {
360 unsigned text_size = va_arg(va, unsigned);
361 md5sha_hash(&pre->hashed_key_xor_ipad, text, text_size);
362 }
363 len = sha_end(&pre->hashed_key_xor_ipad, out);
364
365 /* out = H((key XOR opad) + out) */
366 md5sha_hash(&pre->hashed_key_xor_opad, out, len);
367 return sha_end(&pre->hashed_key_xor_opad, out);
368}
369
370static void hmac_sha256_begin(hmac_precomputed_t *pre, uint8_t *key, unsigned key_size)
371{
372 uint8_t key_xor_ipad[SHA_INSIZE];
373 uint8_t key_xor_opad[SHA_INSIZE];
374 uint8_t tempkey[SHA256_OUTSIZE];
375 unsigned i;
376
377 // "The authentication key can be of any length up to INSIZE, the
378 // block length of the hash function. Applications that use keys longer
379 // than INSIZE bytes will first hash the key using H and then use the
380 // resultant OUTSIZE byte string as the actual key to HMAC."
381 if (key_size > SHA_INSIZE) {
382 md5sha_ctx_t ctx;
383 sha256_begin(&ctx);
384 md5sha_hash(&ctx, key, key_size);
385 key_size = sha_end(&ctx, tempkey);
386 }
387
388 for (i = 0; i < key_size; i++) {
389 key_xor_ipad[i] = key[i] ^ 0x36;
390 key_xor_opad[i] = key[i] ^ 0x5c;
391 }
392 for (; i < SHA_INSIZE; i++) {
393 key_xor_ipad[i] = 0x36;
394 key_xor_opad[i] = 0x5c;
395 }
396
397 sha256_begin(&pre->hashed_key_xor_ipad);
398 sha256_begin(&pre->hashed_key_xor_opad);
399 md5sha_hash(&pre->hashed_key_xor_ipad, key_xor_ipad, SHA_INSIZE);
400 md5sha_hash(&pre->hashed_key_xor_opad, key_xor_opad, SHA_INSIZE);
401}
402// TODO: ^^^ vvv merge?
403static void hmac_sha1_begin(hmac_precomputed_t *pre, uint8_t *key, unsigned key_size)
404{
405 uint8_t key_xor_ipad[SHA_INSIZE];
406 uint8_t key_xor_opad[SHA_INSIZE];
407 uint8_t tempkey[SHA1_OUTSIZE];
408 unsigned i;
409
410 // "The authentication key can be of any length up to INSIZE, the
411 // block length of the hash function. Applications that use keys longer
412 // than INSIZE bytes will first hash the key using H and then use the
413 // resultant OUTSIZE byte string as the actual key to HMAC."
414 if (key_size > SHA_INSIZE) {
415 md5sha_ctx_t ctx;
416 sha1_begin(&ctx);
417 md5sha_hash(&ctx, key, key_size);
418 key_size = sha_end(&ctx, tempkey);
419 }
420
421 for (i = 0; i < key_size; i++) {
422 key_xor_ipad[i] = key[i] ^ 0x36;
423 key_xor_opad[i] = key[i] ^ 0x5c;
424 }
425 for (; i < SHA_INSIZE; i++) {
426 key_xor_ipad[i] = 0x36;
427 key_xor_opad[i] = 0x5c;
428 }
429
430 sha1_begin(&pre->hashed_key_xor_ipad);
431 sha1_begin(&pre->hashed_key_xor_opad);
432 md5sha_hash(&pre->hashed_key_xor_ipad, key_xor_ipad, SHA_INSIZE);
433 md5sha_hash(&pre->hashed_key_xor_opad, key_xor_opad, SHA_INSIZE);
434}
435
436static unsigned hmac(tls_state_t *tls, uint8_t *out, uint8_t *key, unsigned key_size, ...)
437{
438 hmac_precomputed_t pre;
439 va_list va;
440 unsigned len;
441
442 va_start(va, key_size);
443
444 if (tls->MAC_size == SHA256_OUTSIZE)
445 hmac_sha256_begin(&pre, key, key_size);
446 else
447 hmac_sha1_begin(&pre, key, key_size);
448
449 len = hmac_sha_precomputed_v(&pre, out, va);
450
451 va_end(va);
452 return len;
453}
454
455static unsigned hmac_sha256(/*tls_state_t *tls,*/ uint8_t *out, uint8_t *key, unsigned key_size, ...)
456{
457 hmac_precomputed_t pre;
458 va_list va;
459 unsigned len;
460
461 va_start(va, key_size);
462
463 hmac_sha256_begin(&pre, key, key_size);
464 len = hmac_sha_precomputed_v(&pre, out, va);
465
466 va_end(va);
467 return len;
468}
469
470// RFC 5246:
471// 5. HMAC and the Pseudorandom Function
472//...
473// In this section, we define one PRF, based on HMAC. This PRF with the
474// SHA-256 hash function is used for all cipher suites defined in this
475// document and in TLS documents published prior to this document when
476// TLS 1.2 is negotiated.
477// ^^^^^^^^^^^^^ IMPORTANT!
478// PRF uses sha256 regardless of cipher (at least for all ciphers
479// defined by RFC5246). It's not sha1 for AES_128_CBC_SHA!
480//...
481// P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) +
482// HMAC_hash(secret, A(2) + seed) +
483// HMAC_hash(secret, A(3) + seed) + ...
484// where + indicates concatenation.
485// A() is defined as:
486// A(0) = seed
487// A(1) = HMAC_hash(secret, A(0)) = HMAC_hash(secret, seed)
488// A(i) = HMAC_hash(secret, A(i-1))
489// P_hash can be iterated as many times as necessary to produce the
490// required quantity of data. For example, if P_SHA256 is being used to
491// create 80 bytes of data, it will have to be iterated three times
492// (through A(3)), creating 96 bytes of output data; the last 16 bytes
493// of the final iteration will then be discarded, leaving 80 bytes of
494// output data.
495//
496// TLS's PRF is created by applying P_hash to the secret as:
497//
498// PRF(secret, label, seed) = P_<hash>(secret, label + seed)
499//
500// The label is an ASCII string.
501static void prf_hmac_sha256(/*tls_state_t *tls,*/
502 uint8_t *outbuf, unsigned outbuf_size,
503 uint8_t *secret, unsigned secret_size,
504 const char *label,
505 uint8_t *seed, unsigned seed_size)
506{
507 uint8_t a[TLS_MAX_MAC_SIZE];
508 uint8_t *out_p = outbuf;
509 unsigned label_size = strlen(label);
510 unsigned MAC_size = SHA256_OUTSIZE;///tls->MAC_size;
511
512 /* In P_hash() calculation, "seed" is "label + seed": */
513#define SEED label, label_size, seed, seed_size
514#define SECRET secret, secret_size
515#define A a, MAC_size
516
517 /* A(1) = HMAC_hash(secret, seed) */
518 hmac_sha256(/*tls,*/ a, SECRET, SEED, NULL);
519//TODO: convert hmac to precomputed
520
521 for(;;) {
522 /* HMAC_hash(secret, A(1) + seed) */
523 if (outbuf_size <= MAC_size) {
524 /* Last, possibly incomplete, block */
525 /* (use a[] as temp buffer) */
526 hmac_sha256(/*tls,*/ a, SECRET, A, SEED, NULL);
527 memcpy(out_p, a, outbuf_size);
528 return;
529 }
530 /* Not last block. Store directly to result buffer */
531 hmac_sha256(/*tls,*/ out_p, SECRET, A, SEED, NULL);
532 out_p += MAC_size;
533 outbuf_size -= MAC_size;
534 /* A(2) = HMAC_hash(secret, A(1)) */
535 hmac_sha256(/*tls,*/ a, SECRET, A, NULL);
536 }
537#undef A
538#undef SECRET
539#undef SEED
540}
541
542static void bad_record_die(tls_state_t *tls, const char *expected, int len)
543{
544 bb_error_msg("got bad TLS record (len:%d) while expecting %s", len, expected);
545 if (len > 0) {
546 uint8_t *p = tls->inbuf;
547 while (len > 0) {
548 fprintf(stderr, " %02x", *p++);
549 len--;
550 }
551 fputc('\n', stderr);
552 }
553 xfunc_die();
554}
555
556static void tls_error_die(tls_state_t *tls, int line)
557{
558 dump_tls_record(tls->inbuf, tls->ofs_to_buffered + tls->buffered_size);
559 bb_error_msg_and_die("tls error at line %d cipher:%04x", line, tls->cipher_id);
560}
561#define tls_error_die(tls) tls_error_die(tls, __LINE__)
562
563#if 0 //UNUSED
564static void tls_free_inbuf(tls_state_t *tls)
565{
566 if (tls->buffered_size == 0) {
567 free(tls->inbuf);
568 tls->inbuf_size = 0;
569 tls->inbuf = NULL;
570 }
571}
572#endif
573
574static void tls_free_outbuf(tls_state_t *tls)
575{
576 free(tls->outbuf);
577 tls->outbuf_size = 0;
578 tls->outbuf = NULL;
579}
580
581static void *tls_get_outbuf(tls_state_t *tls, int len)
582{
583 if (len > TLS_MAX_OUTBUF)
584 xfunc_die();
585 len += OUTBUF_PFX + OUTBUF_SFX;
586 if (tls->outbuf_size < len) {
587 tls->outbuf_size = len;
588 tls->outbuf = xrealloc(tls->outbuf, len);
589 }
590 return tls->outbuf + OUTBUF_PFX;
591}
592
593static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type)
594{
595 uint8_t *buf = tls->outbuf + OUTBUF_PFX;
596 struct record_hdr *xhdr;
597 uint8_t padding_length;
598
599 xhdr = (void*)(buf - RECHDR_LEN);
600 if (tls->cipher_id != TLS_RSA_WITH_NULL_SHA256)
601 xhdr = (void*)(buf - RECHDR_LEN - AES_BLOCKSIZE); /* place for IV */
602
603 xhdr->type = type;
604 xhdr->proto_maj = TLS_MAJ;
605 xhdr->proto_min = TLS_MIN;
606 /* fake unencrypted record len for MAC calculation */
607 xhdr->len16_hi = size >> 8;
608 xhdr->len16_lo = size & 0xff;
609
610 /* Calculate MAC signature */
611 hmac(tls, buf + size, /* result */
612 tls->client_write_MAC_key, tls->MAC_size,
613 &tls->write_seq64_be, sizeof(tls->write_seq64_be),
614 xhdr, RECHDR_LEN,
615 buf, size,
616 NULL
617 );
618 tls->write_seq64_be = SWAP_BE64(1 + SWAP_BE64(tls->write_seq64_be));
619
620 size += tls->MAC_size;
621
622 // RFC 5246
623 // 6.2.3.1. Null or Standard Stream Cipher
624 //
625 // Stream ciphers (including BulkCipherAlgorithm.null; see Appendix A.6)
626 // convert TLSCompressed.fragment structures to and from stream
627 // TLSCiphertext.fragment structures.
628 //
629 // stream-ciphered struct {
630 // opaque content[TLSCompressed.length];
631 // opaque MAC[SecurityParameters.mac_length];
632 // } GenericStreamCipher;
633 //
634 // The MAC is generated as:
635 // MAC(MAC_write_key, seq_num +
636 // TLSCompressed.type +
637 // TLSCompressed.version +
638 // TLSCompressed.length +
639 // TLSCompressed.fragment);
640 // where "+" denotes concatenation.
641 // seq_num
642 // The sequence number for this record.
643 // MAC
644 // The MAC algorithm specified by SecurityParameters.mac_algorithm.
645 //
646 // Note that the MAC is computed before encryption. The stream cipher
647 // encrypts the entire block, including the MAC.
648 //...
649 // Appendix C. Cipher Suite Definitions
650 //...
651 // MAC Algorithm mac_length mac_key_length
652 // -------- ----------- ---------- --------------
653 // SHA HMAC-SHA1 20 20
654 // SHA256 HMAC-SHA256 32 32
655 if (tls->cipher_id == TLS_RSA_WITH_NULL_SHA256) {
656 /* No encryption, only signing */
657 xhdr->len16_hi = size >> 8;
658 xhdr->len16_lo = size & 0xff;
659 dump_raw_out(">> %s\n", xhdr, RECHDR_LEN + size);
660 xwrite(tls->ofd, xhdr, RECHDR_LEN + size);
661 dbg("wrote %u bytes (NULL crypt, SHA256 hash)\n", size);
662 return;
663 }
664
665 // 6.2.3.2. CBC Block Cipher
666 // For block ciphers (such as 3DES or AES), the encryption and MAC
667 // functions convert TLSCompressed.fragment structures to and from block
668 // TLSCiphertext.fragment structures.
669 // struct {
670 // opaque IV[SecurityParameters.record_iv_length];
671 // block-ciphered struct {
672 // opaque content[TLSCompressed.length];
673 // opaque MAC[SecurityParameters.mac_length];
674 // uint8 padding[GenericBlockCipher.padding_length];
675 // uint8 padding_length;
676 // };
677 // } GenericBlockCipher;
678 //...
679 // IV
680 // The Initialization Vector (IV) SHOULD be chosen at random, and
681 // MUST be unpredictable. Note that in versions of TLS prior to 1.1,
682 // there was no IV field (...). For block ciphers, the IV length is
683 // of length SecurityParameters.record_iv_length, which is equal to the
684 // SecurityParameters.block_size.
685 // padding
686 // Padding that is added to force the length of the plaintext to be
687 // an integral multiple of the block cipher's block length.
688 // padding_length
689 // The padding length MUST be such that the total size of the
690 // GenericBlockCipher structure is a multiple of the cipher's block
691 // length. Legal values range from zero to 255, inclusive.
692 //...
693 // Appendix C. Cipher Suite Definitions
694 //...
695 // Key IV Block
696 // Cipher Type Material Size Size
697 // ------------ ------ -------- ---- -----
698 // AES_128_CBC Block 16 16 16
699 // AES_256_CBC Block 32 16 16
700
701 /* Fill IV and padding in outbuf */
702 tls_get_random(buf - AES_BLOCKSIZE, AES_BLOCKSIZE); /* IV */
703 dbg("before crypt: 5 hdr + %u data + %u hash bytes\n", size, tls->MAC_size);
704 // RFC is talking nonsense:
705 // "Padding that is added to force the length of the plaintext to be
706 // an integral multiple of the block cipher's block length."
707 // WRONG. _padding+padding_length_, not just _padding_,
708 // pads the data.
709 // IOW: padding_length is the last byte of padding[] array,
710 // contrary to what RFC depicts.
711 //
712 // What actually happens is that there is always padding.
713 // If you need one byte to reach BLOCKSIZE, this byte is 0x00.
714 // If you need two bytes, they are both 0x01.
715 // If you need three, they are 0x02,0x02,0x02. And so on.
716 // If you need no bytes to reach BLOCKSIZE, you have to pad a full
717 // BLOCKSIZE with bytes of value (BLOCKSIZE-1).
718 // It's ok to have more than minimum padding, but we do minimum.
719 padding_length = (~size) & (AES_BLOCKSIZE - 1);
720 do {
721 buf[size++] = padding_length; /* padding */
722 } while ((size & (AES_BLOCKSIZE - 1)) != 0);
723
724 /* Encrypt content+MAC+padding in place */
725 aes_cbc_encrypt(
726 tls->client_write_key, tls->key_size, /* selects 128/256 */
727 buf - AES_BLOCKSIZE, /* IV */
728 buf, size, /* plaintext */
729 buf /* ciphertext */
730 );
731
732 /* Write out */
733 dbg("writing 5 + %u IV + %u encrypted bytes, padding_length:0x%02x\n",
734 AES_BLOCKSIZE, size, padding_length);
735 size += AES_BLOCKSIZE; /* + IV */
736 xhdr->len16_hi = size >> 8;
737 xhdr->len16_lo = size & 0xff;
738 dump_raw_out(">> %s\n", xhdr, RECHDR_LEN + size);
739 xwrite(tls->ofd, xhdr, RECHDR_LEN + size);
740 dbg("wrote %u bytes\n", (int)RECHDR_LEN + size);
741}
742
743static void xwrite_handshake_record(tls_state_t *tls, unsigned size)
744{
745 //if (!tls->encrypt_on_write) {
746 uint8_t *buf = tls->outbuf + OUTBUF_PFX;
747 struct record_hdr *xhdr = (void*)(buf - RECHDR_LEN);
748
749 xhdr->type = RECORD_TYPE_HANDSHAKE;
750 xhdr->proto_maj = TLS_MAJ;
751 xhdr->proto_min = TLS_MIN;
752 xhdr->len16_hi = size >> 8;
753 xhdr->len16_lo = size & 0xff;
754 dump_raw_out(">> %s\n", xhdr, RECHDR_LEN + size);
755 xwrite(tls->ofd, xhdr, RECHDR_LEN + size);
756 dbg("wrote %u bytes\n", (int)RECHDR_LEN + size);
757 // return;
758 //}
759 //xwrite_encrypted(tls, size, RECORD_TYPE_HANDSHAKE);
760}
761
762static void xwrite_and_update_handshake_hash(tls_state_t *tls, unsigned size)
763{
764 if (!tls->encrypt_on_write) {
765 uint8_t *buf;
766
767 xwrite_handshake_record(tls, size);
768 /* Handshake hash does not include record headers */
769 buf = tls->outbuf + OUTBUF_PFX;
770 hash_handshake(tls, ">> hash:%s", buf, size);
771 return;
772 }
773 xwrite_encrypted(tls, size, RECORD_TYPE_HANDSHAKE);
774}
775
776static int tls_has_buffered_record(tls_state_t *tls)
777{
778 int buffered = tls->buffered_size;
779 struct record_hdr *xhdr;
780 int rec_size;
781
782 if (buffered < RECHDR_LEN)
783 return 0;
784 xhdr = (void*)(tls->inbuf + tls->ofs_to_buffered);
785 rec_size = RECHDR_LEN + (0x100 * xhdr->len16_hi + xhdr->len16_lo);
786 if (buffered < rec_size)
787 return 0;
788 return rec_size;
789}
790
791static const char *alert_text(int code)
792{
793 switch (code) {
794 case 20: return "bad MAC";
795 case 50: return "decode error";
796 case 51: return "decrypt error";
797 case 40: return "handshake failure";
798 case 112: return "unrecognized name";
799 }
800 return itoa(code);
801}
802
803static int tls_xread_record(tls_state_t *tls)
804{
805 struct record_hdr *xhdr;
806 int sz;
807 int total;
808 int target;
809
810 again:
811 dbg("ofs_to_buffered:%u buffered_size:%u\n", tls->ofs_to_buffered, tls->buffered_size);
812 total = tls->buffered_size;
813 if (total != 0) {
814 memmove(tls->inbuf, tls->inbuf + tls->ofs_to_buffered, total);
815 //dbg("<< remaining at %d [%d] ", tls->ofs_to_buffered, total);
816 //dump_raw_in("<< %s\n", tls->inbuf, total);
817 }
818 errno = 0;
819 target = MAX_INBUF;
820 for (;;) {
821 int rem;
822
823 if (total >= RECHDR_LEN && target == MAX_INBUF) {
824 xhdr = (void*)tls->inbuf;
825 target = RECHDR_LEN + (0x100 * xhdr->len16_hi + xhdr->len16_lo);
826 if (target > MAX_INBUF) {
827 /* malformed input (too long): yell and die */
828 tls->buffered_size = 0;
829 tls->ofs_to_buffered = total;
830 tls_error_die(tls);
831 }
832 /* can also check type/proto_maj/proto_min here */
833 dbg("xhdr type:%d ver:%d.%d len:%d\n",
834 xhdr->type, xhdr->proto_maj, xhdr->proto_min,
835 0x100 * xhdr->len16_hi + xhdr->len16_lo
836 );
837 }
838 /* if total >= target, we have a full packet (and possibly more)... */
839 if (total - target >= 0)
840 break;
841 /* input buffer is grown only as needed */
842 rem = tls->inbuf_size - total;
843 if (rem == 0) {
844 tls->inbuf_size += MAX_INBUF / 8;
845 if (tls->inbuf_size > MAX_INBUF)
846 tls->inbuf_size = MAX_INBUF;
847 dbg("inbuf_size:%d\n", tls->inbuf_size);
848 rem = tls->inbuf_size - total;
849 tls->inbuf = xrealloc(tls->inbuf, tls->inbuf_size);
850 }
851 sz = safe_read(tls->ifd, tls->inbuf + total, rem);
852 if (sz <= 0) {
853 if (sz == 0 && total == 0) {
854 /* "Abrupt" EOF, no TLS shutdown (seen from kernel.org) */
855 dbg("EOF (without TLS shutdown) from peer\n");
856 tls->buffered_size = 0;
857 goto end;
858 }
859 bb_perror_msg_and_die("short read, have only %d", total);
860 }
861 dump_raw_in("<< %s\n", tls->inbuf + total, sz);
862 total += sz;
863 }
864 tls->buffered_size = total - target;
865 tls->ofs_to_buffered = target;
866 //dbg("<< stashing at %d [%d] ", tls->ofs_to_buffered, tls->buffered_size);
867 //dump_hex("<< %s\n", tls->inbuf + tls->ofs_to_buffered, tls->buffered_size);
868
869 sz = target - RECHDR_LEN;
870
871 /* Needs to be decrypted? */
872 if (tls->min_encrypted_len_on_read > tls->MAC_size) {
873 uint8_t *p = tls->inbuf + RECHDR_LEN;
874 int padding_len;
875
876 if (sz & (AES_BLOCKSIZE-1)
877 || sz < (int)tls->min_encrypted_len_on_read
878 ) {
879 bb_error_msg_and_die("bad encrypted len:%u < %u",
880 sz, tls->min_encrypted_len_on_read);
881 }
882 /* Decrypt content+MAC+padding, moving it over IV in the process */
883 sz -= AES_BLOCKSIZE; /* we will overwrite IV now */
884 aes_cbc_decrypt(
885 tls->server_write_key, tls->key_size, /* selects 128/256 */
886 p, /* IV */
887 p + AES_BLOCKSIZE, sz, /* ciphertext */
888 p /* plaintext */
889 );
890 padding_len = p[sz - 1];
891 dbg("encrypted size:%u type:0x%02x padding_length:0x%02x\n", sz, p[0], padding_len);
892 padding_len++;
893 sz -= tls->MAC_size + padding_len; /* drop MAC and padding */
894 //if (sz < 0)
895 // bb_error_msg_and_die("bad padding size:%u", padding_len);
896 } else {
897 /* if nonzero, then it's TLS_RSA_WITH_NULL_SHA256: drop MAC */
898 /* else: no encryption yet on input, subtract zero = NOP */
899 sz -= tls->min_encrypted_len_on_read;
900 }
901 if (sz < 0)
902 bb_error_msg_and_die("encrypted data too short");
903
904 //dump_hex("<< %s\n", tls->inbuf, RECHDR_LEN + sz);
905
906 xhdr = (void*)tls->inbuf;
907 if (xhdr->type == RECORD_TYPE_ALERT && sz >= 2) {
908 uint8_t *p = tls->inbuf + RECHDR_LEN;
909 dbg("ALERT size:%d level:%d description:%d\n", sz, p[0], p[1]);
910 if (p[0] == 2) { /* fatal */
911 bb_error_msg_and_die("TLS %s from peer (alert code %d): %s",
912 "error",
913 p[1], alert_text(p[1])
914 );
915 }
916 if (p[0] == 1) { /* warning */
917 if (p[1] == 0) { /* "close_notify" warning: it's EOF */
918 dbg("EOF (TLS encoded) from peer\n");
919 sz = 0;
920 goto end;
921 }
922//This possibly needs to be cached and shown only if
923//a fatal alert follows
924// bb_error_msg("TLS %s from peer (alert code %d): %s",
925// "warning",
926// p[1], alert_text(p[1])
927// );
928 /* discard it, get next record */
929 goto again;
930 }
931 /* p[0] not 1 or 2: not defined in protocol */
932 sz = 0;
933 goto end;
934 }
935
936 /* RFC 5246 is not saying it explicitly, but sha256 hash
937 * in our FINISHED record must include data of incoming packets too!
938 */
939 if (tls->inbuf[0] == RECORD_TYPE_HANDSHAKE
940 && tls->MAC_size != 0 /* do we know which hash to use? (server_hello() does not!) */
941 ) {
942 hash_handshake(tls, "<< hash:%s", tls->inbuf + RECHDR_LEN, sz);
943 }
944 end:
945 dbg("got block len:%u\n", sz);
946 return sz;
947}
948
949/*
950 * DER parsing routines
951 */
952static unsigned get_der_len(uint8_t **bodyp, uint8_t *der, uint8_t *end)
953{
954 unsigned len, len1;
955
956 if (end - der < 2)
957 xfunc_die();
958// if ((der[0] & 0x1f) == 0x1f) /* not single-byte item code? */
959// xfunc_die();
960
961 len = der[1]; /* maybe it's short len */
962 if (len >= 0x80) {
963 /* no, it's long */
964
965 if (len == 0x80 || end - der < (int)(len - 0x7e)) {
966 /* 0x80 is "0 bytes of len", invalid DER: must use short len if can */
967 /* need 3 or 4 bytes for 81, 82 */
968 xfunc_die();
969 }
970
971 len1 = der[2]; /* if (len == 0x81) it's "ii 81 xx", fetch xx */
972 if (len > 0x82) {
973 /* >0x82 is "3+ bytes of len", should not happen realistically */
974 xfunc_die();
975 }
976 if (len == 0x82) { /* it's "ii 82 xx yy" */
977 len1 = 0x100*len1 + der[3];
978 der += 1; /* skip [yy] */
979 }
980 der += 1; /* skip [xx] */
981 len = len1;
982// if (len < 0x80)
983// xfunc_die(); /* invalid DER: must use short len if can */
984 }
985 der += 2; /* skip [code]+[1byte] */
986
987 if (end - der < (int)len)
988 xfunc_die();
989 *bodyp = der;
990
991 return len;
992}
993
994static uint8_t *enter_der_item(uint8_t *der, uint8_t **endp)
995{
996 uint8_t *new_der;
997 unsigned len = get_der_len(&new_der, der, *endp);
998 dbg_der("entered der @%p:0x%02x len:%u inner_byte @%p:0x%02x\n", der, der[0], len, new_der, new_der[0]);
999 /* Move "end" position to cover only this item */
1000 *endp = new_der + len;
1001 return new_der;
1002}
1003
1004static uint8_t *skip_der_item(uint8_t *der, uint8_t *end)
1005{
1006 uint8_t *new_der;
1007 unsigned len = get_der_len(&new_der, der, end);
1008 /* Skip body */
1009 new_der += len;
1010 dbg_der("skipped der 0x%02x, next byte 0x%02x\n", der[0], new_der[0]);
1011 return new_der;
1012}
1013
1014static void der_binary_to_pstm(pstm_int *pstm_n, uint8_t *der, uint8_t *end)
1015{
1016 uint8_t *bin_ptr;
1017 unsigned len = get_der_len(&bin_ptr, der, end);
1018
1019 dbg_der("binary bytes:%u, first:0x%02x\n", len, bin_ptr[0]);
1020 pstm_init_for_read_unsigned_bin(/*pool:*/ NULL, pstm_n, len);
1021 pstm_read_unsigned_bin(pstm_n, bin_ptr, len);
1022 //return bin + len;
1023}
1024
1025static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len)
1026{
1027/* Certificate is a DER-encoded data structure. Each DER element has a length,
1028 * which makes it easy to skip over large compound elements of any complexity
1029 * without parsing them. Example: partial decode of kernel.org certificate:
1030 * SEQ 0x05ac/1452 bytes (Certificate): 308205ac
1031 * SEQ 0x0494/1172 bytes (tbsCertificate): 30820494
1032 * [ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0] 3 bytes: a003
1033 * INTEGER (version): 0201 02
1034 * INTEGER 0x11 bytes (serialNumber): 0211 00 9f85bf664b0cddafca508679501b2be4
1035 * //^^^^^^note: matrixSSL also allows [ASN_CONTEXT_SPECIFIC | ASN_PRIMITIVE | 2] = 0x82 type
1036 * SEQ 0x0d bytes (signatureAlgo): 300d
1037 * OID 9 bytes: 0609 2a864886f70d01010b (OID_SHA256_RSA_SIG 42.134.72.134.247.13.1.1.11)
1038 * NULL: 0500
1039 * SEQ 0x5f bytes (issuer): 305f
1040 * SET 11 bytes: 310b
1041 * SEQ 9 bytes: 3009
1042 * OID 3 bytes: 0603 550406
1043 * Printable string "FR": 1302 4652
1044 * SET 14 bytes: 310e
1045 * SEQ 12 bytes: 300c
1046 * OID 3 bytes: 0603 550408
1047 * Printable string "Paris": 1305 5061726973
1048 * SET 14 bytes: 310e
1049 * SEQ 12 bytes: 300c
1050 * OID 3 bytes: 0603 550407
1051 * Printable string "Paris": 1305 5061726973
1052 * SET 14 bytes: 310e
1053 * SEQ 12 bytes: 300c
1054 * OID 3 bytes: 0603 55040a
1055 * Printable string "Gandi": 1305 47616e6469
1056 * SET 32 bytes: 3120
1057 * SEQ 30 bytes: 301e
1058 * OID 3 bytes: 0603 550403
1059 * Printable string "Gandi Standard SSL CA 2": 1317 47616e6469205374616e646172642053534c2043412032
1060 * SEQ 30 bytes (validity): 301e
1061 * TIME "161011000000Z": 170d 3136313031313030303030305a
1062 * TIME "191011235959Z": 170d 3139313031313233353935395a
1063 * SEQ 0x5b/91 bytes (subject): 305b //I did not decode this
1064 * 3121301f060355040b1318446f6d61696e20436f
1065 * 6e74726f6c2056616c6964617465643121301f06
1066 * 0355040b1318506f73697469766553534c204d75
1067 * 6c74692d446f6d61696e31133011060355040313
1068 * 0a6b65726e656c2e6f7267
1069 * SEQ 0x01a2/418 bytes (subjectPublicKeyInfo): 308201a2
1070 * SEQ 13 bytes (algorithm): 300d
1071 * OID 9 bytes: 0609 2a864886f70d010101 (OID_RSA_KEY_ALG 42.134.72.134.247.13.1.1.1)
1072 * NULL: 0500
1073 * BITSTRING 0x018f/399 bytes (publicKey): 0382018f
1074 * ????: 00
1075 * //after the zero byte, it appears key itself uses DER encoding:
1076 * SEQ 0x018a/394 bytes: 3082018a
1077 * INTEGER 0x0181/385 bytes (modulus): 02820181
1078 * 00b1ab2fc727a3bef76780c9349bf3
1079 * ...24 more blocks of 15 bytes each...
1080 * 90e895291c6bc8693b65
1081 * INTEGER 3 bytes (exponent): 0203 010001
1082 * [ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0x3] 0x01e5 bytes (X509v3 extensions): a38201e5
1083 * SEQ 0x01e1 bytes: 308201e1
1084 * ...
1085 * Certificate is a sequence of three elements:
1086 * tbsCertificate (SEQ)
1087 * signatureAlgorithm (AlgorithmIdentifier)
1088 * signatureValue (BIT STRING)
1089 *
1090 * In turn, tbsCertificate is a sequence of:
1091 * version
1092 * serialNumber
1093 * signatureAlgo (AlgorithmIdentifier)
1094 * issuer (Name, has complex structure)
1095 * validity (Validity, SEQ of two Times)
1096 * subject (Name)
1097 * subjectPublicKeyInfo (SEQ)
1098 * ...
1099 *
1100 * subjectPublicKeyInfo is a sequence of:
1101 * algorithm (AlgorithmIdentifier)
1102 * publicKey (BIT STRING)
1103 *
1104 * We need Certificate.tbsCertificate.subjectPublicKeyInfo.publicKey
1105 */
1106 uint8_t *end = der + len;
1107
1108 /* enter "Certificate" item: [der, end) will be only Cert */
1109 der = enter_der_item(der, &end);
1110
1111 /* enter "tbsCertificate" item: [der, end) will be only tbsCert */
1112 der = enter_der_item(der, &end);
1113
1114 /* skip up to subjectPublicKeyInfo */
1115 der = skip_der_item(der, end); /* version */
1116 der = skip_der_item(der, end); /* serialNumber */
1117 der = skip_der_item(der, end); /* signatureAlgo */
1118 der = skip_der_item(der, end); /* issuer */
1119 der = skip_der_item(der, end); /* validity */
1120 der = skip_der_item(der, end); /* subject */
1121
1122 /* enter subjectPublicKeyInfo */
1123 der = enter_der_item(der, &end);
1124 { /* check subjectPublicKeyInfo.algorithm */
1125 static const uint8_t expected[] = {
1126 0x30,0x0d, // SEQ 13 bytes
1127 0x06,0x09, 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01, // OID RSA_KEY_ALG 42.134.72.134.247.13.1.1.1
1128 //0x05,0x00, // NULL
1129 };
1130 if (memcmp(der, expected, sizeof(expected)) != 0)
1131 bb_error_msg_and_die("not RSA key");
1132 }
1133 /* skip subjectPublicKeyInfo.algorithm */
1134 der = skip_der_item(der, end);
1135 /* enter subjectPublicKeyInfo.publicKey */
1136// die_if_not_this_der_type(der, end, 0x03); /* must be BITSTRING */
1137 der = enter_der_item(der, &end);
1138
1139 /* parse RSA key: */
1140//based on getAsnRsaPubKey(), pkcs1ParsePrivBin() is also of note
1141 dbg("key bytes:%u, first:0x%02x\n", (int)(end - der), der[0]);
1142 if (end - der < 14) xfunc_die();
1143 /* example format:
1144 * ignore bits: 00
1145 * SEQ 0x018a/394 bytes: 3082018a
1146 * INTEGER 0x0181/385 bytes (modulus): 02820181 XX...XXX
1147 * INTEGER 3 bytes (exponent): 0203 010001
1148 */
1149 if (*der != 0) /* "ignore bits", should be 0 */
1150 xfunc_die();
1151 der++;
1152 der = enter_der_item(der, &end); /* enter SEQ */
1153 /* memset(tls->hsd->server_rsa_pub_key, 0, sizeof(tls->hsd->server_rsa_pub_key)); - already is */
1154 der_binary_to_pstm(&tls->hsd->server_rsa_pub_key.N, der, end); /* modulus */
1155 der = skip_der_item(der, end);
1156 der_binary_to_pstm(&tls->hsd->server_rsa_pub_key.e, der, end); /* exponent */
1157 tls->hsd->server_rsa_pub_key.size = pstm_unsigned_bin_size(&tls->hsd->server_rsa_pub_key.N);
1158 dbg("server_rsa_pub_key.size:%d\n", tls->hsd->server_rsa_pub_key.size);
1159}
1160
1161/*
1162 * TLS Handshake routines
1163 */
1164static int tls_xread_handshake_block(tls_state_t *tls, int min_len)
1165{
1166 struct record_hdr *xhdr;
1167 int len = tls_xread_record(tls);
1168
1169 xhdr = (void*)tls->inbuf;
1170 if (len < min_len
1171 || xhdr->type != RECORD_TYPE_HANDSHAKE
1172 || xhdr->proto_maj != TLS_MAJ
1173 || xhdr->proto_min != TLS_MIN
1174 ) {
1175 bad_record_die(tls, "handshake record", len);
1176 }
1177 dbg("got HANDSHAKE\n");
1178 return len;
1179}
1180
1181static ALWAYS_INLINE void fill_handshake_record_hdr(void *buf, unsigned type, unsigned len)
1182{
1183 struct handshake_hdr {
1184 uint8_t type;
1185 uint8_t len24_hi, len24_mid, len24_lo;
1186 } *h = buf;
1187
1188 len -= 4;
1189 h->type = type;
1190 h->len24_hi = len >> 16;
1191 h->len24_mid = len >> 8;
1192 h->len24_lo = len & 0xff;
1193}
1194
1195static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni)
1196{
1197 struct client_hello {
1198 uint8_t type;
1199 uint8_t len24_hi, len24_mid, len24_lo;
1200 uint8_t proto_maj, proto_min;
1201 uint8_t rand32[32];
1202 uint8_t session_id_len;
1203 /* uint8_t session_id[]; */
1204 uint8_t cipherid_len16_hi, cipherid_len16_lo;
1205 uint8_t cipherid[2 * (2 + !!CIPHER_ID2)]; /* actually variable */
1206 uint8_t comprtypes_len;
1207 uint8_t comprtypes[1]; /* actually variable */
1208 /* Extensions (SNI shown):
1209 * hi,lo // len of all extensions
1210 * 00,00 // extension_type: "Server Name"
1211 * 00,0e // list len (there can be more than one SNI)
1212 * 00,0c // len of 1st Server Name Indication
1213 * 00 // name type: host_name
1214 * 00,09 // name len
1215 * "localhost" // name
1216 */
1217// GNU Wget 1.18 to cdn.kernel.org sends these extensions:
1218// 0055
1219// 0005 0005 0100000000 - status_request
1220// 0000 0013 0011 00 000e 63646e 2e 6b65726e656c 2e 6f7267 - server_name
1221// ff01 0001 00 - renegotiation_info
1222// 0023 0000 - session_ticket
1223// 000a 0008 0006001700180019 - supported_groups
1224// 000b 0002 0100 - ec_point_formats
1225// 000d 0016 00140401040305010503060106030301030302010203 - signature_algorithms
1226 };
1227 struct client_hello *record;
1228 int len;
1229 int sni_len = sni ? strnlen(sni, 127) : 0;
1230
1231 len = sizeof(*record);
1232 if (sni_len)
1233 len += 11 + strlen(sni);
1234 record = tls_get_outbuf(tls, len);
1235 memset(record, 0, len);
1236
1237 fill_handshake_record_hdr(record, HANDSHAKE_CLIENT_HELLO, len);
1238 record->proto_maj = TLS_MAJ; /* the "requested" version of the protocol, */
1239 record->proto_min = TLS_MIN; /* can be higher than one in record headers */
1240 tls_get_random(record->rand32, sizeof(record->rand32));
1241 if (TLS_DEBUG_FIXED_SECRETS)
1242 memset(record->rand32, 0x11, sizeof(record->rand32));
1243 /* record->session_id_len = 0; - already is */
1244
1245 /* record->cipherid_len16_hi = 0; */
1246 record->cipherid_len16_lo = sizeof(record->cipherid);
1247 /* RFC 5746 Renegotiation Indication Extension - some servers will refuse to work with us otherwise */
1248 /*record->cipherid[0] = TLS_EMPTY_RENEGOTIATION_INFO_SCSV >> 8; - zero */
1249 record->cipherid[1] = TLS_EMPTY_RENEGOTIATION_INFO_SCSV & 0xff;
1250 if ((CIPHER_ID1 >> 8) != 0) record->cipherid[2] = CIPHER_ID1 >> 8;
1251 /*************************/ record->cipherid[3] = CIPHER_ID1 & 0xff;
1252#if CIPHER_ID2
1253 if ((CIPHER_ID2 >> 8) != 0) record->cipherid[4] = CIPHER_ID2 >> 8;
1254 /*************************/ record->cipherid[5] = CIPHER_ID2 & 0xff;
1255#endif
1256
1257 record->comprtypes_len = 1;
1258 /* record->comprtypes[0] = 0; */
1259
1260 if (sni_len) {
1261 uint8_t *p = (void*)(record + 1);
1262 //p[0] = 0; //
1263 p[1] = sni_len + 9; //ext_len
1264 //p[2] = 0; //
1265 //p[3] = 0; //extension_type
1266 //p[4] = 0; //
1267 p[5] = sni_len + 5; //list len
1268 //p[6] = 0; //
1269 p[7] = sni_len + 3; //len of 1st SNI
1270 //p[8] = 0; //name type
1271 //p[9] = 0; //
1272 p[10] = sni_len; //name len
1273 memcpy(&p[11], sni, sni_len);
1274 }
1275
1276 dbg(">> CLIENT_HELLO\n");
1277 /* Can hash it only when we know which MAC hash to use */
1278 /*xwrite_and_update_handshake_hash(tls, len); - WRONG! */
1279 xwrite_handshake_record(tls, len);
1280
1281 tls->hsd = xzalloc(sizeof(*tls->hsd) + len);
1282 tls->hsd->saved_client_hello_size = len;
1283 memcpy(tls->hsd->saved_client_hello, record, len);
1284 memcpy(tls->hsd->client_and_server_rand32, record->rand32, sizeof(record->rand32));
1285}
1286
1287static void get_server_hello(tls_state_t *tls)
1288{
1289 struct server_hello {
1290 struct record_hdr xhdr;
1291 uint8_t type;
1292 uint8_t len24_hi, len24_mid, len24_lo;
1293 uint8_t proto_maj, proto_min;
1294 uint8_t rand32[32]; /* first 4 bytes are unix time in BE format */
1295 uint8_t session_id_len;
1296 uint8_t session_id[32];
1297 uint8_t cipherid_hi, cipherid_lo;
1298 uint8_t comprtype;
1299 /* extensions may follow, but only those which client offered in its Hello */
1300 };
1301
1302 struct server_hello *hp;
1303 uint8_t *cipherid;
1304 unsigned cipher;
1305 int len, len24;
1306
1307 len = tls_xread_handshake_block(tls, 74 - 32);
1308
1309 hp = (void*)tls->inbuf;
1310 // 74 bytes:
1311 // 02 000046 03|03 58|78|cf|c1 50|a5|49|ee|7e|29|48|71|fe|97|fa|e8|2d|19|87|72|90|84|9d|37|a3|f0|cb|6f|5f|e3|3c|2f |20 |d8|1a|78|96|52|d6|91|01|24|b3|d6|5b|b7|d0|6c|b3|e1|78|4e|3c|95|de|74|a0|ba|eb|a7|3a|ff|bd|a2|bf |00|9c |00|
1312 //SvHl len=70 maj.min unixtime^^^ 28randbytes^^^^^^^^^^^^^^^^^^^^^^^^^^^^_^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^_^^^ slen sid32bytes^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cipSel comprSel
1313 if (hp->type != HANDSHAKE_SERVER_HELLO
1314 || hp->len24_hi != 0
1315 || hp->len24_mid != 0
1316 /* hp->len24_lo checked later */
1317 || hp->proto_maj != TLS_MAJ
1318 || hp->proto_min != TLS_MIN
1319 ) {
1320 bad_record_die(tls, "'server hello'", len);
1321 }
1322
1323 cipherid = &hp->cipherid_hi;
1324 len24 = hp->len24_lo;
1325 if (hp->session_id_len != 32) {
1326 if (hp->session_id_len != 0)
1327 bad_record_die(tls, "'server hello'", len);
1328
1329 // session_id_len == 0: no session id
1330 // "The server
1331 // may return an empty session_id to indicate that the session will
1332 // not be cached and therefore cannot be resumed."
1333 cipherid -= 32;
1334 len24 += 32; /* what len would be if session id would be present */
1335 }
1336
1337 if (len24 < 70
1338// || cipherid[0] != (CIPHER_ID >> 8)
1339// || cipherid[1] != (CIPHER_ID & 0xff)
1340// || cipherid[2] != 0 /* comprtype */
1341 ) {
1342 bad_record_die(tls, "'server hello'", len);
1343 }
1344 dbg("<< SERVER_HELLO\n");
1345
1346 memcpy(tls->hsd->client_and_server_rand32 + 32, hp->rand32, sizeof(hp->rand32));
1347
1348 tls->cipher_id = cipher = 0x100 * cipherid[0] + cipherid[1];
1349 dbg("server chose cipher %04x\n", cipher);
1350
1351 if (cipher == TLS_RSA_WITH_AES_128_CBC_SHA) {
1352 tls->key_size = AES128_KEYSIZE;
1353 tls->MAC_size = SHA1_OUTSIZE;
1354 }
1355 else { /* TLS_RSA_WITH_AES_256_CBC_SHA256 */
1356 tls->key_size = AES256_KEYSIZE;
1357 tls->MAC_size = SHA256_OUTSIZE;
1358 }
1359 /* Handshake hash eventually destined to FINISHED record
1360 * is sha256 regardless of cipher
1361 * (at least for all ciphers defined by RFC5246).
1362 * It's not sha1 for AES_128_CBC_SHA - only MAC is sha1, not this hash.
1363 */
1364 sha256_begin(&tls->hsd->handshake_hash_ctx);
1365 hash_handshake(tls, ">> client hello hash:%s",
1366 tls->hsd->saved_client_hello, tls->hsd->saved_client_hello_size
1367 );
1368 hash_handshake(tls, "<< server hello hash:%s",
1369 tls->inbuf + RECHDR_LEN, len
1370 );
1371}
1372
1373static void get_server_cert(tls_state_t *tls)
1374{
1375 struct record_hdr *xhdr;
1376 uint8_t *certbuf;
1377 int len, len1;
1378
1379 len = tls_xread_handshake_block(tls, 10);
1380
1381 xhdr = (void*)tls->inbuf;
1382 certbuf = (void*)(xhdr + 1);
1383 if (certbuf[0] != HANDSHAKE_CERTIFICATE)
1384 tls_error_die(tls);
1385 dbg("<< CERTIFICATE\n");
1386 // 4392 bytes:
1387 // 0b 00|11|24 00|11|21 00|05|b0 30|82|05|ac|30|82|04|94|a0|03|02|01|02|02|11|00|9f|85|bf|66|4b|0c|dd|af|ca|50|86|79|50|1b|2b|e4|30|0d...
1388 //Cert len=4388 ChainLen CertLen^ DER encoded X509 starts here. openssl x509 -in FILE -inform DER -noout -text
1389 len1 = get24be(certbuf + 1);
1390 if (len1 > len - 4) tls_error_die(tls);
1391 len = len1;
1392 len1 = get24be(certbuf + 4);
1393 if (len1 > len - 3) tls_error_die(tls);
1394 len = len1;
1395 len1 = get24be(certbuf + 7);
1396 if (len1 > len - 3) tls_error_die(tls);
1397 len = len1;
1398
1399 if (len)
1400 find_key_in_der_cert(tls, certbuf + 10, len);
1401}
1402
1403static void send_empty_client_cert(tls_state_t *tls)
1404{
1405 struct client_empty_cert {
1406 uint8_t type;
1407 uint8_t len24_hi, len24_mid, len24_lo;
1408 uint8_t cert_chain_len24_hi, cert_chain_len24_mid, cert_chain_len24_lo;
1409 };
1410 struct client_empty_cert *record;
1411
1412 record = tls_get_outbuf(tls, sizeof(*record));
1413//FIXME: can just memcpy a ready-made one.
1414 fill_handshake_record_hdr(record, HANDSHAKE_CERTIFICATE, sizeof(*record));
1415 record->cert_chain_len24_hi = 0;
1416 record->cert_chain_len24_mid = 0;
1417 record->cert_chain_len24_lo = 0;
1418
1419 dbg(">> CERTIFICATE\n");
1420 xwrite_and_update_handshake_hash(tls, sizeof(*record));
1421}
1422
1423static void send_client_key_exchange(tls_state_t *tls)
1424{
1425 struct client_key_exchange {
1426 uint8_t type;
1427 uint8_t len24_hi, len24_mid, len24_lo;
1428 /* keylen16 exists for RSA (in TLS, not in SSL), but not for some other key types */
1429 uint8_t keylen16_hi, keylen16_lo;
1430 uint8_t key[4 * 1024]; // size??
1431 };
1432//FIXME: better size estimate
1433 struct client_key_exchange *record = tls_get_outbuf(tls, sizeof(*record));
1434 uint8_t rsa_premaster[RSA_PREMASTER_SIZE];
1435 int len;
1436
1437 tls_get_random(rsa_premaster, sizeof(rsa_premaster));
1438 if (TLS_DEBUG_FIXED_SECRETS)
1439 memset(rsa_premaster, 0x44, sizeof(rsa_premaster));
1440 // RFC 5246
1441 // "Note: The version number in the PreMasterSecret is the version
1442 // offered by the client in the ClientHello.client_version, not the
1443 // version negotiated for the connection."
1444 rsa_premaster[0] = TLS_MAJ;
1445 rsa_premaster[1] = TLS_MIN;
1446 dump_hex("premaster:%s\n", rsa_premaster, sizeof(rsa_premaster));
1447 len = psRsaEncryptPub(/*pool:*/ NULL,
1448 /* psRsaKey_t* */ &tls->hsd->server_rsa_pub_key,
1449 rsa_premaster, /*inlen:*/ sizeof(rsa_premaster),
1450 record->key, sizeof(record->key),
1451 data_param_ignored
1452 );
1453 record->keylen16_hi = len >> 8;
1454 record->keylen16_lo = len & 0xff;
1455 len += 2;
1456 record->type = HANDSHAKE_CLIENT_KEY_EXCHANGE;
1457 record->len24_hi = 0;
1458 record->len24_mid = len >> 8;
1459 record->len24_lo = len & 0xff;
1460 len += 4;
1461
1462 dbg(">> CLIENT_KEY_EXCHANGE\n");
1463 xwrite_and_update_handshake_hash(tls, len);
1464
1465 // RFC 5246
1466 // For all key exchange methods, the same algorithm is used to convert
1467 // the pre_master_secret into the master_secret. The pre_master_secret
1468 // should be deleted from memory once the master_secret has been
1469 // computed.
1470 // master_secret = PRF(pre_master_secret, "master secret",
1471 // ClientHello.random + ServerHello.random)
1472 // [0..47];
1473 // The master secret is always exactly 48 bytes in length. The length
1474 // of the premaster secret will vary depending on key exchange method.
1475 prf_hmac_sha256(/*tls,*/
1476 tls->hsd->master_secret, sizeof(tls->hsd->master_secret),
1477 rsa_premaster, sizeof(rsa_premaster),
1478 "master secret",
1479 tls->hsd->client_and_server_rand32, sizeof(tls->hsd->client_and_server_rand32)
1480 );
1481 dump_hex("master secret:%s\n", tls->hsd->master_secret, sizeof(tls->hsd->master_secret));
1482
1483 // RFC 5246
1484 // 6.3. Key Calculation
1485 //
1486 // The Record Protocol requires an algorithm to generate keys required
1487 // by the current connection state (see Appendix A.6) from the security
1488 // parameters provided by the handshake protocol.
1489 //
1490 // The master secret is expanded into a sequence of secure bytes, which
1491 // is then split to a client write MAC key, a server write MAC key, a
1492 // client write encryption key, and a server write encryption key. Each
1493 // of these is generated from the byte sequence in that order. Unused
1494 // values are empty. Some AEAD ciphers may additionally require a
1495 // client write IV and a server write IV (see Section 6.2.3.3).
1496 //
1497 // When keys and MAC keys are generated, the master secret is used as an
1498 // entropy source.
1499 //
1500 // To generate the key material, compute
1501 //
1502 // key_block = PRF(SecurityParameters.master_secret,
1503 // "key expansion",
1504 // SecurityParameters.server_random +
1505 // SecurityParameters.client_random);
1506 //
1507 // until enough output has been generated. Then, the key_block is
1508 // partitioned as follows:
1509 //
1510 // client_write_MAC_key[SecurityParameters.mac_key_length]
1511 // server_write_MAC_key[SecurityParameters.mac_key_length]
1512 // client_write_key[SecurityParameters.enc_key_length]
1513 // server_write_key[SecurityParameters.enc_key_length]
1514 // client_write_IV[SecurityParameters.fixed_iv_length]
1515 // server_write_IV[SecurityParameters.fixed_iv_length]
1516 {
1517 uint8_t tmp64[64];
1518
1519 /* make "server_rand32 + client_rand32" */
1520 memcpy(&tmp64[0] , &tls->hsd->client_and_server_rand32[32], 32);
1521 memcpy(&tmp64[32], &tls->hsd->client_and_server_rand32[0] , 32);
1522
1523 prf_hmac_sha256(/*tls,*/
1524 tls->client_write_MAC_key, 2 * (tls->MAC_size + tls->key_size),
1525 // also fills:
1526 // server_write_MAC_key[]
1527 // client_write_key[]
1528 // server_write_key[]
1529 tls->hsd->master_secret, sizeof(tls->hsd->master_secret),
1530 "key expansion",
1531 tmp64, 64
1532 );
1533 tls->client_write_key = tls->client_write_MAC_key + (2 * tls->MAC_size);
1534 tls->server_write_key = tls->client_write_key + tls->key_size;
1535 dump_hex("client_write_MAC_key:%s\n",
1536 tls->client_write_MAC_key, tls->MAC_size
1537 );
1538 dump_hex("client_write_key:%s\n",
1539 tls->client_write_key, tls->key_size
1540 );
1541 }
1542}
1543
1544static const uint8_t rec_CHANGE_CIPHER_SPEC[] = {
1545 RECORD_TYPE_CHANGE_CIPHER_SPEC, TLS_MAJ, TLS_MIN, 00, 01,
1546 01
1547};
1548
1549static void send_change_cipher_spec(tls_state_t *tls)
1550{
1551 dbg(">> CHANGE_CIPHER_SPEC\n");
1552 xwrite(tls->ofd, rec_CHANGE_CIPHER_SPEC, sizeof(rec_CHANGE_CIPHER_SPEC));
1553}
1554
1555// 7.4.9. Finished
1556// A Finished message is always sent immediately after a change
1557// cipher spec message to verify that the key exchange and
1558// authentication processes were successful. It is essential that a
1559// change cipher spec message be received between the other handshake
1560// messages and the Finished message.
1561//...
1562// The Finished message is the first one protected with the just
1563// negotiated algorithms, keys, and secrets. Recipients of Finished
1564// messages MUST verify that the contents are correct. Once a side
1565// has sent its Finished message and received and validated the
1566// Finished message from its peer, it may begin to send and receive
1567// application data over the connection.
1568//...
1569// struct {
1570// opaque verify_data[verify_data_length];
1571// } Finished;
1572//
1573// verify_data
1574// PRF(master_secret, finished_label, Hash(handshake_messages))
1575// [0..verify_data_length-1];
1576//
1577// finished_label
1578// For Finished messages sent by the client, the string
1579// "client finished". For Finished messages sent by the server,
1580// the string "server finished".
1581//
1582// Hash denotes a Hash of the handshake messages. For the PRF
1583// defined in Section 5, the Hash MUST be the Hash used as the basis
1584// for the PRF. Any cipher suite which defines a different PRF MUST
1585// also define the Hash to use in the Finished computation.
1586//
1587// In previous versions of TLS, the verify_data was always 12 octets
1588// long. In the current version of TLS, it depends on the cipher
1589// suite. Any cipher suite which does not explicitly specify
1590// verify_data_length has a verify_data_length equal to 12. This
1591// includes all existing cipher suites.
1592static void send_client_finished(tls_state_t *tls)
1593{
1594 struct finished {
1595 uint8_t type;
1596 uint8_t len24_hi, len24_mid, len24_lo;
1597 uint8_t prf_result[12];
1598 };
1599 struct finished *record = tls_get_outbuf(tls, sizeof(*record));
1600 uint8_t handshake_hash[TLS_MAX_MAC_SIZE];
1601 unsigned len;
1602
1603 fill_handshake_record_hdr(record, HANDSHAKE_FINISHED, sizeof(*record));
1604
1605 len = get_handshake_hash(tls, handshake_hash);
1606 prf_hmac_sha256(/*tls,*/
1607 record->prf_result, sizeof(record->prf_result),
1608 tls->hsd->master_secret, sizeof(tls->hsd->master_secret),
1609 "client finished",
1610 handshake_hash, len
1611 );
1612 dump_hex("from secret: %s\n", tls->hsd->master_secret, sizeof(tls->hsd->master_secret));
1613 dump_hex("from labelSeed: %s", "client finished", sizeof("client finished")-1);
1614 dump_hex("%s\n", handshake_hash, sizeof(handshake_hash));
1615 dump_hex("=> digest: %s\n", record->prf_result, sizeof(record->prf_result));
1616
1617 dbg(">> FINISHED\n");
1618 xwrite_encrypted(tls, sizeof(*record), RECORD_TYPE_HANDSHAKE);
1619}
1620
1621void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni)
1622{
1623 // Client RFC 5246 Server
1624 // (*) - optional messages, not always sent
1625 //
1626 // ClientHello ------->
1627 // ServerHello
1628 // Certificate*
1629 // ServerKeyExchange*
1630 // CertificateRequest*
1631 // <------- ServerHelloDone
1632 // Certificate*
1633 // ClientKeyExchange
1634 // CertificateVerify*
1635 // [ChangeCipherSpec]
1636 // Finished ------->
1637 // [ChangeCipherSpec]
1638 // <------- Finished
1639 // Application Data <------> Application Data
1640 int len;
1641
1642 send_client_hello_and_alloc_hsd(tls, sni);
1643 get_server_hello(tls);
1644
1645 // RFC 5246
1646 // The server MUST send a Certificate message whenever the agreed-
1647 // upon key exchange method uses certificates for authentication
1648 // (this includes all key exchange methods defined in this document
1649 // except DH_anon). This message will always immediately follow the
1650 // ServerHello message.
1651 //
1652 // IOW: in practice, Certificate *always* follows.
1653 // (for example, kernel.org does not even accept DH_anon cipher id)
1654 get_server_cert(tls);
1655
1656 len = tls_xread_handshake_block(tls, 4);
1657 if (tls->inbuf[RECHDR_LEN] == HANDSHAKE_SERVER_KEY_EXCHANGE) {
1658 // 459 bytes:
1659 // 0c 00|01|c7 03|00|17|41|04|87|94|2e|2f|68|d0|c9|f4|97|a8|2d|ef|ed|67|ea|c6|f3|b3|56|47|5d|27|b6|bd|ee|70|25|30|5e|b0|8e|f6|21|5a...
1660 //SvKey len=455^
1661 // with TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: 461 bytes:
1662 // 0c 00|01|c9 03|00|17|41|04|cd|9b|b4|29|1f|f6|b0|c2|84|82|7f|29|6a|47|4e|ec|87|0b|c1|9c|69|e1|f8|c6|d0|53|e9|27|90|a5|c8|02|15|75...
1663 dbg("<< SERVER_KEY_EXCHANGE len:%u\n", len);
1664//probably need to save it
1665 len = tls_xread_handshake_block(tls, 4);
1666 }
1667
1668 if (tls->inbuf[RECHDR_LEN] == HANDSHAKE_CERTIFICATE_REQUEST) {
1669 dbg("<< CERTIFICATE_REQUEST\n");
1670 // RFC 5246: "If no suitable certificate is available,
1671 // the client MUST send a certificate message containing no
1672 // certificates. That is, the certificate_list structure has a
1673 // length of zero. ...
1674 // Client certificates are sent using the Certificate structure
1675 // defined in Section 7.4.2."
1676 // (i.e. the same format as server certs)
1677 send_empty_client_cert(tls);
1678 len = tls_xread_handshake_block(tls, 4);
1679 }
1680
1681 if (tls->inbuf[RECHDR_LEN] != HANDSHAKE_SERVER_HELLO_DONE) {
1682 bad_record_die(tls, "'server hello done'", len);
1683 }
1684 // 0e 000000 (len:0)
1685 dbg("<< SERVER_HELLO_DONE\n");
1686
1687 send_client_key_exchange(tls);
1688
1689 send_change_cipher_spec(tls);
1690 /* from now on we should send encrypted */
1691 /* tls->write_seq64_be = 0; - already is */
1692 tls->encrypt_on_write = 1;
1693
1694 send_client_finished(tls);
1695
1696 /* Get CHANGE_CIPHER_SPEC */
1697 len = tls_xread_record(tls);
1698 if (len != 1 || memcmp(tls->inbuf, rec_CHANGE_CIPHER_SPEC, 6) != 0)
1699 bad_record_die(tls, "switch to encrypted traffic", len);
1700 dbg("<< CHANGE_CIPHER_SPEC\n");
1701 if (tls->cipher_id == TLS_RSA_WITH_NULL_SHA256)
1702 tls->min_encrypted_len_on_read = tls->MAC_size;
1703 else {
1704 unsigned mac_blocks = (unsigned)(tls->MAC_size + AES_BLOCKSIZE-1) / AES_BLOCKSIZE;
1705 /* all incoming packets now should be encrypted and have
1706 * at least IV + (MAC padded to blocksize):
1707 */
1708 tls->min_encrypted_len_on_read = AES_BLOCKSIZE + (mac_blocks * AES_BLOCKSIZE);
1709 dbg("min_encrypted_len_on_read: %u", tls->min_encrypted_len_on_read);
1710 }
1711
1712 /* Get (encrypted) FINISHED from the server */
1713 len = tls_xread_record(tls);
1714 if (len < 4 || tls->inbuf[RECHDR_LEN] != HANDSHAKE_FINISHED)
1715 tls_error_die(tls);
1716 dbg("<< FINISHED\n");
1717 /* application data can be sent/received */
1718
1719 /* free handshake data */
1720// if (PARANOIA)
1721// memset(tls->hsd, 0, tls->hsd->hsd_size);
1722 free(tls->hsd);
1723 tls->hsd = NULL;
1724}
1725
1726static void tls_xwrite(tls_state_t *tls, int len)
1727{
1728 dbg(">> DATA\n");
1729 xwrite_encrypted(tls, len, RECORD_TYPE_APPLICATION_DATA);
1730}
1731
1732// To run a test server using openssl:
1733// openssl req -x509 -newkey rsa:$((4096/4*3)) -keyout key.pem -out server.pem -nodes -days 99999 -subj '/CN=localhost'
1734// openssl s_server -key key.pem -cert server.pem -debug -tls1_2 -no_tls1 -no_tls1_1
1735//
1736// Unencryped SHA256 example:
1737// openssl req -x509 -newkey rsa:$((4096/4*3)) -keyout key.pem -out server.pem -nodes -days 99999 -subj '/CN=localhost'
1738// openssl s_server -key key.pem -cert server.pem -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL
1739// openssl s_client -connect 127.0.0.1:4433 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL-SHA256
1740
1741void FAST_FUNC tls_run_copy_loop(tls_state_t *tls)
1742{
1743 fd_set readfds;
1744 int inbuf_size;
1745 const int INBUF_STEP = 4 * 1024;
1746
1747//TODO: convert to poll
1748 /* Select loop copying stdin to ofd, and ifd to stdout */
1749 FD_ZERO(&readfds);
1750 FD_SET(tls->ifd, &readfds);
1751 FD_SET(STDIN_FILENO, &readfds);
1752
1753 inbuf_size = INBUF_STEP;
1754 for (;;) {
1755 fd_set testfds;
1756 int nread;
1757
1758 testfds = readfds;
1759 if (select(tls->ifd + 1, &testfds, NULL, NULL, NULL) < 0)
1760 bb_perror_msg_and_die("select");
1761
1762 if (FD_ISSET(STDIN_FILENO, &testfds)) {
1763 void *buf;
1764
1765 dbg("STDIN HAS DATA\n");
1766 buf = tls_get_outbuf(tls, inbuf_size);
1767 nread = safe_read(STDIN_FILENO, buf, inbuf_size);
1768 if (nread < 1) {
1769 /* We'd want to do this: */
1770 /* Close outgoing half-connection so they get EOF,
1771 * but leave incoming alone so we can see response
1772 */
1773 //shutdown(tls->ofd, SHUT_WR);
1774 /* But TLS has no way to encode this,
1775 * doubt it's ok to do it "raw"
1776 */
1777 FD_CLR(STDIN_FILENO, &readfds);
1778 tls_free_outbuf(tls); /* mem usage optimization */
1779 } else {
1780 if (nread == inbuf_size) {
1781 /* TLS has per record overhead, if input comes fast,
1782 * read, encrypt and send bigger chunks
1783 */
1784 inbuf_size += INBUF_STEP;
1785 if (inbuf_size > TLS_MAX_OUTBUF)
1786 inbuf_size = TLS_MAX_OUTBUF;
1787 }
1788 tls_xwrite(tls, nread);
1789 }
1790 }
1791 if (FD_ISSET(tls->ifd, &testfds)) {
1792 dbg("NETWORK HAS DATA\n");
1793 read_record:
1794 nread = tls_xread_record(tls);
1795 if (nread < 1) {
1796 /* TLS protocol has no real concept of one-sided shutdowns:
1797 * if we get "TLS EOF" from the peer, writes will fail too
1798 */
1799 //FD_CLR(tls->ifd, &readfds);
1800 //close(STDOUT_FILENO);
1801 //tls_free_inbuf(tls); /* mem usage optimization */
1802 //continue;
1803 break;
1804 }
1805 if (tls->inbuf[0] != RECORD_TYPE_APPLICATION_DATA)
1806 bb_error_msg_and_die("unexpected record type %d", tls->inbuf[0]);
1807 xwrite(STDOUT_FILENO, tls->inbuf + RECHDR_LEN, nread);
1808 /* We may already have a complete next record buffered,
1809 * can process it without network reads (and possible blocking)
1810 */
1811 if (tls_has_buffered_record(tls))
1812 goto read_record;
1813 }
1814 }
1815}
diff --git a/networking/tls.h b/networking/tls.h
new file mode 100644
index 000000000..d487f3810
--- /dev/null
+++ b/networking/tls.h
@@ -0,0 +1,99 @@
1/*
2 * Copyright (C) 2017 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6/* Interface glue between bbox code and minimally tweaked matrixssl
7 * code. All C files (matrixssl and bbox (ones which need TLS))
8 * include this file, and guaranteed to see a consistent API,
9 * defines, types, etc.
10 */
11#include "libbb.h"
12
13
14/* Config tweaks */
15#define HAVE_NATIVE_INT64
16#undef USE_1024_KEY_SPEED_OPTIMIZATIONS
17#undef USE_2048_KEY_SPEED_OPTIMIZATIONS
18#define USE_AES
19#undef USE_AES_CBC_EXTERNAL
20#undef USE_AES_CCM
21#undef USE_AES_GCM
22#undef USE_3DES
23#undef USE_ARC4
24#undef USE_IDEA
25#undef USE_RC2
26#undef USE_SEED
27/* pstm: multiprecision numbers */
28#undef DISABLE_PSTM
29#if defined(__GNUC__) && defined(__i386__)
30 /* PSTM_X86 works correctly. +25 bytes. */
31# define PSTM_32BIT
32# define PSTM_X86
33#endif
34//#if defined(__GNUC__) && defined(__x86_64__)
35// /* PSTM_X86_64 works correctly, but +782 bytes. */
36// /* Looks like most of the growth is because of PSTM_64BIT. */
37//# define PSTM_64BIT
38//# define PSTM_X86_64
39//#endif
40//#if SOME_COND #define PSTM_MIPS, #define PSTM_32BIT
41//#if SOME_COND #define PSTM_ARM, #define PSTM_32BIT
42
43
44#define PS_SUCCESS 0
45#define PS_FAILURE -1
46#define PS_ARG_FAIL -6 /* Failure due to bad function param */
47#define PS_PLATFORM_FAIL -7 /* Failure as a result of system call error */
48#define PS_MEM_FAIL -8 /* Failure to allocate requested memory */
49#define PS_LIMIT_FAIL -9 /* Failure on sanity/limit tests */
50
51#define PS_TRUE 1
52#define PS_FALSE 0
53
54#if BB_BIG_ENDIAN
55# define ENDIAN_BIG 1
56# undef ENDIAN_LITTLE
57//#???? ENDIAN_32BITWORD
58// controls only STORE32L, which we don't use
59#else
60# define ENDIAN_LITTLE 1
61# undef ENDIAN_BIG
62#endif
63
64typedef uint64_t uint64;
65typedef int64_t int64;
66typedef uint32_t uint32;
67typedef int32_t int32;
68typedef uint16_t uint16;
69typedef int16_t int16;
70
71//typedef char psPool_t;
72
73//#ifdef PS_PUBKEY_OPTIMIZE_FOR_SMALLER_RAM
74#define PS_EXPTMOD_WINSIZE 3
75//#ifdef PS_PUBKEY_OPTIMIZE_FOR_FASTER_SPEED
76//#define PS_EXPTMOD_WINSIZE 5
77
78#define PUBKEY_TYPE 0x01
79#define PRIVKEY_TYPE 0x02
80
81void tls_get_random(void *buf, unsigned len);
82
83#define matrixCryptoGetPrngData(buf, len, userPtr) (tls_get_random(buf, len), PS_SUCCESS)
84
85#define psFree(p, pool) free(p)
86#define psTraceCrypto(...) bb_error_msg_and_die(__VA_ARGS__)
87
88/* Secure zerofill */
89#define memset_s(A,B,C,D) memset((A),(C),(D))
90/* Constant time memory comparison */
91#define memcmpct(s1, s2, len) memcmp((s1), (s2), (len))
92#undef min
93#define min(x, y) ((x) < (y) ? (x) : (y))
94
95
96#include "tls_pstm.h"
97#include "tls_rsa.h"
98#include "tls_symmetric.h"
99#include "tls_aes.h"
diff --git a/networking/tls_aes.c b/networking/tls_aes.c
new file mode 100644
index 000000000..ebaab15b1
--- /dev/null
+++ b/networking/tls_aes.c
@@ -0,0 +1,1776 @@
1/*
2 * Copyright (C) 2017 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6#include "tls.h"
7
8static
9int32 psAesInitKey(const unsigned char *key, uint32 keylen, psAesKey_t *skey);
10static
11void psAesEncryptBlock(const unsigned char *pt, unsigned char *ct,
12 psAesKey_t *skey);
13static
14void psAesDecryptBlock(const unsigned char *ct, unsigned char *pt,
15 psAesKey_t *skey);
16static
17int32 psAesInit(psCipherContext_t *ctx, unsigned char *IV,
18 const unsigned char *key, uint32 keylen);
19static
20int32 psAesEncrypt(psCipherContext_t *ctx, const unsigned char *pt,
21 unsigned char *ct, uint32 len);
22static
23int32 psAesDecrypt(psCipherContext_t *ctx, const unsigned char *ct,
24 unsigned char *pt, uint32 len);
25
26void aes_cbc_encrypt(const void *key, int klen, void *iv, const void *data, size_t len, void *dst)
27{
28 psCipherContext_t ctx;
29 psAesInit(&ctx, iv, key, klen);
30 psAesEncrypt(&ctx,
31 data, /* plaintext */
32 dst, /* ciphertext */
33 len
34 );
35}
36
37void aes_cbc_decrypt(const void *key, int klen, void *iv, const void *data, size_t len, void *dst)
38{
39 psCipherContext_t ctx;
40 psAesInit(&ctx, iv, key, klen);
41 psAesDecrypt(&ctx,
42 data, /* ciphertext */
43 dst, /* plaintext */
44 len
45 );
46}
47
48/* The file is taken almost verbatim from matrixssl-3-7-2b-open/crypto/symmetric/.
49 * Changes are flagged with //bbox
50 */
51
52/**
53 * @file aes.c
54 * @version 33ef80f (HEAD, tag: MATRIXSSL-3-7-2-OPEN, tag: MATRIXSSL-3-7-2-COMM, origin/master, origin/HEAD, master)
55 *
56 * AES CBC block cipher implementation.
57 */
58/*
59 * Copyright (c) 2013-2015 INSIDE Secure Corporation
60 * Copyright (c) PeerSec Networks, 2002-2011
61 * All Rights Reserved
62 *
63 * The latest version of this code is available at http://www.matrixssl.org
64 *
65 * This software is open source; you can redistribute it and/or modify
66 * it under the terms of the GNU General Public License as published by
67 * the Free Software Foundation; either version 2 of the License, or
68 * (at your option) any later version.
69 *
70 * This General Public License does NOT permit incorporating this software
71 * into proprietary programs. If you are unable to comply with the GPL, a
72 * commercial license for this software may be purchased from INSIDE at
73 * http://www.insidesecure.com/eng/Company/Locations
74 *
75 * This program is distributed in WITHOUT ANY WARRANTY; without even the
76 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
77 * See the GNU General Public License for more details.
78 *
79 * You should have received a copy of the GNU General Public License
80 * along with this program; if not, write to the Free Software
81 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
82 * http://www.gnu.org/copyleft/gpl.html
83 */
84/******************************************************************************/
85
86//bbox
87//#include "../cryptoApi.h"
88
89#ifdef USE_AES
90#ifndef USE_AES_CBC_EXTERNAL
91/******************************************************************************/
92
93/* The precomputed tables for AES */
94/*
95Te0[x] = S [x].[02, 01, 01, 03];
96Te1[x] = S [x].[03, 02, 01, 01];
97Te2[x] = S [x].[01, 03, 02, 01];
98Te3[x] = S [x].[01, 01, 03, 02];
99Te4[x] = S [x].[01, 01, 01, 01];
100
101Td0[x] = Si[x].[0e, 09, 0d, 0b];
102Td1[x] = Si[x].[0b, 0e, 09, 0d];
103Td2[x] = Si[x].[0d, 0b, 0e, 09];
104Td3[x] = Si[x].[09, 0d, 0b, 0e];
105Td4[x] = Si[x].[01, 01, 01, 01];
106*/
107
108static const uint32 TE0[] = {
109 0xc66363a5UL, 0xf87c7c84UL, 0xee777799UL, 0xf67b7b8dUL,
110 0xfff2f20dUL, 0xd66b6bbdUL, 0xde6f6fb1UL, 0x91c5c554UL,
111 0x60303050UL, 0x02010103UL, 0xce6767a9UL, 0x562b2b7dUL,
112 0xe7fefe19UL, 0xb5d7d762UL, 0x4dababe6UL, 0xec76769aUL,
113 0x8fcaca45UL, 0x1f82829dUL, 0x89c9c940UL, 0xfa7d7d87UL,
114 0xeffafa15UL, 0xb25959ebUL, 0x8e4747c9UL, 0xfbf0f00bUL,
115 0x41adadecUL, 0xb3d4d467UL, 0x5fa2a2fdUL, 0x45afafeaUL,
116 0x239c9cbfUL, 0x53a4a4f7UL, 0xe4727296UL, 0x9bc0c05bUL,
117 0x75b7b7c2UL, 0xe1fdfd1cUL, 0x3d9393aeUL, 0x4c26266aUL,
118 0x6c36365aUL, 0x7e3f3f41UL, 0xf5f7f702UL, 0x83cccc4fUL,
119 0x6834345cUL, 0x51a5a5f4UL, 0xd1e5e534UL, 0xf9f1f108UL,
120 0xe2717193UL, 0xabd8d873UL, 0x62313153UL, 0x2a15153fUL,
121 0x0804040cUL, 0x95c7c752UL, 0x46232365UL, 0x9dc3c35eUL,
122 0x30181828UL, 0x379696a1UL, 0x0a05050fUL, 0x2f9a9ab5UL,
123 0x0e070709UL, 0x24121236UL, 0x1b80809bUL, 0xdfe2e23dUL,
124 0xcdebeb26UL, 0x4e272769UL, 0x7fb2b2cdUL, 0xea75759fUL,
125 0x1209091bUL, 0x1d83839eUL, 0x582c2c74UL, 0x341a1a2eUL,
126 0x361b1b2dUL, 0xdc6e6eb2UL, 0xb45a5aeeUL, 0x5ba0a0fbUL,
127 0xa45252f6UL, 0x763b3b4dUL, 0xb7d6d661UL, 0x7db3b3ceUL,
128 0x5229297bUL, 0xdde3e33eUL, 0x5e2f2f71UL, 0x13848497UL,
129 0xa65353f5UL, 0xb9d1d168UL, 0x00000000UL, 0xc1eded2cUL,
130 0x40202060UL, 0xe3fcfc1fUL, 0x79b1b1c8UL, 0xb65b5bedUL,
131 0xd46a6abeUL, 0x8dcbcb46UL, 0x67bebed9UL, 0x7239394bUL,
132 0x944a4adeUL, 0x984c4cd4UL, 0xb05858e8UL, 0x85cfcf4aUL,
133 0xbbd0d06bUL, 0xc5efef2aUL, 0x4faaaae5UL, 0xedfbfb16UL,
134 0x864343c5UL, 0x9a4d4dd7UL, 0x66333355UL, 0x11858594UL,
135 0x8a4545cfUL, 0xe9f9f910UL, 0x04020206UL, 0xfe7f7f81UL,
136 0xa05050f0UL, 0x783c3c44UL, 0x259f9fbaUL, 0x4ba8a8e3UL,
137 0xa25151f3UL, 0x5da3a3feUL, 0x804040c0UL, 0x058f8f8aUL,
138 0x3f9292adUL, 0x219d9dbcUL, 0x70383848UL, 0xf1f5f504UL,
139 0x63bcbcdfUL, 0x77b6b6c1UL, 0xafdada75UL, 0x42212163UL,
140 0x20101030UL, 0xe5ffff1aUL, 0xfdf3f30eUL, 0xbfd2d26dUL,
141 0x81cdcd4cUL, 0x180c0c14UL, 0x26131335UL, 0xc3ecec2fUL,
142 0xbe5f5fe1UL, 0x359797a2UL, 0x884444ccUL, 0x2e171739UL,
143 0x93c4c457UL, 0x55a7a7f2UL, 0xfc7e7e82UL, 0x7a3d3d47UL,
144 0xc86464acUL, 0xba5d5de7UL, 0x3219192bUL, 0xe6737395UL,
145 0xc06060a0UL, 0x19818198UL, 0x9e4f4fd1UL, 0xa3dcdc7fUL,
146 0x44222266UL, 0x542a2a7eUL, 0x3b9090abUL, 0x0b888883UL,
147 0x8c4646caUL, 0xc7eeee29UL, 0x6bb8b8d3UL, 0x2814143cUL,
148 0xa7dede79UL, 0xbc5e5ee2UL, 0x160b0b1dUL, 0xaddbdb76UL,
149 0xdbe0e03bUL, 0x64323256UL, 0x743a3a4eUL, 0x140a0a1eUL,
150 0x924949dbUL, 0x0c06060aUL, 0x4824246cUL, 0xb85c5ce4UL,
151 0x9fc2c25dUL, 0xbdd3d36eUL, 0x43acacefUL, 0xc46262a6UL,
152 0x399191a8UL, 0x319595a4UL, 0xd3e4e437UL, 0xf279798bUL,
153 0xd5e7e732UL, 0x8bc8c843UL, 0x6e373759UL, 0xda6d6db7UL,
154 0x018d8d8cUL, 0xb1d5d564UL, 0x9c4e4ed2UL, 0x49a9a9e0UL,
155 0xd86c6cb4UL, 0xac5656faUL, 0xf3f4f407UL, 0xcfeaea25UL,
156 0xca6565afUL, 0xf47a7a8eUL, 0x47aeaee9UL, 0x10080818UL,
157 0x6fbabad5UL, 0xf0787888UL, 0x4a25256fUL, 0x5c2e2e72UL,
158 0x381c1c24UL, 0x57a6a6f1UL, 0x73b4b4c7UL, 0x97c6c651UL,
159 0xcbe8e823UL, 0xa1dddd7cUL, 0xe874749cUL, 0x3e1f1f21UL,
160 0x964b4bddUL, 0x61bdbddcUL, 0x0d8b8b86UL, 0x0f8a8a85UL,
161 0xe0707090UL, 0x7c3e3e42UL, 0x71b5b5c4UL, 0xcc6666aaUL,
162 0x904848d8UL, 0x06030305UL, 0xf7f6f601UL, 0x1c0e0e12UL,
163 0xc26161a3UL, 0x6a35355fUL, 0xae5757f9UL, 0x69b9b9d0UL,
164 0x17868691UL, 0x99c1c158UL, 0x3a1d1d27UL, 0x279e9eb9UL,
165 0xd9e1e138UL, 0xebf8f813UL, 0x2b9898b3UL, 0x22111133UL,
166 0xd26969bbUL, 0xa9d9d970UL, 0x078e8e89UL, 0x339494a7UL,
167 0x2d9b9bb6UL, 0x3c1e1e22UL, 0x15878792UL, 0xc9e9e920UL,
168 0x87cece49UL, 0xaa5555ffUL, 0x50282878UL, 0xa5dfdf7aUL,
169 0x038c8c8fUL, 0x59a1a1f8UL, 0x09898980UL, 0x1a0d0d17UL,
170 0x65bfbfdaUL, 0xd7e6e631UL, 0x844242c6UL, 0xd06868b8UL,
171 0x824141c3UL, 0x299999b0UL, 0x5a2d2d77UL, 0x1e0f0f11UL,
172 0x7bb0b0cbUL, 0xa85454fcUL, 0x6dbbbbd6UL, 0x2c16163aUL,
173};
174
175static const uint32 Te4[] = {
176 0x63636363UL, 0x7c7c7c7cUL, 0x77777777UL, 0x7b7b7b7bUL,
177 0xf2f2f2f2UL, 0x6b6b6b6bUL, 0x6f6f6f6fUL, 0xc5c5c5c5UL,
178 0x30303030UL, 0x01010101UL, 0x67676767UL, 0x2b2b2b2bUL,
179 0xfefefefeUL, 0xd7d7d7d7UL, 0xababababUL, 0x76767676UL,
180 0xcacacacaUL, 0x82828282UL, 0xc9c9c9c9UL, 0x7d7d7d7dUL,
181 0xfafafafaUL, 0x59595959UL, 0x47474747UL, 0xf0f0f0f0UL,
182 0xadadadadUL, 0xd4d4d4d4UL, 0xa2a2a2a2UL, 0xafafafafUL,
183 0x9c9c9c9cUL, 0xa4a4a4a4UL, 0x72727272UL, 0xc0c0c0c0UL,
184 0xb7b7b7b7UL, 0xfdfdfdfdUL, 0x93939393UL, 0x26262626UL,
185 0x36363636UL, 0x3f3f3f3fUL, 0xf7f7f7f7UL, 0xccccccccUL,
186 0x34343434UL, 0xa5a5a5a5UL, 0xe5e5e5e5UL, 0xf1f1f1f1UL,
187 0x71717171UL, 0xd8d8d8d8UL, 0x31313131UL, 0x15151515UL,
188 0x04040404UL, 0xc7c7c7c7UL, 0x23232323UL, 0xc3c3c3c3UL,
189 0x18181818UL, 0x96969696UL, 0x05050505UL, 0x9a9a9a9aUL,
190 0x07070707UL, 0x12121212UL, 0x80808080UL, 0xe2e2e2e2UL,
191 0xebebebebUL, 0x27272727UL, 0xb2b2b2b2UL, 0x75757575UL,
192 0x09090909UL, 0x83838383UL, 0x2c2c2c2cUL, 0x1a1a1a1aUL,
193 0x1b1b1b1bUL, 0x6e6e6e6eUL, 0x5a5a5a5aUL, 0xa0a0a0a0UL,
194 0x52525252UL, 0x3b3b3b3bUL, 0xd6d6d6d6UL, 0xb3b3b3b3UL,
195 0x29292929UL, 0xe3e3e3e3UL, 0x2f2f2f2fUL, 0x84848484UL,
196 0x53535353UL, 0xd1d1d1d1UL, 0x00000000UL, 0xededededUL,
197 0x20202020UL, 0xfcfcfcfcUL, 0xb1b1b1b1UL, 0x5b5b5b5bUL,
198 0x6a6a6a6aUL, 0xcbcbcbcbUL, 0xbebebebeUL, 0x39393939UL,
199 0x4a4a4a4aUL, 0x4c4c4c4cUL, 0x58585858UL, 0xcfcfcfcfUL,
200 0xd0d0d0d0UL, 0xefefefefUL, 0xaaaaaaaaUL, 0xfbfbfbfbUL,
201 0x43434343UL, 0x4d4d4d4dUL, 0x33333333UL, 0x85858585UL,
202 0x45454545UL, 0xf9f9f9f9UL, 0x02020202UL, 0x7f7f7f7fUL,
203 0x50505050UL, 0x3c3c3c3cUL, 0x9f9f9f9fUL, 0xa8a8a8a8UL,
204 0x51515151UL, 0xa3a3a3a3UL, 0x40404040UL, 0x8f8f8f8fUL,
205 0x92929292UL, 0x9d9d9d9dUL, 0x38383838UL, 0xf5f5f5f5UL,
206 0xbcbcbcbcUL, 0xb6b6b6b6UL, 0xdadadadaUL, 0x21212121UL,
207 0x10101010UL, 0xffffffffUL, 0xf3f3f3f3UL, 0xd2d2d2d2UL,
208 0xcdcdcdcdUL, 0x0c0c0c0cUL, 0x13131313UL, 0xececececUL,
209 0x5f5f5f5fUL, 0x97979797UL, 0x44444444UL, 0x17171717UL,
210 0xc4c4c4c4UL, 0xa7a7a7a7UL, 0x7e7e7e7eUL, 0x3d3d3d3dUL,
211 0x64646464UL, 0x5d5d5d5dUL, 0x19191919UL, 0x73737373UL,
212 0x60606060UL, 0x81818181UL, 0x4f4f4f4fUL, 0xdcdcdcdcUL,
213 0x22222222UL, 0x2a2a2a2aUL, 0x90909090UL, 0x88888888UL,
214 0x46464646UL, 0xeeeeeeeeUL, 0xb8b8b8b8UL, 0x14141414UL,
215 0xdedededeUL, 0x5e5e5e5eUL, 0x0b0b0b0bUL, 0xdbdbdbdbUL,
216 0xe0e0e0e0UL, 0x32323232UL, 0x3a3a3a3aUL, 0x0a0a0a0aUL,
217 0x49494949UL, 0x06060606UL, 0x24242424UL, 0x5c5c5c5cUL,
218 0xc2c2c2c2UL, 0xd3d3d3d3UL, 0xacacacacUL, 0x62626262UL,
219 0x91919191UL, 0x95959595UL, 0xe4e4e4e4UL, 0x79797979UL,
220 0xe7e7e7e7UL, 0xc8c8c8c8UL, 0x37373737UL, 0x6d6d6d6dUL,
221 0x8d8d8d8dUL, 0xd5d5d5d5UL, 0x4e4e4e4eUL, 0xa9a9a9a9UL,
222 0x6c6c6c6cUL, 0x56565656UL, 0xf4f4f4f4UL, 0xeaeaeaeaUL,
223 0x65656565UL, 0x7a7a7a7aUL, 0xaeaeaeaeUL, 0x08080808UL,
224 0xbabababaUL, 0x78787878UL, 0x25252525UL, 0x2e2e2e2eUL,
225 0x1c1c1c1cUL, 0xa6a6a6a6UL, 0xb4b4b4b4UL, 0xc6c6c6c6UL,
226 0xe8e8e8e8UL, 0xddddddddUL, 0x74747474UL, 0x1f1f1f1fUL,
227 0x4b4b4b4bUL, 0xbdbdbdbdUL, 0x8b8b8b8bUL, 0x8a8a8a8aUL,
228 0x70707070UL, 0x3e3e3e3eUL, 0xb5b5b5b5UL, 0x66666666UL,
229 0x48484848UL, 0x03030303UL, 0xf6f6f6f6UL, 0x0e0e0e0eUL,
230 0x61616161UL, 0x35353535UL, 0x57575757UL, 0xb9b9b9b9UL,
231 0x86868686UL, 0xc1c1c1c1UL, 0x1d1d1d1dUL, 0x9e9e9e9eUL,
232 0xe1e1e1e1UL, 0xf8f8f8f8UL, 0x98989898UL, 0x11111111UL,
233 0x69696969UL, 0xd9d9d9d9UL, 0x8e8e8e8eUL, 0x94949494UL,
234 0x9b9b9b9bUL, 0x1e1e1e1eUL, 0x87878787UL, 0xe9e9e9e9UL,
235 0xcecececeUL, 0x55555555UL, 0x28282828UL, 0xdfdfdfdfUL,
236 0x8c8c8c8cUL, 0xa1a1a1a1UL, 0x89898989UL, 0x0d0d0d0dUL,
237 0xbfbfbfbfUL, 0xe6e6e6e6UL, 0x42424242UL, 0x68686868UL,
238 0x41414141UL, 0x99999999UL, 0x2d2d2d2dUL, 0x0f0f0f0fUL,
239 0xb0b0b0b0UL, 0x54545454UL, 0xbbbbbbbbUL, 0x16161616UL,
240};
241
242static const uint32 TD0[] = {
243 0x51f4a750UL, 0x7e416553UL, 0x1a17a4c3UL, 0x3a275e96UL,
244 0x3bab6bcbUL, 0x1f9d45f1UL, 0xacfa58abUL, 0x4be30393UL,
245 0x2030fa55UL, 0xad766df6UL, 0x88cc7691UL, 0xf5024c25UL,
246 0x4fe5d7fcUL, 0xc52acbd7UL, 0x26354480UL, 0xb562a38fUL,
247 0xdeb15a49UL, 0x25ba1b67UL, 0x45ea0e98UL, 0x5dfec0e1UL,
248 0xc32f7502UL, 0x814cf012UL, 0x8d4697a3UL, 0x6bd3f9c6UL,
249 0x038f5fe7UL, 0x15929c95UL, 0xbf6d7aebUL, 0x955259daUL,
250 0xd4be832dUL, 0x587421d3UL, 0x49e06929UL, 0x8ec9c844UL,
251 0x75c2896aUL, 0xf48e7978UL, 0x99583e6bUL, 0x27b971ddUL,
252 0xbee14fb6UL, 0xf088ad17UL, 0xc920ac66UL, 0x7dce3ab4UL,
253 0x63df4a18UL, 0xe51a3182UL, 0x97513360UL, 0x62537f45UL,
254 0xb16477e0UL, 0xbb6bae84UL, 0xfe81a01cUL, 0xf9082b94UL,
255 0x70486858UL, 0x8f45fd19UL, 0x94de6c87UL, 0x527bf8b7UL,
256 0xab73d323UL, 0x724b02e2UL, 0xe31f8f57UL, 0x6655ab2aUL,
257 0xb2eb2807UL, 0x2fb5c203UL, 0x86c57b9aUL, 0xd33708a5UL,
258 0x302887f2UL, 0x23bfa5b2UL, 0x02036abaUL, 0xed16825cUL,
259 0x8acf1c2bUL, 0xa779b492UL, 0xf307f2f0UL, 0x4e69e2a1UL,
260 0x65daf4cdUL, 0x0605bed5UL, 0xd134621fUL, 0xc4a6fe8aUL,
261 0x342e539dUL, 0xa2f355a0UL, 0x058ae132UL, 0xa4f6eb75UL,
262 0x0b83ec39UL, 0x4060efaaUL, 0x5e719f06UL, 0xbd6e1051UL,
263 0x3e218af9UL, 0x96dd063dUL, 0xdd3e05aeUL, 0x4de6bd46UL,
264 0x91548db5UL, 0x71c45d05UL, 0x0406d46fUL, 0x605015ffUL,
265 0x1998fb24UL, 0xd6bde997UL, 0x894043ccUL, 0x67d99e77UL,
266 0xb0e842bdUL, 0x07898b88UL, 0xe7195b38UL, 0x79c8eedbUL,
267 0xa17c0a47UL, 0x7c420fe9UL, 0xf8841ec9UL, 0x00000000UL,
268 0x09808683UL, 0x322bed48UL, 0x1e1170acUL, 0x6c5a724eUL,
269 0xfd0efffbUL, 0x0f853856UL, 0x3daed51eUL, 0x362d3927UL,
270 0x0a0fd964UL, 0x685ca621UL, 0x9b5b54d1UL, 0x24362e3aUL,
271 0x0c0a67b1UL, 0x9357e70fUL, 0xb4ee96d2UL, 0x1b9b919eUL,
272 0x80c0c54fUL, 0x61dc20a2UL, 0x5a774b69UL, 0x1c121a16UL,
273 0xe293ba0aUL, 0xc0a02ae5UL, 0x3c22e043UL, 0x121b171dUL,
274 0x0e090d0bUL, 0xf28bc7adUL, 0x2db6a8b9UL, 0x141ea9c8UL,
275 0x57f11985UL, 0xaf75074cUL, 0xee99ddbbUL, 0xa37f60fdUL,
276 0xf701269fUL, 0x5c72f5bcUL, 0x44663bc5UL, 0x5bfb7e34UL,
277 0x8b432976UL, 0xcb23c6dcUL, 0xb6edfc68UL, 0xb8e4f163UL,
278 0xd731dccaUL, 0x42638510UL, 0x13972240UL, 0x84c61120UL,
279 0x854a247dUL, 0xd2bb3df8UL, 0xaef93211UL, 0xc729a16dUL,
280 0x1d9e2f4bUL, 0xdcb230f3UL, 0x0d8652ecUL, 0x77c1e3d0UL,
281 0x2bb3166cUL, 0xa970b999UL, 0x119448faUL, 0x47e96422UL,
282 0xa8fc8cc4UL, 0xa0f03f1aUL, 0x567d2cd8UL, 0x223390efUL,
283 0x87494ec7UL, 0xd938d1c1UL, 0x8ccaa2feUL, 0x98d40b36UL,
284 0xa6f581cfUL, 0xa57ade28UL, 0xdab78e26UL, 0x3fadbfa4UL,
285 0x2c3a9de4UL, 0x5078920dUL, 0x6a5fcc9bUL, 0x547e4662UL,
286 0xf68d13c2UL, 0x90d8b8e8UL, 0x2e39f75eUL, 0x82c3aff5UL,
287 0x9f5d80beUL, 0x69d0937cUL, 0x6fd52da9UL, 0xcf2512b3UL,
288 0xc8ac993bUL, 0x10187da7UL, 0xe89c636eUL, 0xdb3bbb7bUL,
289 0xcd267809UL, 0x6e5918f4UL, 0xec9ab701UL, 0x834f9aa8UL,
290 0xe6956e65UL, 0xaaffe67eUL, 0x21bccf08UL, 0xef15e8e6UL,
291 0xbae79bd9UL, 0x4a6f36ceUL, 0xea9f09d4UL, 0x29b07cd6UL,
292 0x31a4b2afUL, 0x2a3f2331UL, 0xc6a59430UL, 0x35a266c0UL,
293 0x744ebc37UL, 0xfc82caa6UL, 0xe090d0b0UL, 0x33a7d815UL,
294 0xf104984aUL, 0x41ecdaf7UL, 0x7fcd500eUL, 0x1791f62fUL,
295 0x764dd68dUL, 0x43efb04dUL, 0xccaa4d54UL, 0xe49604dfUL,
296 0x9ed1b5e3UL, 0x4c6a881bUL, 0xc12c1fb8UL, 0x4665517fUL,
297 0x9d5eea04UL, 0x018c355dUL, 0xfa877473UL, 0xfb0b412eUL,
298 0xb3671d5aUL, 0x92dbd252UL, 0xe9105633UL, 0x6dd64713UL,
299 0x9ad7618cUL, 0x37a10c7aUL, 0x59f8148eUL, 0xeb133c89UL,
300 0xcea927eeUL, 0xb761c935UL, 0xe11ce5edUL, 0x7a47b13cUL,
301 0x9cd2df59UL, 0x55f2733fUL, 0x1814ce79UL, 0x73c737bfUL,
302 0x53f7cdeaUL, 0x5ffdaa5bUL, 0xdf3d6f14UL, 0x7844db86UL,
303 0xcaaff381UL, 0xb968c43eUL, 0x3824342cUL, 0xc2a3405fUL,
304 0x161dc372UL, 0xbce2250cUL, 0x283c498bUL, 0xff0d9541UL,
305 0x39a80171UL, 0x080cb3deUL, 0xd8b4e49cUL, 0x6456c190UL,
306 0x7bcb8461UL, 0xd532b670UL, 0x486c5c74UL, 0xd0b85742UL,
307};
308
309static const uint32 Td4[] = {
310 0x52525252UL, 0x09090909UL, 0x6a6a6a6aUL, 0xd5d5d5d5UL,
311 0x30303030UL, 0x36363636UL, 0xa5a5a5a5UL, 0x38383838UL,
312 0xbfbfbfbfUL, 0x40404040UL, 0xa3a3a3a3UL, 0x9e9e9e9eUL,
313 0x81818181UL, 0xf3f3f3f3UL, 0xd7d7d7d7UL, 0xfbfbfbfbUL,
314 0x7c7c7c7cUL, 0xe3e3e3e3UL, 0x39393939UL, 0x82828282UL,
315 0x9b9b9b9bUL, 0x2f2f2f2fUL, 0xffffffffUL, 0x87878787UL,
316 0x34343434UL, 0x8e8e8e8eUL, 0x43434343UL, 0x44444444UL,
317 0xc4c4c4c4UL, 0xdedededeUL, 0xe9e9e9e9UL, 0xcbcbcbcbUL,
318 0x54545454UL, 0x7b7b7b7bUL, 0x94949494UL, 0x32323232UL,
319 0xa6a6a6a6UL, 0xc2c2c2c2UL, 0x23232323UL, 0x3d3d3d3dUL,
320 0xeeeeeeeeUL, 0x4c4c4c4cUL, 0x95959595UL, 0x0b0b0b0bUL,
321 0x42424242UL, 0xfafafafaUL, 0xc3c3c3c3UL, 0x4e4e4e4eUL,
322 0x08080808UL, 0x2e2e2e2eUL, 0xa1a1a1a1UL, 0x66666666UL,
323 0x28282828UL, 0xd9d9d9d9UL, 0x24242424UL, 0xb2b2b2b2UL,
324 0x76767676UL, 0x5b5b5b5bUL, 0xa2a2a2a2UL, 0x49494949UL,
325 0x6d6d6d6dUL, 0x8b8b8b8bUL, 0xd1d1d1d1UL, 0x25252525UL,
326 0x72727272UL, 0xf8f8f8f8UL, 0xf6f6f6f6UL, 0x64646464UL,
327 0x86868686UL, 0x68686868UL, 0x98989898UL, 0x16161616UL,
328 0xd4d4d4d4UL, 0xa4a4a4a4UL, 0x5c5c5c5cUL, 0xccccccccUL,
329 0x5d5d5d5dUL, 0x65656565UL, 0xb6b6b6b6UL, 0x92929292UL,
330 0x6c6c6c6cUL, 0x70707070UL, 0x48484848UL, 0x50505050UL,
331 0xfdfdfdfdUL, 0xededededUL, 0xb9b9b9b9UL, 0xdadadadaUL,
332 0x5e5e5e5eUL, 0x15151515UL, 0x46464646UL, 0x57575757UL,
333 0xa7a7a7a7UL, 0x8d8d8d8dUL, 0x9d9d9d9dUL, 0x84848484UL,
334 0x90909090UL, 0xd8d8d8d8UL, 0xababababUL, 0x00000000UL,
335 0x8c8c8c8cUL, 0xbcbcbcbcUL, 0xd3d3d3d3UL, 0x0a0a0a0aUL,
336 0xf7f7f7f7UL, 0xe4e4e4e4UL, 0x58585858UL, 0x05050505UL,
337 0xb8b8b8b8UL, 0xb3b3b3b3UL, 0x45454545UL, 0x06060606UL,
338 0xd0d0d0d0UL, 0x2c2c2c2cUL, 0x1e1e1e1eUL, 0x8f8f8f8fUL,
339 0xcacacacaUL, 0x3f3f3f3fUL, 0x0f0f0f0fUL, 0x02020202UL,
340 0xc1c1c1c1UL, 0xafafafafUL, 0xbdbdbdbdUL, 0x03030303UL,
341 0x01010101UL, 0x13131313UL, 0x8a8a8a8aUL, 0x6b6b6b6bUL,
342 0x3a3a3a3aUL, 0x91919191UL, 0x11111111UL, 0x41414141UL,
343 0x4f4f4f4fUL, 0x67676767UL, 0xdcdcdcdcUL, 0xeaeaeaeaUL,
344 0x97979797UL, 0xf2f2f2f2UL, 0xcfcfcfcfUL, 0xcecececeUL,
345 0xf0f0f0f0UL, 0xb4b4b4b4UL, 0xe6e6e6e6UL, 0x73737373UL,
346 0x96969696UL, 0xacacacacUL, 0x74747474UL, 0x22222222UL,
347 0xe7e7e7e7UL, 0xadadadadUL, 0x35353535UL, 0x85858585UL,
348 0xe2e2e2e2UL, 0xf9f9f9f9UL, 0x37373737UL, 0xe8e8e8e8UL,
349 0x1c1c1c1cUL, 0x75757575UL, 0xdfdfdfdfUL, 0x6e6e6e6eUL,
350 0x47474747UL, 0xf1f1f1f1UL, 0x1a1a1a1aUL, 0x71717171UL,
351 0x1d1d1d1dUL, 0x29292929UL, 0xc5c5c5c5UL, 0x89898989UL,
352 0x6f6f6f6fUL, 0xb7b7b7b7UL, 0x62626262UL, 0x0e0e0e0eUL,
353 0xaaaaaaaaUL, 0x18181818UL, 0xbebebebeUL, 0x1b1b1b1bUL,
354 0xfcfcfcfcUL, 0x56565656UL, 0x3e3e3e3eUL, 0x4b4b4b4bUL,
355 0xc6c6c6c6UL, 0xd2d2d2d2UL, 0x79797979UL, 0x20202020UL,
356 0x9a9a9a9aUL, 0xdbdbdbdbUL, 0xc0c0c0c0UL, 0xfefefefeUL,
357 0x78787878UL, 0xcdcdcdcdUL, 0x5a5a5a5aUL, 0xf4f4f4f4UL,
358 0x1f1f1f1fUL, 0xddddddddUL, 0xa8a8a8a8UL, 0x33333333UL,
359 0x88888888UL, 0x07070707UL, 0xc7c7c7c7UL, 0x31313131UL,
360 0xb1b1b1b1UL, 0x12121212UL, 0x10101010UL, 0x59595959UL,
361 0x27272727UL, 0x80808080UL, 0xececececUL, 0x5f5f5f5fUL,
362 0x60606060UL, 0x51515151UL, 0x7f7f7f7fUL, 0xa9a9a9a9UL,
363 0x19191919UL, 0xb5b5b5b5UL, 0x4a4a4a4aUL, 0x0d0d0d0dUL,
364 0x2d2d2d2dUL, 0xe5e5e5e5UL, 0x7a7a7a7aUL, 0x9f9f9f9fUL,
365 0x93939393UL, 0xc9c9c9c9UL, 0x9c9c9c9cUL, 0xefefefefUL,
366 0xa0a0a0a0UL, 0xe0e0e0e0UL, 0x3b3b3b3bUL, 0x4d4d4d4dUL,
367 0xaeaeaeaeUL, 0x2a2a2a2aUL, 0xf5f5f5f5UL, 0xb0b0b0b0UL,
368 0xc8c8c8c8UL, 0xebebebebUL, 0xbbbbbbbbUL, 0x3c3c3c3cUL,
369 0x83838383UL, 0x53535353UL, 0x99999999UL, 0x61616161UL,
370 0x17171717UL, 0x2b2b2b2bUL, 0x04040404UL, 0x7e7e7e7eUL,
371 0xbabababaUL, 0x77777777UL, 0xd6d6d6d6UL, 0x26262626UL,
372 0xe1e1e1e1UL, 0x69696969UL, 0x14141414UL, 0x63636363UL,
373 0x55555555UL, 0x21212121UL, 0x0c0c0c0cUL, 0x7d7d7d7dUL,
374 0xe1f27f3aUL, 0xf5710fb0UL, 0xada0e5c4UL, 0x98e4c919UL
375};
376
377#ifndef PS_AES_IMPROVE_PERF_INCREASE_CODESIZE
378
379#define Te0(x) TE0[x]
380#define Te1(x) ROR(TE0[x], 8)
381#define Te2(x) ROR(TE0[x], 16)
382#define Te3(x) ROR(TE0[x], 24)
383
384#define Td0(x) TD0[x]
385#define Td1(x) ROR(TD0[x], 8)
386#define Td2(x) ROR(TD0[x], 16)
387#define Td3(x) ROR(TD0[x], 24)
388
389#define Te4_0 0x000000FF & Te4
390#define Te4_1 0x0000FF00 & Te4
391#define Te4_2 0x00FF0000 & Te4
392#define Te4_3 0xFF000000 & Te4
393
394#else /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */
395
396#define Te0(x) TE0[x]
397#define Te1(x) TE1[x]
398#define Te2(x) TE2[x]
399#define Te3(x) TE3[x]
400
401#define Td0(x) TD0[x]
402#define Td1(x) TD1[x]
403#define Td2(x) TD2[x]
404#define Td3(x) TD3[x]
405
406static const uint32 TE1[256] = {
407 0xa5c66363UL, 0x84f87c7cUL, 0x99ee7777UL, 0x8df67b7bUL,
408 0x0dfff2f2UL, 0xbdd66b6bUL, 0xb1de6f6fUL, 0x5491c5c5UL,
409 0x50603030UL, 0x03020101UL, 0xa9ce6767UL, 0x7d562b2bUL,
410 0x19e7fefeUL, 0x62b5d7d7UL, 0xe64dababUL, 0x9aec7676UL,
411 0x458fcacaUL, 0x9d1f8282UL, 0x4089c9c9UL, 0x87fa7d7dUL,
412 0x15effafaUL, 0xebb25959UL, 0xc98e4747UL, 0x0bfbf0f0UL,
413 0xec41adadUL, 0x67b3d4d4UL, 0xfd5fa2a2UL, 0xea45afafUL,
414 0xbf239c9cUL, 0xf753a4a4UL, 0x96e47272UL, 0x5b9bc0c0UL,
415 0xc275b7b7UL, 0x1ce1fdfdUL, 0xae3d9393UL, 0x6a4c2626UL,
416 0x5a6c3636UL, 0x417e3f3fUL, 0x02f5f7f7UL, 0x4f83ccccUL,
417 0x5c683434UL, 0xf451a5a5UL, 0x34d1e5e5UL, 0x08f9f1f1UL,
418 0x93e27171UL, 0x73abd8d8UL, 0x53623131UL, 0x3f2a1515UL,
419 0x0c080404UL, 0x5295c7c7UL, 0x65462323UL, 0x5e9dc3c3UL,
420 0x28301818UL, 0xa1379696UL, 0x0f0a0505UL, 0xb52f9a9aUL,
421 0x090e0707UL, 0x36241212UL, 0x9b1b8080UL, 0x3ddfe2e2UL,
422 0x26cdebebUL, 0x694e2727UL, 0xcd7fb2b2UL, 0x9fea7575UL,
423 0x1b120909UL, 0x9e1d8383UL, 0x74582c2cUL, 0x2e341a1aUL,
424 0x2d361b1bUL, 0xb2dc6e6eUL, 0xeeb45a5aUL, 0xfb5ba0a0UL,
425 0xf6a45252UL, 0x4d763b3bUL, 0x61b7d6d6UL, 0xce7db3b3UL,
426 0x7b522929UL, 0x3edde3e3UL, 0x715e2f2fUL, 0x97138484UL,
427 0xf5a65353UL, 0x68b9d1d1UL, 0x00000000UL, 0x2cc1ededUL,
428 0x60402020UL, 0x1fe3fcfcUL, 0xc879b1b1UL, 0xedb65b5bUL,
429 0xbed46a6aUL, 0x468dcbcbUL, 0xd967bebeUL, 0x4b723939UL,
430 0xde944a4aUL, 0xd4984c4cUL, 0xe8b05858UL, 0x4a85cfcfUL,
431 0x6bbbd0d0UL, 0x2ac5efefUL, 0xe54faaaaUL, 0x16edfbfbUL,
432 0xc5864343UL, 0xd79a4d4dUL, 0x55663333UL, 0x94118585UL,
433 0xcf8a4545UL, 0x10e9f9f9UL, 0x06040202UL, 0x81fe7f7fUL,
434 0xf0a05050UL, 0x44783c3cUL, 0xba259f9fUL, 0xe34ba8a8UL,
435 0xf3a25151UL, 0xfe5da3a3UL, 0xc0804040UL, 0x8a058f8fUL,
436 0xad3f9292UL, 0xbc219d9dUL, 0x48703838UL, 0x04f1f5f5UL,
437 0xdf63bcbcUL, 0xc177b6b6UL, 0x75afdadaUL, 0x63422121UL,
438 0x30201010UL, 0x1ae5ffffUL, 0x0efdf3f3UL, 0x6dbfd2d2UL,
439 0x4c81cdcdUL, 0x14180c0cUL, 0x35261313UL, 0x2fc3ececUL,
440 0xe1be5f5fUL, 0xa2359797UL, 0xcc884444UL, 0x392e1717UL,
441 0x5793c4c4UL, 0xf255a7a7UL, 0x82fc7e7eUL, 0x477a3d3dUL,
442 0xacc86464UL, 0xe7ba5d5dUL, 0x2b321919UL, 0x95e67373UL,
443 0xa0c06060UL, 0x98198181UL, 0xd19e4f4fUL, 0x7fa3dcdcUL,
444 0x66442222UL, 0x7e542a2aUL, 0xab3b9090UL, 0x830b8888UL,
445 0xca8c4646UL, 0x29c7eeeeUL, 0xd36bb8b8UL, 0x3c281414UL,
446 0x79a7dedeUL, 0xe2bc5e5eUL, 0x1d160b0bUL, 0x76addbdbUL,
447 0x3bdbe0e0UL, 0x56643232UL, 0x4e743a3aUL, 0x1e140a0aUL,
448 0xdb924949UL, 0x0a0c0606UL, 0x6c482424UL, 0xe4b85c5cUL,
449 0x5d9fc2c2UL, 0x6ebdd3d3UL, 0xef43acacUL, 0xa6c46262UL,
450 0xa8399191UL, 0xa4319595UL, 0x37d3e4e4UL, 0x8bf27979UL,
451 0x32d5e7e7UL, 0x438bc8c8UL, 0x596e3737UL, 0xb7da6d6dUL,
452 0x8c018d8dUL, 0x64b1d5d5UL, 0xd29c4e4eUL, 0xe049a9a9UL,
453 0xb4d86c6cUL, 0xfaac5656UL, 0x07f3f4f4UL, 0x25cfeaeaUL,
454 0xafca6565UL, 0x8ef47a7aUL, 0xe947aeaeUL, 0x18100808UL,
455 0xd56fbabaUL, 0x88f07878UL, 0x6f4a2525UL, 0x725c2e2eUL,
456 0x24381c1cUL, 0xf157a6a6UL, 0xc773b4b4UL, 0x5197c6c6UL,
457 0x23cbe8e8UL, 0x7ca1ddddUL, 0x9ce87474UL, 0x213e1f1fUL,
458 0xdd964b4bUL, 0xdc61bdbdUL, 0x860d8b8bUL, 0x850f8a8aUL,
459 0x90e07070UL, 0x427c3e3eUL, 0xc471b5b5UL, 0xaacc6666UL,
460 0xd8904848UL, 0x05060303UL, 0x01f7f6f6UL, 0x121c0e0eUL,
461 0xa3c26161UL, 0x5f6a3535UL, 0xf9ae5757UL, 0xd069b9b9UL,
462 0x91178686UL, 0x5899c1c1UL, 0x273a1d1dUL, 0xb9279e9eUL,
463 0x38d9e1e1UL, 0x13ebf8f8UL, 0xb32b9898UL, 0x33221111UL,
464 0xbbd26969UL, 0x70a9d9d9UL, 0x89078e8eUL, 0xa7339494UL,
465 0xb62d9b9bUL, 0x223c1e1eUL, 0x92158787UL, 0x20c9e9e9UL,
466 0x4987ceceUL, 0xffaa5555UL, 0x78502828UL, 0x7aa5dfdfUL,
467 0x8f038c8cUL, 0xf859a1a1UL, 0x80098989UL, 0x171a0d0dUL,
468 0xda65bfbfUL, 0x31d7e6e6UL, 0xc6844242UL, 0xb8d06868UL,
469 0xc3824141UL, 0xb0299999UL, 0x775a2d2dUL, 0x111e0f0fUL,
470 0xcb7bb0b0UL, 0xfca85454UL, 0xd66dbbbbUL, 0x3a2c1616UL,
471};
472static const uint32 TE2[256] = {
473 0x63a5c663UL, 0x7c84f87cUL, 0x7799ee77UL, 0x7b8df67bUL,
474 0xf20dfff2UL, 0x6bbdd66bUL, 0x6fb1de6fUL, 0xc55491c5UL,
475 0x30506030UL, 0x01030201UL, 0x67a9ce67UL, 0x2b7d562bUL,
476 0xfe19e7feUL, 0xd762b5d7UL, 0xabe64dabUL, 0x769aec76UL,
477 0xca458fcaUL, 0x829d1f82UL, 0xc94089c9UL, 0x7d87fa7dUL,
478 0xfa15effaUL, 0x59ebb259UL, 0x47c98e47UL, 0xf00bfbf0UL,
479 0xadec41adUL, 0xd467b3d4UL, 0xa2fd5fa2UL, 0xafea45afUL,
480 0x9cbf239cUL, 0xa4f753a4UL, 0x7296e472UL, 0xc05b9bc0UL,
481 0xb7c275b7UL, 0xfd1ce1fdUL, 0x93ae3d93UL, 0x266a4c26UL,
482 0x365a6c36UL, 0x3f417e3fUL, 0xf702f5f7UL, 0xcc4f83ccUL,
483 0x345c6834UL, 0xa5f451a5UL, 0xe534d1e5UL, 0xf108f9f1UL,
484 0x7193e271UL, 0xd873abd8UL, 0x31536231UL, 0x153f2a15UL,
485 0x040c0804UL, 0xc75295c7UL, 0x23654623UL, 0xc35e9dc3UL,
486 0x18283018UL, 0x96a13796UL, 0x050f0a05UL, 0x9ab52f9aUL,
487 0x07090e07UL, 0x12362412UL, 0x809b1b80UL, 0xe23ddfe2UL,
488 0xeb26cdebUL, 0x27694e27UL, 0xb2cd7fb2UL, 0x759fea75UL,
489 0x091b1209UL, 0x839e1d83UL, 0x2c74582cUL, 0x1a2e341aUL,
490 0x1b2d361bUL, 0x6eb2dc6eUL, 0x5aeeb45aUL, 0xa0fb5ba0UL,
491 0x52f6a452UL, 0x3b4d763bUL, 0xd661b7d6UL, 0xb3ce7db3UL,
492 0x297b5229UL, 0xe33edde3UL, 0x2f715e2fUL, 0x84971384UL,
493 0x53f5a653UL, 0xd168b9d1UL, 0x00000000UL, 0xed2cc1edUL,
494 0x20604020UL, 0xfc1fe3fcUL, 0xb1c879b1UL, 0x5bedb65bUL,
495 0x6abed46aUL, 0xcb468dcbUL, 0xbed967beUL, 0x394b7239UL,
496 0x4ade944aUL, 0x4cd4984cUL, 0x58e8b058UL, 0xcf4a85cfUL,
497 0xd06bbbd0UL, 0xef2ac5efUL, 0xaae54faaUL, 0xfb16edfbUL,
498 0x43c58643UL, 0x4dd79a4dUL, 0x33556633UL, 0x85941185UL,
499 0x45cf8a45UL, 0xf910e9f9UL, 0x02060402UL, 0x7f81fe7fUL,
500 0x50f0a050UL, 0x3c44783cUL, 0x9fba259fUL, 0xa8e34ba8UL,
501 0x51f3a251UL, 0xa3fe5da3UL, 0x40c08040UL, 0x8f8a058fUL,
502 0x92ad3f92UL, 0x9dbc219dUL, 0x38487038UL, 0xf504f1f5UL,
503 0xbcdf63bcUL, 0xb6c177b6UL, 0xda75afdaUL, 0x21634221UL,
504 0x10302010UL, 0xff1ae5ffUL, 0xf30efdf3UL, 0xd26dbfd2UL,
505 0xcd4c81cdUL, 0x0c14180cUL, 0x13352613UL, 0xec2fc3ecUL,
506 0x5fe1be5fUL, 0x97a23597UL, 0x44cc8844UL, 0x17392e17UL,
507 0xc45793c4UL, 0xa7f255a7UL, 0x7e82fc7eUL, 0x3d477a3dUL,
508 0x64acc864UL, 0x5de7ba5dUL, 0x192b3219UL, 0x7395e673UL,
509 0x60a0c060UL, 0x81981981UL, 0x4fd19e4fUL, 0xdc7fa3dcUL,
510 0x22664422UL, 0x2a7e542aUL, 0x90ab3b90UL, 0x88830b88UL,
511 0x46ca8c46UL, 0xee29c7eeUL, 0xb8d36bb8UL, 0x143c2814UL,
512 0xde79a7deUL, 0x5ee2bc5eUL, 0x0b1d160bUL, 0xdb76addbUL,
513 0xe03bdbe0UL, 0x32566432UL, 0x3a4e743aUL, 0x0a1e140aUL,
514 0x49db9249UL, 0x060a0c06UL, 0x246c4824UL, 0x5ce4b85cUL,
515 0xc25d9fc2UL, 0xd36ebdd3UL, 0xacef43acUL, 0x62a6c462UL,
516 0x91a83991UL, 0x95a43195UL, 0xe437d3e4UL, 0x798bf279UL,
517 0xe732d5e7UL, 0xc8438bc8UL, 0x37596e37UL, 0x6db7da6dUL,
518 0x8d8c018dUL, 0xd564b1d5UL, 0x4ed29c4eUL, 0xa9e049a9UL,
519 0x6cb4d86cUL, 0x56faac56UL, 0xf407f3f4UL, 0xea25cfeaUL,
520 0x65afca65UL, 0x7a8ef47aUL, 0xaee947aeUL, 0x08181008UL,
521 0xbad56fbaUL, 0x7888f078UL, 0x256f4a25UL, 0x2e725c2eUL,
522 0x1c24381cUL, 0xa6f157a6UL, 0xb4c773b4UL, 0xc65197c6UL,
523 0xe823cbe8UL, 0xdd7ca1ddUL, 0x749ce874UL, 0x1f213e1fUL,
524 0x4bdd964bUL, 0xbddc61bdUL, 0x8b860d8bUL, 0x8a850f8aUL,
525 0x7090e070UL, 0x3e427c3eUL, 0xb5c471b5UL, 0x66aacc66UL,
526 0x48d89048UL, 0x03050603UL, 0xf601f7f6UL, 0x0e121c0eUL,
527 0x61a3c261UL, 0x355f6a35UL, 0x57f9ae57UL, 0xb9d069b9UL,
528 0x86911786UL, 0xc15899c1UL, 0x1d273a1dUL, 0x9eb9279eUL,
529 0xe138d9e1UL, 0xf813ebf8UL, 0x98b32b98UL, 0x11332211UL,
530 0x69bbd269UL, 0xd970a9d9UL, 0x8e89078eUL, 0x94a73394UL,
531 0x9bb62d9bUL, 0x1e223c1eUL, 0x87921587UL, 0xe920c9e9UL,
532 0xce4987ceUL, 0x55ffaa55UL, 0x28785028UL, 0xdf7aa5dfUL,
533 0x8c8f038cUL, 0xa1f859a1UL, 0x89800989UL, 0x0d171a0dUL,
534 0xbfda65bfUL, 0xe631d7e6UL, 0x42c68442UL, 0x68b8d068UL,
535 0x41c38241UL, 0x99b02999UL, 0x2d775a2dUL, 0x0f111e0fUL,
536 0xb0cb7bb0UL, 0x54fca854UL, 0xbbd66dbbUL, 0x163a2c16UL,
537};
538static const uint32 TE3[256] = {
539
540 0x6363a5c6UL, 0x7c7c84f8UL, 0x777799eeUL, 0x7b7b8df6UL,
541 0xf2f20dffUL, 0x6b6bbdd6UL, 0x6f6fb1deUL, 0xc5c55491UL,
542 0x30305060UL, 0x01010302UL, 0x6767a9ceUL, 0x2b2b7d56UL,
543 0xfefe19e7UL, 0xd7d762b5UL, 0xababe64dUL, 0x76769aecUL,
544 0xcaca458fUL, 0x82829d1fUL, 0xc9c94089UL, 0x7d7d87faUL,
545 0xfafa15efUL, 0x5959ebb2UL, 0x4747c98eUL, 0xf0f00bfbUL,
546 0xadadec41UL, 0xd4d467b3UL, 0xa2a2fd5fUL, 0xafafea45UL,
547 0x9c9cbf23UL, 0xa4a4f753UL, 0x727296e4UL, 0xc0c05b9bUL,
548 0xb7b7c275UL, 0xfdfd1ce1UL, 0x9393ae3dUL, 0x26266a4cUL,
549 0x36365a6cUL, 0x3f3f417eUL, 0xf7f702f5UL, 0xcccc4f83UL,
550 0x34345c68UL, 0xa5a5f451UL, 0xe5e534d1UL, 0xf1f108f9UL,
551 0x717193e2UL, 0xd8d873abUL, 0x31315362UL, 0x15153f2aUL,
552 0x04040c08UL, 0xc7c75295UL, 0x23236546UL, 0xc3c35e9dUL,
553 0x18182830UL, 0x9696a137UL, 0x05050f0aUL, 0x9a9ab52fUL,
554 0x0707090eUL, 0x12123624UL, 0x80809b1bUL, 0xe2e23ddfUL,
555 0xebeb26cdUL, 0x2727694eUL, 0xb2b2cd7fUL, 0x75759feaUL,
556 0x09091b12UL, 0x83839e1dUL, 0x2c2c7458UL, 0x1a1a2e34UL,
557 0x1b1b2d36UL, 0x6e6eb2dcUL, 0x5a5aeeb4UL, 0xa0a0fb5bUL,
558 0x5252f6a4UL, 0x3b3b4d76UL, 0xd6d661b7UL, 0xb3b3ce7dUL,
559 0x29297b52UL, 0xe3e33eddUL, 0x2f2f715eUL, 0x84849713UL,
560 0x5353f5a6UL, 0xd1d168b9UL, 0x00000000UL, 0xeded2cc1UL,
561 0x20206040UL, 0xfcfc1fe3UL, 0xb1b1c879UL, 0x5b5bedb6UL,
562 0x6a6abed4UL, 0xcbcb468dUL, 0xbebed967UL, 0x39394b72UL,
563 0x4a4ade94UL, 0x4c4cd498UL, 0x5858e8b0UL, 0xcfcf4a85UL,
564 0xd0d06bbbUL, 0xefef2ac5UL, 0xaaaae54fUL, 0xfbfb16edUL,
565 0x4343c586UL, 0x4d4dd79aUL, 0x33335566UL, 0x85859411UL,
566 0x4545cf8aUL, 0xf9f910e9UL, 0x02020604UL, 0x7f7f81feUL,
567 0x5050f0a0UL, 0x3c3c4478UL, 0x9f9fba25UL, 0xa8a8e34bUL,
568 0x5151f3a2UL, 0xa3a3fe5dUL, 0x4040c080UL, 0x8f8f8a05UL,
569 0x9292ad3fUL, 0x9d9dbc21UL, 0x38384870UL, 0xf5f504f1UL,
570 0xbcbcdf63UL, 0xb6b6c177UL, 0xdada75afUL, 0x21216342UL,
571 0x10103020UL, 0xffff1ae5UL, 0xf3f30efdUL, 0xd2d26dbfUL,
572 0xcdcd4c81UL, 0x0c0c1418UL, 0x13133526UL, 0xecec2fc3UL,
573 0x5f5fe1beUL, 0x9797a235UL, 0x4444cc88UL, 0x1717392eUL,
574 0xc4c45793UL, 0xa7a7f255UL, 0x7e7e82fcUL, 0x3d3d477aUL,
575 0x6464acc8UL, 0x5d5de7baUL, 0x19192b32UL, 0x737395e6UL,
576 0x6060a0c0UL, 0x81819819UL, 0x4f4fd19eUL, 0xdcdc7fa3UL,
577 0x22226644UL, 0x2a2a7e54UL, 0x9090ab3bUL, 0x8888830bUL,
578 0x4646ca8cUL, 0xeeee29c7UL, 0xb8b8d36bUL, 0x14143c28UL,
579 0xdede79a7UL, 0x5e5ee2bcUL, 0x0b0b1d16UL, 0xdbdb76adUL,
580 0xe0e03bdbUL, 0x32325664UL, 0x3a3a4e74UL, 0x0a0a1e14UL,
581 0x4949db92UL, 0x06060a0cUL, 0x24246c48UL, 0x5c5ce4b8UL,
582 0xc2c25d9fUL, 0xd3d36ebdUL, 0xacacef43UL, 0x6262a6c4UL,
583 0x9191a839UL, 0x9595a431UL, 0xe4e437d3UL, 0x79798bf2UL,
584 0xe7e732d5UL, 0xc8c8438bUL, 0x3737596eUL, 0x6d6db7daUL,
585 0x8d8d8c01UL, 0xd5d564b1UL, 0x4e4ed29cUL, 0xa9a9e049UL,
586 0x6c6cb4d8UL, 0x5656faacUL, 0xf4f407f3UL, 0xeaea25cfUL,
587 0x6565afcaUL, 0x7a7a8ef4UL, 0xaeaee947UL, 0x08081810UL,
588 0xbabad56fUL, 0x787888f0UL, 0x25256f4aUL, 0x2e2e725cUL,
589 0x1c1c2438UL, 0xa6a6f157UL, 0xb4b4c773UL, 0xc6c65197UL,
590 0xe8e823cbUL, 0xdddd7ca1UL, 0x74749ce8UL, 0x1f1f213eUL,
591 0x4b4bdd96UL, 0xbdbddc61UL, 0x8b8b860dUL, 0x8a8a850fUL,
592 0x707090e0UL, 0x3e3e427cUL, 0xb5b5c471UL, 0x6666aaccUL,
593 0x4848d890UL, 0x03030506UL, 0xf6f601f7UL, 0x0e0e121cUL,
594 0x6161a3c2UL, 0x35355f6aUL, 0x5757f9aeUL, 0xb9b9d069UL,
595 0x86869117UL, 0xc1c15899UL, 0x1d1d273aUL, 0x9e9eb927UL,
596 0xe1e138d9UL, 0xf8f813ebUL, 0x9898b32bUL, 0x11113322UL,
597 0x6969bbd2UL, 0xd9d970a9UL, 0x8e8e8907UL, 0x9494a733UL,
598 0x9b9bb62dUL, 0x1e1e223cUL, 0x87879215UL, 0xe9e920c9UL,
599 0xcece4987UL, 0x5555ffaaUL, 0x28287850UL, 0xdfdf7aa5UL,
600 0x8c8c8f03UL, 0xa1a1f859UL, 0x89898009UL, 0x0d0d171aUL,
601 0xbfbfda65UL, 0xe6e631d7UL, 0x4242c684UL, 0x6868b8d0UL,
602 0x4141c382UL, 0x9999b029UL, 0x2d2d775aUL, 0x0f0f111eUL,
603 0xb0b0cb7bUL, 0x5454fca8UL, 0xbbbbd66dUL, 0x16163a2cUL,
604};
605
606static const uint32 Te4_0[] = {
6070x00000063UL, 0x0000007cUL, 0x00000077UL, 0x0000007bUL, 0x000000f2UL, 0x0000006bUL, 0x0000006fUL, 0x000000c5UL,
6080x00000030UL, 0x00000001UL, 0x00000067UL, 0x0000002bUL, 0x000000feUL, 0x000000d7UL, 0x000000abUL, 0x00000076UL,
6090x000000caUL, 0x00000082UL, 0x000000c9UL, 0x0000007dUL, 0x000000faUL, 0x00000059UL, 0x00000047UL, 0x000000f0UL,
6100x000000adUL, 0x000000d4UL, 0x000000a2UL, 0x000000afUL, 0x0000009cUL, 0x000000a4UL, 0x00000072UL, 0x000000c0UL,
6110x000000b7UL, 0x000000fdUL, 0x00000093UL, 0x00000026UL, 0x00000036UL, 0x0000003fUL, 0x000000f7UL, 0x000000ccUL,
6120x00000034UL, 0x000000a5UL, 0x000000e5UL, 0x000000f1UL, 0x00000071UL, 0x000000d8UL, 0x00000031UL, 0x00000015UL,
6130x00000004UL, 0x000000c7UL, 0x00000023UL, 0x000000c3UL, 0x00000018UL, 0x00000096UL, 0x00000005UL, 0x0000009aUL,
6140x00000007UL, 0x00000012UL, 0x00000080UL, 0x000000e2UL, 0x000000ebUL, 0x00000027UL, 0x000000b2UL, 0x00000075UL,
6150x00000009UL, 0x00000083UL, 0x0000002cUL, 0x0000001aUL, 0x0000001bUL, 0x0000006eUL, 0x0000005aUL, 0x000000a0UL,
6160x00000052UL, 0x0000003bUL, 0x000000d6UL, 0x000000b3UL, 0x00000029UL, 0x000000e3UL, 0x0000002fUL, 0x00000084UL,
6170x00000053UL, 0x000000d1UL, 0x00000000UL, 0x000000edUL, 0x00000020UL, 0x000000fcUL, 0x000000b1UL, 0x0000005bUL,
6180x0000006aUL, 0x000000cbUL, 0x000000beUL, 0x00000039UL, 0x0000004aUL, 0x0000004cUL, 0x00000058UL, 0x000000cfUL,
6190x000000d0UL, 0x000000efUL, 0x000000aaUL, 0x000000fbUL, 0x00000043UL, 0x0000004dUL, 0x00000033UL, 0x00000085UL,
6200x00000045UL, 0x000000f9UL, 0x00000002UL, 0x0000007fUL, 0x00000050UL, 0x0000003cUL, 0x0000009fUL, 0x000000a8UL,
6210x00000051UL, 0x000000a3UL, 0x00000040UL, 0x0000008fUL, 0x00000092UL, 0x0000009dUL, 0x00000038UL, 0x000000f5UL,
6220x000000bcUL, 0x000000b6UL, 0x000000daUL, 0x00000021UL, 0x00000010UL, 0x000000ffUL, 0x000000f3UL, 0x000000d2UL,
6230x000000cdUL, 0x0000000cUL, 0x00000013UL, 0x000000ecUL, 0x0000005fUL, 0x00000097UL, 0x00000044UL, 0x00000017UL,
6240x000000c4UL, 0x000000a7UL, 0x0000007eUL, 0x0000003dUL, 0x00000064UL, 0x0000005dUL, 0x00000019UL, 0x00000073UL,
6250x00000060UL, 0x00000081UL, 0x0000004fUL, 0x000000dcUL, 0x00000022UL, 0x0000002aUL, 0x00000090UL, 0x00000088UL,
6260x00000046UL, 0x000000eeUL, 0x000000b8UL, 0x00000014UL, 0x000000deUL, 0x0000005eUL, 0x0000000bUL, 0x000000dbUL,
6270x000000e0UL, 0x00000032UL, 0x0000003aUL, 0x0000000aUL, 0x00000049UL, 0x00000006UL, 0x00000024UL, 0x0000005cUL,
6280x000000c2UL, 0x000000d3UL, 0x000000acUL, 0x00000062UL, 0x00000091UL, 0x00000095UL, 0x000000e4UL, 0x00000079UL,
6290x000000e7UL, 0x000000c8UL, 0x00000037UL, 0x0000006dUL, 0x0000008dUL, 0x000000d5UL, 0x0000004eUL, 0x000000a9UL,
6300x0000006cUL, 0x00000056UL, 0x000000f4UL, 0x000000eaUL, 0x00000065UL, 0x0000007aUL, 0x000000aeUL, 0x00000008UL,
6310x000000baUL, 0x00000078UL, 0x00000025UL, 0x0000002eUL, 0x0000001cUL, 0x000000a6UL, 0x000000b4UL, 0x000000c6UL,
6320x000000e8UL, 0x000000ddUL, 0x00000074UL, 0x0000001fUL, 0x0000004bUL, 0x000000bdUL, 0x0000008bUL, 0x0000008aUL,
6330x00000070UL, 0x0000003eUL, 0x000000b5UL, 0x00000066UL, 0x00000048UL, 0x00000003UL, 0x000000f6UL, 0x0000000eUL,
6340x00000061UL, 0x00000035UL, 0x00000057UL, 0x000000b9UL, 0x00000086UL, 0x000000c1UL, 0x0000001dUL, 0x0000009eUL,
6350x000000e1UL, 0x000000f8UL, 0x00000098UL, 0x00000011UL, 0x00000069UL, 0x000000d9UL, 0x0000008eUL, 0x00000094UL,
6360x0000009bUL, 0x0000001eUL, 0x00000087UL, 0x000000e9UL, 0x000000ceUL, 0x00000055UL, 0x00000028UL, 0x000000dfUL,
6370x0000008cUL, 0x000000a1UL, 0x00000089UL, 0x0000000dUL, 0x000000bfUL, 0x000000e6UL, 0x00000042UL, 0x00000068UL,
6380x00000041UL, 0x00000099UL, 0x0000002dUL, 0x0000000fUL, 0x000000b0UL, 0x00000054UL, 0x000000bbUL, 0x00000016UL
639};
640
641static const uint32 Te4_1[] = {
6420x00006300UL, 0x00007c00UL, 0x00007700UL, 0x00007b00UL, 0x0000f200UL, 0x00006b00UL, 0x00006f00UL, 0x0000c500UL,
6430x00003000UL, 0x00000100UL, 0x00006700UL, 0x00002b00UL, 0x0000fe00UL, 0x0000d700UL, 0x0000ab00UL, 0x00007600UL,
6440x0000ca00UL, 0x00008200UL, 0x0000c900UL, 0x00007d00UL, 0x0000fa00UL, 0x00005900UL, 0x00004700UL, 0x0000f000UL,
6450x0000ad00UL, 0x0000d400UL, 0x0000a200UL, 0x0000af00UL, 0x00009c00UL, 0x0000a400UL, 0x00007200UL, 0x0000c000UL,
6460x0000b700UL, 0x0000fd00UL, 0x00009300UL, 0x00002600UL, 0x00003600UL, 0x00003f00UL, 0x0000f700UL, 0x0000cc00UL,
6470x00003400UL, 0x0000a500UL, 0x0000e500UL, 0x0000f100UL, 0x00007100UL, 0x0000d800UL, 0x00003100UL, 0x00001500UL,
6480x00000400UL, 0x0000c700UL, 0x00002300UL, 0x0000c300UL, 0x00001800UL, 0x00009600UL, 0x00000500UL, 0x00009a00UL,
6490x00000700UL, 0x00001200UL, 0x00008000UL, 0x0000e200UL, 0x0000eb00UL, 0x00002700UL, 0x0000b200UL, 0x00007500UL,
6500x00000900UL, 0x00008300UL, 0x00002c00UL, 0x00001a00UL, 0x00001b00UL, 0x00006e00UL, 0x00005a00UL, 0x0000a000UL,
6510x00005200UL, 0x00003b00UL, 0x0000d600UL, 0x0000b300UL, 0x00002900UL, 0x0000e300UL, 0x00002f00UL, 0x00008400UL,
6520x00005300UL, 0x0000d100UL, 0x00000000UL, 0x0000ed00UL, 0x00002000UL, 0x0000fc00UL, 0x0000b100UL, 0x00005b00UL,
6530x00006a00UL, 0x0000cb00UL, 0x0000be00UL, 0x00003900UL, 0x00004a00UL, 0x00004c00UL, 0x00005800UL, 0x0000cf00UL,
6540x0000d000UL, 0x0000ef00UL, 0x0000aa00UL, 0x0000fb00UL, 0x00004300UL, 0x00004d00UL, 0x00003300UL, 0x00008500UL,
6550x00004500UL, 0x0000f900UL, 0x00000200UL, 0x00007f00UL, 0x00005000UL, 0x00003c00UL, 0x00009f00UL, 0x0000a800UL,
6560x00005100UL, 0x0000a300UL, 0x00004000UL, 0x00008f00UL, 0x00009200UL, 0x00009d00UL, 0x00003800UL, 0x0000f500UL,
6570x0000bc00UL, 0x0000b600UL, 0x0000da00UL, 0x00002100UL, 0x00001000UL, 0x0000ff00UL, 0x0000f300UL, 0x0000d200UL,
6580x0000cd00UL, 0x00000c00UL, 0x00001300UL, 0x0000ec00UL, 0x00005f00UL, 0x00009700UL, 0x00004400UL, 0x00001700UL,
6590x0000c400UL, 0x0000a700UL, 0x00007e00UL, 0x00003d00UL, 0x00006400UL, 0x00005d00UL, 0x00001900UL, 0x00007300UL,
6600x00006000UL, 0x00008100UL, 0x00004f00UL, 0x0000dc00UL, 0x00002200UL, 0x00002a00UL, 0x00009000UL, 0x00008800UL,
6610x00004600UL, 0x0000ee00UL, 0x0000b800UL, 0x00001400UL, 0x0000de00UL, 0x00005e00UL, 0x00000b00UL, 0x0000db00UL,
6620x0000e000UL, 0x00003200UL, 0x00003a00UL, 0x00000a00UL, 0x00004900UL, 0x00000600UL, 0x00002400UL, 0x00005c00UL,
6630x0000c200UL, 0x0000d300UL, 0x0000ac00UL, 0x00006200UL, 0x00009100UL, 0x00009500UL, 0x0000e400UL, 0x00007900UL,
6640x0000e700UL, 0x0000c800UL, 0x00003700UL, 0x00006d00UL, 0x00008d00UL, 0x0000d500UL, 0x00004e00UL, 0x0000a900UL,
6650x00006c00UL, 0x00005600UL, 0x0000f400UL, 0x0000ea00UL, 0x00006500UL, 0x00007a00UL, 0x0000ae00UL, 0x00000800UL,
6660x0000ba00UL, 0x00007800UL, 0x00002500UL, 0x00002e00UL, 0x00001c00UL, 0x0000a600UL, 0x0000b400UL, 0x0000c600UL,
6670x0000e800UL, 0x0000dd00UL, 0x00007400UL, 0x00001f00UL, 0x00004b00UL, 0x0000bd00UL, 0x00008b00UL, 0x00008a00UL,
6680x00007000UL, 0x00003e00UL, 0x0000b500UL, 0x00006600UL, 0x00004800UL, 0x00000300UL, 0x0000f600UL, 0x00000e00UL,
6690x00006100UL, 0x00003500UL, 0x00005700UL, 0x0000b900UL, 0x00008600UL, 0x0000c100UL, 0x00001d00UL, 0x00009e00UL,
6700x0000e100UL, 0x0000f800UL, 0x00009800UL, 0x00001100UL, 0x00006900UL, 0x0000d900UL, 0x00008e00UL, 0x00009400UL,
6710x00009b00UL, 0x00001e00UL, 0x00008700UL, 0x0000e900UL, 0x0000ce00UL, 0x00005500UL, 0x00002800UL, 0x0000df00UL,
6720x00008c00UL, 0x0000a100UL, 0x00008900UL, 0x00000d00UL, 0x0000bf00UL, 0x0000e600UL, 0x00004200UL, 0x00006800UL,
6730x00004100UL, 0x00009900UL, 0x00002d00UL, 0x00000f00UL, 0x0000b000UL, 0x00005400UL, 0x0000bb00UL, 0x00001600UL
674};
675
676static const uint32 Te4_2[] = {
6770x00630000UL, 0x007c0000UL, 0x00770000UL, 0x007b0000UL, 0x00f20000UL, 0x006b0000UL, 0x006f0000UL, 0x00c50000UL,
6780x00300000UL, 0x00010000UL, 0x00670000UL, 0x002b0000UL, 0x00fe0000UL, 0x00d70000UL, 0x00ab0000UL, 0x00760000UL,
6790x00ca0000UL, 0x00820000UL, 0x00c90000UL, 0x007d0000UL, 0x00fa0000UL, 0x00590000UL, 0x00470000UL, 0x00f00000UL,
6800x00ad0000UL, 0x00d40000UL, 0x00a20000UL, 0x00af0000UL, 0x009c0000UL, 0x00a40000UL, 0x00720000UL, 0x00c00000UL,
6810x00b70000UL, 0x00fd0000UL, 0x00930000UL, 0x00260000UL, 0x00360000UL, 0x003f0000UL, 0x00f70000UL, 0x00cc0000UL,
6820x00340000UL, 0x00a50000UL, 0x00e50000UL, 0x00f10000UL, 0x00710000UL, 0x00d80000UL, 0x00310000UL, 0x00150000UL,
6830x00040000UL, 0x00c70000UL, 0x00230000UL, 0x00c30000UL, 0x00180000UL, 0x00960000UL, 0x00050000UL, 0x009a0000UL,
6840x00070000UL, 0x00120000UL, 0x00800000UL, 0x00e20000UL, 0x00eb0000UL, 0x00270000UL, 0x00b20000UL, 0x00750000UL,
6850x00090000UL, 0x00830000UL, 0x002c0000UL, 0x001a0000UL, 0x001b0000UL, 0x006e0000UL, 0x005a0000UL, 0x00a00000UL,
6860x00520000UL, 0x003b0000UL, 0x00d60000UL, 0x00b30000UL, 0x00290000UL, 0x00e30000UL, 0x002f0000UL, 0x00840000UL,
6870x00530000UL, 0x00d10000UL, 0x00000000UL, 0x00ed0000UL, 0x00200000UL, 0x00fc0000UL, 0x00b10000UL, 0x005b0000UL,
6880x006a0000UL, 0x00cb0000UL, 0x00be0000UL, 0x00390000UL, 0x004a0000UL, 0x004c0000UL, 0x00580000UL, 0x00cf0000UL,
6890x00d00000UL, 0x00ef0000UL, 0x00aa0000UL, 0x00fb0000UL, 0x00430000UL, 0x004d0000UL, 0x00330000UL, 0x00850000UL,
6900x00450000UL, 0x00f90000UL, 0x00020000UL, 0x007f0000UL, 0x00500000UL, 0x003c0000UL, 0x009f0000UL, 0x00a80000UL,
6910x00510000UL, 0x00a30000UL, 0x00400000UL, 0x008f0000UL, 0x00920000UL, 0x009d0000UL, 0x00380000UL, 0x00f50000UL,
6920x00bc0000UL, 0x00b60000UL, 0x00da0000UL, 0x00210000UL, 0x00100000UL, 0x00ff0000UL, 0x00f30000UL, 0x00d20000UL,
6930x00cd0000UL, 0x000c0000UL, 0x00130000UL, 0x00ec0000UL, 0x005f0000UL, 0x00970000UL, 0x00440000UL, 0x00170000UL,
6940x00c40000UL, 0x00a70000UL, 0x007e0000UL, 0x003d0000UL, 0x00640000UL, 0x005d0000UL, 0x00190000UL, 0x00730000UL,
6950x00600000UL, 0x00810000UL, 0x004f0000UL, 0x00dc0000UL, 0x00220000UL, 0x002a0000UL, 0x00900000UL, 0x00880000UL,
6960x00460000UL, 0x00ee0000UL, 0x00b80000UL, 0x00140000UL, 0x00de0000UL, 0x005e0000UL, 0x000b0000UL, 0x00db0000UL,
6970x00e00000UL, 0x00320000UL, 0x003a0000UL, 0x000a0000UL, 0x00490000UL, 0x00060000UL, 0x00240000UL, 0x005c0000UL,
6980x00c20000UL, 0x00d30000UL, 0x00ac0000UL, 0x00620000UL, 0x00910000UL, 0x00950000UL, 0x00e40000UL, 0x00790000UL,
6990x00e70000UL, 0x00c80000UL, 0x00370000UL, 0x006d0000UL, 0x008d0000UL, 0x00d50000UL, 0x004e0000UL, 0x00a90000UL,
7000x006c0000UL, 0x00560000UL, 0x00f40000UL, 0x00ea0000UL, 0x00650000UL, 0x007a0000UL, 0x00ae0000UL, 0x00080000UL,
7010x00ba0000UL, 0x00780000UL, 0x00250000UL, 0x002e0000UL, 0x001c0000UL, 0x00a60000UL, 0x00b40000UL, 0x00c60000UL,
7020x00e80000UL, 0x00dd0000UL, 0x00740000UL, 0x001f0000UL, 0x004b0000UL, 0x00bd0000UL, 0x008b0000UL, 0x008a0000UL,
7030x00700000UL, 0x003e0000UL, 0x00b50000UL, 0x00660000UL, 0x00480000UL, 0x00030000UL, 0x00f60000UL, 0x000e0000UL,
7040x00610000UL, 0x00350000UL, 0x00570000UL, 0x00b90000UL, 0x00860000UL, 0x00c10000UL, 0x001d0000UL, 0x009e0000UL,
7050x00e10000UL, 0x00f80000UL, 0x00980000UL, 0x00110000UL, 0x00690000UL, 0x00d90000UL, 0x008e0000UL, 0x00940000UL,
7060x009b0000UL, 0x001e0000UL, 0x00870000UL, 0x00e90000UL, 0x00ce0000UL, 0x00550000UL, 0x00280000UL, 0x00df0000UL,
7070x008c0000UL, 0x00a10000UL, 0x00890000UL, 0x000d0000UL, 0x00bf0000UL, 0x00e60000UL, 0x00420000UL, 0x00680000UL,
7080x00410000UL, 0x00990000UL, 0x002d0000UL, 0x000f0000UL, 0x00b00000UL, 0x00540000UL, 0x00bb0000UL, 0x00160000UL
709};
710
711static const uint32 Te4_3[] = {
7120x63000000UL, 0x7c000000UL, 0x77000000UL, 0x7b000000UL, 0xf2000000UL, 0x6b000000UL, 0x6f000000UL, 0xc5000000UL,
7130x30000000UL, 0x01000000UL, 0x67000000UL, 0x2b000000UL, 0xfe000000UL, 0xd7000000UL, 0xab000000UL, 0x76000000UL,
7140xca000000UL, 0x82000000UL, 0xc9000000UL, 0x7d000000UL, 0xfa000000UL, 0x59000000UL, 0x47000000UL, 0xf0000000UL,
7150xad000000UL, 0xd4000000UL, 0xa2000000UL, 0xaf000000UL, 0x9c000000UL, 0xa4000000UL, 0x72000000UL, 0xc0000000UL,
7160xb7000000UL, 0xfd000000UL, 0x93000000UL, 0x26000000UL, 0x36000000UL, 0x3f000000UL, 0xf7000000UL, 0xcc000000UL,
7170x34000000UL, 0xa5000000UL, 0xe5000000UL, 0xf1000000UL, 0x71000000UL, 0xd8000000UL, 0x31000000UL, 0x15000000UL,
7180x04000000UL, 0xc7000000UL, 0x23000000UL, 0xc3000000UL, 0x18000000UL, 0x96000000UL, 0x05000000UL, 0x9a000000UL,
7190x07000000UL, 0x12000000UL, 0x80000000UL, 0xe2000000UL, 0xeb000000UL, 0x27000000UL, 0xb2000000UL, 0x75000000UL,
7200x09000000UL, 0x83000000UL, 0x2c000000UL, 0x1a000000UL, 0x1b000000UL, 0x6e000000UL, 0x5a000000UL, 0xa0000000UL,
7210x52000000UL, 0x3b000000UL, 0xd6000000UL, 0xb3000000UL, 0x29000000UL, 0xe3000000UL, 0x2f000000UL, 0x84000000UL,
7220x53000000UL, 0xd1000000UL, 0x00000000UL, 0xed000000UL, 0x20000000UL, 0xfc000000UL, 0xb1000000UL, 0x5b000000UL,
7230x6a000000UL, 0xcb000000UL, 0xbe000000UL, 0x39000000UL, 0x4a000000UL, 0x4c000000UL, 0x58000000UL, 0xcf000000UL,
7240xd0000000UL, 0xef000000UL, 0xaa000000UL, 0xfb000000UL, 0x43000000UL, 0x4d000000UL, 0x33000000UL, 0x85000000UL,
7250x45000000UL, 0xf9000000UL, 0x02000000UL, 0x7f000000UL, 0x50000000UL, 0x3c000000UL, 0x9f000000UL, 0xa8000000UL,
7260x51000000UL, 0xa3000000UL, 0x40000000UL, 0x8f000000UL, 0x92000000UL, 0x9d000000UL, 0x38000000UL, 0xf5000000UL,
7270xbc000000UL, 0xb6000000UL, 0xda000000UL, 0x21000000UL, 0x10000000UL, 0xff000000UL, 0xf3000000UL, 0xd2000000UL,
7280xcd000000UL, 0x0c000000UL, 0x13000000UL, 0xec000000UL, 0x5f000000UL, 0x97000000UL, 0x44000000UL, 0x17000000UL,
7290xc4000000UL, 0xa7000000UL, 0x7e000000UL, 0x3d000000UL, 0x64000000UL, 0x5d000000UL, 0x19000000UL, 0x73000000UL,
7300x60000000UL, 0x81000000UL, 0x4f000000UL, 0xdc000000UL, 0x22000000UL, 0x2a000000UL, 0x90000000UL, 0x88000000UL,
7310x46000000UL, 0xee000000UL, 0xb8000000UL, 0x14000000UL, 0xde000000UL, 0x5e000000UL, 0x0b000000UL, 0xdb000000UL,
7320xe0000000UL, 0x32000000UL, 0x3a000000UL, 0x0a000000UL, 0x49000000UL, 0x06000000UL, 0x24000000UL, 0x5c000000UL,
7330xc2000000UL, 0xd3000000UL, 0xac000000UL, 0x62000000UL, 0x91000000UL, 0x95000000UL, 0xe4000000UL, 0x79000000UL,
7340xe7000000UL, 0xc8000000UL, 0x37000000UL, 0x6d000000UL, 0x8d000000UL, 0xd5000000UL, 0x4e000000UL, 0xa9000000UL,
7350x6c000000UL, 0x56000000UL, 0xf4000000UL, 0xea000000UL, 0x65000000UL, 0x7a000000UL, 0xae000000UL, 0x08000000UL,
7360xba000000UL, 0x78000000UL, 0x25000000UL, 0x2e000000UL, 0x1c000000UL, 0xa6000000UL, 0xb4000000UL, 0xc6000000UL,
7370xe8000000UL, 0xdd000000UL, 0x74000000UL, 0x1f000000UL, 0x4b000000UL, 0xbd000000UL, 0x8b000000UL, 0x8a000000UL,
7380x70000000UL, 0x3e000000UL, 0xb5000000UL, 0x66000000UL, 0x48000000UL, 0x03000000UL, 0xf6000000UL, 0x0e000000UL,
7390x61000000UL, 0x35000000UL, 0x57000000UL, 0xb9000000UL, 0x86000000UL, 0xc1000000UL, 0x1d000000UL, 0x9e000000UL,
7400xe1000000UL, 0xf8000000UL, 0x98000000UL, 0x11000000UL, 0x69000000UL, 0xd9000000UL, 0x8e000000UL, 0x94000000UL,
7410x9b000000UL, 0x1e000000UL, 0x87000000UL, 0xe9000000UL, 0xce000000UL, 0x55000000UL, 0x28000000UL, 0xdf000000UL,
7420x8c000000UL, 0xa1000000UL, 0x89000000UL, 0x0d000000UL, 0xbf000000UL, 0xe6000000UL, 0x42000000UL, 0x68000000UL,
7430x41000000UL, 0x99000000UL, 0x2d000000UL, 0x0f000000UL, 0xb0000000UL, 0x54000000UL, 0xbb000000UL, 0x16000000UL
744};
745
746static const uint32 TD1[256] = {
747 0x5051f4a7UL, 0x537e4165UL, 0xc31a17a4UL, 0x963a275eUL,
748 0xcb3bab6bUL, 0xf11f9d45UL, 0xabacfa58UL, 0x934be303UL,
749 0x552030faUL, 0xf6ad766dUL, 0x9188cc76UL, 0x25f5024cUL,
750 0xfc4fe5d7UL, 0xd7c52acbUL, 0x80263544UL, 0x8fb562a3UL,
751 0x49deb15aUL, 0x6725ba1bUL, 0x9845ea0eUL, 0xe15dfec0UL,
752 0x02c32f75UL, 0x12814cf0UL, 0xa38d4697UL, 0xc66bd3f9UL,
753 0xe7038f5fUL, 0x9515929cUL, 0xebbf6d7aUL, 0xda955259UL,
754 0x2dd4be83UL, 0xd3587421UL, 0x2949e069UL, 0x448ec9c8UL,
755 0x6a75c289UL, 0x78f48e79UL, 0x6b99583eUL, 0xdd27b971UL,
756 0xb6bee14fUL, 0x17f088adUL, 0x66c920acUL, 0xb47dce3aUL,
757 0x1863df4aUL, 0x82e51a31UL, 0x60975133UL, 0x4562537fUL,
758 0xe0b16477UL, 0x84bb6baeUL, 0x1cfe81a0UL, 0x94f9082bUL,
759 0x58704868UL, 0x198f45fdUL, 0x8794de6cUL, 0xb7527bf8UL,
760 0x23ab73d3UL, 0xe2724b02UL, 0x57e31f8fUL, 0x2a6655abUL,
761 0x07b2eb28UL, 0x032fb5c2UL, 0x9a86c57bUL, 0xa5d33708UL,
762 0xf2302887UL, 0xb223bfa5UL, 0xba02036aUL, 0x5ced1682UL,
763 0x2b8acf1cUL, 0x92a779b4UL, 0xf0f307f2UL, 0xa14e69e2UL,
764 0xcd65daf4UL, 0xd50605beUL, 0x1fd13462UL, 0x8ac4a6feUL,
765 0x9d342e53UL, 0xa0a2f355UL, 0x32058ae1UL, 0x75a4f6ebUL,
766 0x390b83ecUL, 0xaa4060efUL, 0x065e719fUL, 0x51bd6e10UL,
767 0xf93e218aUL, 0x3d96dd06UL, 0xaedd3e05UL, 0x464de6bdUL,
768 0xb591548dUL, 0x0571c45dUL, 0x6f0406d4UL, 0xff605015UL,
769 0x241998fbUL, 0x97d6bde9UL, 0xcc894043UL, 0x7767d99eUL,
770 0xbdb0e842UL, 0x8807898bUL, 0x38e7195bUL, 0xdb79c8eeUL,
771 0x47a17c0aUL, 0xe97c420fUL, 0xc9f8841eUL, 0x00000000UL,
772 0x83098086UL, 0x48322bedUL, 0xac1e1170UL, 0x4e6c5a72UL,
773 0xfbfd0effUL, 0x560f8538UL, 0x1e3daed5UL, 0x27362d39UL,
774 0x640a0fd9UL, 0x21685ca6UL, 0xd19b5b54UL, 0x3a24362eUL,
775 0xb10c0a67UL, 0x0f9357e7UL, 0xd2b4ee96UL, 0x9e1b9b91UL,
776 0x4f80c0c5UL, 0xa261dc20UL, 0x695a774bUL, 0x161c121aUL,
777 0x0ae293baUL, 0xe5c0a02aUL, 0x433c22e0UL, 0x1d121b17UL,
778 0x0b0e090dUL, 0xadf28bc7UL, 0xb92db6a8UL, 0xc8141ea9UL,
779 0x8557f119UL, 0x4caf7507UL, 0xbbee99ddUL, 0xfda37f60UL,
780 0x9ff70126UL, 0xbc5c72f5UL, 0xc544663bUL, 0x345bfb7eUL,
781 0x768b4329UL, 0xdccb23c6UL, 0x68b6edfcUL, 0x63b8e4f1UL,
782 0xcad731dcUL, 0x10426385UL, 0x40139722UL, 0x2084c611UL,
783 0x7d854a24UL, 0xf8d2bb3dUL, 0x11aef932UL, 0x6dc729a1UL,
784 0x4b1d9e2fUL, 0xf3dcb230UL, 0xec0d8652UL, 0xd077c1e3UL,
785 0x6c2bb316UL, 0x99a970b9UL, 0xfa119448UL, 0x2247e964UL,
786 0xc4a8fc8cUL, 0x1aa0f03fUL, 0xd8567d2cUL, 0xef223390UL,
787 0xc787494eUL, 0xc1d938d1UL, 0xfe8ccaa2UL, 0x3698d40bUL,
788 0xcfa6f581UL, 0x28a57adeUL, 0x26dab78eUL, 0xa43fadbfUL,
789 0xe42c3a9dUL, 0x0d507892UL, 0x9b6a5fccUL, 0x62547e46UL,
790 0xc2f68d13UL, 0xe890d8b8UL, 0x5e2e39f7UL, 0xf582c3afUL,
791 0xbe9f5d80UL, 0x7c69d093UL, 0xa96fd52dUL, 0xb3cf2512UL,
792 0x3bc8ac99UL, 0xa710187dUL, 0x6ee89c63UL, 0x7bdb3bbbUL,
793 0x09cd2678UL, 0xf46e5918UL, 0x01ec9ab7UL, 0xa8834f9aUL,
794 0x65e6956eUL, 0x7eaaffe6UL, 0x0821bccfUL, 0xe6ef15e8UL,
795 0xd9bae79bUL, 0xce4a6f36UL, 0xd4ea9f09UL, 0xd629b07cUL,
796 0xaf31a4b2UL, 0x312a3f23UL, 0x30c6a594UL, 0xc035a266UL,
797 0x37744ebcUL, 0xa6fc82caUL, 0xb0e090d0UL, 0x1533a7d8UL,
798 0x4af10498UL, 0xf741ecdaUL, 0x0e7fcd50UL, 0x2f1791f6UL,
799 0x8d764dd6UL, 0x4d43efb0UL, 0x54ccaa4dUL, 0xdfe49604UL,
800 0xe39ed1b5UL, 0x1b4c6a88UL, 0xb8c12c1fUL, 0x7f466551UL,
801 0x049d5eeaUL, 0x5d018c35UL, 0x73fa8774UL, 0x2efb0b41UL,
802 0x5ab3671dUL, 0x5292dbd2UL, 0x33e91056UL, 0x136dd647UL,
803 0x8c9ad761UL, 0x7a37a10cUL, 0x8e59f814UL, 0x89eb133cUL,
804 0xeecea927UL, 0x35b761c9UL, 0xede11ce5UL, 0x3c7a47b1UL,
805 0x599cd2dfUL, 0x3f55f273UL, 0x791814ceUL, 0xbf73c737UL,
806 0xea53f7cdUL, 0x5b5ffdaaUL, 0x14df3d6fUL, 0x867844dbUL,
807 0x81caaff3UL, 0x3eb968c4UL, 0x2c382434UL, 0x5fc2a340UL,
808 0x72161dc3UL, 0x0cbce225UL, 0x8b283c49UL, 0x41ff0d95UL,
809 0x7139a801UL, 0xde080cb3UL, 0x9cd8b4e4UL, 0x906456c1UL,
810 0x617bcb84UL, 0x70d532b6UL, 0x74486c5cUL, 0x42d0b857UL,
811};
812static const uint32 TD2[256] = {
813 0xa75051f4UL, 0x65537e41UL, 0xa4c31a17UL, 0x5e963a27UL,
814 0x6bcb3babUL, 0x45f11f9dUL, 0x58abacfaUL, 0x03934be3UL,
815 0xfa552030UL, 0x6df6ad76UL, 0x769188ccUL, 0x4c25f502UL,
816 0xd7fc4fe5UL, 0xcbd7c52aUL, 0x44802635UL, 0xa38fb562UL,
817 0x5a49deb1UL, 0x1b6725baUL, 0x0e9845eaUL, 0xc0e15dfeUL,
818 0x7502c32fUL, 0xf012814cUL, 0x97a38d46UL, 0xf9c66bd3UL,
819 0x5fe7038fUL, 0x9c951592UL, 0x7aebbf6dUL, 0x59da9552UL,
820 0x832dd4beUL, 0x21d35874UL, 0x692949e0UL, 0xc8448ec9UL,
821 0x896a75c2UL, 0x7978f48eUL, 0x3e6b9958UL, 0x71dd27b9UL,
822 0x4fb6bee1UL, 0xad17f088UL, 0xac66c920UL, 0x3ab47dceUL,
823 0x4a1863dfUL, 0x3182e51aUL, 0x33609751UL, 0x7f456253UL,
824 0x77e0b164UL, 0xae84bb6bUL, 0xa01cfe81UL, 0x2b94f908UL,
825 0x68587048UL, 0xfd198f45UL, 0x6c8794deUL, 0xf8b7527bUL,
826 0xd323ab73UL, 0x02e2724bUL, 0x8f57e31fUL, 0xab2a6655UL,
827 0x2807b2ebUL, 0xc2032fb5UL, 0x7b9a86c5UL, 0x08a5d337UL,
828 0x87f23028UL, 0xa5b223bfUL, 0x6aba0203UL, 0x825ced16UL,
829 0x1c2b8acfUL, 0xb492a779UL, 0xf2f0f307UL, 0xe2a14e69UL,
830 0xf4cd65daUL, 0xbed50605UL, 0x621fd134UL, 0xfe8ac4a6UL,
831 0x539d342eUL, 0x55a0a2f3UL, 0xe132058aUL, 0xeb75a4f6UL,
832 0xec390b83UL, 0xefaa4060UL, 0x9f065e71UL, 0x1051bd6eUL,
833 0x8af93e21UL, 0x063d96ddUL, 0x05aedd3eUL, 0xbd464de6UL,
834 0x8db59154UL, 0x5d0571c4UL, 0xd46f0406UL, 0x15ff6050UL,
835 0xfb241998UL, 0xe997d6bdUL, 0x43cc8940UL, 0x9e7767d9UL,
836 0x42bdb0e8UL, 0x8b880789UL, 0x5b38e719UL, 0xeedb79c8UL,
837 0x0a47a17cUL, 0x0fe97c42UL, 0x1ec9f884UL, 0x00000000UL,
838 0x86830980UL, 0xed48322bUL, 0x70ac1e11UL, 0x724e6c5aUL,
839 0xfffbfd0eUL, 0x38560f85UL, 0xd51e3daeUL, 0x3927362dUL,
840 0xd9640a0fUL, 0xa621685cUL, 0x54d19b5bUL, 0x2e3a2436UL,
841 0x67b10c0aUL, 0xe70f9357UL, 0x96d2b4eeUL, 0x919e1b9bUL,
842 0xc54f80c0UL, 0x20a261dcUL, 0x4b695a77UL, 0x1a161c12UL,
843 0xba0ae293UL, 0x2ae5c0a0UL, 0xe0433c22UL, 0x171d121bUL,
844 0x0d0b0e09UL, 0xc7adf28bUL, 0xa8b92db6UL, 0xa9c8141eUL,
845 0x198557f1UL, 0x074caf75UL, 0xddbbee99UL, 0x60fda37fUL,
846 0x269ff701UL, 0xf5bc5c72UL, 0x3bc54466UL, 0x7e345bfbUL,
847 0x29768b43UL, 0xc6dccb23UL, 0xfc68b6edUL, 0xf163b8e4UL,
848 0xdccad731UL, 0x85104263UL, 0x22401397UL, 0x112084c6UL,
849 0x247d854aUL, 0x3df8d2bbUL, 0x3211aef9UL, 0xa16dc729UL,
850 0x2f4b1d9eUL, 0x30f3dcb2UL, 0x52ec0d86UL, 0xe3d077c1UL,
851 0x166c2bb3UL, 0xb999a970UL, 0x48fa1194UL, 0x642247e9UL,
852 0x8cc4a8fcUL, 0x3f1aa0f0UL, 0x2cd8567dUL, 0x90ef2233UL,
853 0x4ec78749UL, 0xd1c1d938UL, 0xa2fe8ccaUL, 0x0b3698d4UL,
854 0x81cfa6f5UL, 0xde28a57aUL, 0x8e26dab7UL, 0xbfa43fadUL,
855 0x9de42c3aUL, 0x920d5078UL, 0xcc9b6a5fUL, 0x4662547eUL,
856 0x13c2f68dUL, 0xb8e890d8UL, 0xf75e2e39UL, 0xaff582c3UL,
857 0x80be9f5dUL, 0x937c69d0UL, 0x2da96fd5UL, 0x12b3cf25UL,
858 0x993bc8acUL, 0x7da71018UL, 0x636ee89cUL, 0xbb7bdb3bUL,
859 0x7809cd26UL, 0x18f46e59UL, 0xb701ec9aUL, 0x9aa8834fUL,
860 0x6e65e695UL, 0xe67eaaffUL, 0xcf0821bcUL, 0xe8e6ef15UL,
861 0x9bd9bae7UL, 0x36ce4a6fUL, 0x09d4ea9fUL, 0x7cd629b0UL,
862 0xb2af31a4UL, 0x23312a3fUL, 0x9430c6a5UL, 0x66c035a2UL,
863 0xbc37744eUL, 0xcaa6fc82UL, 0xd0b0e090UL, 0xd81533a7UL,
864 0x984af104UL, 0xdaf741ecUL, 0x500e7fcdUL, 0xf62f1791UL,
865 0xd68d764dUL, 0xb04d43efUL, 0x4d54ccaaUL, 0x04dfe496UL,
866 0xb5e39ed1UL, 0x881b4c6aUL, 0x1fb8c12cUL, 0x517f4665UL,
867 0xea049d5eUL, 0x355d018cUL, 0x7473fa87UL, 0x412efb0bUL,
868 0x1d5ab367UL, 0xd25292dbUL, 0x5633e910UL, 0x47136dd6UL,
869 0x618c9ad7UL, 0x0c7a37a1UL, 0x148e59f8UL, 0x3c89eb13UL,
870 0x27eecea9UL, 0xc935b761UL, 0xe5ede11cUL, 0xb13c7a47UL,
871 0xdf599cd2UL, 0x733f55f2UL, 0xce791814UL, 0x37bf73c7UL,
872 0xcdea53f7UL, 0xaa5b5ffdUL, 0x6f14df3dUL, 0xdb867844UL,
873 0xf381caafUL, 0xc43eb968UL, 0x342c3824UL, 0x405fc2a3UL,
874 0xc372161dUL, 0x250cbce2UL, 0x498b283cUL, 0x9541ff0dUL,
875 0x017139a8UL, 0xb3de080cUL, 0xe49cd8b4UL, 0xc1906456UL,
876 0x84617bcbUL, 0xb670d532UL, 0x5c74486cUL, 0x5742d0b8UL,
877};
878static const uint32 TD3[256] = {
879 0xf4a75051UL, 0x4165537eUL, 0x17a4c31aUL, 0x275e963aUL,
880 0xab6bcb3bUL, 0x9d45f11fUL, 0xfa58abacUL, 0xe303934bUL,
881 0x30fa5520UL, 0x766df6adUL, 0xcc769188UL, 0x024c25f5UL,
882 0xe5d7fc4fUL, 0x2acbd7c5UL, 0x35448026UL, 0x62a38fb5UL,
883 0xb15a49deUL, 0xba1b6725UL, 0xea0e9845UL, 0xfec0e15dUL,
884 0x2f7502c3UL, 0x4cf01281UL, 0x4697a38dUL, 0xd3f9c66bUL,
885 0x8f5fe703UL, 0x929c9515UL, 0x6d7aebbfUL, 0x5259da95UL,
886 0xbe832dd4UL, 0x7421d358UL, 0xe0692949UL, 0xc9c8448eUL,
887 0xc2896a75UL, 0x8e7978f4UL, 0x583e6b99UL, 0xb971dd27UL,
888 0xe14fb6beUL, 0x88ad17f0UL, 0x20ac66c9UL, 0xce3ab47dUL,
889 0xdf4a1863UL, 0x1a3182e5UL, 0x51336097UL, 0x537f4562UL,
890 0x6477e0b1UL, 0x6bae84bbUL, 0x81a01cfeUL, 0x082b94f9UL,
891 0x48685870UL, 0x45fd198fUL, 0xde6c8794UL, 0x7bf8b752UL,
892 0x73d323abUL, 0x4b02e272UL, 0x1f8f57e3UL, 0x55ab2a66UL,
893 0xeb2807b2UL, 0xb5c2032fUL, 0xc57b9a86UL, 0x3708a5d3UL,
894 0x2887f230UL, 0xbfa5b223UL, 0x036aba02UL, 0x16825cedUL,
895 0xcf1c2b8aUL, 0x79b492a7UL, 0x07f2f0f3UL, 0x69e2a14eUL,
896 0xdaf4cd65UL, 0x05bed506UL, 0x34621fd1UL, 0xa6fe8ac4UL,
897 0x2e539d34UL, 0xf355a0a2UL, 0x8ae13205UL, 0xf6eb75a4UL,
898 0x83ec390bUL, 0x60efaa40UL, 0x719f065eUL, 0x6e1051bdUL,
899 0x218af93eUL, 0xdd063d96UL, 0x3e05aeddUL, 0xe6bd464dUL,
900 0x548db591UL, 0xc45d0571UL, 0x06d46f04UL, 0x5015ff60UL,
901 0x98fb2419UL, 0xbde997d6UL, 0x4043cc89UL, 0xd99e7767UL,
902 0xe842bdb0UL, 0x898b8807UL, 0x195b38e7UL, 0xc8eedb79UL,
903 0x7c0a47a1UL, 0x420fe97cUL, 0x841ec9f8UL, 0x00000000UL,
904 0x80868309UL, 0x2bed4832UL, 0x1170ac1eUL, 0x5a724e6cUL,
905 0x0efffbfdUL, 0x8538560fUL, 0xaed51e3dUL, 0x2d392736UL,
906 0x0fd9640aUL, 0x5ca62168UL, 0x5b54d19bUL, 0x362e3a24UL,
907 0x0a67b10cUL, 0x57e70f93UL, 0xee96d2b4UL, 0x9b919e1bUL,
908 0xc0c54f80UL, 0xdc20a261UL, 0x774b695aUL, 0x121a161cUL,
909 0x93ba0ae2UL, 0xa02ae5c0UL, 0x22e0433cUL, 0x1b171d12UL,
910 0x090d0b0eUL, 0x8bc7adf2UL, 0xb6a8b92dUL, 0x1ea9c814UL,
911 0xf1198557UL, 0x75074cafUL, 0x99ddbbeeUL, 0x7f60fda3UL,
912 0x01269ff7UL, 0x72f5bc5cUL, 0x663bc544UL, 0xfb7e345bUL,
913 0x4329768bUL, 0x23c6dccbUL, 0xedfc68b6UL, 0xe4f163b8UL,
914 0x31dccad7UL, 0x63851042UL, 0x97224013UL, 0xc6112084UL,
915 0x4a247d85UL, 0xbb3df8d2UL, 0xf93211aeUL, 0x29a16dc7UL,
916 0x9e2f4b1dUL, 0xb230f3dcUL, 0x8652ec0dUL, 0xc1e3d077UL,
917 0xb3166c2bUL, 0x70b999a9UL, 0x9448fa11UL, 0xe9642247UL,
918 0xfc8cc4a8UL, 0xf03f1aa0UL, 0x7d2cd856UL, 0x3390ef22UL,
919 0x494ec787UL, 0x38d1c1d9UL, 0xcaa2fe8cUL, 0xd40b3698UL,
920 0xf581cfa6UL, 0x7ade28a5UL, 0xb78e26daUL, 0xadbfa43fUL,
921 0x3a9de42cUL, 0x78920d50UL, 0x5fcc9b6aUL, 0x7e466254UL,
922 0x8d13c2f6UL, 0xd8b8e890UL, 0x39f75e2eUL, 0xc3aff582UL,
923 0x5d80be9fUL, 0xd0937c69UL, 0xd52da96fUL, 0x2512b3cfUL,
924 0xac993bc8UL, 0x187da710UL, 0x9c636ee8UL, 0x3bbb7bdbUL,
925 0x267809cdUL, 0x5918f46eUL, 0x9ab701ecUL, 0x4f9aa883UL,
926 0x956e65e6UL, 0xffe67eaaUL, 0xbccf0821UL, 0x15e8e6efUL,
927 0xe79bd9baUL, 0x6f36ce4aUL, 0x9f09d4eaUL, 0xb07cd629UL,
928 0xa4b2af31UL, 0x3f23312aUL, 0xa59430c6UL, 0xa266c035UL,
929 0x4ebc3774UL, 0x82caa6fcUL, 0x90d0b0e0UL, 0xa7d81533UL,
930 0x04984af1UL, 0xecdaf741UL, 0xcd500e7fUL, 0x91f62f17UL,
931 0x4dd68d76UL, 0xefb04d43UL, 0xaa4d54ccUL, 0x9604dfe4UL,
932 0xd1b5e39eUL, 0x6a881b4cUL, 0x2c1fb8c1UL, 0x65517f46UL,
933 0x5eea049dUL, 0x8c355d01UL, 0x877473faUL, 0x0b412efbUL,
934 0x671d5ab3UL, 0xdbd25292UL, 0x105633e9UL, 0xd647136dUL,
935 0xd7618c9aUL, 0xa10c7a37UL, 0xf8148e59UL, 0x133c89ebUL,
936 0xa927eeceUL, 0x61c935b7UL, 0x1ce5ede1UL, 0x47b13c7aUL,
937 0xd2df599cUL, 0xf2733f55UL, 0x14ce7918UL, 0xc737bf73UL,
938 0xf7cdea53UL, 0xfdaa5b5fUL, 0x3d6f14dfUL, 0x44db8678UL,
939 0xaff381caUL, 0x68c43eb9UL, 0x24342c38UL, 0xa3405fc2UL,
940 0x1dc37216UL, 0xe2250cbcUL, 0x3c498b28UL, 0x0d9541ffUL,
941 0xa8017139UL, 0x0cb3de08UL, 0xb4e49cd8UL, 0x56c19064UL,
942 0xcb84617bUL, 0x32b670d5UL, 0x6c5c7448UL, 0xb85742d0UL,
943};
944
945static const uint32 Tks0[] = {
9460x00000000UL, 0x0e090d0bUL, 0x1c121a16UL, 0x121b171dUL, 0x3824342cUL, 0x362d3927UL, 0x24362e3aUL, 0x2a3f2331UL,
9470x70486858UL, 0x7e416553UL, 0x6c5a724eUL, 0x62537f45UL, 0x486c5c74UL, 0x4665517fUL, 0x547e4662UL, 0x5a774b69UL,
9480xe090d0b0UL, 0xee99ddbbUL, 0xfc82caa6UL, 0xf28bc7adUL, 0xd8b4e49cUL, 0xd6bde997UL, 0xc4a6fe8aUL, 0xcaaff381UL,
9490x90d8b8e8UL, 0x9ed1b5e3UL, 0x8ccaa2feUL, 0x82c3aff5UL, 0xa8fc8cc4UL, 0xa6f581cfUL, 0xb4ee96d2UL, 0xbae79bd9UL,
9500xdb3bbb7bUL, 0xd532b670UL, 0xc729a16dUL, 0xc920ac66UL, 0xe31f8f57UL, 0xed16825cUL, 0xff0d9541UL, 0xf104984aUL,
9510xab73d323UL, 0xa57ade28UL, 0xb761c935UL, 0xb968c43eUL, 0x9357e70fUL, 0x9d5eea04UL, 0x8f45fd19UL, 0x814cf012UL,
9520x3bab6bcbUL, 0x35a266c0UL, 0x27b971ddUL, 0x29b07cd6UL, 0x038f5fe7UL, 0x0d8652ecUL, 0x1f9d45f1UL, 0x119448faUL,
9530x4be30393UL, 0x45ea0e98UL, 0x57f11985UL, 0x59f8148eUL, 0x73c737bfUL, 0x7dce3ab4UL, 0x6fd52da9UL, 0x61dc20a2UL,
9540xad766df6UL, 0xa37f60fdUL, 0xb16477e0UL, 0xbf6d7aebUL, 0x955259daUL, 0x9b5b54d1UL, 0x894043ccUL, 0x87494ec7UL,
9550xdd3e05aeUL, 0xd33708a5UL, 0xc12c1fb8UL, 0xcf2512b3UL, 0xe51a3182UL, 0xeb133c89UL, 0xf9082b94UL, 0xf701269fUL,
9560x4de6bd46UL, 0x43efb04dUL, 0x51f4a750UL, 0x5ffdaa5bUL, 0x75c2896aUL, 0x7bcb8461UL, 0x69d0937cUL, 0x67d99e77UL,
9570x3daed51eUL, 0x33a7d815UL, 0x21bccf08UL, 0x2fb5c203UL, 0x058ae132UL, 0x0b83ec39UL, 0x1998fb24UL, 0x1791f62fUL,
9580x764dd68dUL, 0x7844db86UL, 0x6a5fcc9bUL, 0x6456c190UL, 0x4e69e2a1UL, 0x4060efaaUL, 0x527bf8b7UL, 0x5c72f5bcUL,
9590x0605bed5UL, 0x080cb3deUL, 0x1a17a4c3UL, 0x141ea9c8UL, 0x3e218af9UL, 0x302887f2UL, 0x223390efUL, 0x2c3a9de4UL,
9600x96dd063dUL, 0x98d40b36UL, 0x8acf1c2bUL, 0x84c61120UL, 0xaef93211UL, 0xa0f03f1aUL, 0xb2eb2807UL, 0xbce2250cUL,
9610xe6956e65UL, 0xe89c636eUL, 0xfa877473UL, 0xf48e7978UL, 0xdeb15a49UL, 0xd0b85742UL, 0xc2a3405fUL, 0xccaa4d54UL,
9620x41ecdaf7UL, 0x4fe5d7fcUL, 0x5dfec0e1UL, 0x53f7cdeaUL, 0x79c8eedbUL, 0x77c1e3d0UL, 0x65daf4cdUL, 0x6bd3f9c6UL,
9630x31a4b2afUL, 0x3fadbfa4UL, 0x2db6a8b9UL, 0x23bfa5b2UL, 0x09808683UL, 0x07898b88UL, 0x15929c95UL, 0x1b9b919eUL,
9640xa17c0a47UL, 0xaf75074cUL, 0xbd6e1051UL, 0xb3671d5aUL, 0x99583e6bUL, 0x97513360UL, 0x854a247dUL, 0x8b432976UL,
9650xd134621fUL, 0xdf3d6f14UL, 0xcd267809UL, 0xc32f7502UL, 0xe9105633UL, 0xe7195b38UL, 0xf5024c25UL, 0xfb0b412eUL,
9660x9ad7618cUL, 0x94de6c87UL, 0x86c57b9aUL, 0x88cc7691UL, 0xa2f355a0UL, 0xacfa58abUL, 0xbee14fb6UL, 0xb0e842bdUL,
9670xea9f09d4UL, 0xe49604dfUL, 0xf68d13c2UL, 0xf8841ec9UL, 0xd2bb3df8UL, 0xdcb230f3UL, 0xcea927eeUL, 0xc0a02ae5UL,
9680x7a47b13cUL, 0x744ebc37UL, 0x6655ab2aUL, 0x685ca621UL, 0x42638510UL, 0x4c6a881bUL, 0x5e719f06UL, 0x5078920dUL,
9690x0a0fd964UL, 0x0406d46fUL, 0x161dc372UL, 0x1814ce79UL, 0x322bed48UL, 0x3c22e043UL, 0x2e39f75eUL, 0x2030fa55UL,
9700xec9ab701UL, 0xe293ba0aUL, 0xf088ad17UL, 0xfe81a01cUL, 0xd4be832dUL, 0xdab78e26UL, 0xc8ac993bUL, 0xc6a59430UL,
9710x9cd2df59UL, 0x92dbd252UL, 0x80c0c54fUL, 0x8ec9c844UL, 0xa4f6eb75UL, 0xaaffe67eUL, 0xb8e4f163UL, 0xb6edfc68UL,
9720x0c0a67b1UL, 0x02036abaUL, 0x10187da7UL, 0x1e1170acUL, 0x342e539dUL, 0x3a275e96UL, 0x283c498bUL, 0x26354480UL,
9730x7c420fe9UL, 0x724b02e2UL, 0x605015ffUL, 0x6e5918f4UL, 0x44663bc5UL, 0x4a6f36ceUL, 0x587421d3UL, 0x567d2cd8UL,
9740x37a10c7aUL, 0x39a80171UL, 0x2bb3166cUL, 0x25ba1b67UL, 0x0f853856UL, 0x018c355dUL, 0x13972240UL, 0x1d9e2f4bUL,
9750x47e96422UL, 0x49e06929UL, 0x5bfb7e34UL, 0x55f2733fUL, 0x7fcd500eUL, 0x71c45d05UL, 0x63df4a18UL, 0x6dd64713UL,
9760xd731dccaUL, 0xd938d1c1UL, 0xcb23c6dcUL, 0xc52acbd7UL, 0xef15e8e6UL, 0xe11ce5edUL, 0xf307f2f0UL, 0xfd0efffbUL,
9770xa779b492UL, 0xa970b999UL, 0xbb6bae84UL, 0xb562a38fUL, 0x9f5d80beUL, 0x91548db5UL, 0x834f9aa8UL, 0x8d4697a3UL
978};
979
980static const uint32 Tks1[] = {
9810x00000000UL, 0x0b0e090dUL, 0x161c121aUL, 0x1d121b17UL, 0x2c382434UL, 0x27362d39UL, 0x3a24362eUL, 0x312a3f23UL,
9820x58704868UL, 0x537e4165UL, 0x4e6c5a72UL, 0x4562537fUL, 0x74486c5cUL, 0x7f466551UL, 0x62547e46UL, 0x695a774bUL,
9830xb0e090d0UL, 0xbbee99ddUL, 0xa6fc82caUL, 0xadf28bc7UL, 0x9cd8b4e4UL, 0x97d6bde9UL, 0x8ac4a6feUL, 0x81caaff3UL,
9840xe890d8b8UL, 0xe39ed1b5UL, 0xfe8ccaa2UL, 0xf582c3afUL, 0xc4a8fc8cUL, 0xcfa6f581UL, 0xd2b4ee96UL, 0xd9bae79bUL,
9850x7bdb3bbbUL, 0x70d532b6UL, 0x6dc729a1UL, 0x66c920acUL, 0x57e31f8fUL, 0x5ced1682UL, 0x41ff0d95UL, 0x4af10498UL,
9860x23ab73d3UL, 0x28a57adeUL, 0x35b761c9UL, 0x3eb968c4UL, 0x0f9357e7UL, 0x049d5eeaUL, 0x198f45fdUL, 0x12814cf0UL,
9870xcb3bab6bUL, 0xc035a266UL, 0xdd27b971UL, 0xd629b07cUL, 0xe7038f5fUL, 0xec0d8652UL, 0xf11f9d45UL, 0xfa119448UL,
9880x934be303UL, 0x9845ea0eUL, 0x8557f119UL, 0x8e59f814UL, 0xbf73c737UL, 0xb47dce3aUL, 0xa96fd52dUL, 0xa261dc20UL,
9890xf6ad766dUL, 0xfda37f60UL, 0xe0b16477UL, 0xebbf6d7aUL, 0xda955259UL, 0xd19b5b54UL, 0xcc894043UL, 0xc787494eUL,
9900xaedd3e05UL, 0xa5d33708UL, 0xb8c12c1fUL, 0xb3cf2512UL, 0x82e51a31UL, 0x89eb133cUL, 0x94f9082bUL, 0x9ff70126UL,
9910x464de6bdUL, 0x4d43efb0UL, 0x5051f4a7UL, 0x5b5ffdaaUL, 0x6a75c289UL, 0x617bcb84UL, 0x7c69d093UL, 0x7767d99eUL,
9920x1e3daed5UL, 0x1533a7d8UL, 0x0821bccfUL, 0x032fb5c2UL, 0x32058ae1UL, 0x390b83ecUL, 0x241998fbUL, 0x2f1791f6UL,
9930x8d764dd6UL, 0x867844dbUL, 0x9b6a5fccUL, 0x906456c1UL, 0xa14e69e2UL, 0xaa4060efUL, 0xb7527bf8UL, 0xbc5c72f5UL,
9940xd50605beUL, 0xde080cb3UL, 0xc31a17a4UL, 0xc8141ea9UL, 0xf93e218aUL, 0xf2302887UL, 0xef223390UL, 0xe42c3a9dUL,
9950x3d96dd06UL, 0x3698d40bUL, 0x2b8acf1cUL, 0x2084c611UL, 0x11aef932UL, 0x1aa0f03fUL, 0x07b2eb28UL, 0x0cbce225UL,
9960x65e6956eUL, 0x6ee89c63UL, 0x73fa8774UL, 0x78f48e79UL, 0x49deb15aUL, 0x42d0b857UL, 0x5fc2a340UL, 0x54ccaa4dUL,
9970xf741ecdaUL, 0xfc4fe5d7UL, 0xe15dfec0UL, 0xea53f7cdUL, 0xdb79c8eeUL, 0xd077c1e3UL, 0xcd65daf4UL, 0xc66bd3f9UL,
9980xaf31a4b2UL, 0xa43fadbfUL, 0xb92db6a8UL, 0xb223bfa5UL, 0x83098086UL, 0x8807898bUL, 0x9515929cUL, 0x9e1b9b91UL,
9990x47a17c0aUL, 0x4caf7507UL, 0x51bd6e10UL, 0x5ab3671dUL, 0x6b99583eUL, 0x60975133UL, 0x7d854a24UL, 0x768b4329UL,
10000x1fd13462UL, 0x14df3d6fUL, 0x09cd2678UL, 0x02c32f75UL, 0x33e91056UL, 0x38e7195bUL, 0x25f5024cUL, 0x2efb0b41UL,
10010x8c9ad761UL, 0x8794de6cUL, 0x9a86c57bUL, 0x9188cc76UL, 0xa0a2f355UL, 0xabacfa58UL, 0xb6bee14fUL, 0xbdb0e842UL,
10020xd4ea9f09UL, 0xdfe49604UL, 0xc2f68d13UL, 0xc9f8841eUL, 0xf8d2bb3dUL, 0xf3dcb230UL, 0xeecea927UL, 0xe5c0a02aUL,
10030x3c7a47b1UL, 0x37744ebcUL, 0x2a6655abUL, 0x21685ca6UL, 0x10426385UL, 0x1b4c6a88UL, 0x065e719fUL, 0x0d507892UL,
10040x640a0fd9UL, 0x6f0406d4UL, 0x72161dc3UL, 0x791814ceUL, 0x48322bedUL, 0x433c22e0UL, 0x5e2e39f7UL, 0x552030faUL,
10050x01ec9ab7UL, 0x0ae293baUL, 0x17f088adUL, 0x1cfe81a0UL, 0x2dd4be83UL, 0x26dab78eUL, 0x3bc8ac99UL, 0x30c6a594UL,
10060x599cd2dfUL, 0x5292dbd2UL, 0x4f80c0c5UL, 0x448ec9c8UL, 0x75a4f6ebUL, 0x7eaaffe6UL, 0x63b8e4f1UL, 0x68b6edfcUL,
10070xb10c0a67UL, 0xba02036aUL, 0xa710187dUL, 0xac1e1170UL, 0x9d342e53UL, 0x963a275eUL, 0x8b283c49UL, 0x80263544UL,
10080xe97c420fUL, 0xe2724b02UL, 0xff605015UL, 0xf46e5918UL, 0xc544663bUL, 0xce4a6f36UL, 0xd3587421UL, 0xd8567d2cUL,
10090x7a37a10cUL, 0x7139a801UL, 0x6c2bb316UL, 0x6725ba1bUL, 0x560f8538UL, 0x5d018c35UL, 0x40139722UL, 0x4b1d9e2fUL,
10100x2247e964UL, 0x2949e069UL, 0x345bfb7eUL, 0x3f55f273UL, 0x0e7fcd50UL, 0x0571c45dUL, 0x1863df4aUL, 0x136dd647UL,
10110xcad731dcUL, 0xc1d938d1UL, 0xdccb23c6UL, 0xd7c52acbUL, 0xe6ef15e8UL, 0xede11ce5UL, 0xf0f307f2UL, 0xfbfd0effUL,
10120x92a779b4UL, 0x99a970b9UL, 0x84bb6baeUL, 0x8fb562a3UL, 0xbe9f5d80UL, 0xb591548dUL, 0xa8834f9aUL, 0xa38d4697UL
1013};
1014
1015static const uint32 Tks2[] = {
10160x00000000UL, 0x0d0b0e09UL, 0x1a161c12UL, 0x171d121bUL, 0x342c3824UL, 0x3927362dUL, 0x2e3a2436UL, 0x23312a3fUL,
10170x68587048UL, 0x65537e41UL, 0x724e6c5aUL, 0x7f456253UL, 0x5c74486cUL, 0x517f4665UL, 0x4662547eUL, 0x4b695a77UL,
10180xd0b0e090UL, 0xddbbee99UL, 0xcaa6fc82UL, 0xc7adf28bUL, 0xe49cd8b4UL, 0xe997d6bdUL, 0xfe8ac4a6UL, 0xf381caafUL,
10190xb8e890d8UL, 0xb5e39ed1UL, 0xa2fe8ccaUL, 0xaff582c3UL, 0x8cc4a8fcUL, 0x81cfa6f5UL, 0x96d2b4eeUL, 0x9bd9bae7UL,
10200xbb7bdb3bUL, 0xb670d532UL, 0xa16dc729UL, 0xac66c920UL, 0x8f57e31fUL, 0x825ced16UL, 0x9541ff0dUL, 0x984af104UL,
10210xd323ab73UL, 0xde28a57aUL, 0xc935b761UL, 0xc43eb968UL, 0xe70f9357UL, 0xea049d5eUL, 0xfd198f45UL, 0xf012814cUL,
10220x6bcb3babUL, 0x66c035a2UL, 0x71dd27b9UL, 0x7cd629b0UL, 0x5fe7038fUL, 0x52ec0d86UL, 0x45f11f9dUL, 0x48fa1194UL,
10230x03934be3UL, 0x0e9845eaUL, 0x198557f1UL, 0x148e59f8UL, 0x37bf73c7UL, 0x3ab47dceUL, 0x2da96fd5UL, 0x20a261dcUL,
10240x6df6ad76UL, 0x60fda37fUL, 0x77e0b164UL, 0x7aebbf6dUL, 0x59da9552UL, 0x54d19b5bUL, 0x43cc8940UL, 0x4ec78749UL,
10250x05aedd3eUL, 0x08a5d337UL, 0x1fb8c12cUL, 0x12b3cf25UL, 0x3182e51aUL, 0x3c89eb13UL, 0x2b94f908UL, 0x269ff701UL,
10260xbd464de6UL, 0xb04d43efUL, 0xa75051f4UL, 0xaa5b5ffdUL, 0x896a75c2UL, 0x84617bcbUL, 0x937c69d0UL, 0x9e7767d9UL,
10270xd51e3daeUL, 0xd81533a7UL, 0xcf0821bcUL, 0xc2032fb5UL, 0xe132058aUL, 0xec390b83UL, 0xfb241998UL, 0xf62f1791UL,
10280xd68d764dUL, 0xdb867844UL, 0xcc9b6a5fUL, 0xc1906456UL, 0xe2a14e69UL, 0xefaa4060UL, 0xf8b7527bUL, 0xf5bc5c72UL,
10290xbed50605UL, 0xb3de080cUL, 0xa4c31a17UL, 0xa9c8141eUL, 0x8af93e21UL, 0x87f23028UL, 0x90ef2233UL, 0x9de42c3aUL,
10300x063d96ddUL, 0x0b3698d4UL, 0x1c2b8acfUL, 0x112084c6UL, 0x3211aef9UL, 0x3f1aa0f0UL, 0x2807b2ebUL, 0x250cbce2UL,
10310x6e65e695UL, 0x636ee89cUL, 0x7473fa87UL, 0x7978f48eUL, 0x5a49deb1UL, 0x5742d0b8UL, 0x405fc2a3UL, 0x4d54ccaaUL,
10320xdaf741ecUL, 0xd7fc4fe5UL, 0xc0e15dfeUL, 0xcdea53f7UL, 0xeedb79c8UL, 0xe3d077c1UL, 0xf4cd65daUL, 0xf9c66bd3UL,
10330xb2af31a4UL, 0xbfa43fadUL, 0xa8b92db6UL, 0xa5b223bfUL, 0x86830980UL, 0x8b880789UL, 0x9c951592UL, 0x919e1b9bUL,
10340x0a47a17cUL, 0x074caf75UL, 0x1051bd6eUL, 0x1d5ab367UL, 0x3e6b9958UL, 0x33609751UL, 0x247d854aUL, 0x29768b43UL,
10350x621fd134UL, 0x6f14df3dUL, 0x7809cd26UL, 0x7502c32fUL, 0x5633e910UL, 0x5b38e719UL, 0x4c25f502UL, 0x412efb0bUL,
10360x618c9ad7UL, 0x6c8794deUL, 0x7b9a86c5UL, 0x769188ccUL, 0x55a0a2f3UL, 0x58abacfaUL, 0x4fb6bee1UL, 0x42bdb0e8UL,
10370x09d4ea9fUL, 0x04dfe496UL, 0x13c2f68dUL, 0x1ec9f884UL, 0x3df8d2bbUL, 0x30f3dcb2UL, 0x27eecea9UL, 0x2ae5c0a0UL,
10380xb13c7a47UL, 0xbc37744eUL, 0xab2a6655UL, 0xa621685cUL, 0x85104263UL, 0x881b4c6aUL, 0x9f065e71UL, 0x920d5078UL,
10390xd9640a0fUL, 0xd46f0406UL, 0xc372161dUL, 0xce791814UL, 0xed48322bUL, 0xe0433c22UL, 0xf75e2e39UL, 0xfa552030UL,
10400xb701ec9aUL, 0xba0ae293UL, 0xad17f088UL, 0xa01cfe81UL, 0x832dd4beUL, 0x8e26dab7UL, 0x993bc8acUL, 0x9430c6a5UL,
10410xdf599cd2UL, 0xd25292dbUL, 0xc54f80c0UL, 0xc8448ec9UL, 0xeb75a4f6UL, 0xe67eaaffUL, 0xf163b8e4UL, 0xfc68b6edUL,
10420x67b10c0aUL, 0x6aba0203UL, 0x7da71018UL, 0x70ac1e11UL, 0x539d342eUL, 0x5e963a27UL, 0x498b283cUL, 0x44802635UL,
10430x0fe97c42UL, 0x02e2724bUL, 0x15ff6050UL, 0x18f46e59UL, 0x3bc54466UL, 0x36ce4a6fUL, 0x21d35874UL, 0x2cd8567dUL,
10440x0c7a37a1UL, 0x017139a8UL, 0x166c2bb3UL, 0x1b6725baUL, 0x38560f85UL, 0x355d018cUL, 0x22401397UL, 0x2f4b1d9eUL,
10450x642247e9UL, 0x692949e0UL, 0x7e345bfbUL, 0x733f55f2UL, 0x500e7fcdUL, 0x5d0571c4UL, 0x4a1863dfUL, 0x47136dd6UL,
10460xdccad731UL, 0xd1c1d938UL, 0xc6dccb23UL, 0xcbd7c52aUL, 0xe8e6ef15UL, 0xe5ede11cUL, 0xf2f0f307UL, 0xfffbfd0eUL,
10470xb492a779UL, 0xb999a970UL, 0xae84bb6bUL, 0xa38fb562UL, 0x80be9f5dUL, 0x8db59154UL, 0x9aa8834fUL, 0x97a38d46UL
1048};
1049
1050static const uint32 Tks3[] = {
10510x00000000UL, 0x090d0b0eUL, 0x121a161cUL, 0x1b171d12UL, 0x24342c38UL, 0x2d392736UL, 0x362e3a24UL, 0x3f23312aUL,
10520x48685870UL, 0x4165537eUL, 0x5a724e6cUL, 0x537f4562UL, 0x6c5c7448UL, 0x65517f46UL, 0x7e466254UL, 0x774b695aUL,
10530x90d0b0e0UL, 0x99ddbbeeUL, 0x82caa6fcUL, 0x8bc7adf2UL, 0xb4e49cd8UL, 0xbde997d6UL, 0xa6fe8ac4UL, 0xaff381caUL,
10540xd8b8e890UL, 0xd1b5e39eUL, 0xcaa2fe8cUL, 0xc3aff582UL, 0xfc8cc4a8UL, 0xf581cfa6UL, 0xee96d2b4UL, 0xe79bd9baUL,
10550x3bbb7bdbUL, 0x32b670d5UL, 0x29a16dc7UL, 0x20ac66c9UL, 0x1f8f57e3UL, 0x16825cedUL, 0x0d9541ffUL, 0x04984af1UL,
10560x73d323abUL, 0x7ade28a5UL, 0x61c935b7UL, 0x68c43eb9UL, 0x57e70f93UL, 0x5eea049dUL, 0x45fd198fUL, 0x4cf01281UL,
10570xab6bcb3bUL, 0xa266c035UL, 0xb971dd27UL, 0xb07cd629UL, 0x8f5fe703UL, 0x8652ec0dUL, 0x9d45f11fUL, 0x9448fa11UL,
10580xe303934bUL, 0xea0e9845UL, 0xf1198557UL, 0xf8148e59UL, 0xc737bf73UL, 0xce3ab47dUL, 0xd52da96fUL, 0xdc20a261UL,
10590x766df6adUL, 0x7f60fda3UL, 0x6477e0b1UL, 0x6d7aebbfUL, 0x5259da95UL, 0x5b54d19bUL, 0x4043cc89UL, 0x494ec787UL,
10600x3e05aeddUL, 0x3708a5d3UL, 0x2c1fb8c1UL, 0x2512b3cfUL, 0x1a3182e5UL, 0x133c89ebUL, 0x082b94f9UL, 0x01269ff7UL,
10610xe6bd464dUL, 0xefb04d43UL, 0xf4a75051UL, 0xfdaa5b5fUL, 0xc2896a75UL, 0xcb84617bUL, 0xd0937c69UL, 0xd99e7767UL,
10620xaed51e3dUL, 0xa7d81533UL, 0xbccf0821UL, 0xb5c2032fUL, 0x8ae13205UL, 0x83ec390bUL, 0x98fb2419UL, 0x91f62f17UL,
10630x4dd68d76UL, 0x44db8678UL, 0x5fcc9b6aUL, 0x56c19064UL, 0x69e2a14eUL, 0x60efaa40UL, 0x7bf8b752UL, 0x72f5bc5cUL,
10640x05bed506UL, 0x0cb3de08UL, 0x17a4c31aUL, 0x1ea9c814UL, 0x218af93eUL, 0x2887f230UL, 0x3390ef22UL, 0x3a9de42cUL,
10650xdd063d96UL, 0xd40b3698UL, 0xcf1c2b8aUL, 0xc6112084UL, 0xf93211aeUL, 0xf03f1aa0UL, 0xeb2807b2UL, 0xe2250cbcUL,
10660x956e65e6UL, 0x9c636ee8UL, 0x877473faUL, 0x8e7978f4UL, 0xb15a49deUL, 0xb85742d0UL, 0xa3405fc2UL, 0xaa4d54ccUL,
10670xecdaf741UL, 0xe5d7fc4fUL, 0xfec0e15dUL, 0xf7cdea53UL, 0xc8eedb79UL, 0xc1e3d077UL, 0xdaf4cd65UL, 0xd3f9c66bUL,
10680xa4b2af31UL, 0xadbfa43fUL, 0xb6a8b92dUL, 0xbfa5b223UL, 0x80868309UL, 0x898b8807UL, 0x929c9515UL, 0x9b919e1bUL,
10690x7c0a47a1UL, 0x75074cafUL, 0x6e1051bdUL, 0x671d5ab3UL, 0x583e6b99UL, 0x51336097UL, 0x4a247d85UL, 0x4329768bUL,
10700x34621fd1UL, 0x3d6f14dfUL, 0x267809cdUL, 0x2f7502c3UL, 0x105633e9UL, 0x195b38e7UL, 0x024c25f5UL, 0x0b412efbUL,
10710xd7618c9aUL, 0xde6c8794UL, 0xc57b9a86UL, 0xcc769188UL, 0xf355a0a2UL, 0xfa58abacUL, 0xe14fb6beUL, 0xe842bdb0UL,
10720x9f09d4eaUL, 0x9604dfe4UL, 0x8d13c2f6UL, 0x841ec9f8UL, 0xbb3df8d2UL, 0xb230f3dcUL, 0xa927eeceUL, 0xa02ae5c0UL,
10730x47b13c7aUL, 0x4ebc3774UL, 0x55ab2a66UL, 0x5ca62168UL, 0x63851042UL, 0x6a881b4cUL, 0x719f065eUL, 0x78920d50UL,
10740x0fd9640aUL, 0x06d46f04UL, 0x1dc37216UL, 0x14ce7918UL, 0x2bed4832UL, 0x22e0433cUL, 0x39f75e2eUL, 0x30fa5520UL,
10750x9ab701ecUL, 0x93ba0ae2UL, 0x88ad17f0UL, 0x81a01cfeUL, 0xbe832dd4UL, 0xb78e26daUL, 0xac993bc8UL, 0xa59430c6UL,
10760xd2df599cUL, 0xdbd25292UL, 0xc0c54f80UL, 0xc9c8448eUL, 0xf6eb75a4UL, 0xffe67eaaUL, 0xe4f163b8UL, 0xedfc68b6UL,
10770x0a67b10cUL, 0x036aba02UL, 0x187da710UL, 0x1170ac1eUL, 0x2e539d34UL, 0x275e963aUL, 0x3c498b28UL, 0x35448026UL,
10780x420fe97cUL, 0x4b02e272UL, 0x5015ff60UL, 0x5918f46eUL, 0x663bc544UL, 0x6f36ce4aUL, 0x7421d358UL, 0x7d2cd856UL,
10790xa10c7a37UL, 0xa8017139UL, 0xb3166c2bUL, 0xba1b6725UL, 0x8538560fUL, 0x8c355d01UL, 0x97224013UL, 0x9e2f4b1dUL,
10800xe9642247UL, 0xe0692949UL, 0xfb7e345bUL, 0xf2733f55UL, 0xcd500e7fUL, 0xc45d0571UL, 0xdf4a1863UL, 0xd647136dUL,
10810x31dccad7UL, 0x38d1c1d9UL, 0x23c6dccbUL, 0x2acbd7c5UL, 0x15e8e6efUL, 0x1ce5ede1UL, 0x07f2f0f3UL, 0x0efffbfdUL,
10820x79b492a7UL, 0x70b999a9UL, 0x6bae84bbUL, 0x62a38fb5UL, 0x5d80be9fUL, 0x548db591UL, 0x4f9aa883UL, 0x4697a38dUL
1083};
1084
1085#endif /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */
1086
1087static const uint32 rcon[] = {
1088 0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL,
1089 0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL,
1090 0x1B000000UL, 0x36000000UL, /* for 128-bit blocks, AES never uses more than 10 rcon values */
1091};
1092
1093#ifdef USE_BURN_STACK
1094static void _aes_ecb_decrypt(const unsigned char *ct, unsigned char *pt,
1095 psAesKey_t *skey);
1096static void _aes_ecb_encrypt(const unsigned char *pt, unsigned char *ct,
1097 psAesKey_t *skey);
1098#endif
1099
1100static uint32 setup_mix(uint32 temp)
1101{
1102 return (Te4_3[byte(temp, 2)]) ^
1103 (Te4_2[byte(temp, 1)]) ^
1104 (Te4_1[byte(temp, 0)]) ^
1105 (Te4_0[byte(temp, 3)]);
1106}
1107
1108#ifndef PS_AES_IMPROVE_PERF_INCREASE_CODESIZE
1109static uint32 setup_mix2(uint32 temp)
1110{
1111 return Td0(255 & Te4[byte(temp, 3)]) ^
1112 Td1(255 & Te4[byte(temp, 2)]) ^
1113 Td2(255 & Te4[byte(temp, 1)]) ^
1114 Td3(255 & Te4[byte(temp, 0)]);
1115}
1116#endif /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */
1117
1118/*
1119 Software implementation of AES CBC APIs
1120 */
1121#ifndef USE_AES_CBC_EXTERNAL
1122static //bbox
1123int32 psAesInit(psCipherContext_t *ctx, unsigned char *IV,
1124 const unsigned char *key, uint32 keylen)
1125{
1126 int32 x, err;
1127
1128//bbox
1129// if (IV == NULL || key == NULL || ctx == NULL) {
1130// psTraceCrypto("psAesInit arg fail\n");
1131// return PS_ARG_FAIL;
1132// }
1133 memset(ctx, 0x0, sizeof(psCipherContext_t));
1134/*
1135 setup cipher
1136 */
1137 if ((err = psAesInitKey(key, keylen, &ctx->aes.key)) != PS_SUCCESS) {
1138 return err;
1139 }
1140/*
1141 copy IV
1142 */
1143 ctx->aes.blocklen = 16;
1144 for (x = 0; x < ctx->aes.blocklen; x++) {
1145 ctx->aes.IV[x] = IV[x];
1146 }
1147 return PS_SUCCESS;
1148}
1149
1150static //bbox
1151int32 psAesEncrypt(psCipherContext_t *ctx, const unsigned char *pt,
1152 unsigned char *ct, uint32 len)
1153{
1154 int32 x;
1155 uint32 i;
1156 unsigned char tmp[MAXBLOCKSIZE];
1157
1158//bbox
1159// if (pt == NULL || ct == NULL || ctx == NULL || (len & 0x7) != 0) {
1160// psTraceCrypto("Bad parameters to psAesEncrypt\n");
1161// return PS_ARG_FAIL;
1162// }
1163 if ((len & 0x7) != 0)
1164 bb_error_msg_and_die("AES len:%d", len);
1165
1166/*
1167 is blocklen valid?
1168 */
1169 if (ctx->aes.blocklen < 0 || (ctx->aes.blocklen >
1170 (int32)sizeof(ctx->aes.IV))) {
1171 psTraceCrypto("Bad blocklen in psAesEncrypt\n");
1172 return PS_LIMIT_FAIL;
1173 }
1174
1175 for (i = 0; i < len; i += ctx->aes.blocklen) {
1176/*
1177 xor IV against plaintext
1178 */
1179 for (x = 0; x < ctx->aes.blocklen; x++) {
1180 tmp[x] = pt[x] ^ ctx->aes.IV[x];
1181 }
1182/*
1183 encrypt
1184 */
1185 psAesEncryptBlock(tmp, ct, &ctx->aes.key);
1186
1187/*
1188 store IV [ciphertext] for a future block
1189 */
1190 for (x = 0; x < ctx->aes.blocklen; x++) {
1191 ctx->aes.IV[x] = ct[x];
1192 }
1193 ct += ctx->aes.blocklen;
1194 pt += ctx->aes.blocklen;
1195 }
1196
1197 memset_s(tmp, sizeof(tmp), 0x0, sizeof(tmp));
1198 return len;
1199}
1200
1201static //bbox
1202int32 psAesDecrypt(psCipherContext_t *ctx, const unsigned char *ct,
1203 unsigned char *pt, uint32 len)
1204{
1205 int32 x;
1206 uint32 i;
1207 unsigned char tmp[MAXBLOCKSIZE], tmp2[MAXBLOCKSIZE];
1208
1209//bbox
1210// if (pt == NULL || ct == NULL || ctx == NULL || (len & 0x7) != 0) {
1211// psTraceCrypto("Bad parameters to psAesDecrypt\n");
1212// return PS_ARG_FAIL;
1213// }
1214 if ((len & 0x7) != 0)
1215 bb_error_msg_and_die("AES len:%d", len);
1216
1217/*
1218 is blocklen valid?
1219 */
1220 if (ctx->aes.blocklen < 0 || (ctx->aes.blocklen >
1221 (int32)sizeof(ctx->aes.IV))) {
1222 psTraceCrypto("Bad blocklen in psAesDecrypt\n");
1223 return PS_LIMIT_FAIL;
1224 }
1225 for (i = 0; i < len; i += ctx->aes.blocklen) {
1226/*
1227 decrypt the block from ct into tmp
1228 */
1229 psAesDecryptBlock(ct, tmp, &ctx->aes.key);
1230/*
1231 xor IV against the plaintext of the previous step
1232 */
1233 for (x = 0; x < ctx->aes.blocklen; x++) {
1234/*
1235 copy CT in case ct == pt
1236 */
1237 tmp2[x] = ct[x];
1238/*
1239 actually decrypt the byte
1240 */
1241 pt[x] = tmp[x] ^ ctx->aes.IV[x];
1242 }
1243/*
1244 replace IV with this current ciphertext
1245 */
1246 for (x = 0; x < ctx->aes.blocklen; x++) {
1247 ctx->aes.IV[x] = tmp2[x];
1248 }
1249 ct += ctx->aes.blocklen;
1250 pt += ctx->aes.blocklen;
1251 }
1252 memset_s(tmp, sizeof(tmp), 0x0, sizeof(tmp));
1253 memset_s(tmp2, sizeof(tmp2), 0x0, sizeof(tmp2));
1254
1255 return len;
1256}
1257
1258#endif /* USE_AES_CBC_EXTERNAL */
1259
1260/******************************************************************************/
1261/*
1262 Initialize the AES (Rijndael) block cipher
1263
1264 key: The symmetric key you wish to pass
1265 keylen: The key length in bytes
1266 skey: The key in as scheduled by this function.
1267*/
1268
1269static //bbox
1270int32 psAesInitKey(const unsigned char *key, uint32 keylen, psAesKey_t *skey)
1271{
1272 int32 i, j;
1273 uint32 temp, *rk, *rrk;
1274
1275//bbox
1276// if (key == NULL || skey == NULL) {
1277// psTraceCrypto("Bad args to psAesInitKey\n");
1278// return PS_ARG_FAIL;
1279// }
1280
1281 if (keylen != 16 && keylen != 24 && keylen != 32) {
1282 psTraceCrypto("Invalid AES key length\n");
1283 //bbox return CRYPT_INVALID_KEYSIZE;
1284 //unreachable anyway
1285 return PS_ARG_FAIL;
1286 }
1287
1288 memset(skey, 0x0, sizeof(psAesKey_t));
1289 skey->Nr = 10 + ((keylen/8)-2)*2;
1290
1291/*
1292 setup the forward key
1293 */
1294 i = 0;
1295 rk = skey->eK;
1296 LOAD32H(rk[0], key );
1297 LOAD32H(rk[1], key + 4);
1298 LOAD32H(rk[2], key + 8);
1299 LOAD32H(rk[3], key + 12);
1300 if (keylen == 16) {
1301 j = 44;
1302 for (;;) {
1303 temp = rk[3];
1304 rk[4] = rk[0] ^ setup_mix(temp) ^ rcon[i];
1305 rk[5] = rk[1] ^ rk[4];
1306 rk[6] = rk[2] ^ rk[5];
1307 rk[7] = rk[3] ^ rk[6];
1308 if (++i == 10) {
1309 break;
1310 }
1311 rk += 4;
1312 }
1313 } else if (keylen == 24) {
1314 j = 52;
1315 LOAD32H(rk[4], key + 16);
1316 LOAD32H(rk[5], key + 20);
1317 for (;;) {
1318 #ifdef _MSC_VER
1319 temp = skey->eK[rk - skey->eK + 5];
1320 #else
1321 temp = rk[5];
1322 #endif /* _MSC_VER */
1323 rk[ 6] = rk[ 0] ^ setup_mix(temp) ^ rcon[i];
1324 rk[ 7] = rk[ 1] ^ rk[ 6];
1325 rk[ 8] = rk[ 2] ^ rk[ 7];
1326 rk[ 9] = rk[ 3] ^ rk[ 8];
1327 if (++i == 8) {
1328 break;
1329 }
1330 rk[10] = rk[ 4] ^ rk[ 9];
1331 rk[11] = rk[ 5] ^ rk[10];
1332 rk += 6;
1333 }
1334 } else if (keylen == 32) {
1335 j = 60;
1336 LOAD32H(rk[4], key + 16);
1337 LOAD32H(rk[5], key + 20);
1338 LOAD32H(rk[6], key + 24);
1339 LOAD32H(rk[7], key + 28);
1340 for (;;) {
1341 #ifdef _MSC_VER
1342 temp = skey->eK[rk - skey->eK + 7];
1343 #else
1344 temp = rk[7];
1345 #endif /* _MSC_VER */
1346 rk[ 8] = rk[ 0] ^ setup_mix(temp) ^ rcon[i];
1347 rk[ 9] = rk[ 1] ^ rk[ 8];
1348 rk[10] = rk[ 2] ^ rk[ 9];
1349 rk[11] = rk[ 3] ^ rk[10];
1350 if (++i == 7) {
1351 break;
1352 }
1353 temp = rk[11];
1354 rk[12] = rk[ 4] ^ setup_mix(ROR(temp, 8));
1355 rk[13] = rk[ 5] ^ rk[12];
1356 rk[14] = rk[ 6] ^ rk[13];
1357 rk[15] = rk[ 7] ^ rk[14];
1358 rk += 8;
1359 }
1360 } else {
1361/*
1362 this can't happen
1363 */
1364 return PS_FAILURE;
1365 }
1366
1367/*
1368 setup the inverse key now
1369 */
1370 rk = skey->dK;
1371 rrk = skey->eK + j - 4;
1372
1373/*
1374 apply the inverse MixColumn transform to all round keys but
1375 the first and the last:
1376 */
1377 /* copy first */
1378 *rk++ = *rrk++;
1379 *rk++ = *rrk++;
1380 *rk++ = *rrk++;
1381 *rk = *rrk;
1382 rk -= 3; rrk -= 3;
1383
1384 for (i = 1; i < skey->Nr; i++) {
1385 rrk -= 4;
1386 rk += 4;
1387#ifndef PS_AES_IMPROVE_PERF_INCREASE_CODESIZE
1388 temp = rrk[0];
1389 rk[0] = setup_mix2(temp);
1390 temp = rrk[1];
1391 rk[1] = setup_mix2(temp);
1392 temp = rrk[2];
1393 rk[2] = setup_mix2(temp);
1394 temp = rrk[3];
1395 rk[3] = setup_mix2(temp);
1396#else /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */
1397 temp = rrk[0];
1398 rk[0] =
1399 Tks0[byte(temp, 3)] ^
1400 Tks1[byte(temp, 2)] ^
1401 Tks2[byte(temp, 1)] ^
1402 Tks3[byte(temp, 0)];
1403 temp = rrk[1];
1404 rk[1] =
1405 Tks0[byte(temp, 3)] ^
1406 Tks1[byte(temp, 2)] ^
1407 Tks2[byte(temp, 1)] ^
1408 Tks3[byte(temp, 0)];
1409 temp = rrk[2];
1410 rk[2] =
1411 Tks0[byte(temp, 3)] ^
1412 Tks1[byte(temp, 2)] ^
1413 Tks2[byte(temp, 1)] ^
1414 Tks3[byte(temp, 0)];
1415 temp = rrk[3];
1416 rk[3] =
1417 Tks0[byte(temp, 3)] ^
1418 Tks1[byte(temp, 2)] ^
1419 Tks2[byte(temp, 1)] ^
1420 Tks3[byte(temp, 0)];
1421#endif /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */
1422 }
1423
1424 /* copy last */
1425 rrk -= 4;
1426 rk += 4;
1427 *rk++ = *rrk++;
1428 *rk++ = *rrk++;
1429 *rk++ = *rrk++;
1430 *rk = *rrk;
1431
1432 return PS_SUCCESS;
1433}
1434
1435
1436#ifdef USE_BURN_STACK
1437static //bbox
1438void psAesEncryptBlock(const unsigned char *pt, unsigned char *ct,
1439 psAesKey_t *skey)
1440{
1441 _aes_ecb_encrypt(pt, ct, skey);
1442 psBurnStack(sizeof(uint32)*8 + sizeof(uint32*) + sizeof(int32)*2);
1443}
1444static void _aes_ecb_encrypt(const unsigned char *pt, unsigned char *ct,
1445 psAesKey_t *skey)
1446#else
1447static //bbox
1448void psAesEncryptBlock(const unsigned char *pt, unsigned char *ct,
1449 psAesKey_t *skey)
1450#endif /* USE_BURN_STACK */
1451{
1452 uint32 s0, s1, s2, s3, t0, t1, t2, t3, *rk;
1453 int32 Nr, r;
1454
1455//bbox
1456// if (pt == NULL || ct == NULL || skey == NULL) {
1457// return;
1458// }
1459
1460 Nr = skey->Nr;
1461 rk = skey->eK;
1462
1463/*
1464 map byte array block to cipher state
1465 and add initial round key:
1466 */
1467 LOAD32H(s0, pt ); s0 ^= rk[0];
1468 LOAD32H(s1, pt + 4); s1 ^= rk[1];
1469 LOAD32H(s2, pt + 8); s2 ^= rk[2];
1470 LOAD32H(s3, pt + 12); s3 ^= rk[3];
1471
1472#ifndef PS_AES_IMPROVE_PERF_INCREASE_CODESIZE
1473 for (r = 0; ; r++) {
1474 rk += 4;
1475 t0 =
1476 Te0(byte(s0, 3)) ^
1477 Te1(byte(s1, 2)) ^
1478 Te2(byte(s2, 1)) ^
1479 Te3(byte(s3, 0)) ^
1480 rk[0];
1481 t1 =
1482 Te0(byte(s1, 3)) ^
1483 Te1(byte(s2, 2)) ^
1484 Te2(byte(s3, 1)) ^
1485 Te3(byte(s0, 0)) ^
1486 rk[1];
1487 t2 =
1488 Te0(byte(s2, 3)) ^
1489 Te1(byte(s3, 2)) ^
1490 Te2(byte(s0, 1)) ^
1491 Te3(byte(s1, 0)) ^
1492 rk[2];
1493 t3 =
1494 Te0(byte(s3, 3)) ^
1495 Te1(byte(s0, 2)) ^
1496 Te2(byte(s1, 1)) ^
1497 Te3(byte(s2, 0)) ^
1498 rk[3];
1499 if (r == Nr-2) {
1500 break;
1501 }
1502 s0 = t0; s1 = t1; s2 = t2; s3 = t3;
1503 }
1504 rk += 4;
1505#else /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */
1506
1507/*
1508 Nr - 1 full rounds:
1509 */
1510 r = Nr >> 1;
1511 for (;;) {
1512
1513 t0 =
1514 Te0(byte(s0, 3)) ^
1515 Te1(byte(s1, 2)) ^
1516 Te2(byte(s2, 1)) ^
1517 Te3(byte(s3, 0)) ^
1518 rk[4];
1519 t1 =
1520 Te0(byte(s1, 3)) ^
1521 Te1(byte(s2, 2)) ^
1522 Te2(byte(s3, 1)) ^
1523 Te3(byte(s0, 0)) ^
1524 rk[5];
1525 t2 =
1526 Te0(byte(s2, 3)) ^
1527 Te1(byte(s3, 2)) ^
1528 Te2(byte(s0, 1)) ^
1529 Te3(byte(s1, 0)) ^
1530 rk[6];
1531 t3 =
1532 Te0(byte(s3, 3)) ^
1533 Te1(byte(s0, 2)) ^
1534 Te2(byte(s1, 1)) ^
1535 Te3(byte(s2, 0)) ^
1536 rk[7];
1537
1538 rk += 8;
1539 if (--r == 0) {
1540 break;
1541 }
1542
1543 s0 =
1544 Te0(byte(t0, 3)) ^
1545 Te1(byte(t1, 2)) ^
1546 Te2(byte(t2, 1)) ^
1547 Te3(byte(t3, 0)) ^
1548 rk[0];
1549 s1 =
1550 Te0(byte(t1, 3)) ^
1551 Te1(byte(t2, 2)) ^
1552 Te2(byte(t3, 1)) ^
1553 Te3(byte(t0, 0)) ^
1554 rk[1];
1555 s2 =
1556 Te0(byte(t2, 3)) ^
1557 Te1(byte(t3, 2)) ^
1558 Te2(byte(t0, 1)) ^
1559 Te3(byte(t1, 0)) ^
1560 rk[2];
1561 s3 =
1562 Te0(byte(t3, 3)) ^
1563 Te1(byte(t0, 2)) ^
1564 Te2(byte(t1, 1)) ^
1565 Te3(byte(t2, 0)) ^
1566 rk[3];
1567 }
1568#endif /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */
1569
1570/*
1571 apply last round and map cipher state to byte array block:
1572 */
1573 s0 =
1574 (Te4_3[byte(t0, 3)]) ^
1575 (Te4_2[byte(t1, 2)]) ^
1576 (Te4_1[byte(t2, 1)]) ^
1577 (Te4_0[byte(t3, 0)]) ^
1578 rk[0];
1579 STORE32H(s0, ct);
1580 s1 =
1581 (Te4_3[byte(t1, 3)]) ^
1582 (Te4_2[byte(t2, 2)]) ^
1583 (Te4_1[byte(t3, 1)]) ^
1584 (Te4_0[byte(t0, 0)]) ^
1585 rk[1];
1586 STORE32H(s1, ct+4);
1587 s2 =
1588 (Te4_3[byte(t2, 3)]) ^
1589 (Te4_2[byte(t3, 2)]) ^
1590 (Te4_1[byte(t0, 1)]) ^
1591 (Te4_0[byte(t1, 0)]) ^
1592 rk[2];
1593 STORE32H(s2, ct+8);
1594 s3 =
1595 (Te4_3[byte(t3, 3)]) ^
1596 (Te4_2[byte(t0, 2)]) ^
1597 (Te4_1[byte(t1, 1)]) ^
1598 (Te4_0[byte(t2, 0)]) ^
1599 rk[3];
1600 STORE32H(s3, ct+12);
1601}
1602
1603#ifdef USE_BURN_STACK
1604static //bbox
1605void psAesDecryptBlock(const unsigned char *ct, unsigned char *pt,
1606 psAesKey_t *skey)
1607{
1608 _aes_ecb_decrypt(ct, pt, skey);
1609 psBurnStack(sizeof(uint32)*8 + sizeof(uint32*) + sizeof(int32)*2);
1610}
1611static void _aes_ecb_decrypt(const unsigned char *ct, unsigned char *pt,
1612 psAesKey_t *skey)
1613#else
1614static //bbox
1615void psAesDecryptBlock(const unsigned char *ct, unsigned char *pt,
1616 psAesKey_t *skey)
1617#endif /* USE_BURN_STACK */
1618{
1619 uint32 s0, s1, s2, s3, t0, t1, t2, t3, *rk;
1620 int32 Nr, r;
1621
1622//bbox
1623// if (pt == NULL || ct == NULL || skey == NULL) {
1624// return;
1625// }
1626
1627 Nr = skey->Nr;
1628 rk = skey->dK;
1629
1630/*
1631 map byte array block to cipher state and add initial round key:
1632 */
1633 LOAD32H(s0, ct ); s0 ^= rk[0];
1634 LOAD32H(s1, ct + 4); s1 ^= rk[1];
1635 LOAD32H(s2, ct + 8); s2 ^= rk[2];
1636 LOAD32H(s3, ct + 12); s3 ^= rk[3];
1637
1638#ifndef PS_AES_IMPROVE_PERF_INCREASE_CODESIZE
1639 for (r = 0; ; r++) {
1640 rk += 4;
1641 t0 =
1642 Td0(byte(s0, 3)) ^
1643 Td1(byte(s3, 2)) ^
1644 Td2(byte(s2, 1)) ^
1645 Td3(byte(s1, 0)) ^
1646 rk[0];
1647 t1 =
1648 Td0(byte(s1, 3)) ^
1649 Td1(byte(s0, 2)) ^
1650 Td2(byte(s3, 1)) ^
1651 Td3(byte(s2, 0)) ^
1652 rk[1];
1653 t2 =
1654 Td0(byte(s2, 3)) ^
1655 Td1(byte(s1, 2)) ^
1656 Td2(byte(s0, 1)) ^
1657 Td3(byte(s3, 0)) ^
1658 rk[2];
1659 t3 =
1660 Td0(byte(s3, 3)) ^
1661 Td1(byte(s2, 2)) ^
1662 Td2(byte(s1, 1)) ^
1663 Td3(byte(s0, 0)) ^
1664 rk[3];
1665 if (r == Nr-2) {
1666 break;
1667 }
1668 s0 = t0; s1 = t1; s2 = t2; s3 = t3;
1669 }
1670 rk += 4;
1671
1672#else /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */
1673
1674/*
1675 Nr - 1 full rounds:
1676 */
1677 r = Nr >> 1;
1678 for (;;) {
1679
1680 t0 =
1681 Td0(byte(s0, 3)) ^
1682 Td1(byte(s3, 2)) ^
1683 Td2(byte(s2, 1)) ^
1684 Td3(byte(s1, 0)) ^
1685 rk[4];
1686 t1 =
1687 Td0(byte(s1, 3)) ^
1688 Td1(byte(s0, 2)) ^
1689 Td2(byte(s3, 1)) ^
1690 Td3(byte(s2, 0)) ^
1691 rk[5];
1692 t2 =
1693 Td0(byte(s2, 3)) ^
1694 Td1(byte(s1, 2)) ^
1695 Td2(byte(s0, 1)) ^
1696 Td3(byte(s3, 0)) ^
1697 rk[6];
1698 t3 =
1699 Td0(byte(s3, 3)) ^
1700 Td1(byte(s2, 2)) ^
1701 Td2(byte(s1, 1)) ^
1702 Td3(byte(s0, 0)) ^
1703 rk[7];
1704
1705 rk += 8;
1706 if (--r == 0) {
1707 break;
1708 }
1709
1710 s0 =
1711 Td0(byte(t0, 3)) ^
1712 Td1(byte(t3, 2)) ^
1713 Td2(byte(t2, 1)) ^
1714 Td3(byte(t1, 0)) ^
1715 rk[0];
1716 s1 =
1717 Td0(byte(t1, 3)) ^
1718 Td1(byte(t0, 2)) ^
1719 Td2(byte(t3, 1)) ^
1720 Td3(byte(t2, 0)) ^
1721 rk[1];
1722 s2 =
1723 Td0(byte(t2, 3)) ^
1724 Td1(byte(t1, 2)) ^
1725 Td2(byte(t0, 1)) ^
1726 Td3(byte(t3, 0)) ^
1727 rk[2];
1728 s3 =
1729 Td0(byte(t3, 3)) ^
1730 Td1(byte(t2, 2)) ^
1731 Td2(byte(t1, 1)) ^
1732 Td3(byte(t0, 0)) ^
1733 rk[3];
1734 }
1735#endif /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */
1736
1737/*
1738 apply last round and map cipher state to byte array block:
1739 */
1740 s0 =
1741 (Td4[byte(t0, 3)] & 0xff000000) ^
1742 (Td4[byte(t3, 2)] & 0x00ff0000) ^
1743 (Td4[byte(t2, 1)] & 0x0000ff00) ^
1744 (Td4[byte(t1, 0)] & 0x000000ff) ^
1745 rk[0];
1746 STORE32H(s0, pt);
1747 s1 =
1748 (Td4[byte(t1, 3)] & 0xff000000) ^
1749 (Td4[byte(t0, 2)] & 0x00ff0000) ^
1750 (Td4[byte(t3, 1)] & 0x0000ff00) ^
1751 (Td4[byte(t2, 0)] & 0x000000ff) ^
1752 rk[1];
1753 STORE32H(s1, pt+4);
1754 s2 =
1755 (Td4[byte(t2, 3)] & 0xff000000) ^
1756 (Td4[byte(t1, 2)] & 0x00ff0000) ^
1757 (Td4[byte(t0, 1)] & 0x0000ff00) ^
1758 (Td4[byte(t3, 0)] & 0x000000ff) ^
1759 rk[2];
1760 STORE32H(s2, pt+8);
1761 s3 =
1762 (Td4[byte(t3, 3)] & 0xff000000) ^
1763 (Td4[byte(t2, 2)] & 0x00ff0000) ^
1764 (Td4[byte(t1, 1)] & 0x0000ff00) ^
1765 (Td4[byte(t0, 0)] & 0x000000ff) ^
1766 rk[3];
1767 STORE32H(s3, pt+12);
1768}
1769
1770
1771/******************************************************************************/
1772/******************************************************************************/
1773#endif /* !USE_AES_CBC_EXTERNAL */
1774#endif /* USE_AES */
1775/******************************************************************************/
1776
diff --git a/networking/tls_aes.h b/networking/tls_aes.h
new file mode 100644
index 000000000..c6791866a
--- /dev/null
+++ b/networking/tls_aes.h
@@ -0,0 +1,10 @@
1/*
2 * Copyright (C) 2017 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 *
6 * Selected few declarations for AES.
7 */
8
9void aes_cbc_encrypt(const void *key, int klen, void *iv, const void *data, size_t len, void *dst);
10void aes_cbc_decrypt(const void *key, int klen, void *iv, const void *data, size_t len, void *dst);
diff --git a/networking/tls_pstm.c b/networking/tls_pstm.c
new file mode 100644
index 000000000..acd800307
--- /dev/null
+++ b/networking/tls_pstm.c
@@ -0,0 +1,2263 @@
1/*
2 * Copyright (C) 2017 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6#include "tls.h"
7
8/* The file is taken almost verbatim from matrixssl-3-7-2b-open/crypto/math/.
9 * Changes are flagged with //bbox
10 */
11
12/**
13 * @file pstm.c
14 * @version 33ef80f (HEAD, tag: MATRIXSSL-3-7-2-OPEN, tag: MATRIXSSL-3-7-2-COMM, origin/master, origin/HEAD, master)
15 *
16 * Multiprecision number implementation.
17 */
18/*
19 * Copyright (c) 2013-2015 INSIDE Secure Corporation
20 * Copyright (c) PeerSec Networks, 2002-2011
21 * All Rights Reserved
22 *
23 * The latest version of this code is available at http://www.matrixssl.org
24 *
25 * This software is open source; you can redistribute it and/or modify
26 * it under the terms of the GNU General Public License as published by
27 * the Free Software Foundation; either version 2 of the License, or
28 * (at your option) any later version.
29 *
30 * This General Public License does NOT permit incorporating this software
31 * into proprietary programs. If you are unable to comply with the GPL, a
32 * commercial license for this software may be purchased from INSIDE at
33 * http://www.insidesecure.com/eng/Company/Locations
34 *
35 * This program is distributed in WITHOUT ANY WARRANTY; without even the
36 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
37 * See the GNU General Public License for more details.
38 *
39 * You should have received a copy of the GNU General Public License
40 * along with this program; if not, write to the Free Software
41 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
42 * http://www.gnu.org/copyleft/gpl.html
43 */
44/******************************************************************************/
45
46//bbox
47//#include "../cryptoApi.h"
48#ifndef DISABLE_PSTM
49
50static int32 pstm_mul_2d(pstm_int *a, int16 b, pstm_int *c);
51
52/******************************************************************************/
53/*
54 init an pstm_int for a given size
55 */
56int32 pstm_init_size(psPool_t *pool, pstm_int * a, uint32 size)
57{
58//bbox
59// uint16 x;
60
61/*
62 alloc mem
63 */
64 a->dp = xzalloc(sizeof (pstm_digit) * size);//bbox
65//bbox a->pool = pool;
66 a->used = 0;
67 a->alloc = (int16)size;
68 a->sign = PSTM_ZPOS;
69/*
70 zero the digits
71 */
72//bbox
73// for (x = 0; x < size; x++) {
74// a->dp[x] = 0;
75// }
76 return PSTM_OKAY;
77}
78
79/******************************************************************************/
80/*
81 Init a new pstm_int.
82*/
83int32 pstm_init(psPool_t *pool, pstm_int * a)
84{
85//bbox
86// int32 i;
87/*
88 allocate memory required and clear it
89 */
90 a->dp = xzalloc(sizeof (pstm_digit) * PSTM_DEFAULT_INIT);//bbox
91/*
92 set the digits to zero
93 */
94//bbox
95// for (i = 0; i < PSTM_DEFAULT_INIT; i++) {
96// a->dp[i] = 0;
97// }
98/*
99 set the used to zero, allocated digits to the default precision and sign
100 to positive
101 */
102//bbox a->pool = pool;
103 a->used = 0;
104 a->alloc = PSTM_DEFAULT_INIT;
105 a->sign = PSTM_ZPOS;
106
107 return PSTM_OKAY;
108}
109
110/******************************************************************************/
111/*
112 Grow as required
113 */
114int32 pstm_grow(pstm_int * a, int16 size)
115{
116 int16 i;
117 pstm_digit *tmp;
118
119/*
120 If the alloc size is smaller alloc more ram.
121 */
122 if (a->alloc < size) {
123/*
124 Reallocate the array a->dp
125
126 We store the return in a temporary variable in case the operation
127 failed we don't want to overwrite the dp member of a.
128*/
129 tmp = xrealloc(a->dp, sizeof (pstm_digit) * size);//bbox
130/*
131 reallocation succeeded so set a->dp
132 */
133 a->dp = tmp;
134/*
135 zero excess digits
136 */
137 i = a->alloc;
138 a->alloc = size;
139 for (; i < a->alloc; i++) {
140 a->dp[i] = 0;
141 }
142 }
143 return PSTM_OKAY;
144}
145
146/******************************************************************************/
147/*
148 copy, b = a (b must be pre-allocated)
149 */
150int32 pstm_copy(pstm_int * a, pstm_int * b)
151{
152 int32 res, n;
153
154/*
155 If dst == src do nothing
156 */
157 if (a == b) {
158 return PSTM_OKAY;
159 }
160/*
161 Grow dest
162 */
163 if (b->alloc < a->used) {
164 if ((res = pstm_grow (b, a->used)) != PSTM_OKAY) {
165 return res;
166 }
167 }
168/*
169 Zero b and copy the parameters over
170 */
171 {
172 register pstm_digit *tmpa, *tmpb;
173
174 /* pointer aliases */
175 /* source */
176 tmpa = a->dp;
177
178 /* destination */
179 tmpb = b->dp;
180
181 /* copy all the digits */
182 for (n = 0; n < a->used; n++) {
183 *tmpb++ = *tmpa++;
184 }
185
186 /* clear high digits */
187 for (; n < b->used; n++) {
188 *tmpb++ = 0;
189 }
190 }
191/*
192 copy used count and sign
193 */
194 b->used = a->used;
195 b->sign = a->sign;
196 return PSTM_OKAY;
197}
198
199/******************************************************************************/
200/*
201 Trim unused digits
202
203 This is used to ensure that leading zero digits are trimed and the
204 leading "used" digit will be non-zero. Typically very fast. Also fixes
205 the sign if there are no more leading digits
206*/
207void pstm_clamp(pstm_int * a)
208{
209/* decrease used while the most significant digit is zero. */
210 while (a->used > 0 && a->dp[a->used - 1] == 0) {
211 --(a->used);
212 }
213/* reset the sign flag if used == 0 */
214 if (a->used == 0) {
215 a->sign = PSTM_ZPOS;
216 }
217}
218
219/******************************************************************************/
220/*
221 clear one (frees).
222 */
223void pstm_clear(pstm_int * a)
224{
225 int32 i;
226/*
227 only do anything if a hasn't been freed previously
228 */
229 if (a != NULL && a->dp != NULL) {
230/*
231 first zero the digits
232 */
233 for (i = 0; i < a->used; i++) {
234 a->dp[i] = 0;
235 }
236
237 psFree (a->dp, a->pool);
238/*
239 reset members to make debugging easier
240 */
241 a->dp = NULL;
242 a->alloc = a->used = 0;
243 a->sign = PSTM_ZPOS;
244 }
245}
246
247/******************************************************************************/
248/*
249 clear many (frees).
250 */
251void pstm_clear_multi(pstm_int *mp0, pstm_int *mp1, pstm_int *mp2,
252 pstm_int *mp3, pstm_int *mp4, pstm_int *mp5,
253 pstm_int *mp6, pstm_int *mp7)
254{
255 int32 n; /* Number of ok inits */
256
257 pstm_int *tempArray[9];
258
259 tempArray[0] = mp0;
260 tempArray[1] = mp1;
261 tempArray[2] = mp2;
262 tempArray[3] = mp3;
263 tempArray[4] = mp4;
264 tempArray[5] = mp5;
265 tempArray[6] = mp6;
266 tempArray[7] = mp7;
267 tempArray[8] = NULL;
268
269 for (n = 0; tempArray[n] != NULL; n++) {
270 if ((tempArray[n] != NULL) && (tempArray[n]->dp != NULL)) {
271 pstm_clear(tempArray[n]);
272 }
273 }
274}
275
276/******************************************************************************/
277/*
278 Set to zero.
279 */
280void pstm_zero(pstm_int * a)
281{
282 int32 n;
283 pstm_digit *tmp;
284
285 a->sign = PSTM_ZPOS;
286 a->used = 0;
287
288 tmp = a->dp;
289 for (n = 0; n < a->alloc; n++) {
290 *tmp++ = 0;
291 }
292}
293
294
295/******************************************************************************/
296/*
297 Compare maginitude of two ints (unsigned).
298 */
299int32 pstm_cmp_mag(pstm_int * a, pstm_int * b)
300{
301 int16 n;
302 pstm_digit *tmpa, *tmpb;
303
304/*
305 compare based on # of non-zero digits
306 */
307 if (a->used > b->used) {
308 return PSTM_GT;
309 }
310
311 if (a->used < b->used) {
312 return PSTM_LT;
313 }
314
315 /* alias for a */
316 tmpa = a->dp + (a->used - 1);
317
318 /* alias for b */
319 tmpb = b->dp + (a->used - 1);
320
321/*
322 compare based on digits
323 */
324 for (n = 0; n < a->used; ++n, --tmpa, --tmpb) {
325 if (*tmpa > *tmpb) {
326 return PSTM_GT;
327 }
328 if (*tmpa < *tmpb) {
329 return PSTM_LT;
330 }
331 }
332 return PSTM_EQ;
333}
334
335/******************************************************************************/
336/*
337 Compare two ints (signed)
338 */
339int32 pstm_cmp(pstm_int * a, pstm_int * b)
340{
341/*
342 compare based on sign
343 */
344 if (a->sign != b->sign) {
345 if (a->sign == PSTM_NEG) {
346 return PSTM_LT;
347 } else {
348 return PSTM_GT;
349 }
350 }
351/*
352 compare digits
353 */
354 if (a->sign == PSTM_NEG) {
355 /* if negative compare opposite direction */
356 return pstm_cmp_mag(b, a);
357 } else {
358 return pstm_cmp_mag(a, b);
359 }
360}
361
362/******************************************************************************/
363/*
364 pstm_ints can be initialized more precisely when they will populated
365 using pstm_read_unsigned_bin since the length of the byte stream is known
366*/
367int32 pstm_init_for_read_unsigned_bin(psPool_t *pool, pstm_int *a, uint32 len)
368{
369 int32 size;
370/*
371 Need to set this based on how many words max it will take to store the bin.
372 The magic + 2:
373 1 to round up for the remainder of this integer math
374 1 for the initial carry of '1' bits that fall between DIGIT_BIT and 8
375*/
376 size = (((len / sizeof(pstm_digit)) * (sizeof(pstm_digit) * CHAR_BIT))
377 / DIGIT_BIT) + 2;
378 return pstm_init_size(pool, a, size);
379}
380
381
382/******************************************************************************/
383/*
384 Reads a unsigned char array into pstm_int format. User should have
385 called pstm_init_for_read_unsigned_bin first. There is some grow logic
386 here if the default pstm_init was used but we don't really want to hit it.
387*/
388int32 pstm_read_unsigned_bin(pstm_int *a, unsigned char *b, int32 c)
389{
390 /* zero the int */
391 pstm_zero (a);
392
393/*
394 If we know the endianness of this architecture, and we're using
395 32-bit pstm_digits, we can optimize this
396*/
397#if (defined(ENDIAN_LITTLE) || defined(ENDIAN_BIG)) && !defined(PSTM_64BIT)
398 /* But not for both simultaneously */
399#if defined(ENDIAN_LITTLE) && defined(ENDIAN_BIG)
400#error Both ENDIAN_LITTLE and ENDIAN_BIG defined.
401#endif
402 {
403 unsigned char *pd;
404 if ((unsigned)c > (PSTM_MAX_SIZE * sizeof(pstm_digit))) {
405 uint32 excess = c - (PSTM_MAX_SIZE * sizeof(pstm_digit));
406 c -= excess;
407 b += excess;
408 }
409 a->used = (int16)((c + sizeof(pstm_digit) - 1)/sizeof(pstm_digit));
410 if (a->alloc < a->used) {
411 if (pstm_grow(a, a->used) != PSTM_OKAY) {
412 return PSTM_MEM;
413 }
414 }
415 pd = (unsigned char *)a->dp;
416 /* read the bytes in */
417#ifdef ENDIAN_BIG
418 {
419 /* Use Duff's device to unroll the loop. */
420 int32 idx = (c - 1) & ~3;
421 switch (c % 4) {
422 case 0: do { pd[idx+0] = *b++;
423 case 3: pd[idx+1] = *b++;
424 case 2: pd[idx+2] = *b++;
425 case 1: pd[idx+3] = *b++;
426 idx -= 4;
427 } while ((c -= 4) > 0);
428 }
429 }
430#else
431 for (c -= 1; c >= 0; c -= 1) {
432 pd[c] = *b++;
433 }
434#endif
435 }
436#else
437 /* Big enough based on the len? */
438 a->used = (((c / sizeof(pstm_digit)) * (sizeof(pstm_digit) * CHAR_BIT))
439 / DIGIT_BIT) + 2;
440
441 if (a->alloc < a->used) {
442 if (pstm_grow(a, a->used) != PSTM_OKAY) {
443 return PSTM_MEM;
444 }
445 }
446 /* read the bytes in */
447 for (; c > 0; c--) {
448 if (pstm_mul_2d (a, 8, a) != PSTM_OKAY) {
449 return PS_MEM_FAIL;
450 }
451 a->dp[0] |= *b++;
452 a->used += 1;
453 }
454#endif
455
456 pstm_clamp (a);
457 return PS_SUCCESS;
458}
459
460/******************************************************************************/
461/*
462*/
463int16 pstm_count_bits (pstm_int * a)
464{
465 int16 r;
466 pstm_digit q;
467
468 if (a->used == 0) {
469 return 0;
470 }
471
472 /* get number of digits and add that */
473 r = (a->used - 1) * DIGIT_BIT;
474
475 /* take the last digit and count the bits in it */
476 q = a->dp[a->used - 1];
477 while (q > ((pstm_digit) 0)) {
478 ++r;
479 q >>= ((pstm_digit) 1);
480 }
481 return r;
482}
483
484/******************************************************************************/
485int32 pstm_unsigned_bin_size(pstm_int *a)
486{
487 int32 size = pstm_count_bits (a);
488 return (size / 8 + ((size & 7) != 0 ? 1 : 0));
489}
490
491/******************************************************************************/
492void pstm_set(pstm_int *a, pstm_digit b)
493{
494 pstm_zero(a);
495 a->dp[0] = b;
496 a->used = a->dp[0] ? 1 : 0;
497}
498
499/******************************************************************************/
500/*
501 Right shift
502*/
503void pstm_rshd(pstm_int *a, int16 x)
504{
505 int16 y;
506
507 /* too many digits just zero and return */
508 if (x >= a->used) {
509 pstm_zero(a);
510 return;
511 }
512
513 /* shift */
514 for (y = 0; y < a->used - x; y++) {
515 a->dp[y] = a->dp[y+x];
516 }
517
518 /* zero rest */
519 for (; y < a->used; y++) {
520 a->dp[y] = 0;
521 }
522
523 /* decrement count */
524 a->used -= x;
525 pstm_clamp(a);
526}
527
528/******************************************************************************/
529/*
530 Shift left a certain amount of digits.
531 */
532int32 pstm_lshd(pstm_int * a, int16 b)
533{
534 int16 x;
535 int32 res;
536
537/*
538 If its less than zero return.
539 */
540 if (b <= 0) {
541 return PSTM_OKAY;
542 }
543/*
544 Grow to fit the new digits.
545 */
546 if (a->alloc < a->used + b) {
547 if ((res = pstm_grow (a, a->used + b)) != PSTM_OKAY) {
548 return res;
549 }
550 }
551
552 {
553 register pstm_digit *top, *bottom;
554/*
555 Increment the used by the shift amount then copy upwards.
556 */
557 a->used += b;
558
559 /* top */
560 top = a->dp + a->used - 1;
561
562 /* base */
563 bottom = a->dp + a->used - 1 - b;
564/*
565 This is implemented using a sliding window except the window goes the
566 other way around. Copying from the bottom to the top.
567 */
568 for (x = a->used - 1; x >= b; x--) {
569 *top-- = *bottom--;
570 }
571
572 /* zero the lower digits */
573 top = a->dp;
574 for (x = 0; x < b; x++) {
575 *top++ = 0;
576 }
577 }
578 return PSTM_OKAY;
579}
580
581/******************************************************************************/
582/*
583 computes a = 2**b
584*/
585int32 pstm_2expt(pstm_int *a, int16 b)
586{
587 int16 z;
588
589 /* zero a as per default */
590 pstm_zero (a);
591
592 if (b < 0) {
593 return PSTM_OKAY;
594 }
595
596 z = b / DIGIT_BIT;
597 if (z >= PSTM_MAX_SIZE) {
598 return PS_LIMIT_FAIL;
599 }
600
601 /* set the used count of where the bit will go */
602 a->used = z + 1;
603
604 if (a->used > a->alloc) {
605 if (pstm_grow(a, a->used) != PSTM_OKAY) {
606 return PS_MEM_FAIL;
607 }
608 }
609
610 /* put the single bit in its place */
611 a->dp[z] = ((pstm_digit)1) << (b % DIGIT_BIT);
612 return PSTM_OKAY;
613}
614
615/******************************************************************************/
616/*
617
618*/
619int32 pstm_mul_2(pstm_int * a, pstm_int * b)
620{
621 int32 res;
622 int16 x, oldused;
623
624/*
625 grow to accomodate result
626 */
627 if (b->alloc < a->used + 1) {
628 if ((res = pstm_grow (b, a->used + 1)) != PSTM_OKAY) {
629 return res;
630 }
631 }
632 oldused = b->used;
633 b->used = a->used;
634
635 {
636 register pstm_digit r, rr, *tmpa, *tmpb;
637
638 /* alias for source */
639 tmpa = a->dp;
640
641 /* alias for dest */
642 tmpb = b->dp;
643
644 /* carry */
645 r = 0;
646 for (x = 0; x < a->used; x++) {
647/*
648 get what will be the *next* carry bit from the
649 MSB of the current digit
650*/
651 rr = *tmpa >> ((pstm_digit)(DIGIT_BIT - 1));
652/*
653 now shift up this digit, add in the carry [from the previous]
654*/
655 *tmpb++ = ((*tmpa++ << ((pstm_digit)1)) | r);
656/*
657 copy the carry that would be from the source
658 digit into the next iteration
659*/
660 r = rr;
661 }
662
663 /* new leading digit? */
664 if (r != 0 && b->used != (PSTM_MAX_SIZE-1)) {
665 /* add a MSB which is always 1 at this point */
666 *tmpb = 1;
667 ++(b->used);
668 }
669/*
670 now zero any excess digits on the destination that we didn't write to
671*/
672 tmpb = b->dp + b->used;
673 for (x = b->used; x < oldused; x++) {
674 *tmpb++ = 0;
675 }
676 }
677 b->sign = a->sign;
678 return PSTM_OKAY;
679}
680
681/******************************************************************************/
682/*
683 unsigned subtraction ||a|| >= ||b|| ALWAYS!
684*/
685int32 s_pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c)
686{
687 int16 oldbused, oldused;
688 int32 x;
689 pstm_word t;
690
691 if (b->used > a->used) {
692 return PS_LIMIT_FAIL;
693 }
694 if (c->alloc < a->used) {
695 if ((x = pstm_grow (c, a->used)) != PSTM_OKAY) {
696 return x;
697 }
698 }
699 oldused = c->used;
700 oldbused = b->used;
701 c->used = a->used;
702 t = 0;
703
704 for (x = 0; x < oldbused; x++) {
705 t = ((pstm_word)a->dp[x]) - (((pstm_word)b->dp[x]) + t);
706 c->dp[x] = (pstm_digit)t;
707 t = (t >> DIGIT_BIT)&1;
708 }
709 for (; x < a->used; x++) {
710 t = ((pstm_word)a->dp[x]) - t;
711 c->dp[x] = (pstm_digit)t;
712 t = (t >> DIGIT_BIT);
713 }
714 for (; x < oldused; x++) {
715 c->dp[x] = 0;
716 }
717 pstm_clamp(c);
718 return PSTM_OKAY;
719}
720
721/******************************************************************************/
722/*
723 unsigned addition
724*/
725static int32 s_pstm_add(pstm_int *a, pstm_int *b, pstm_int *c)
726{
727 int16 x, y, oldused;
728 register pstm_word t, adp, bdp;
729
730 y = a->used;
731 if (b->used > y) {
732 y = b->used;
733 }
734 oldused = c->used;
735 c->used = y;
736
737 if (c->used > c->alloc) {
738 if (pstm_grow(c, c->used) != PSTM_OKAY) {
739 return PS_MEM_FAIL;
740 }
741 }
742
743 t = 0;
744 for (x = 0; x < y; x++) {
745 if (a->used < x) {
746 adp = 0;
747 } else {
748 adp = (pstm_word)a->dp[x];
749 }
750 if (b->used < x) {
751 bdp = 0;
752 } else {
753 bdp = (pstm_word)b->dp[x];
754 }
755 t += (adp) + (bdp);
756 c->dp[x] = (pstm_digit)t;
757 t >>= DIGIT_BIT;
758 }
759 if (t != 0 && x < PSTM_MAX_SIZE) {
760 if (c->used == c->alloc) {
761 if (pstm_grow(c, c->alloc + 1) != PSTM_OKAY) {
762 return PS_MEM_FAIL;
763 }
764 }
765 c->dp[c->used++] = (pstm_digit)t;
766 ++x;
767 }
768
769 c->used = x;
770 for (; x < oldused; x++) {
771 c->dp[x] = 0;
772 }
773 pstm_clamp(c);
774 return PSTM_OKAY;
775}
776
777
778/******************************************************************************/
779/*
780
781*/
782int32 pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c)
783{
784 int32 res;
785 int16 sa, sb;
786
787 sa = a->sign;
788 sb = b->sign;
789
790 if (sa != sb) {
791/*
792 subtract a negative from a positive, OR a positive from a negative.
793 For both, ADD their magnitudes, and use the sign of the first number.
794 */
795 c->sign = sa;
796 if ((res = s_pstm_add (a, b, c)) != PSTM_OKAY) {
797 return res;
798 }
799 } else {
800/*
801 subtract a positive from a positive, OR a negative from a negative.
802 First, take the difference between their magnitudes, then...
803 */
804 if (pstm_cmp_mag (a, b) != PSTM_LT) {
805 /* Copy the sign from the first */
806 c->sign = sa;
807 /* The first has a larger or equal magnitude */
808 if ((res = s_pstm_sub (a, b, c)) != PSTM_OKAY) {
809 return res;
810 }
811 } else {
812 /* The result has the _opposite_ sign from the first number. */
813 c->sign = (sa == PSTM_ZPOS) ? PSTM_NEG : PSTM_ZPOS;
814 /* The second has a larger magnitude */
815 if ((res = s_pstm_sub (b, a, c)) != PSTM_OKAY) {
816 return res;
817 }
818 }
819 }
820 return PS_SUCCESS;
821}
822
823/******************************************************************************/
824/*
825 c = a - b
826*/
827int32 pstm_sub_d(psPool_t *pool, pstm_int *a, pstm_digit b, pstm_int *c)
828{
829 pstm_int tmp;
830 int32 res;
831
832 if (pstm_init_size(pool, &tmp, sizeof(pstm_digit)) != PSTM_OKAY) {
833 return PS_MEM_FAIL;
834 }
835 pstm_set(&tmp, b);
836 res = pstm_sub(a, &tmp, c);
837 pstm_clear(&tmp);
838 return res;
839}
840
841/******************************************************************************/
842/*
843 setups the montgomery reduction
844*/
845int32 pstm_montgomery_setup(pstm_int *a, pstm_digit *rho)
846{
847 pstm_digit x, b;
848
849/*
850 fast inversion mod 2**k
851 Based on the fact that
852 XA = 1 (mod 2**n) => (X(2-XA)) A = 1 (mod 2**2n)
853 => 2*X*A - X*X*A*A = 1
854 => 2*(1) - (1) = 1
855 */
856 b = a->dp[0];
857
858 if ((b & 1) == 0) {
859 psTraceCrypto("pstm_montogomery_setup failure\n");
860 return PS_ARG_FAIL;
861 }
862
863 x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
864 x *= 2 - b * x; /* here x*a==1 mod 2**8 */
865 x *= 2 - b * x; /* here x*a==1 mod 2**16 */
866 x *= 2 - b * x; /* here x*a==1 mod 2**32 */
867#ifdef PSTM_64BIT
868 x *= 2 - b * x; /* here x*a==1 mod 2**64 */
869#endif
870 /* rho = -1/m mod b */
871 *rho = (pstm_digit)(((pstm_word) 1 << ((pstm_word) DIGIT_BIT)) -
872 ((pstm_word)x));
873 return PSTM_OKAY;
874}
875
876/******************************************************************************/
877/*
878 * computes a = B**n mod b without division or multiplication useful for
879 * normalizing numbers in a Montgomery system.
880 */
881int32 pstm_montgomery_calc_normalization(pstm_int *a, pstm_int *b)
882{
883 int32 x;
884 int16 bits;
885
886 /* how many bits of last digit does b use */
887 bits = pstm_count_bits (b) % DIGIT_BIT;
888 if (!bits) bits = DIGIT_BIT;
889
890 /* compute A = B^(n-1) * 2^(bits-1) */
891 if (b->used > 1) {
892 if ((x = pstm_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) !=
893 PSTM_OKAY) {
894 return x;
895 }
896 } else {
897 pstm_set(a, 1);
898 bits = 1;
899 }
900
901 /* now compute C = A * B mod b */
902 for (x = bits - 1; x < (int32)DIGIT_BIT; x++) {
903 if (pstm_mul_2 (a, a) != PSTM_OKAY) {
904 return PS_MEM_FAIL;
905 }
906 if (pstm_cmp_mag (a, b) != PSTM_LT) {
907 if (s_pstm_sub (a, b, a) != PSTM_OKAY) {
908 return PS_MEM_FAIL;
909 }
910 }
911 }
912 return PSTM_OKAY;
913}
914
915/******************************************************************************/
916/*
917 c = a * 2**d
918*/
919static int32 pstm_mul_2d(pstm_int *a, int16 b, pstm_int *c)
920{
921 pstm_digit carry, carrytmp, shift;
922 int16 x;
923
924 /* copy it */
925 if (pstm_copy(a, c) != PSTM_OKAY) {
926 return PS_MEM_FAIL;
927 }
928
929 /* handle whole digits */
930 if (b >= DIGIT_BIT) {
931 if (pstm_lshd(c, b/DIGIT_BIT) != PSTM_OKAY) {
932 return PS_MEM_FAIL;
933 }
934 }
935 b %= DIGIT_BIT;
936
937 /* shift the digits */
938 if (b != 0) {
939 carry = 0;
940 shift = DIGIT_BIT - b;
941 for (x = 0; x < c->used; x++) {
942 carrytmp = c->dp[x] >> shift;
943 c->dp[x] = (c->dp[x] << b) + carry;
944 carry = carrytmp;
945 }
946 /* store last carry if room */
947 if (carry && x < PSTM_MAX_SIZE) {
948 if (c->used == c->alloc) {
949 if (pstm_grow(c, c->alloc + 1) != PSTM_OKAY) {
950 return PS_MEM_FAIL;
951 }
952 }
953 c->dp[c->used++] = carry;
954 }
955 }
956 pstm_clamp(c);
957 return PSTM_OKAY;
958}
959
960/******************************************************************************/
961/*
962 c = a mod 2**d
963*/
964static int32 pstm_mod_2d(pstm_int *a, int16 b, pstm_int *c)
965{
966 int16 x;
967
968 /* zero if count less than or equal to zero */
969 if (b <= 0) {
970 pstm_zero(c);
971 return PSTM_OKAY;
972 }
973
974 /* get copy of input */
975 if (pstm_copy(a, c) != PSTM_OKAY) {
976 return PS_MEM_FAIL;
977 }
978
979 /* if 2**d is larger than we just return */
980 if (b >= (DIGIT_BIT * a->used)) {
981 return PSTM_OKAY;
982 }
983
984 /* zero digits above the last digit of the modulus */
985 for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++)
986 {
987 c->dp[x] = 0;
988 }
989 /* clear the digit that is not completely outside/inside the modulus */
990 c->dp[b / DIGIT_BIT] &= ~((pstm_digit)0) >> (DIGIT_BIT - b);
991 pstm_clamp (c);
992 return PSTM_OKAY;
993}
994
995
996/******************************************************************************/
997/*
998 c = a * b
999*/
1000int32 pstm_mul_d(pstm_int *a, pstm_digit b, pstm_int *c)
1001{
1002 pstm_word w;
1003 int32 res;
1004 int16 x, oldused;
1005
1006 if (c->alloc < a->used + 1) {
1007 if ((res = pstm_grow (c, a->used + 1)) != PSTM_OKAY) {
1008 return res;
1009 }
1010 }
1011 oldused = c->used;
1012 c->used = a->used;
1013 c->sign = a->sign;
1014 w = 0;
1015 for (x = 0; x < a->used; x++) {
1016 w = ((pstm_word)a->dp[x]) * ((pstm_word)b) + w;
1017 c->dp[x] = (pstm_digit)w;
1018 w = w >> DIGIT_BIT;
1019 }
1020 if (w != 0 && (a->used != PSTM_MAX_SIZE)) {
1021 c->dp[c->used++] = (pstm_digit)w;
1022 ++x;
1023 }
1024 for (; x < oldused; x++) {
1025 c->dp[x] = 0;
1026 }
1027 pstm_clamp(c);
1028 return PSTM_OKAY;
1029}
1030
1031/******************************************************************************/
1032/*
1033 c = a / 2**b
1034*/
1035int32 pstm_div_2d(psPool_t *pool, pstm_int *a, int16 b, pstm_int *c,
1036 pstm_int *d)
1037{
1038 pstm_digit D, r, rr;
1039 int32 res;
1040 int16 x;
1041 pstm_int t;
1042
1043 /* if the shift count is <= 0 then we do no work */
1044 if (b <= 0) {
1045 if (pstm_copy (a, c) != PSTM_OKAY) {
1046 return PS_MEM_FAIL;
1047 }
1048 if (d != NULL) {
1049 pstm_zero (d);
1050 }
1051 return PSTM_OKAY;
1052 }
1053
1054 /* get the remainder */
1055 if (d != NULL) {
1056 if (pstm_init(pool, &t) != PSTM_OKAY) {
1057 return PS_MEM_FAIL;
1058 }
1059 if (pstm_mod_2d (a, b, &t) != PSTM_OKAY) {
1060 res = PS_MEM_FAIL;
1061 goto LBL_DONE;
1062 }
1063 }
1064
1065 /* copy */
1066 if (pstm_copy(a, c) != PSTM_OKAY) {
1067 res = PS_MEM_FAIL;
1068 goto LBL_DONE;
1069 }
1070
1071 /* shift by as many digits in the bit count */
1072 if (b >= (int32)DIGIT_BIT) {
1073 pstm_rshd (c, b / DIGIT_BIT);
1074 }
1075
1076 /* shift any bit count < DIGIT_BIT */
1077 D = (pstm_digit) (b % DIGIT_BIT);
1078 if (D != 0) {
1079 register pstm_digit *tmpc, mask, shift;
1080
1081 /* mask */
1082 mask = (((pstm_digit)1) << D) - 1;
1083
1084 /* shift for lsb */
1085 shift = DIGIT_BIT - D;
1086
1087 /* alias */
1088 tmpc = c->dp + (c->used - 1);
1089
1090 /* carry */
1091 r = 0;
1092 for (x = c->used - 1; x >= 0; x--) {
1093 /* get the lower bits of this word in a temp */
1094 rr = *tmpc & mask;
1095
1096 /* shift the current word and mix in the carry bits from previous */
1097 *tmpc = (*tmpc >> D) | (r << shift);
1098 --tmpc;
1099
1100 /* set the carry to the carry bits of the current word above */
1101 r = rr;
1102 }
1103 }
1104 pstm_clamp (c);
1105
1106 res = PSTM_OKAY;
1107LBL_DONE:
1108 if (d != NULL) {
1109 if (pstm_copy(&t, d) != PSTM_OKAY) {
1110 res = PS_MEM_FAIL;
1111 }
1112 pstm_clear(&t);
1113 }
1114 return res;
1115}
1116
1117/******************************************************************************/
1118/*
1119 b = a/2
1120*/
1121int32 pstm_div_2(pstm_int * a, pstm_int * b)
1122{
1123 int16 x, oldused;
1124
1125 if (b->alloc < a->used) {
1126 if (pstm_grow(b, a->used) != PSTM_OKAY) {
1127 return PS_MEM_FAIL;
1128 }
1129 }
1130 oldused = b->used;
1131 b->used = a->used;
1132 {
1133 register pstm_digit r, rr, *tmpa, *tmpb;
1134
1135 /* source alias */
1136 tmpa = a->dp + b->used - 1;
1137
1138 /* dest alias */
1139 tmpb = b->dp + b->used - 1;
1140
1141 /* carry */
1142 r = 0;
1143 for (x = b->used - 1; x >= 0; x--) {
1144 /* get the carry for the next iteration */
1145 rr = *tmpa & 1;
1146
1147 /* shift the current digit, add in carry and store */
1148 *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1));
1149
1150 /* forward carry to next iteration */
1151 r = rr;
1152 }
1153
1154 /* zero excess digits */
1155 tmpb = b->dp + b->used;
1156 for (x = b->used; x < oldused; x++) {
1157 *tmpb++ = 0;
1158 }
1159 }
1160 b->sign = a->sign;
1161 pstm_clamp (b);
1162 return PSTM_OKAY;
1163}
1164
1165/******************************************************************************/
1166/*
1167 Creates "a" then copies b into it
1168 */
1169int32 pstm_init_copy(psPool_t *pool, pstm_int * a, pstm_int * b, int16 toSqr)
1170{
1171 int16 x;
1172 int32 res;
1173
1174 if (a == b) {
1175 return PSTM_OKAY;
1176 }
1177 x = b->alloc;
1178
1179 if (toSqr) {
1180/*
1181 Smart-size: Increasing size of a if b->used is roughly half
1182 of b->alloc because usage has shown that a lot of these copies
1183 go on to be squared and need these extra digits
1184*/
1185 if ((b->used * 2) + 2 >= x) {
1186 x = (b->used * 2) + 3;
1187 }
1188 }
1189 if ((res = pstm_init_size(pool, a, x)) != PSTM_OKAY) {
1190 return res;
1191 }
1192 return pstm_copy(b, a);
1193}
1194
1195/******************************************************************************/
1196/*
1197 With some compilers, we have seen issues linking with the builtin
1198 64 bit division routine. The issues with either manifest in a failure
1199 to find 'udivdi3' at link time, or a runtime invalid instruction fault
1200 during an RSA operation.
1201 The routine below divides a 64 bit unsigned int by a 32 bit unsigned int
1202 explicitly, rather than using the division operation
1203 The 64 bit result is placed in the 'numerator' parameter
1204 The 32 bit mod (remainder) of the division is the return parameter
1205 Based on implementations by:
1206 Copyright (C) 2003 Bernardo Innocenti <bernie@develer.com>
1207 Copyright (C) 1999 Hewlett-Packard Co
1208 Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
1209*/
1210#if defined(USE_MATRIX_DIV64) && defined(PSTM_32BIT)
1211static uint32 psDiv64(uint64 *numerator, uint32 denominator)
1212{
1213 uint64 rem = *numerator;
1214 uint64 b = denominator;
1215 uint64 res = 0;
1216 uint64 d = 1;
1217 uint32 high = rem >> 32;
1218
1219 if (high >= denominator) {
1220 high /= denominator;
1221 res = (uint64) high << 32;
1222 rem -= (uint64) (high * denominator) << 32;
1223 }
1224 while ((int64)b > 0 && b < rem) {
1225 b = b+b;
1226 d = d+d;
1227 }
1228 do {
1229 if (rem >= b) {
1230 rem -= b;
1231 res += d;
1232 }
1233 b >>= 1;
1234 d >>= 1;
1235 } while (d);
1236 *numerator = res;
1237 return rem;
1238}
1239#endif /* USE_MATRIX_DIV64 */
1240
1241#if defined(USE_MATRIX_DIV128) && defined(PSTM_64BIT)
1242typedef unsigned long uint128 __attribute__ ((mode(TI)));
1243static uint64 psDiv128(uint128 *numerator, uint64 denominator)
1244{
1245 uint128 rem = *numerator;
1246 uint128 b = denominator;
1247 uint128 res = 0;
1248 uint128 d = 1;
1249 uint64 high = rem >> 64;
1250
1251 if (high >= denominator) {
1252 high /= denominator;
1253 res = (uint128) high << 64;
1254 rem -= (uint128) (high * denominator) << 64;
1255 }
1256 while ((uint128)b > 0 && b < rem) {
1257 b = b+b;
1258 d = d+d;
1259 }
1260 do {
1261 if (rem >= b) {
1262 rem -= b;
1263 res += d;
1264 }
1265 b >>= 1;
1266 d >>= 1;
1267 } while (d);
1268 *numerator = res;
1269 return rem;
1270}
1271#endif /* USE_MATRIX_DIV128 */
1272
1273/******************************************************************************/
1274/*
1275 a/b => cb + d == a
1276*/
1277int32 pstm_div(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c,
1278 pstm_int *d)
1279{
1280 pstm_int q, x, y, t1, t2;
1281 int32 res;
1282 int16 n, t, i, norm, neg;
1283
1284 /* is divisor zero ? */
1285 if (pstm_iszero (b) == 1) {
1286 return PS_LIMIT_FAIL;
1287 }
1288
1289 /* if a < b then q=0, r = a */
1290 if (pstm_cmp_mag (a, b) == PSTM_LT) {
1291 if (d != NULL) {
1292 if (pstm_copy(a, d) != PSTM_OKAY) {
1293 return PS_MEM_FAIL;
1294 }
1295 }
1296 if (c != NULL) {
1297 pstm_zero (c);
1298 }
1299 return PSTM_OKAY;
1300 }
1301/*
1302 Smart-size inits
1303*/
1304 if ((res = pstm_init_size(pool, &t1, a->alloc)) != PSTM_OKAY) {
1305 return res;
1306 }
1307 if ((res = pstm_init_size(pool, &t2, 3)) != PSTM_OKAY) {
1308 goto LBL_T1;
1309 }
1310 if ((res = pstm_init_copy(pool, &x, a, 0)) != PSTM_OKAY) {
1311 goto LBL_T2;
1312 }
1313/*
1314 Used to be an init_copy on b but pstm_grow was always hit with triple size
1315*/
1316 if ((res = pstm_init_size(pool, &y, b->used * 3)) != PSTM_OKAY) {
1317 goto LBL_X;
1318 }
1319 if ((res = pstm_copy(b, &y)) != PSTM_OKAY) {
1320 goto LBL_Y;
1321 }
1322
1323 /* fix the sign */
1324 neg = (a->sign == b->sign) ? PSTM_ZPOS : PSTM_NEG;
1325 x.sign = y.sign = PSTM_ZPOS;
1326
1327 /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */
1328 norm = pstm_count_bits(&y) % DIGIT_BIT;
1329 if (norm < (int32)(DIGIT_BIT-1)) {
1330 norm = (DIGIT_BIT-1) - norm;
1331 if ((res = pstm_mul_2d(&x, norm, &x)) != PSTM_OKAY) {
1332 goto LBL_Y;
1333 }
1334 if ((res = pstm_mul_2d(&y, norm, &y)) != PSTM_OKAY) {
1335 goto LBL_Y;
1336 }
1337 } else {
1338 norm = 0;
1339 }
1340
1341 /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */
1342 n = x.used - 1;
1343 t = y.used - 1;
1344
1345 if ((res = pstm_init_size(pool, &q, n - t + 1)) != PSTM_OKAY) {
1346 goto LBL_Y;
1347 }
1348 q.used = n - t + 1;
1349
1350 /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */
1351 if ((res = pstm_lshd(&y, n - t)) != PSTM_OKAY) { /* y = y*b**{n-t} */
1352 goto LBL_Q;
1353 }
1354
1355 while (pstm_cmp (&x, &y) != PSTM_LT) {
1356 ++(q.dp[n - t]);
1357 if ((res = pstm_sub(&x, &y, &x)) != PSTM_OKAY) {
1358 goto LBL_Q;
1359 }
1360 }
1361
1362 /* reset y by shifting it back down */
1363 pstm_rshd (&y, n - t);
1364
1365 /* step 3. for i from n down to (t + 1) */
1366 for (i = n; i >= (t + 1); i--) {
1367 if (i > x.used) {
1368 continue;
1369 }
1370
1371 /* step 3.1 if xi == yt then set q{i-t-1} to b-1,
1372 * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */
1373 if (x.dp[i] == y.dp[t]) {
1374 q.dp[i - t - 1] = (pstm_digit)((((pstm_word)1) << DIGIT_BIT) - 1);
1375 } else {
1376 pstm_word tmp;
1377 tmp = ((pstm_word) x.dp[i]) << ((pstm_word) DIGIT_BIT);
1378 tmp |= ((pstm_word) x.dp[i - 1]);
1379#if defined(USE_MATRIX_DIV64) && defined(PSTM_32BIT)
1380 psDiv64(&tmp, y.dp[t]);
1381#elif defined(USE_MATRIX_DIV128) && defined(PSTM_64BIT)
1382 psDiv128(&tmp, y.dp[t]);
1383#else
1384 tmp /= ((pstm_word) y.dp[t]);
1385#endif /* USE_MATRIX_DIV64 */
1386 q.dp[i - t - 1] = (pstm_digit) (tmp);
1387 }
1388
1389 /* while (q{i-t-1} * (yt * b + y{t-1})) >
1390 xi * b**2 + xi-1 * b + xi-2
1391
1392 do q{i-t-1} -= 1;
1393 */
1394 q.dp[i - t - 1] = (q.dp[i - t - 1] + 1);
1395 do {
1396 q.dp[i - t - 1] = (q.dp[i - t - 1] - 1);
1397
1398 /* find left hand */
1399 pstm_zero (&t1);
1400 t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1];
1401 t1.dp[1] = y.dp[t];
1402 t1.used = 2;
1403 if ((res = pstm_mul_d (&t1, q.dp[i - t - 1], &t1)) != PSTM_OKAY) {
1404 goto LBL_Q;
1405 }
1406
1407 /* find right hand */
1408 t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2];
1409 t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1];
1410 t2.dp[2] = x.dp[i];
1411 t2.used = 3;
1412 } while (pstm_cmp_mag(&t1, &t2) == PSTM_GT);
1413
1414 /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */
1415 if ((res = pstm_mul_d(&y, q.dp[i - t - 1], &t1)) != PSTM_OKAY) {
1416 goto LBL_Q;
1417 }
1418
1419 if ((res = pstm_lshd(&t1, i - t - 1)) != PSTM_OKAY) {
1420 goto LBL_Q;
1421 }
1422
1423 if ((res = pstm_sub(&x, &t1, &x)) != PSTM_OKAY) {
1424 goto LBL_Q;
1425 }
1426
1427 /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */
1428 if (x.sign == PSTM_NEG) {
1429 if ((res = pstm_copy(&y, &t1)) != PSTM_OKAY) {
1430 goto LBL_Q;
1431 }
1432 if ((res = pstm_lshd (&t1, i - t - 1)) != PSTM_OKAY) {
1433 goto LBL_Q;
1434 }
1435 if ((res = pstm_add (&x, &t1, &x)) != PSTM_OKAY) {
1436 goto LBL_Q;
1437 }
1438 q.dp[i - t - 1] = q.dp[i - t - 1] - 1;
1439 }
1440 }
1441/*
1442 now q is the quotient and x is the remainder (which we have to normalize)
1443*/
1444 /* get sign before writing to c */
1445 x.sign = x.used == 0 ? PSTM_ZPOS : a->sign;
1446
1447 if (c != NULL) {
1448 pstm_clamp (&q);
1449 if (pstm_copy (&q, c) != PSTM_OKAY) {
1450 res = PS_MEM_FAIL;
1451 goto LBL_Q;
1452 }
1453 c->sign = neg;
1454 }
1455
1456 if (d != NULL) {
1457 if ((res = pstm_div_2d (pool, &x, norm, &x, NULL)) != PSTM_OKAY) {
1458 goto LBL_Q;
1459 }
1460/*
1461 the following is a kludge, essentially we were seeing the right
1462 remainder but with excess digits that should have been zero
1463 */
1464 for (i = b->used; i < x.used; i++) {
1465 x.dp[i] = 0;
1466 }
1467 pstm_clamp(&x);
1468 if (pstm_copy (&x, d) != PSTM_OKAY) {
1469 res = PS_MEM_FAIL;
1470 goto LBL_Q;
1471 }
1472 }
1473
1474 res = PSTM_OKAY;
1475
1476LBL_Q:pstm_clear (&q);
1477LBL_Y:pstm_clear (&y);
1478LBL_X:pstm_clear (&x);
1479LBL_T2:pstm_clear (&t2);
1480LBL_T1:pstm_clear (&t1);
1481
1482 return res;
1483}
1484
1485/******************************************************************************/
1486/*
1487 Swap the elements of two integers, for cases where you can't simply swap
1488 the pstm_int pointers around
1489*/
1490void pstm_exch(pstm_int * a, pstm_int * b)
1491{
1492 pstm_int t;
1493
1494 t = *a;
1495 *a = *b;
1496 *b = t;
1497}
1498
1499/******************************************************************************/
1500/*
1501 c = a mod b, 0 <= c < b
1502*/
1503int32 pstm_mod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c)
1504{
1505 pstm_int t;
1506 int32 err;
1507/*
1508 Smart-size
1509*/
1510 if ((err = pstm_init_size(pool, &t, b->alloc)) != PSTM_OKAY) {
1511 return err;
1512 }
1513 if ((err = pstm_div(pool, a, b, NULL, &t)) != PSTM_OKAY) {
1514 pstm_clear (&t);
1515 return err;
1516 }
1517 if (t.sign != b->sign) {
1518 err = pstm_add(&t, b, c);
1519 } else {
1520 pstm_exch (&t, c);
1521 }
1522 pstm_clear (&t);
1523 return err;
1524}
1525
1526/******************************************************************************/
1527/*
1528 d = a * b (mod c)
1529*/
1530int32 pstm_mulmod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c,
1531 pstm_int *d)
1532{
1533 int32 res;
1534 int16 size;
1535 pstm_int tmp;
1536
1537/*
1538 Smart-size pstm_inits. d is an output that is influenced by this local 't'
1539 so don't shrink 'd' if it wants to becuase this will lead to an pstm_grow
1540 in RSA operations
1541*/
1542 size = a->used + b->used + 1;
1543 if ((a == d) && (size < a->alloc)) {
1544 size = a->alloc;
1545 }
1546 if ((res = pstm_init_size(pool, &tmp, size)) != PSTM_OKAY) {
1547 return res;
1548 }
1549 if ((res = pstm_mul_comba(pool, a, b, &tmp, NULL, 0)) != PSTM_OKAY) {
1550 pstm_clear(&tmp);
1551 return res;
1552 }
1553 res = pstm_mod(pool, &tmp, c, d);
1554 pstm_clear(&tmp);
1555 return res;
1556}
1557
1558/******************************************************************************/
1559/*
1560 * y = g**x (mod b)
1561 * Some restrictions... x must be positive and < b
1562 */
1563int32 pstm_exptmod(psPool_t *pool, pstm_int *G, pstm_int *X, pstm_int *P,
1564 pstm_int *Y)
1565{
1566 pstm_int M[32], res; /* Keep this winsize based: (1 << max_winsize) */
1567 pstm_digit buf, mp;
1568 pstm_digit *paD;
1569 int32 err, bitbuf;
1570 int16 bitcpy, bitcnt, mode, digidx, x, y, winsize;
1571 uint32 paDlen;
1572
1573 /* set window size from what user set as optimization */
1574 x = pstm_count_bits(X);
1575 if (x < 50) {
1576 winsize = 2;
1577 } else {
1578 winsize = PS_EXPTMOD_WINSIZE;
1579 }
1580
1581 /* now setup montgomery */
1582 if ((err = pstm_montgomery_setup (P, &mp)) != PSTM_OKAY) {
1583 return err;
1584 }
1585
1586 /* setup result */
1587 if ((err = pstm_init_size(pool, &res, (P->used * 2) + 1)) != PSTM_OKAY) {
1588 return err;
1589 }
1590/*
1591 create M table
1592 The M table contains powers of the input base, e.g. M[x] = G^x mod P
1593 The first half of the table is not computed though except for M[0] and M[1]
1594 */
1595 /* now we need R mod m */
1596 if ((err = pstm_montgomery_calc_normalization (&res, P)) != PSTM_OKAY) {
1597 goto LBL_RES;
1598 }
1599/*
1600 init M array
1601 init first cell
1602 */
1603 if ((err = pstm_init_size(pool, &M[1], res.used)) != PSTM_OKAY) {
1604 goto LBL_RES;
1605 }
1606
1607 /* now set M[1] to G * R mod m */
1608 if (pstm_cmp_mag(P, G) != PSTM_GT) {
1609 /* G > P so we reduce it first */
1610 if ((err = pstm_mod(pool, G, P, &M[1])) != PSTM_OKAY) {
1611 goto LBL_M;
1612 }
1613 } else {
1614 if ((err = pstm_copy(G, &M[1])) != PSTM_OKAY) {
1615 goto LBL_M;
1616 }
1617 }
1618 if ((err = pstm_mulmod (pool, &M[1], &res, P, &M[1])) != PSTM_OKAY) {
1619 goto LBL_M;
1620 }
1621/*
1622 Pre-allocated digit. Used for mul, sqr, AND reduce
1623*/
1624 paDlen = ((M[1].used + 3) * 2) * sizeof(pstm_digit);
1625 paD = xzalloc(paDlen);//bbox
1626/*
1627 compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times
1628 */
1629 if (pstm_init_copy(pool, &M[1 << (winsize - 1)], &M[1], 1) != PSTM_OKAY) {
1630 err = PS_MEM_FAIL;
1631 goto LBL_PAD;
1632 }
1633 for (x = 0; x < (winsize - 1); x++) {
1634 if ((err = pstm_sqr_comba (pool, &M[1 << (winsize - 1)],
1635 &M[1 << (winsize - 1)], paD, paDlen)) != PSTM_OKAY) {
1636 goto LBL_PAD;
1637 }
1638 if ((err = pstm_montgomery_reduce(pool, &M[1 << (winsize - 1)], P, mp,
1639 paD, paDlen)) != PSTM_OKAY) {
1640 goto LBL_PAD;
1641 }
1642 }
1643/*
1644 now init the second half of the array
1645*/
1646 for (x = (1<<(winsize-1)) + 1; x < (1 << winsize); x++) {
1647 if ((err = pstm_init_size(pool, &M[x], M[1<<(winsize-1)].alloc + 1))
1648 != PSTM_OKAY) {
1649 for (y = 1<<(winsize-1); y < x; y++) {
1650 pstm_clear(&M[y]);
1651 }
1652 goto LBL_PAD;
1653 }
1654 }
1655
1656 /* create upper table */
1657 for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
1658 if ((err = pstm_mul_comba(pool, &M[x - 1], &M[1], &M[x], paD, paDlen))
1659 != PSTM_OKAY) {
1660 goto LBL_MARRAY;
1661 }
1662 if ((err = pstm_montgomery_reduce(pool, &M[x], P, mp, paD, paDlen)) !=
1663 PSTM_OKAY) {
1664 goto LBL_MARRAY;
1665 }
1666 }
1667
1668 /* set initial mode and bit cnt */
1669 mode = 0;
1670 bitcnt = 1;
1671 buf = 0;
1672 digidx = X->used - 1;
1673 bitcpy = 0;
1674 bitbuf = 0;
1675
1676 for (;;) {
1677 /* grab next digit as required */
1678 if (--bitcnt == 0) {
1679 /* if digidx == -1 we are out of digits so break */
1680 if (digidx == -1) {
1681 break;
1682 }
1683 /* read next digit and reset bitcnt */
1684 buf = X->dp[digidx--];
1685 bitcnt = (int32)DIGIT_BIT;
1686 }
1687
1688 /* grab the next msb from the exponent */
1689 y = (pstm_digit)(buf >> (DIGIT_BIT - 1)) & 1;
1690 buf <<= (pstm_digit)1;
1691/*
1692 If the bit is zero and mode == 0 then we ignore it.
1693 These represent the leading zero bits before the first 1 bit
1694 in the exponent. Technically this opt is not required but it
1695 does lower the # of trivial squaring/reductions used
1696*/
1697 if (mode == 0 && y == 0) {
1698 continue;
1699 }
1700
1701 /* if the bit is zero and mode == 1 then we square */
1702 if (mode == 1 && y == 0) {
1703 if ((err = pstm_sqr_comba(pool, &res, &res, paD, paDlen)) !=
1704 PSTM_OKAY) {
1705 goto LBL_MARRAY;
1706 }
1707 if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD, paDlen))
1708 != PSTM_OKAY) {
1709 goto LBL_MARRAY;
1710 }
1711 continue;
1712 }
1713
1714 /* else we add it to the window */
1715 bitbuf |= (y << (winsize - ++bitcpy));
1716 mode = 2;
1717
1718 if (bitcpy == winsize) {
1719 /* ok window is filled so square as required and mul square first */
1720 for (x = 0; x < winsize; x++) {
1721 if ((err = pstm_sqr_comba(pool, &res, &res, paD, paDlen)) !=
1722 PSTM_OKAY) {
1723 goto LBL_MARRAY;
1724 }
1725 if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD,
1726 paDlen)) != PSTM_OKAY) {
1727 goto LBL_MARRAY;
1728 }
1729 }
1730
1731 /* then multiply */
1732 if ((err = pstm_mul_comba(pool, &res, &M[bitbuf], &res, paD,
1733 paDlen)) != PSTM_OKAY) {
1734 goto LBL_MARRAY;
1735 }
1736 if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD, paDlen))
1737 != PSTM_OKAY) {
1738 goto LBL_MARRAY;
1739 }
1740
1741 /* empty window and reset */
1742 bitcpy = 0;
1743 bitbuf = 0;
1744 mode = 1;
1745 }
1746 }
1747
1748 /* if bits remain then square/multiply */
1749 if (mode == 2 && bitcpy > 0) {
1750 /* square then multiply if the bit is set */
1751 for (x = 0; x < bitcpy; x++) {
1752 if ((err = pstm_sqr_comba(pool, &res, &res, paD, paDlen)) !=
1753 PSTM_OKAY) {
1754 goto LBL_MARRAY;
1755 }
1756 if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD, paDlen))
1757 != PSTM_OKAY) {
1758 goto LBL_MARRAY;
1759 }
1760
1761 /* get next bit of the window */
1762 bitbuf <<= 1;
1763 if ((bitbuf & (1 << winsize)) != 0) {
1764 /* then multiply */
1765 if ((err = pstm_mul_comba(pool, &res, &M[1], &res, paD, paDlen))
1766 != PSTM_OKAY) {
1767 goto LBL_MARRAY;
1768 }
1769 if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD,
1770 paDlen)) != PSTM_OKAY) {
1771 goto LBL_MARRAY;
1772 }
1773 }
1774 }
1775 }
1776/*
1777 Fix up result if Montgomery reduction is used recall that any value in a
1778 Montgomery system is actually multiplied by R mod n. So we have to reduce
1779 one more time to cancel out the factor of R.
1780*/
1781 if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD, paDlen)) !=
1782 PSTM_OKAY) {
1783 goto LBL_MARRAY;
1784 }
1785 /* swap res with Y */
1786 if ((err = pstm_copy (&res, Y)) != PSTM_OKAY) {
1787 goto LBL_MARRAY;
1788 }
1789 err = PSTM_OKAY;
1790LBL_MARRAY:
1791 for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
1792 pstm_clear(&M[x]);
1793 }
1794LBL_PAD:psFree(paD, pool);
1795LBL_M: pstm_clear(&M[1]);
1796LBL_RES:pstm_clear(&res);
1797 return err;
1798}
1799
1800/******************************************************************************/
1801/*
1802
1803*/
1804int32 pstm_add(pstm_int *a, pstm_int *b, pstm_int *c)
1805{
1806 int32 res;
1807 int16 sa, sb;
1808
1809 /* get sign of both inputs */
1810 sa = a->sign;
1811 sb = b->sign;
1812
1813 /* handle two cases, not four */
1814 if (sa == sb) {
1815 /* both positive or both negative, add their mags, copy the sign */
1816 c->sign = sa;
1817 if ((res = s_pstm_add (a, b, c)) != PSTM_OKAY) {
1818 return res;
1819 }
1820 } else {
1821/*
1822 one positive, the other negative
1823 subtract the one with the greater magnitude from the one of the lesser
1824 magnitude. The result gets the sign of the one with the greater mag.
1825 */
1826 if (pstm_cmp_mag (a, b) == PSTM_LT) {
1827 c->sign = sb;
1828 if ((res = s_pstm_sub (b, a, c)) != PSTM_OKAY) {
1829 return res;
1830 }
1831 } else {
1832 c->sign = sa;
1833 if ((res = s_pstm_sub (a, b, c)) != PSTM_OKAY) {
1834 return res;
1835 }
1836 }
1837 }
1838 return PS_SUCCESS;
1839}
1840
1841/******************************************************************************/
1842/*
1843 reverse an array, used for radix code
1844*/
1845static void pstm_reverse (unsigned char *s, int16 len)
1846{
1847 int32 ix, iy;
1848 unsigned char t;
1849
1850 ix = 0;
1851 iy = len - 1;
1852 while (ix < iy) {
1853 t = s[ix];
1854 s[ix] = s[iy];
1855 s[iy] = t;
1856 ++ix;
1857 --iy;
1858 }
1859}
1860/******************************************************************************/
1861/*
1862 No reverse. Useful in some of the EIP-154 PKA stuff where special byte
1863 order seems to come into play more often
1864*/
1865int32 pstm_to_unsigned_bin_nr(psPool_t *pool, pstm_int *a, unsigned char *b)
1866{
1867 int32 res;
1868 int16 x;
1869 pstm_int t = { 0 };
1870
1871 if ((res = pstm_init_copy(pool, &t, a, 0)) != PSTM_OKAY) {
1872 return res;
1873 }
1874
1875 x = 0;
1876 while (pstm_iszero (&t) == 0) {
1877 b[x++] = (unsigned char) (t.dp[0] & 255);
1878 if ((res = pstm_div_2d (pool, &t, 8, &t, NULL)) != PSTM_OKAY) {
1879 pstm_clear(&t);
1880 return res;
1881 }
1882 }
1883 pstm_clear(&t);
1884 return PS_SUCCESS;
1885}
1886/******************************************************************************/
1887/*
1888
1889*/
1890int32 pstm_to_unsigned_bin(psPool_t *pool, pstm_int *a, unsigned char *b)
1891{
1892 int32 res;
1893 int16 x;
1894 pstm_int t = { 0 };
1895
1896 if ((res = pstm_init_copy(pool, &t, a, 0)) != PSTM_OKAY) {
1897 return res;
1898 }
1899
1900 x = 0;
1901 while (pstm_iszero (&t) == 0) {
1902 b[x++] = (unsigned char) (t.dp[0] & 255);
1903 if ((res = pstm_div_2d (pool, &t, 8, &t, NULL)) != PSTM_OKAY) {
1904 pstm_clear(&t);
1905 return res;
1906 }
1907 }
1908 pstm_reverse (b, x);
1909 pstm_clear(&t);
1910 return PS_SUCCESS;
1911}
1912
1913/******************************************************************************/
1914/*
1915 compare against a single digit
1916*/
1917int32 pstm_cmp_d(pstm_int *a, pstm_digit b)
1918{
1919 /* compare based on sign */
1920 if ((b && a->used == 0) || a->sign == PSTM_NEG) {
1921 return PSTM_LT;
1922 }
1923
1924 /* compare based on magnitude */
1925 if (a->used > 1) {
1926 return PSTM_GT;
1927 }
1928
1929 /* compare the only digit of a to b */
1930 if (a->dp[0] > b) {
1931 return PSTM_GT;
1932 } else if (a->dp[0] < b) {
1933 return PSTM_LT;
1934 } else {
1935 return PSTM_EQ;
1936 }
1937}
1938
1939/*
1940 Need invmod for ECC and also private key loading for hardware crypto
1941 in cases where dQ > dP. The values must be switched and a new qP must be
1942 calculated using this function
1943*/
1944//bbox: pool unused
1945#define pstm_invmod_slow(pool, a, b, c) \
1946 pstm_invmod_slow( a, b, c)
1947static int32 pstm_invmod_slow(psPool_t *pool, pstm_int * a, pstm_int * b,
1948 pstm_int * c)
1949{
1950 pstm_int x, y, u, v, A, B, C, D;
1951 int32 res;
1952
1953 /* b cannot be negative */
1954 if (b->sign == PSTM_NEG || pstm_iszero(b) == 1) {
1955 return PS_LIMIT_FAIL;
1956 }
1957
1958 /* init temps */
1959 if (pstm_init_size(pool, &x, b->used) != PSTM_OKAY) {
1960 return PS_MEM_FAIL;
1961 }
1962
1963 /* x = a, y = b */
1964 if ((res = pstm_mod(pool, a, b, &x)) != PSTM_OKAY) {
1965 goto LBL_X;
1966 }
1967
1968 if (pstm_init_copy(pool, &y, b, 0) != PSTM_OKAY) {
1969 goto LBL_X;
1970 }
1971
1972 /* 2. [modified] if x,y are both even then return an error! */
1973 if (pstm_iseven (&x) == 1 && pstm_iseven (&y) == 1) {
1974 res = PS_FAILURE;
1975 goto LBL_Y;
1976 }
1977
1978 /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
1979 if ((res = pstm_init_copy(pool, &u, &x, 0)) != PSTM_OKAY) {
1980 goto LBL_Y;
1981 }
1982 if ((res = pstm_init_copy(pool, &v, &y, 0)) != PSTM_OKAY) {
1983 goto LBL_U;
1984 }
1985
1986 if ((res = pstm_init_size(pool, &A, sizeof(pstm_digit))) != PSTM_OKAY) {
1987 goto LBL_V;
1988 }
1989
1990 if ((res = pstm_init_size(pool, &D, sizeof(pstm_digit))) != PSTM_OKAY) {
1991 goto LBL_A;
1992 }
1993 pstm_set (&A, 1);
1994 pstm_set (&D, 1);
1995
1996 if ((res = pstm_init(pool, &B)) != PSTM_OKAY) {
1997 goto LBL_D;
1998 }
1999 if ((res = pstm_init(pool, &C)) != PSTM_OKAY) {
2000 goto LBL_B;
2001 }
2002
2003top:
2004 /* 4. while u is even do */
2005 while (pstm_iseven (&u) == 1) {
2006 /* 4.1 u = u/2 */
2007 if ((res = pstm_div_2 (&u, &u)) != PSTM_OKAY) {
2008 goto LBL_C;
2009 }
2010
2011 /* 4.2 if A or B is odd then */
2012 if (pstm_isodd (&A) == 1 || pstm_isodd (&B) == 1) {
2013 /* A = (A+y)/2, B = (B-x)/2 */
2014 if ((res = pstm_add (&A, &y, &A)) != PSTM_OKAY) {
2015 goto LBL_C;
2016 }
2017 if ((res = pstm_sub (&B, &x, &B)) != PSTM_OKAY) {
2018 goto LBL_C;
2019 }
2020 }
2021 /* A = A/2, B = B/2 */
2022 if ((res = pstm_div_2 (&A, &A)) != PSTM_OKAY) {
2023 goto LBL_C;
2024 }
2025 if ((res = pstm_div_2 (&B, &B)) != PSTM_OKAY) {
2026 goto LBL_C;
2027 }
2028 }
2029
2030 /* 5. while v is even do */
2031 while (pstm_iseven (&v) == 1) {
2032 /* 5.1 v = v/2 */
2033 if ((res = pstm_div_2 (&v, &v)) != PSTM_OKAY) {
2034 goto LBL_C;
2035 }
2036
2037 /* 5.2 if C or D is odd then */
2038 if (pstm_isodd (&C) == 1 || pstm_isodd (&D) == 1) {
2039 /* C = (C+y)/2, D = (D-x)/2 */
2040 if ((res = pstm_add (&C, &y, &C)) != PSTM_OKAY) {
2041 goto LBL_C;
2042 }
2043 if ((res = pstm_sub (&D, &x, &D)) != PSTM_OKAY) {
2044 goto LBL_C;
2045 }
2046 }
2047 /* C = C/2, D = D/2 */
2048 if ((res = pstm_div_2 (&C, &C)) != PSTM_OKAY) {
2049 goto LBL_C;
2050 }
2051 if ((res = pstm_div_2 (&D, &D)) != PSTM_OKAY) {
2052 goto LBL_C;
2053 }
2054 }
2055
2056 /* 6. if u >= v then */
2057 if (pstm_cmp (&u, &v) != PSTM_LT) {
2058 /* u = u - v, A = A - C, B = B - D */
2059 if ((res = pstm_sub (&u, &v, &u)) != PSTM_OKAY) {
2060 goto LBL_C;
2061 }
2062 if ((res = pstm_sub (&A, &C, &A)) != PSTM_OKAY) {
2063 goto LBL_C;
2064 }
2065 if ((res = pstm_sub (&B, &D, &B)) != PSTM_OKAY) {
2066 goto LBL_C;
2067 }
2068 } else {
2069 /* v - v - u, C = C - A, D = D - B */
2070 if ((res = pstm_sub (&v, &u, &v)) != PSTM_OKAY) {
2071 goto LBL_C;
2072 }
2073 if ((res = pstm_sub (&C, &A, &C)) != PSTM_OKAY) {
2074 goto LBL_C;
2075 }
2076 if ((res = pstm_sub (&D, &B, &D)) != PSTM_OKAY) {
2077 goto LBL_C;
2078 }
2079 }
2080
2081 /* if not zero goto step 4 */
2082 if (pstm_iszero (&u) == 0)
2083 goto top;
2084
2085 /* now a = C, b = D, gcd == g*v */
2086
2087 /* if v != 1 then there is no inverse */
2088 if (pstm_cmp_d (&v, 1) != PSTM_EQ) {
2089 res = PS_FAILURE;
2090 goto LBL_C;
2091 }
2092
2093 /* if its too low */
2094 while (pstm_cmp_d(&C, 0) == PSTM_LT) {
2095 if ((res = pstm_add(&C, b, &C)) != PSTM_OKAY) {
2096 goto LBL_C;
2097 }
2098 }
2099
2100 /* too big */
2101 while (pstm_cmp_mag(&C, b) != PSTM_LT) {
2102 if ((res = pstm_sub(&C, b, &C)) != PSTM_OKAY) {
2103 goto LBL_C;
2104 }
2105 }
2106
2107 /* C is now the inverse */
2108 if ((res = pstm_copy(&C, c)) != PSTM_OKAY) {
2109 goto LBL_C;
2110 }
2111 res = PSTM_OKAY;
2112
2113LBL_C: pstm_clear(&C);
2114LBL_D: pstm_clear(&D);
2115LBL_B: pstm_clear(&B);
2116LBL_A: pstm_clear(&A);
2117LBL_V: pstm_clear(&v);
2118LBL_U: pstm_clear(&u);
2119LBL_Y: pstm_clear(&y);
2120LBL_X: pstm_clear(&x);
2121
2122 return res;
2123}
2124
2125/* c = 1/a (mod b) for odd b only */
2126int32 pstm_invmod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c)
2127{
2128 pstm_int x, y, u, v, B, D;
2129 int32 res;
2130 uint16 neg, sanity;
2131
2132 /* 2. [modified] b must be odd */
2133 if (pstm_iseven (b) == 1) {
2134 return pstm_invmod_slow(pool, a,b,c);
2135 }
2136
2137 /* x == modulus, y == value to invert */
2138 if ((res = pstm_init_copy(pool, &x, b, 0)) != PSTM_OKAY) {
2139 return res;
2140 }
2141
2142 if ((res = pstm_init_size(pool, &y, a->alloc)) != PSTM_OKAY) {
2143 goto LBL_X;
2144 }
2145
2146 /* we need y = |a| */
2147 pstm_abs(a, &y);
2148
2149 /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
2150 if ((res = pstm_init_copy(pool, &u, &x, 0)) != PSTM_OKAY) {
2151 goto LBL_Y;
2152 }
2153 if ((res = pstm_init_copy(pool, &v, &y, 0)) != PSTM_OKAY) {
2154 goto LBL_U;
2155 }
2156 if ((res = pstm_init(pool, &B)) != PSTM_OKAY) {
2157 goto LBL_V;
2158 }
2159 if ((res = pstm_init(pool, &D)) != PSTM_OKAY) {
2160 goto LBL_B;
2161 }
2162
2163 pstm_set (&D, 1);
2164
2165 sanity = 0;
2166top:
2167 /* 4. while u is even do */
2168 while (pstm_iseven (&u) == 1) {
2169 /* 4.1 u = u/2 */
2170 if ((res = pstm_div_2 (&u, &u)) != PSTM_OKAY) {
2171 goto LBL_D;
2172 }
2173
2174 /* 4.2 if B is odd then */
2175 if (pstm_isodd (&B) == 1) {
2176 if ((res = pstm_sub (&B, &x, &B)) != PSTM_OKAY) {
2177 goto LBL_D;
2178 }
2179 }
2180 /* B = B/2 */
2181 if ((res = pstm_div_2 (&B, &B)) != PSTM_OKAY) {
2182 goto LBL_D;
2183 }
2184 }
2185
2186 /* 5. while v is even do */
2187 while (pstm_iseven (&v) == 1) {
2188 /* 5.1 v = v/2 */
2189 if ((res = pstm_div_2 (&v, &v)) != PSTM_OKAY) {
2190 goto LBL_D;
2191 }
2192 /* 5.2 if D is odd then */
2193 if (pstm_isodd (&D) == 1) {
2194 /* D = (D-x)/2 */
2195 if ((res = pstm_sub (&D, &x, &D)) != PSTM_OKAY) {
2196 goto LBL_D;
2197 }
2198 }
2199 /* D = D/2 */
2200 if ((res = pstm_div_2 (&D, &D)) != PSTM_OKAY) {
2201 goto LBL_D;
2202 }
2203 }
2204
2205 /* 6. if u >= v then */
2206 if (pstm_cmp (&u, &v) != PSTM_LT) {
2207 /* u = u - v, B = B - D */
2208 if ((res = pstm_sub (&u, &v, &u)) != PSTM_OKAY) {
2209 goto LBL_D;
2210 }
2211 if ((res = pstm_sub (&B, &D, &B)) != PSTM_OKAY) {
2212 goto LBL_D;
2213 }
2214 } else {
2215 /* v - v - u, D = D - B */
2216 if ((res = pstm_sub (&v, &u, &v)) != PSTM_OKAY) {
2217 goto LBL_D;
2218 }
2219 if ((res = pstm_sub (&D, &B, &D)) != PSTM_OKAY) {
2220 goto LBL_D;
2221 }
2222 }
2223
2224 /* if not zero goto step 4 */
2225 if (sanity++ > 1000) {
2226 res = PS_LIMIT_FAIL;
2227 goto LBL_D;
2228 }
2229 if (pstm_iszero (&u) == 0) {
2230 goto top;
2231 }
2232
2233 /* now a = C, b = D, gcd == g*v */
2234
2235 /* if v != 1 then there is no inverse */
2236 if (pstm_cmp_d (&v, 1) != PSTM_EQ) {
2237 res = PS_FAILURE;
2238 goto LBL_D;
2239 }
2240
2241 /* b is now the inverse */
2242 neg = a->sign;
2243 while (D.sign == PSTM_NEG) {
2244 if ((res = pstm_add (&D, b, &D)) != PSTM_OKAY) {
2245 goto LBL_D;
2246 }
2247 }
2248 if ((res = pstm_copy (&D, c)) != PSTM_OKAY) {
2249 goto LBL_D;
2250 }
2251 c->sign = neg;
2252 res = PSTM_OKAY;
2253
2254LBL_D: pstm_clear(&D);
2255LBL_B: pstm_clear(&B);
2256LBL_V: pstm_clear(&v);
2257LBL_U: pstm_clear(&u);
2258LBL_Y: pstm_clear(&y);
2259LBL_X: pstm_clear(&x);
2260 return res;
2261}
2262#endif /* !DISABLE_PSTM */
2263/******************************************************************************/
diff --git a/networking/tls_pstm.h b/networking/tls_pstm.h
new file mode 100644
index 000000000..3a0fd8ce6
--- /dev/null
+++ b/networking/tls_pstm.h
@@ -0,0 +1,286 @@
1/*
2 * Copyright (C) 2017 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6/* The file is taken almost verbatim from matrixssl-3-7-2b-open/crypto/math/.
7 * Changes are flagged with //bbox
8 */
9
10/**
11 * @file pstm.h
12 * @version 33ef80f (HEAD, tag: MATRIXSSL-3-7-2-OPEN, tag: MATRIXSSL-3-7-2-COMM, origin/master, origin/HEAD, master)
13 *
14 * multiple-precision integer library.
15 */
16/*
17 * Copyright (c) 2013-2015 INSIDE Secure Corporation
18 * Copyright (c) PeerSec Networks, 2002-2011
19 * All Rights Reserved
20 *
21 * The latest version of this code is available at http://www.matrixssl.org
22 *
23 * This software is open source; you can redistribute it and/or modify
24 * it under the terms of the GNU General Public License as published by
25 * the Free Software Foundation; either version 2 of the License, or
26 * (at your option) any later version.
27 *
28 * This General Public License does NOT permit incorporating this software
29 * into proprietary programs. If you are unable to comply with the GPL, a
30 * commercial license for this software may be purchased from INSIDE at
31 * http://www.insidesecure.com/eng/Company/Locations
32 *
33 * This program is distributed in WITHOUT ANY WARRANTY; without even the
34 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
35 * See the GNU General Public License for more details.
36 *
37 * You should have received a copy of the GNU General Public License
38 * along with this program; if not, write to the Free Software
39 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
40 * http://www.gnu.org/copyleft/gpl.html
41 */
42/******************************************************************************/
43
44#ifndef _h_PSTMATH
45#define _h_PSTMATH
46#ifndef DISABLE_PSTM
47
48/* Define this here to avoid including circular limits.h on some platforms */
49#ifndef CHAR_BIT
50#define CHAR_BIT 8
51#endif
52
53/******************************************************************************/
54/*
55 If native 64 bit integers are not supported, we do not support 32x32->64
56 in hardware, so we must set the 16 bit flag to produce 16x16->32 products.
57*/
58#ifndef HAVE_NATIVE_INT64
59 #define PSTM_16BIT
60#endif /* ! HAVE_NATIVE_INT64 */
61
62/******************************************************************************/
63/*
64 Some default configurations.
65
66 pstm_word should be the largest value the processor can hold as the product
67 of a multiplication. Most platforms support a 32x32->64 MAC instruction,
68 so 64bits is the default pstm_word size.
69 pstm_digit should be half the size of pstm_word
70 */
71#ifdef PSTM_8BIT
72/* 8-bit digits, 16-bit word products */
73 typedef unsigned char pstm_digit;
74 typedef unsigned short pstm_word;
75 #define DIGIT_BIT 8
76
77#elif defined(PSTM_16BIT)
78/* 16-bit digits, 32-bit word products */
79 typedef unsigned short pstm_digit;
80 typedef unsigned long pstm_word;
81 #define DIGIT_BIT 16
82
83#elif defined(PSTM_64BIT)
84/* 64-bit digits, 128-bit word products */
85 #ifndef __GNUC__
86 #error "64bit digits requires GCC"
87 #endif
88 typedef unsigned long pstm_digit;
89 typedef unsigned long pstm_word __attribute__ ((mode(TI)));
90 #define DIGIT_BIT 64
91
92#else
93/* This is the default case, 32-bit digits, 64-bit word products */
94 typedef uint32 pstm_digit;
95 typedef uint64 pstm_word;
96 #define DIGIT_BIT 32
97 #define PSTM_32BIT
98#endif /* digit and word size */
99
100#define PSTM_MASK (pstm_digit)(-1)
101#define PSTM_DIGIT_MAX PSTM_MASK
102
103/******************************************************************************/
104/*
105 equalities
106 */
107#define PSTM_LT -1 /* less than */
108#define PSTM_EQ 0 /* equal to */
109#define PSTM_GT 1 /* greater than */
110
111#define PSTM_ZPOS 0 /* positive integer */
112#define PSTM_NEG 1 /* negative */
113
114#define PSTM_OKAY PS_SUCCESS
115#define PSTM_MEM PS_MEM_FAIL
116
117/******************************************************************************/
118/*
119 Various build options
120 */
121#define PSTM_DEFAULT_INIT 64 /* default (64) digits of allocation */
122#define PSTM_MAX_SIZE 4096
123
124typedef struct {
125 int16 used, alloc, sign;
126 pstm_digit *dp;
127//bbox psPool_t *pool;
128} pstm_int;
129
130/******************************************************************************/
131/*
132 Operations on large integers
133 */
134#define pstm_iszero(a) (((a)->used == 0) ? PS_TRUE : PS_FALSE)
135#define pstm_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? PS_TRUE : PS_FALSE)
136#define pstm_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? PS_TRUE : PS_FALSE)
137#define pstm_abs(a, b) { pstm_copy(a, b); (b)->sign = 0; }
138
139extern void pstm_set(pstm_int *a, pstm_digit b);
140
141extern void pstm_zero(pstm_int * a);
142
143//bbox: pool unused
144#define pstm_init(pool, a) \
145 pstm_init( a)
146extern int32 pstm_init(psPool_t *pool, pstm_int * a);
147
148//bbox: pool unused
149#define pstm_init_size(pool, a, size) \
150 pstm_init_size( a, size)
151extern int32 pstm_init_size(psPool_t *pool, pstm_int * a, uint32 size);
152
153//bbox: pool unused
154#define pstm_init_copy(pool, a, b, toSqr) \
155 pstm_init_copy( a, b, toSqr)
156extern int32 pstm_init_copy(psPool_t *pool, pstm_int * a, pstm_int * b,
157 int16 toSqr);
158
159extern int16 pstm_count_bits (pstm_int * a);
160
161//bbox: pool unused
162#define pstm_init_for_read_unsigned_bin(pool, a, len) \
163 pstm_init_for_read_unsigned_bin( a, len)
164extern int32 pstm_init_for_read_unsigned_bin(psPool_t *pool, pstm_int *a,
165 uint32 len);
166
167extern int32 pstm_read_unsigned_bin(pstm_int *a, unsigned char *b, int32 c);
168
169extern int32 pstm_unsigned_bin_size(pstm_int *a);
170
171extern int32 pstm_copy(pstm_int * a, pstm_int * b);
172
173extern void pstm_exch(pstm_int * a, pstm_int * b);
174
175extern void pstm_clear(pstm_int * a);
176
177extern void pstm_clear_multi(pstm_int *mp0, pstm_int *mp1, pstm_int *mp2,
178 pstm_int *mp3, pstm_int *mp4, pstm_int *mp5, pstm_int *mp6,
179 pstm_int *mp7);
180
181extern int32 pstm_grow(pstm_int * a, int16 size);
182
183extern void pstm_clamp(pstm_int * a);
184
185extern int32 pstm_cmp(pstm_int * a, pstm_int * b);
186
187extern int32 pstm_cmp_mag(pstm_int * a, pstm_int * b);
188
189extern void pstm_rshd(pstm_int *a, int16 x);
190
191extern int32 pstm_lshd(pstm_int * a, int16 b);
192
193//bbox: pool unused
194#define pstm_div(pool, a, b, c, d) \
195 pstm_div( a, b, c, d)
196extern int32 pstm_div(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c,
197 pstm_int *d);
198
199//bbox: pool unused
200#define pstm_div_2d(pool, a, b, c, d) \
201 pstm_div_2d( a, b, c, d)
202extern int32 pstm_div_2d(psPool_t *pool, pstm_int *a, int16 b, pstm_int *c,
203 pstm_int *d);
204
205extern int32 pstm_div_2(pstm_int * a, pstm_int * b);
206
207extern int32 s_pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c);
208
209extern int32 pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c);
210
211//bbox: pool unused
212#define pstm_sub_d(pool, a, b, c) \
213 pstm_sub_d( a, b, c)
214extern int32 pstm_sub_d(psPool_t *pool, pstm_int *a, pstm_digit b, pstm_int *c);
215
216extern int32 pstm_mul_2(pstm_int * a, pstm_int * b);
217
218//bbox: pool unused
219#define pstm_mod(pool, a, b, c) \
220 pstm_mod( a, b, c)
221extern int32 pstm_mod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c);
222
223//bbox: pool unused
224#define pstm_mulmod(pool, a, b, c, d) \
225 pstm_mulmod( a, b, c, d)
226extern int32 pstm_mulmod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c,
227 pstm_int *d);
228
229//bbox: pool unused
230#define pstm_exptmod(pool, G, X, P, Y) \
231 pstm_exptmod( G, X, P, Y)
232extern int32 pstm_exptmod(psPool_t *pool, pstm_int *G, pstm_int *X, pstm_int *P,
233 pstm_int *Y);
234
235extern int32 pstm_2expt(pstm_int *a, int16 b);
236
237extern int32 pstm_add(pstm_int *a, pstm_int *b, pstm_int *c);
238
239//bbox: pool unused
240#define pstm_to_unsigned_bin(pool, a, b) \
241 pstm_to_unsigned_bin( a, b)
242extern int32 pstm_to_unsigned_bin(psPool_t *pool, pstm_int *a,
243 unsigned char *b);
244
245//bbox: pool unused
246#define pstm_to_unsigned_bin_nr(pool, a, b) \
247 pstm_to_unsigned_bin_nr( a, b)
248extern int32 pstm_to_unsigned_bin_nr(psPool_t *pool, pstm_int *a,
249 unsigned char *b);
250
251extern int32 pstm_montgomery_setup(pstm_int *a, pstm_digit *rho);
252
253//bbox: pool unused
254#define pstm_montgomery_reduce(pool, a, m, mp, paD, paDlen) \
255 pstm_montgomery_reduce( a, m, mp, paD, paDlen)
256extern int32 pstm_montgomery_reduce(psPool_t *pool, pstm_int *a, pstm_int *m,
257 pstm_digit mp, pstm_digit *paD, uint32 paDlen);
258
259#define pstm_mul_comba(pool, A, B, C, paD, paDlen) \
260 pstm_mul_comba( A, B, C, paD, paDlen)
261extern int32 pstm_mul_comba(psPool_t *pool, pstm_int *A, pstm_int *B,
262 pstm_int *C, pstm_digit *paD, uint32 paDlen);
263
264//bbox: pool unused
265#define pstm_sqr_comba(pool, A, B, paD, paDlen) \
266 pstm_sqr_comba( A, B, paD, paDlen)
267extern int32 pstm_sqr_comba(psPool_t *pool, pstm_int *A, pstm_int *B,
268 pstm_digit *paD, uint32 paDlen);
269
270extern int32 pstm_cmp_d(pstm_int *a, pstm_digit b);
271
272extern int32 pstm_montgomery_calc_normalization(pstm_int *a, pstm_int *b);
273
274extern int32 pstm_mul_d(pstm_int *a, pstm_digit b, pstm_int *c);
275
276//bbox: pool unused
277#define pstm_invmod(pool, a, b, c) \
278 pstm_invmod( a, b, c)
279extern int32 pstm_invmod(psPool_t *pool, pstm_int * a, pstm_int * b,
280 pstm_int * c);
281
282#else /* DISABLE_PSTM */
283 typedef int32 pstm_int;
284#endif /* !DISABLE_PSTM */
285#endif /* _h_PSTMATH */
286
diff --git a/networking/tls_pstm_montgomery_reduce.c b/networking/tls_pstm_montgomery_reduce.c
new file mode 100644
index 000000000..dc2fe0a48
--- /dev/null
+++ b/networking/tls_pstm_montgomery_reduce.c
@@ -0,0 +1,427 @@
1/*
2 * Copyright (C) 2017 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6#include "tls.h"
7
8/* The file is taken almost verbatim from matrixssl-3-7-2b-open/crypto/math/.
9 * Changes are flagged with //bbox
10 */
11
12/**
13 * @file pstm_montgomery_reduce.c
14 * @version 33ef80f (HEAD, tag: MATRIXSSL-3-7-2-OPEN, tag: MATRIXSSL-3-7-2-COMM, origin/master, origin/HEAD, master)
15 *
16 * Multiprecision Montgomery Reduction.
17 */
18/*
19 * Copyright (c) 2013-2015 INSIDE Secure Corporation
20 * Copyright (c) PeerSec Networks, 2002-2011
21 * All Rights Reserved
22 *
23 * The latest version of this code is available at http://www.matrixssl.org
24 *
25 * This software is open source; you can redistribute it and/or modify
26 * it under the terms of the GNU General Public License as published by
27 * the Free Software Foundation; either version 2 of the License, or
28 * (at your option) any later version.
29 *
30 * This General Public License does NOT permit incorporating this software
31 * into proprietary programs. If you are unable to comply with the GPL, a
32 * commercial license for this software may be purchased from INSIDE at
33 * http://www.insidesecure.com/eng/Company/Locations
34 *
35 * This program is distributed in WITHOUT ANY WARRANTY; without even the
36 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
37 * See the GNU General Public License for more details.
38 *
39 * You should have received a copy of the GNU General Public License
40 * along with this program; if not, write to the Free Software
41 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
42 * http://www.gnu.org/copyleft/gpl.html
43 */
44/******************************************************************************/
45
46//bbox
47//#include "../cryptoApi.h"
48#ifndef DISABLE_PSTM
49
50/******************************************************************************/
51
52#if defined(PSTM_X86)
53/* x86-32 optimized for 32 bit platforms. For 64 bit mode use X86_64 instead */
54#if !defined(__GNUC__) || !defined(__i386__) || !defined(PSTM_32BIT)
55#error "PSTM_X86 option requires GCC and 32 bit mode x86 processor"
56#endif
57//#pragma message ("Using 32 bit x86 Assembly Optimizations")
58
59#define MONT_START
60#define MONT_FINI
61#define LOOP_END
62#define LOOP_START \
63 mu = c[x] * mp
64
65#define INNERMUL \
66asm( \
67 "movl %5,%%eax \n\t" \
68 "mull %4 \n\t" \
69 "addl %1,%%eax \n\t" \
70 "adcl $0,%%edx \n\t" \
71 "addl %%eax,%0 \n\t" \
72 "adcl $0,%%edx \n\t" \
73 "movl %%edx,%1 \n\t" \
74:"=g"(_c[LO]), "=r"(cy) \
75:"0"(_c[LO]), "1"(cy), "g"(mu), "g"(*tmpm++) \
76: "%eax", "%edx", "%cc")
77
78#define PROPCARRY \
79asm( \
80 "addl %1,%0 \n\t" \
81 "setb %%al \n\t" \
82 "movzbl %%al,%1 \n\t" \
83:"=g"(_c[LO]), "=r"(cy) \
84:"0"(_c[LO]), "1"(cy) \
85: "%eax", "%cc")
86
87/******************************************************************************/
88#elif defined(PSTM_X86_64)
89/* x86-64 optimized */
90#if !defined(__GNUC__) || !defined(__x86_64__) || !defined(PSTM_64BIT)
91#error "PSTM_X86_64 option requires PSTM_64BIT, GCC and 64 bit mode x86 processor"
92#endif
93//#pragma message ("Using 64 bit x86_64 Assembly Optimizations")
94
95#define MONT_START
96#define MONT_FINI
97#define LOOP_END
98#define LOOP_START \
99mu = c[x] * mp
100
101#define INNERMUL \
102asm( \
103 "movq %5,%%rax \n\t" \
104 "mulq %4 \n\t" \
105 "addq %1,%%rax \n\t" \
106 "adcq $0,%%rdx \n\t" \
107 "addq %%rax,%0 \n\t" \
108 "adcq $0,%%rdx \n\t" \
109 "movq %%rdx,%1 \n\t" \
110 :"=g"(_c[LO]), "=r"(cy) \
111 :"0"(_c[LO]), "1"(cy), "r"(mu), "r"(*tmpm++) \
112 : "%rax", "%rdx", "cc")
113
114#define INNERMUL8 \
115asm( \
116 "movq 0(%5),%%rax \n\t" \
117 "movq 0(%2),%%r10 \n\t" \
118 "movq 0x8(%5),%%r11 \n\t" \
119 "mulq %4 \n\t" \
120 "addq %%r10,%%rax \n\t" \
121 "adcq $0,%%rdx \n\t" \
122 "movq 0x8(%2),%%r10 \n\t" \
123 "addq %3,%%rax \n\t" \
124 "adcq $0,%%rdx \n\t" \
125 "movq %%rax,0(%0) \n\t" \
126 "movq %%rdx,%1 \n\t" \
127 \
128 "movq %%r11,%%rax \n\t" \
129 "movq 0x10(%5),%%r11 \n\t" \
130 "mulq %4 \n\t" \
131 "addq %%r10,%%rax \n\t" \
132 "adcq $0,%%rdx \n\t" \
133 "movq 0x10(%2),%%r10 \n\t" \
134 "addq %3,%%rax \n\t" \
135 "adcq $0,%%rdx \n\t" \
136 "movq %%rax,0x8(%0) \n\t" \
137 "movq %%rdx,%1 \n\t" \
138 \
139 "movq %%r11,%%rax \n\t" \
140 "movq 0x18(%5),%%r11 \n\t" \
141 "mulq %4 \n\t" \
142 "addq %%r10,%%rax \n\t" \
143 "adcq $0,%%rdx \n\t" \
144 "movq 0x18(%2),%%r10 \n\t" \
145 "addq %3,%%rax \n\t" \
146 "adcq $0,%%rdx \n\t" \
147 "movq %%rax,0x10(%0) \n\t" \
148 "movq %%rdx,%1 \n\t" \
149 \
150 "movq %%r11,%%rax \n\t" \
151 "movq 0x20(%5),%%r11 \n\t" \
152 "mulq %4 \n\t" \
153 "addq %%r10,%%rax \n\t" \
154 "adcq $0,%%rdx \n\t" \
155 "movq 0x20(%2),%%r10 \n\t" \
156 "addq %3,%%rax \n\t" \
157 "adcq $0,%%rdx \n\t" \
158 "movq %%rax,0x18(%0) \n\t" \
159 "movq %%rdx,%1 \n\t" \
160 \
161 "movq %%r11,%%rax \n\t" \
162 "movq 0x28(%5),%%r11 \n\t" \
163 "mulq %4 \n\t" \
164 "addq %%r10,%%rax \n\t" \
165 "adcq $0,%%rdx \n\t" \
166 "movq 0x28(%2),%%r10 \n\t" \
167 "addq %3,%%rax \n\t" \
168 "adcq $0,%%rdx \n\t" \
169 "movq %%rax,0x20(%0) \n\t" \
170 "movq %%rdx,%1 \n\t" \
171 \
172 "movq %%r11,%%rax \n\t" \
173 "movq 0x30(%5),%%r11 \n\t" \
174 "mulq %4 \n\t" \
175 "addq %%r10,%%rax \n\t" \
176 "adcq $0,%%rdx \n\t" \
177 "movq 0x30(%2),%%r10 \n\t" \
178 "addq %3,%%rax \n\t" \
179 "adcq $0,%%rdx \n\t" \
180 "movq %%rax,0x28(%0) \n\t" \
181 "movq %%rdx,%1 \n\t" \
182 \
183 "movq %%r11,%%rax \n\t" \
184 "movq 0x38(%5),%%r11 \n\t" \
185 "mulq %4 \n\t" \
186 "addq %%r10,%%rax \n\t" \
187 "adcq $0,%%rdx \n\t" \
188 "movq 0x38(%2),%%r10 \n\t" \
189 "addq %3,%%rax \n\t" \
190 "adcq $0,%%rdx \n\t" \
191 "movq %%rax,0x30(%0) \n\t" \
192 "movq %%rdx,%1 \n\t" \
193 \
194 "movq %%r11,%%rax \n\t" \
195 "mulq %4 \n\t" \
196 "addq %%r10,%%rax \n\t" \
197 "adcq $0,%%rdx \n\t" \
198 "addq %3,%%rax \n\t" \
199 "adcq $0,%%rdx \n\t" \
200 "movq %%rax,0x38(%0) \n\t" \
201 "movq %%rdx,%1 \n\t" \
202 \
203 :"=r"(_c), "=r"(cy) \
204 : "0"(_c), "1"(cy), "g"(mu), "r"(tmpm)\
205 : "%rax", "%rdx", "%r10", "%r11", "cc")
206
207#define PROPCARRY \
208asm( \
209 "addq %1,%0 \n\t" \
210 "setb %%al \n\t" \
211 "movzbq %%al,%1 \n\t" \
212 :"=g"(_c[LO]), "=r"(cy) \
213 :"0"(_c[LO]), "1"(cy) \
214 : "%rax", "cc")
215
216/******************************************************************************/
217#elif defined(PSTM_ARM)
218
219#define MONT_START
220#define MONT_FINI
221#define LOOP_END
222#define LOOP_START \
223mu = c[x] * mp
224
225#ifdef __thumb2__
226//#pragma message ("Using 32 bit ARM Thumb2 Assembly Optimizations")
227#define INNERMUL \
228asm( \
229 " LDR r0,%1 \n\t" \
230 " ADDS r0,r0,%0 \n\t" \
231 " ITE CS \n\t" \
232 " MOVCS %0,#1 \n\t" \
233 " MOVCC %0,#0 \n\t" \
234 " UMLAL r0,%0,%3,%4 \n\t" \
235 " STR r0,%1 \n\t" \
236 :"=r"(cy),"=m"(_c[0])\
237 :"0"(cy),"r"(mu),"r"(*tmpm++),"m"(_c[0])\
238 :"r0","%cc");
239#define PROPCARRY \
240asm( \
241 " LDR r0,%1 \n\t" \
242 " ADDS r0,r0,%0 \n\t" \
243 " STR r0,%1 \n\t" \
244 " ITE CS \n\t" \
245 " MOVCS %0,#1 \n\t" \
246 " MOVCC %0,#0 \n\t" \
247 :"=r"(cy),"=m"(_c[0])\
248 :"0"(cy),"m"(_c[0])\
249 :"r0","%cc");
250#else /* Non-Thumb2 code */
251//#pragma message ("Using 32 bit ARM Assembly Optimizations")
252#define INNERMUL \
253asm( \
254 " LDR r0,%1 \n\t" \
255 " ADDS r0,r0,%0 \n\t" \
256 " MOVCS %0,#1 \n\t" \
257 " MOVCC %0,#0 \n\t" \
258 " UMLAL r0,%0,%3,%4 \n\t" \
259 " STR r0,%1 \n\t" \
260 :"=r"(cy),"=m"(_c[0])\
261 :"0"(cy),"r"(mu),"r"(*tmpm++),"m"(_c[0])\
262 :"r0","%cc");
263#define PROPCARRY \
264asm( \
265 " LDR r0,%1 \n\t" \
266 " ADDS r0,r0,%0 \n\t" \
267 " STR r0,%1 \n\t" \
268 " MOVCS %0,#1 \n\t" \
269 " MOVCC %0,#0 \n\t" \
270 :"=r"(cy),"=m"(_c[0])\
271 :"0"(cy),"m"(_c[0])\
272 :"r0","%cc");
273#endif /* __thumb2__ */
274
275
276/******************************************************************************/
277#elif defined(PSTM_MIPS)
278/* MIPS32 */
279//#pragma message ("Using 32 bit MIPS Assembly Optimizations")
280#define MONT_START
281#define MONT_FINI
282#define LOOP_END
283#define LOOP_START \
284mu = c[x] * mp
285
286#define INNERMUL \
287asm( \
288 " multu %3,%4 \n\t" \
289 " mflo $12 \n\t" \
290 " mfhi $13 \n\t" \
291 " addu $12,$12,%0 \n\t" \
292 " sltu $10,$12,%0 \n\t" \
293 " addu $13,$13,$10 \n\t" \
294 " lw $10,%1 \n\t" \
295 " addu $12,$12,$10 \n\t" \
296 " sltu $10,$12,$10 \n\t" \
297 " addu %0,$13,$10 \n\t" \
298 " sw $12,%1 \n\t" \
299 :"=r"(cy),"=m"(_c[0])\
300 :"r"(cy),"r"(mu),"r"(tmpm[0]),"r"(_c[0])\
301 :"$10","$12","$13")\
302; ++tmpm;
303
304#define PROPCARRY \
305asm( \
306 " lw $10,%1 \n\t" \
307 " addu $10,$10,%0 \n\t" \
308 " sw $10,%1 \n\t" \
309 " sltu %0,$10,%0 \n\t" \
310 :"=r"(cy),"=m"(_c[0])\
311 :"r"(cy),"r"(_c[0])\
312 :"$10");
313
314
315/******************************************************************************/
316#else
317
318/* ISO C code */
319#define MONT_START
320#define MONT_FINI
321#define LOOP_END
322#define LOOP_START \
323 mu = c[x] * mp
324
325#define INNERMUL \
326 do { pstm_word t; \
327 t = ((pstm_word)_c[0] + (pstm_word)cy) + \
328 (((pstm_word)mu) * ((pstm_word)*tmpm++)); \
329 _c[0] = (pstm_digit)t; \
330 cy = (pstm_digit)(t >> DIGIT_BIT); \
331 } while (0)
332
333#define PROPCARRY \
334 do { pstm_digit t = _c[0] += cy; cy = (t < cy); } while (0)
335
336#endif
337
338/******************************************************************************/
339
340#define LO 0
341
342/* computes x/R == x (mod N) via Montgomery Reduction */
343int32 pstm_montgomery_reduce(psPool_t *pool, pstm_int *a, pstm_int *m,
344 pstm_digit mp, pstm_digit *paD, uint32 paDlen)
345{
346 pstm_digit *c, *_c, *tmpm, mu;
347 int32 oldused, x, y;
348 int16 pa;
349
350 pa = m->used;
351 if (pa > a->alloc) {
352 /* Sanity test for bad numbers. This will confirm no buffer overruns */
353 return PS_LIMIT_FAIL;
354 }
355
356 if (paD && paDlen >= (uint32)2*pa+1) {
357 c = paD;
358 memset(c, 0x0, paDlen);
359 } else {
360 c = xzalloc(2*pa+1);//bbox
361 }
362 /* copy the input */
363 oldused = a->used;
364 for (x = 0; x < oldused; x++) {
365 c[x] = a->dp[x];
366 }
367
368 MONT_START;
369
370 for (x = 0; x < pa; x++) {
371 pstm_digit cy = 0;
372 /* get Mu for this round */
373 LOOP_START;
374 _c = c + x;
375 tmpm = m->dp;
376 y = 0;
377#ifdef PSTM_X86_64
378 for (; y < (pa & ~7); y += 8) {
379 INNERMUL8;
380 _c += 8;
381 tmpm += 8;
382 }
383#endif /* PSTM_X86_64 */
384 for (; y < pa; y++) {
385 INNERMUL;
386 ++_c;
387 }
388 LOOP_END;
389 while (cy) {
390 PROPCARRY;
391 ++_c;
392 }
393 }
394
395 /* now copy out */
396 _c = c + pa;
397 tmpm = a->dp;
398 for (x = 0; x < pa+1; x++) {
399 *tmpm++ = *_c++;
400 }
401
402 for (; x < oldused; x++) {
403 *tmpm++ = 0;
404 }
405
406 MONT_FINI;
407
408 a->used = pa+1;
409 pstm_clamp(a);
410
411 /* reuse x as return code */
412 x = PSTM_OKAY;
413
414 /* if A >= m then A = A - m */
415 if (pstm_cmp_mag (a, m) != PSTM_LT) {
416 if (s_pstm_sub (a, m, a) != PSTM_OKAY) {
417 x = PS_MEM_FAIL;
418 }
419 }
420 if (paDlen < (uint32)2*pa+1) {
421 psFree(c, pool);
422 }
423 return x;
424}
425
426#endif /* !DISABLE_PSTM */
427/******************************************************************************/
diff --git a/networking/tls_pstm_mul_comba.c b/networking/tls_pstm_mul_comba.c
new file mode 100644
index 000000000..47cbb9618
--- /dev/null
+++ b/networking/tls_pstm_mul_comba.c
@@ -0,0 +1,781 @@
1/*
2 * Copyright (C) 2017 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6#include "tls.h"
7
8/* The file is taken almost verbatim from matrixssl-3-7-2b-open/crypto/math/.
9 * Changes are flagged with //bbox
10 */
11
12/**
13 * @file pstm_mul_comba.c
14 * @version 33ef80f (HEAD, tag: MATRIXSSL-3-7-2-OPEN, tag: MATRIXSSL-3-7-2-COMM, origin/master, origin/HEAD, master)
15 *
16 * Multiprecision multiplication with Comba technique.
17 */
18/*
19 * Copyright (c) 2013-2015 INSIDE Secure Corporation
20 * Copyright (c) PeerSec Networks, 2002-2011
21 * All Rights Reserved
22 *
23 * The latest version of this code is available at http://www.matrixssl.org
24 *
25 * This software is open source; you can redistribute it and/or modify
26 * it under the terms of the GNU General Public License as published by
27 * the Free Software Foundation; either version 2 of the License, or
28 * (at your option) any later version.
29 *
30 * This General Public License does NOT permit incorporating this software
31 * into proprietary programs. If you are unable to comply with the GPL, a
32 * commercial license for this software may be purchased from INSIDE at
33 * http://www.insidesecure.com/eng/Company/Locations
34 *
35 * This program is distributed in WITHOUT ANY WARRANTY; without even the
36 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
37 * See the GNU General Public License for more details.
38 *
39 * You should have received a copy of the GNU General Public License
40 * along with this program; if not, write to the Free Software
41 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
42 * http://www.gnu.org/copyleft/gpl.html
43 */
44/******************************************************************************/
45
46//bbox
47//#include "../cryptoApi.h"
48#ifndef DISABLE_PSTM
49
50/******************************************************************************/
51#if defined(PSTM_X86)
52/* x86-32 optimized for 32 bit platforms. For 64 bit mode use X86_64 instead */
53#if !defined(__GNUC__) || !defined(__i386__) || !defined(PSTM_32BIT)
54#error "PSTM_X86 option requires GCC and 32 bit mode x86 processor"
55#endif
56//#pragma message ("Using 32 bit x86 Assembly Optimizations")
57
58/* anything you need at the start */
59#define COMBA_START
60
61/* clear the chaining variables */
62#define COMBA_CLEAR \
63 c0 = c1 = c2 = 0;
64
65/* forward the carry to the next digit */
66#define COMBA_FORWARD \
67 do { c0 = c1; c1 = c2; c2 = 0; } while (0);
68
69/* store the first sum */
70#define COMBA_STORE(x) \
71 x = c0;
72
73/* store the second sum [carry] */
74#define COMBA_STORE2(x) \
75 x = c1;
76
77/* anything you need at the end */
78#define COMBA_FINI
79
80/* this should multiply i and j */
81#define MULADD(i, j) \
82asm( \
83 "movl %6,%%eax \n\t" \
84 "mull %7 \n\t" \
85 "addl %%eax,%0 \n\t" \
86 "adcl %%edx,%1 \n\t" \
87 "adcl $0,%2 \n\t" \
88 :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j) :"%eax","%edx","%cc");
89
90/******************************************************************************/
91#elif defined(PSTM_X86_64)
92/* x86-64 optimized */
93#if !defined(__GNUC__) || !defined(__x86_64__) || !defined(PSTM_64BIT)
94#error "PSTM_X86_64 option requires PSTM_64BIT, GCC and 64 bit mode x86 processor"
95#endif
96//#pragma message ("Using 64 bit x86_64 Assembly Optimizations")
97
98/* anything you need at the start */
99#define COMBA_START
100
101/* clear the chaining variables */
102#define COMBA_CLEAR \
103c0 = c1 = c2 = 0;
104
105/* forward the carry to the next digit */
106#define COMBA_FORWARD \
107do { c0 = c1; c1 = c2; c2 = 0; } while (0);
108
109/* store the first sum */
110#define COMBA_STORE(x) \
111x = c0;
112
113/* store the second sum [carry] */
114#define COMBA_STORE2(x) \
115x = c1;
116
117/* anything you need at the end */
118#define COMBA_FINI
119
120/* this should multiply i and j */
121#define MULADD(i, j) \
122asm ( \
123 "movq %6,%%rax \n\t" \
124 "mulq %7 \n\t" \
125 "addq %%rax,%0 \n\t" \
126 "adcq %%rdx,%1 \n\t" \
127 "adcq $0,%2 \n\t" \
128 :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "g"(i), "g"(j) :"%rax","%rdx","cc");
129
130/******************************************************************************/
131#elif defined(PSTM_ARM)
132/* ARM code */
133//#pragma message ("Using 32 bit ARM Assembly Optimizations")
134
135#define COMBA_START
136
137#define COMBA_CLEAR \
138c0 = c1 = c2 = 0;
139
140#define COMBA_FORWARD \
141do { c0 = c1; c1 = c2; c2 = 0; } while (0);
142
143#define COMBA_STORE(x) \
144x = c0;
145
146#define COMBA_STORE2(x) \
147x = c1;
148
149#define COMBA_FINI
150
151#define MULADD(i, j) \
152asm( \
153 " UMULL r0,r1,%6,%7 \n\t" \
154 " ADDS %0,%0,r0 \n\t" \
155 " ADCS %1,%1,r1 \n\t" \
156 " ADC %2,%2,#0 \n\t" \
157 :"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j) : "r0", "r1", "%cc");
158
159/******************************************************************************/
160#elif defined(PSTM_MIPS)
161/* MIPS32 code */
162//#pragma message ("Using 32 bit MIPS Assembly Optimizations")
163
164#define COMBA_START
165
166#define COMBA_CLEAR \
167c0 = c1 = c2 = 0;
168
169#define COMBA_FORWARD \
170do { c0 = c1; c1 = c2; c2 = 0; } while (0);
171
172#define COMBA_STORE(x) \
173x = c0;
174
175#define COMBA_STORE2(x) \
176x = c1;
177
178#define COMBA_FINI
179
180#define MULADD(i, j) \
181asm( \
182 " multu %6,%7 \n\t" \
183 " mflo $12 \n\t" \
184 " mfhi $13 \n\t" \
185 " addu %0,%0,$12 \n\t" \
186 " sltu $12,%0,$12 \n\t" \
187 " addu %1,%1,$13 \n\t" \
188 " sltu $13,%1,$13 \n\t" \
189 " addu %1,%1,$12 \n\t" \
190 " sltu $12,%1,$12 \n\t" \
191 " addu %2,%2,$13 \n\t" \
192 " addu %2,%2,$12 \n\t" \
193 :"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"$12","$13");
194
195/******************************************************************************/
196#else
197
198#define COMBA_START
199
200#define COMBA_CLEAR \
201 c0 = c1 = c2 = 0;
202
203#define COMBA_FORWARD \
204 do { c0 = c1; c1 = c2; c2 = 0; } while (0);
205
206#define COMBA_STORE(x) \
207 x = c0;
208
209#define COMBA_STORE2(x) \
210 x = c1;
211
212#define COMBA_FINI
213
214#define MULADD(i, j) \
215 do { pstm_word t; \
216 t = (pstm_word)c0 + ((pstm_word)i) * ((pstm_word)j); c0 = (pstm_digit)t; \
217 t = (pstm_word)c1 + (t >> DIGIT_BIT); \
218 c1 = (pstm_digit)t; c2 += (pstm_digit)(t >> DIGIT_BIT); \
219 } while (0);
220
221#endif
222
223/******************************************************************************/
224/* generic PxQ multiplier */
225//bbox: pool unused
226#define pstm_mul_comba_gen(pool, A, B, C, paD, paDlen) \
227 pstm_mul_comba_gen( A, B, C, paD, paDlen)
228static int32 pstm_mul_comba_gen(psPool_t *pool, pstm_int *A, pstm_int *B,
229 pstm_int *C, pstm_digit *paD, uint32 paDlen)
230{
231 int16 paDfail, pa;
232 int32 ix, iy, iz, tx, ty;
233 pstm_digit c0, c1, c2, *tmpx, *tmpy, *dst;
234
235 COMBA_START;
236 COMBA_CLEAR;
237
238 paDfail = 0;
239 /* get size of output and trim */
240 pa = A->used + B->used;
241
242/*
243 If c is not large enough grow it and continue
244*/
245 if (C->alloc < pa) {
246 if (pstm_grow(C, pa) != PSTM_OKAY) {
247 return PS_MEM_FAIL;
248 }
249 }
250 if (paD != NULL) {
251 if (paDlen < (sizeof(pstm_digit) * pa)) {
252 paDfail = 1; /* have a paD but it's not large enough */
253 dst = xzalloc(sizeof(pstm_digit) * pa);//bbox
254 } else {
255 dst = paD;
256 memset(dst, 0x0, paDlen);
257 }
258 } else {
259 dst = xzalloc(sizeof(pstm_digit) * pa);//bbox
260 }
261
262 for (ix = 0; ix < pa; ix++) {
263 /* get offsets into the two bignums */
264 ty = min(ix, B->used-1);
265 tx = ix - ty;
266
267 /* setup temp aliases */
268 tmpx = A->dp + tx;
269 tmpy = B->dp + ty;
270/*
271 This is the number of times the loop will iterate, essentially it's
272 while (tx++ < a->used && ty-- >= 0) { ... }
273*/
274 iy = min(A->used-tx, ty+1);
275
276 /* execute loop */
277 COMBA_FORWARD;
278 for (iz = 0; iz < iy; ++iz) {
279 MULADD(*tmpx++, *tmpy--);
280 }
281
282 /* store term */
283 COMBA_STORE(dst[ix]);
284 }
285 COMBA_FINI;
286/*
287 setup dest
288 */
289 iy = C->used;
290 C->used = pa;
291 C->sign = A->sign ^ B->sign;
292 {
293 pstm_digit *tmpc;
294 tmpc = C->dp;
295 for (ix = 0; ix < pa; ix++) {
296 *tmpc++ = dst[ix];
297 }
298/*
299 clear unused digits [that existed in the old copy of c]
300 */
301 for (; ix < iy; ix++) {
302 *tmpc++ = 0;
303 }
304 }
305 pstm_clamp(C);
306
307 if ((paD == NULL) || (paDfail == 1)) {
308 psFree(dst, pool);
309 }
310
311 return PS_SUCCESS;
312}
313
314/******************************************************************************/
315#ifdef USE_1024_KEY_SPEED_OPTIMIZATIONS
316static int32 pstm_mul_comba16(pstm_int *A, pstm_int *B, pstm_int *C)
317{
318 pstm_digit c0, c1, c2, at[32];
319
320 if (C->alloc < 32) {
321 if (pstm_grow(C, 32) != PSTM_OKAY) {
322 return PS_MEM_FAIL;
323 }
324 }
325 memcpy(at, A->dp, 16 * sizeof(pstm_digit));
326 memcpy(at+16, B->dp, 16 * sizeof(pstm_digit));
327
328 COMBA_START;
329
330 COMBA_CLEAR;
331 /* 0 */
332 MULADD(at[0], at[16]);
333 COMBA_STORE(C->dp[0]);
334 /* 1 */
335 COMBA_FORWARD;
336 MULADD(at[0], at[17]); MULADD(at[1], at[16]);
337 COMBA_STORE(C->dp[1]);
338 /* 2 */
339 COMBA_FORWARD;
340 MULADD(at[0], at[18]); MULADD(at[1], at[17]); MULADD(at[2], at[16]);
341 COMBA_STORE(C->dp[2]);
342 /* 3 */
343 COMBA_FORWARD;
344 MULADD(at[0], at[19]); MULADD(at[1], at[18]); MULADD(at[2], at[17]); MULADD(at[3], at[16]);
345 COMBA_STORE(C->dp[3]);
346 /* 4 */
347 COMBA_FORWARD;
348 MULADD(at[0], at[20]); MULADD(at[1], at[19]); MULADD(at[2], at[18]); MULADD(at[3], at[17]); MULADD(at[4], at[16]);
349 COMBA_STORE(C->dp[4]);
350 /* 5 */
351 COMBA_FORWARD;
352 MULADD(at[0], at[21]); MULADD(at[1], at[20]); MULADD(at[2], at[19]); MULADD(at[3], at[18]); MULADD(at[4], at[17]); MULADD(at[5], at[16]);
353 COMBA_STORE(C->dp[5]);
354 /* 6 */
355 COMBA_FORWARD;
356 MULADD(at[0], at[22]); MULADD(at[1], at[21]); MULADD(at[2], at[20]); MULADD(at[3], at[19]); MULADD(at[4], at[18]); MULADD(at[5], at[17]); MULADD(at[6], at[16]);
357 COMBA_STORE(C->dp[6]);
358 /* 7 */
359 COMBA_FORWARD;
360 MULADD(at[0], at[23]); MULADD(at[1], at[22]); MULADD(at[2], at[21]); MULADD(at[3], at[20]); MULADD(at[4], at[19]); MULADD(at[5], at[18]); MULADD(at[6], at[17]); MULADD(at[7], at[16]);
361 COMBA_STORE(C->dp[7]);
362 /* 8 */
363 COMBA_FORWARD;
364 MULADD(at[0], at[24]); MULADD(at[1], at[23]); MULADD(at[2], at[22]); MULADD(at[3], at[21]); MULADD(at[4], at[20]); MULADD(at[5], at[19]); MULADD(at[6], at[18]); MULADD(at[7], at[17]); MULADD(at[8], at[16]);
365 COMBA_STORE(C->dp[8]);
366 /* 9 */
367 COMBA_FORWARD;
368 MULADD(at[0], at[25]); MULADD(at[1], at[24]); MULADD(at[2], at[23]); MULADD(at[3], at[22]); MULADD(at[4], at[21]); MULADD(at[5], at[20]); MULADD(at[6], at[19]); MULADD(at[7], at[18]); MULADD(at[8], at[17]); MULADD(at[9], at[16]);
369 COMBA_STORE(C->dp[9]);
370 /* 10 */
371 COMBA_FORWARD;
372 MULADD(at[0], at[26]); MULADD(at[1], at[25]); MULADD(at[2], at[24]); MULADD(at[3], at[23]); MULADD(at[4], at[22]); MULADD(at[5], at[21]); MULADD(at[6], at[20]); MULADD(at[7], at[19]); MULADD(at[8], at[18]); MULADD(at[9], at[17]); MULADD(at[10], at[16]);
373 COMBA_STORE(C->dp[10]);
374 /* 11 */
375 COMBA_FORWARD;
376 MULADD(at[0], at[27]); MULADD(at[1], at[26]); MULADD(at[2], at[25]); MULADD(at[3], at[24]); MULADD(at[4], at[23]); MULADD(at[5], at[22]); MULADD(at[6], at[21]); MULADD(at[7], at[20]); MULADD(at[8], at[19]); MULADD(at[9], at[18]); MULADD(at[10], at[17]); MULADD(at[11], at[16]);
377 COMBA_STORE(C->dp[11]);
378 /* 12 */
379 COMBA_FORWARD;
380 MULADD(at[0], at[28]); MULADD(at[1], at[27]); MULADD(at[2], at[26]); MULADD(at[3], at[25]); MULADD(at[4], at[24]); MULADD(at[5], at[23]); MULADD(at[6], at[22]); MULADD(at[7], at[21]); MULADD(at[8], at[20]); MULADD(at[9], at[19]); MULADD(at[10], at[18]); MULADD(at[11], at[17]); MULADD(at[12], at[16]);
381 COMBA_STORE(C->dp[12]);
382 /* 13 */
383 COMBA_FORWARD;
384 MULADD(at[0], at[29]); MULADD(at[1], at[28]); MULADD(at[2], at[27]); MULADD(at[3], at[26]); MULADD(at[4], at[25]); MULADD(at[5], at[24]); MULADD(at[6], at[23]); MULADD(at[7], at[22]); MULADD(at[8], at[21]); MULADD(at[9], at[20]); MULADD(at[10], at[19]); MULADD(at[11], at[18]); MULADD(at[12], at[17]); MULADD(at[13], at[16]);
385 COMBA_STORE(C->dp[13]);
386 /* 14 */
387 COMBA_FORWARD;
388 MULADD(at[0], at[30]); MULADD(at[1], at[29]); MULADD(at[2], at[28]); MULADD(at[3], at[27]); MULADD(at[4], at[26]); MULADD(at[5], at[25]); MULADD(at[6], at[24]); MULADD(at[7], at[23]); MULADD(at[8], at[22]); MULADD(at[9], at[21]); MULADD(at[10], at[20]); MULADD(at[11], at[19]); MULADD(at[12], at[18]); MULADD(at[13], at[17]); MULADD(at[14], at[16]);
389 COMBA_STORE(C->dp[14]);
390 /* 15 */
391 COMBA_FORWARD;
392 MULADD(at[0], at[31]); MULADD(at[1], at[30]); MULADD(at[2], at[29]); MULADD(at[3], at[28]); MULADD(at[4], at[27]); MULADD(at[5], at[26]); MULADD(at[6], at[25]); MULADD(at[7], at[24]); MULADD(at[8], at[23]); MULADD(at[9], at[22]); MULADD(at[10], at[21]); MULADD(at[11], at[20]); MULADD(at[12], at[19]); MULADD(at[13], at[18]); MULADD(at[14], at[17]); MULADD(at[15], at[16]);
393 COMBA_STORE(C->dp[15]);
394 /* 16 */
395 COMBA_FORWARD;
396 MULADD(at[1], at[31]); MULADD(at[2], at[30]); MULADD(at[3], at[29]); MULADD(at[4], at[28]); MULADD(at[5], at[27]); MULADD(at[6], at[26]); MULADD(at[7], at[25]); MULADD(at[8], at[24]); MULADD(at[9], at[23]); MULADD(at[10], at[22]); MULADD(at[11], at[21]); MULADD(at[12], at[20]); MULADD(at[13], at[19]); MULADD(at[14], at[18]); MULADD(at[15], at[17]);
397 COMBA_STORE(C->dp[16]);
398 /* 17 */
399 COMBA_FORWARD;
400 MULADD(at[2], at[31]); MULADD(at[3], at[30]); MULADD(at[4], at[29]); MULADD(at[5], at[28]); MULADD(at[6], at[27]); MULADD(at[7], at[26]); MULADD(at[8], at[25]); MULADD(at[9], at[24]); MULADD(at[10], at[23]); MULADD(at[11], at[22]); MULADD(at[12], at[21]); MULADD(at[13], at[20]); MULADD(at[14], at[19]); MULADD(at[15], at[18]);
401 COMBA_STORE(C->dp[17]);
402 /* 18 */
403 COMBA_FORWARD;
404 MULADD(at[3], at[31]); MULADD(at[4], at[30]); MULADD(at[5], at[29]); MULADD(at[6], at[28]); MULADD(at[7], at[27]); MULADD(at[8], at[26]); MULADD(at[9], at[25]); MULADD(at[10], at[24]); MULADD(at[11], at[23]); MULADD(at[12], at[22]); MULADD(at[13], at[21]); MULADD(at[14], at[20]); MULADD(at[15], at[19]);
405 COMBA_STORE(C->dp[18]);
406 /* 19 */
407 COMBA_FORWARD;
408 MULADD(at[4], at[31]); MULADD(at[5], at[30]); MULADD(at[6], at[29]); MULADD(at[7], at[28]); MULADD(at[8], at[27]); MULADD(at[9], at[26]); MULADD(at[10], at[25]); MULADD(at[11], at[24]); MULADD(at[12], at[23]); MULADD(at[13], at[22]); MULADD(at[14], at[21]); MULADD(at[15], at[20]);
409 COMBA_STORE(C->dp[19]);
410 /* 20 */
411 COMBA_FORWARD;
412 MULADD(at[5], at[31]); MULADD(at[6], at[30]); MULADD(at[7], at[29]); MULADD(at[8], at[28]); MULADD(at[9], at[27]); MULADD(at[10], at[26]); MULADD(at[11], at[25]); MULADD(at[12], at[24]); MULADD(at[13], at[23]); MULADD(at[14], at[22]); MULADD(at[15], at[21]);
413 COMBA_STORE(C->dp[20]);
414 /* 21 */
415 COMBA_FORWARD;
416 MULADD(at[6], at[31]); MULADD(at[7], at[30]); MULADD(at[8], at[29]); MULADD(at[9], at[28]); MULADD(at[10], at[27]); MULADD(at[11], at[26]); MULADD(at[12], at[25]); MULADD(at[13], at[24]); MULADD(at[14], at[23]); MULADD(at[15], at[22]);
417 COMBA_STORE(C->dp[21]);
418 /* 22 */
419 COMBA_FORWARD;
420 MULADD(at[7], at[31]); MULADD(at[8], at[30]); MULADD(at[9], at[29]); MULADD(at[10], at[28]); MULADD(at[11], at[27]); MULADD(at[12], at[26]); MULADD(at[13], at[25]); MULADD(at[14], at[24]); MULADD(at[15], at[23]);
421 COMBA_STORE(C->dp[22]);
422 /* 23 */
423 COMBA_FORWARD;
424 MULADD(at[8], at[31]); MULADD(at[9], at[30]); MULADD(at[10], at[29]); MULADD(at[11], at[28]); MULADD(at[12], at[27]); MULADD(at[13], at[26]); MULADD(at[14], at[25]); MULADD(at[15], at[24]);
425 COMBA_STORE(C->dp[23]);
426 /* 24 */
427 COMBA_FORWARD;
428 MULADD(at[9], at[31]); MULADD(at[10], at[30]); MULADD(at[11], at[29]); MULADD(at[12], at[28]); MULADD(at[13], at[27]); MULADD(at[14], at[26]); MULADD(at[15], at[25]);
429 COMBA_STORE(C->dp[24]);
430 /* 25 */
431 COMBA_FORWARD;
432 MULADD(at[10], at[31]); MULADD(at[11], at[30]); MULADD(at[12], at[29]); MULADD(at[13], at[28]); MULADD(at[14], at[27]); MULADD(at[15], at[26]);
433 COMBA_STORE(C->dp[25]);
434 /* 26 */
435 COMBA_FORWARD;
436 MULADD(at[11], at[31]); MULADD(at[12], at[30]); MULADD(at[13], at[29]); MULADD(at[14], at[28]); MULADD(at[15], at[27]);
437 COMBA_STORE(C->dp[26]);
438 /* 27 */
439 COMBA_FORWARD;
440 MULADD(at[12], at[31]); MULADD(at[13], at[30]); MULADD(at[14], at[29]); MULADD(at[15], at[28]);
441 COMBA_STORE(C->dp[27]);
442 /* 28 */
443 COMBA_FORWARD;
444 MULADD(at[13], at[31]); MULADD(at[14], at[30]); MULADD(at[15], at[29]);
445 COMBA_STORE(C->dp[28]);
446 /* 29 */
447 COMBA_FORWARD;
448 MULADD(at[14], at[31]); MULADD(at[15], at[30]);
449 COMBA_STORE(C->dp[29]);
450 /* 30 */
451 COMBA_FORWARD;
452 MULADD(at[15], at[31]);
453 COMBA_STORE(C->dp[30]);
454 COMBA_STORE2(C->dp[31]);
455 C->used = 32;
456 C->sign = A->sign ^ B->sign;
457 pstm_clamp(C);
458 COMBA_FINI;
459 return PSTM_OKAY;
460}
461#endif /* USE_1024_KEY_SPEED_OPTIMIZATIONS */
462
463
464#ifdef USE_2048_KEY_SPEED_OPTIMIZATIONS
465static int32 pstm_mul_comba32(pstm_int *A, pstm_int *B, pstm_int *C)
466{
467 pstm_digit c0, c1, c2, at[64];
468 int32 out_size;
469
470 if (C->alloc < 64) {
471 if (pstm_grow(C, 64) != PSTM_OKAY) {
472 return PS_MEM_FAIL;
473 }
474 }
475
476 out_size = A->used + B->used;
477 memcpy(at, A->dp, 32 * sizeof(pstm_digit));
478 memcpy(at+32, B->dp, 32 * sizeof(pstm_digit));
479 COMBA_START;
480
481 COMBA_CLEAR;
482 /* 0 */
483 MULADD(at[0], at[32]);
484 COMBA_STORE(C->dp[0]);
485 /* 1 */
486 COMBA_FORWARD;
487 MULADD(at[0], at[33]); MULADD(at[1], at[32]);
488 COMBA_STORE(C->dp[1]);
489 /* 2 */
490 COMBA_FORWARD;
491 MULADD(at[0], at[34]); MULADD(at[1], at[33]); MULADD(at[2], at[32]);
492 COMBA_STORE(C->dp[2]);
493 /* 3 */
494 COMBA_FORWARD;
495 MULADD(at[0], at[35]); MULADD(at[1], at[34]); MULADD(at[2], at[33]); MULADD(at[3], at[32]);
496 COMBA_STORE(C->dp[3]);
497 /* 4 */
498 COMBA_FORWARD;
499 MULADD(at[0], at[36]); MULADD(at[1], at[35]); MULADD(at[2], at[34]); MULADD(at[3], at[33]); MULADD(at[4], at[32]);
500 COMBA_STORE(C->dp[4]);
501 /* 5 */
502 COMBA_FORWARD;
503 MULADD(at[0], at[37]); MULADD(at[1], at[36]); MULADD(at[2], at[35]); MULADD(at[3], at[34]); MULADD(at[4], at[33]); MULADD(at[5], at[32]);
504 COMBA_STORE(C->dp[5]);
505 /* 6 */
506 COMBA_FORWARD;
507 MULADD(at[0], at[38]); MULADD(at[1], at[37]); MULADD(at[2], at[36]); MULADD(at[3], at[35]); MULADD(at[4], at[34]); MULADD(at[5], at[33]); MULADD(at[6], at[32]);
508 COMBA_STORE(C->dp[6]);
509 /* 7 */
510 COMBA_FORWARD;
511 MULADD(at[0], at[39]); MULADD(at[1], at[38]); MULADD(at[2], at[37]); MULADD(at[3], at[36]); MULADD(at[4], at[35]); MULADD(at[5], at[34]); MULADD(at[6], at[33]); MULADD(at[7], at[32]);
512 COMBA_STORE(C->dp[7]);
513 /* 8 */
514 COMBA_FORWARD;
515 MULADD(at[0], at[40]); MULADD(at[1], at[39]); MULADD(at[2], at[38]); MULADD(at[3], at[37]); MULADD(at[4], at[36]); MULADD(at[5], at[35]); MULADD(at[6], at[34]); MULADD(at[7], at[33]); MULADD(at[8], at[32]);
516 COMBA_STORE(C->dp[8]);
517 /* 9 */
518 COMBA_FORWARD;
519 MULADD(at[0], at[41]); MULADD(at[1], at[40]); MULADD(at[2], at[39]); MULADD(at[3], at[38]); MULADD(at[4], at[37]); MULADD(at[5], at[36]); MULADD(at[6], at[35]); MULADD(at[7], at[34]); MULADD(at[8], at[33]); MULADD(at[9], at[32]);
520 COMBA_STORE(C->dp[9]);
521 /* 10 */
522 COMBA_FORWARD;
523 MULADD(at[0], at[42]); MULADD(at[1], at[41]); MULADD(at[2], at[40]); MULADD(at[3], at[39]); MULADD(at[4], at[38]); MULADD(at[5], at[37]); MULADD(at[6], at[36]); MULADD(at[7], at[35]); MULADD(at[8], at[34]); MULADD(at[9], at[33]); MULADD(at[10], at[32]);
524 COMBA_STORE(C->dp[10]);
525 /* 11 */
526 COMBA_FORWARD;
527 MULADD(at[0], at[43]); MULADD(at[1], at[42]); MULADD(at[2], at[41]); MULADD(at[3], at[40]); MULADD(at[4], at[39]); MULADD(at[5], at[38]); MULADD(at[6], at[37]); MULADD(at[7], at[36]); MULADD(at[8], at[35]); MULADD(at[9], at[34]); MULADD(at[10], at[33]); MULADD(at[11], at[32]);
528 COMBA_STORE(C->dp[11]);
529 /* 12 */
530 COMBA_FORWARD;
531 MULADD(at[0], at[44]); MULADD(at[1], at[43]); MULADD(at[2], at[42]); MULADD(at[3], at[41]); MULADD(at[4], at[40]); MULADD(at[5], at[39]); MULADD(at[6], at[38]); MULADD(at[7], at[37]); MULADD(at[8], at[36]); MULADD(at[9], at[35]); MULADD(at[10], at[34]); MULADD(at[11], at[33]); MULADD(at[12], at[32]);
532 COMBA_STORE(C->dp[12]);
533 /* 13 */
534 COMBA_FORWARD;
535 MULADD(at[0], at[45]); MULADD(at[1], at[44]); MULADD(at[2], at[43]); MULADD(at[3], at[42]); MULADD(at[4], at[41]); MULADD(at[5], at[40]); MULADD(at[6], at[39]); MULADD(at[7], at[38]); MULADD(at[8], at[37]); MULADD(at[9], at[36]); MULADD(at[10], at[35]); MULADD(at[11], at[34]); MULADD(at[12], at[33]); MULADD(at[13], at[32]);
536 COMBA_STORE(C->dp[13]);
537 /* 14 */
538 COMBA_FORWARD;
539 MULADD(at[0], at[46]); MULADD(at[1], at[45]); MULADD(at[2], at[44]); MULADD(at[3], at[43]); MULADD(at[4], at[42]); MULADD(at[5], at[41]); MULADD(at[6], at[40]); MULADD(at[7], at[39]); MULADD(at[8], at[38]); MULADD(at[9], at[37]); MULADD(at[10], at[36]); MULADD(at[11], at[35]); MULADD(at[12], at[34]); MULADD(at[13], at[33]); MULADD(at[14], at[32]);
540 COMBA_STORE(C->dp[14]);
541 /* 15 */
542 COMBA_FORWARD;
543 MULADD(at[0], at[47]); MULADD(at[1], at[46]); MULADD(at[2], at[45]); MULADD(at[3], at[44]); MULADD(at[4], at[43]); MULADD(at[5], at[42]); MULADD(at[6], at[41]); MULADD(at[7], at[40]); MULADD(at[8], at[39]); MULADD(at[9], at[38]); MULADD(at[10], at[37]); MULADD(at[11], at[36]); MULADD(at[12], at[35]); MULADD(at[13], at[34]); MULADD(at[14], at[33]); MULADD(at[15], at[32]);
544 COMBA_STORE(C->dp[15]);
545 /* 16 */
546 COMBA_FORWARD;
547 MULADD(at[0], at[48]); MULADD(at[1], at[47]); MULADD(at[2], at[46]); MULADD(at[3], at[45]); MULADD(at[4], at[44]); MULADD(at[5], at[43]); MULADD(at[6], at[42]); MULADD(at[7], at[41]); MULADD(at[8], at[40]); MULADD(at[9], at[39]); MULADD(at[10], at[38]); MULADD(at[11], at[37]); MULADD(at[12], at[36]); MULADD(at[13], at[35]); MULADD(at[14], at[34]); MULADD(at[15], at[33]); MULADD(at[16], at[32]);
548 COMBA_STORE(C->dp[16]);
549 /* 17 */
550 COMBA_FORWARD;
551 MULADD(at[0], at[49]); MULADD(at[1], at[48]); MULADD(at[2], at[47]); MULADD(at[3], at[46]); MULADD(at[4], at[45]); MULADD(at[5], at[44]); MULADD(at[6], at[43]); MULADD(at[7], at[42]); MULADD(at[8], at[41]); MULADD(at[9], at[40]); MULADD(at[10], at[39]); MULADD(at[11], at[38]); MULADD(at[12], at[37]); MULADD(at[13], at[36]); MULADD(at[14], at[35]); MULADD(at[15], at[34]); MULADD(at[16], at[33]); MULADD(at[17], at[32]);
552 COMBA_STORE(C->dp[17]);
553 /* 18 */
554 COMBA_FORWARD;
555 MULADD(at[0], at[50]); MULADD(at[1], at[49]); MULADD(at[2], at[48]); MULADD(at[3], at[47]); MULADD(at[4], at[46]); MULADD(at[5], at[45]); MULADD(at[6], at[44]); MULADD(at[7], at[43]); MULADD(at[8], at[42]); MULADD(at[9], at[41]); MULADD(at[10], at[40]); MULADD(at[11], at[39]); MULADD(at[12], at[38]); MULADD(at[13], at[37]); MULADD(at[14], at[36]); MULADD(at[15], at[35]); MULADD(at[16], at[34]); MULADD(at[17], at[33]); MULADD(at[18], at[32]);
556 COMBA_STORE(C->dp[18]);
557 /* 19 */
558 COMBA_FORWARD;
559 MULADD(at[0], at[51]); MULADD(at[1], at[50]); MULADD(at[2], at[49]); MULADD(at[3], at[48]); MULADD(at[4], at[47]); MULADD(at[5], at[46]); MULADD(at[6], at[45]); MULADD(at[7], at[44]); MULADD(at[8], at[43]); MULADD(at[9], at[42]); MULADD(at[10], at[41]); MULADD(at[11], at[40]); MULADD(at[12], at[39]); MULADD(at[13], at[38]); MULADD(at[14], at[37]); MULADD(at[15], at[36]); MULADD(at[16], at[35]); MULADD(at[17], at[34]); MULADD(at[18], at[33]); MULADD(at[19], at[32]);
560 COMBA_STORE(C->dp[19]);
561 /* 20 */
562 COMBA_FORWARD;
563 MULADD(at[0], at[52]); MULADD(at[1], at[51]); MULADD(at[2], at[50]); MULADD(at[3], at[49]); MULADD(at[4], at[48]); MULADD(at[5], at[47]); MULADD(at[6], at[46]); MULADD(at[7], at[45]); MULADD(at[8], at[44]); MULADD(at[9], at[43]); MULADD(at[10], at[42]); MULADD(at[11], at[41]); MULADD(at[12], at[40]); MULADD(at[13], at[39]); MULADD(at[14], at[38]); MULADD(at[15], at[37]); MULADD(at[16], at[36]); MULADD(at[17], at[35]); MULADD(at[18], at[34]); MULADD(at[19], at[33]); MULADD(at[20], at[32]);
564 COMBA_STORE(C->dp[20]);
565 /* 21 */
566 COMBA_FORWARD;
567 MULADD(at[0], at[53]); MULADD(at[1], at[52]); MULADD(at[2], at[51]); MULADD(at[3], at[50]); MULADD(at[4], at[49]); MULADD(at[5], at[48]); MULADD(at[6], at[47]); MULADD(at[7], at[46]); MULADD(at[8], at[45]); MULADD(at[9], at[44]); MULADD(at[10], at[43]); MULADD(at[11], at[42]); MULADD(at[12], at[41]); MULADD(at[13], at[40]); MULADD(at[14], at[39]); MULADD(at[15], at[38]); MULADD(at[16], at[37]); MULADD(at[17], at[36]); MULADD(at[18], at[35]); MULADD(at[19], at[34]); MULADD(at[20], at[33]); MULADD(at[21], at[32]);
568 COMBA_STORE(C->dp[21]);
569 /* 22 */
570 COMBA_FORWARD;
571 MULADD(at[0], at[54]); MULADD(at[1], at[53]); MULADD(at[2], at[52]); MULADD(at[3], at[51]); MULADD(at[4], at[50]); MULADD(at[5], at[49]); MULADD(at[6], at[48]); MULADD(at[7], at[47]); MULADD(at[8], at[46]); MULADD(at[9], at[45]); MULADD(at[10], at[44]); MULADD(at[11], at[43]); MULADD(at[12], at[42]); MULADD(at[13], at[41]); MULADD(at[14], at[40]); MULADD(at[15], at[39]); MULADD(at[16], at[38]); MULADD(at[17], at[37]); MULADD(at[18], at[36]); MULADD(at[19], at[35]); MULADD(at[20], at[34]); MULADD(at[21], at[33]); MULADD(at[22], at[32]);
572 COMBA_STORE(C->dp[22]);
573 /* 23 */
574 COMBA_FORWARD;
575 MULADD(at[0], at[55]); MULADD(at[1], at[54]); MULADD(at[2], at[53]); MULADD(at[3], at[52]); MULADD(at[4], at[51]); MULADD(at[5], at[50]); MULADD(at[6], at[49]); MULADD(at[7], at[48]); MULADD(at[8], at[47]); MULADD(at[9], at[46]); MULADD(at[10], at[45]); MULADD(at[11], at[44]); MULADD(at[12], at[43]); MULADD(at[13], at[42]); MULADD(at[14], at[41]); MULADD(at[15], at[40]); MULADD(at[16], at[39]); MULADD(at[17], at[38]); MULADD(at[18], at[37]); MULADD(at[19], at[36]); MULADD(at[20], at[35]); MULADD(at[21], at[34]); MULADD(at[22], at[33]); MULADD(at[23], at[32]);
576 COMBA_STORE(C->dp[23]);
577 /* 24 */
578 COMBA_FORWARD;
579 MULADD(at[0], at[56]); MULADD(at[1], at[55]); MULADD(at[2], at[54]); MULADD(at[3], at[53]); MULADD(at[4], at[52]); MULADD(at[5], at[51]); MULADD(at[6], at[50]); MULADD(at[7], at[49]); MULADD(at[8], at[48]); MULADD(at[9], at[47]); MULADD(at[10], at[46]); MULADD(at[11], at[45]); MULADD(at[12], at[44]); MULADD(at[13], at[43]); MULADD(at[14], at[42]); MULADD(at[15], at[41]); MULADD(at[16], at[40]); MULADD(at[17], at[39]); MULADD(at[18], at[38]); MULADD(at[19], at[37]); MULADD(at[20], at[36]); MULADD(at[21], at[35]); MULADD(at[22], at[34]); MULADD(at[23], at[33]); MULADD(at[24], at[32]);
580 COMBA_STORE(C->dp[24]);
581 /* 25 */
582 COMBA_FORWARD;
583 MULADD(at[0], at[57]); MULADD(at[1], at[56]); MULADD(at[2], at[55]); MULADD(at[3], at[54]); MULADD(at[4], at[53]); MULADD(at[5], at[52]); MULADD(at[6], at[51]); MULADD(at[7], at[50]); MULADD(at[8], at[49]); MULADD(at[9], at[48]); MULADD(at[10], at[47]); MULADD(at[11], at[46]); MULADD(at[12], at[45]); MULADD(at[13], at[44]); MULADD(at[14], at[43]); MULADD(at[15], at[42]); MULADD(at[16], at[41]); MULADD(at[17], at[40]); MULADD(at[18], at[39]); MULADD(at[19], at[38]); MULADD(at[20], at[37]); MULADD(at[21], at[36]); MULADD(at[22], at[35]); MULADD(at[23], at[34]); MULADD(at[24], at[33]); MULADD(at[25], at[32]);
584 COMBA_STORE(C->dp[25]);
585 /* 26 */
586 COMBA_FORWARD;
587 MULADD(at[0], at[58]); MULADD(at[1], at[57]); MULADD(at[2], at[56]); MULADD(at[3], at[55]); MULADD(at[4], at[54]); MULADD(at[5], at[53]); MULADD(at[6], at[52]); MULADD(at[7], at[51]); MULADD(at[8], at[50]); MULADD(at[9], at[49]); MULADD(at[10], at[48]); MULADD(at[11], at[47]); MULADD(at[12], at[46]); MULADD(at[13], at[45]); MULADD(at[14], at[44]); MULADD(at[15], at[43]); MULADD(at[16], at[42]); MULADD(at[17], at[41]); MULADD(at[18], at[40]); MULADD(at[19], at[39]); MULADD(at[20], at[38]); MULADD(at[21], at[37]); MULADD(at[22], at[36]); MULADD(at[23], at[35]); MULADD(at[24], at[34]); MULADD(at[25], at[33]); MULADD(at[26], at[32]);
588 COMBA_STORE(C->dp[26]);
589 /* 27 */
590 COMBA_FORWARD;
591 MULADD(at[0], at[59]); MULADD(at[1], at[58]); MULADD(at[2], at[57]); MULADD(at[3], at[56]); MULADD(at[4], at[55]); MULADD(at[5], at[54]); MULADD(at[6], at[53]); MULADD(at[7], at[52]); MULADD(at[8], at[51]); MULADD(at[9], at[50]); MULADD(at[10], at[49]); MULADD(at[11], at[48]); MULADD(at[12], at[47]); MULADD(at[13], at[46]); MULADD(at[14], at[45]); MULADD(at[15], at[44]); MULADD(at[16], at[43]); MULADD(at[17], at[42]); MULADD(at[18], at[41]); MULADD(at[19], at[40]); MULADD(at[20], at[39]); MULADD(at[21], at[38]); MULADD(at[22], at[37]); MULADD(at[23], at[36]); MULADD(at[24], at[35]); MULADD(at[25], at[34]); MULADD(at[26], at[33]); MULADD(at[27], at[32]);
592 COMBA_STORE(C->dp[27]);
593 /* 28 */
594 COMBA_FORWARD;
595 MULADD(at[0], at[60]); MULADD(at[1], at[59]); MULADD(at[2], at[58]); MULADD(at[3], at[57]); MULADD(at[4], at[56]); MULADD(at[5], at[55]); MULADD(at[6], at[54]); MULADD(at[7], at[53]); MULADD(at[8], at[52]); MULADD(at[9], at[51]); MULADD(at[10], at[50]); MULADD(at[11], at[49]); MULADD(at[12], at[48]); MULADD(at[13], at[47]); MULADD(at[14], at[46]); MULADD(at[15], at[45]); MULADD(at[16], at[44]); MULADD(at[17], at[43]); MULADD(at[18], at[42]); MULADD(at[19], at[41]); MULADD(at[20], at[40]); MULADD(at[21], at[39]); MULADD(at[22], at[38]); MULADD(at[23], at[37]); MULADD(at[24], at[36]); MULADD(at[25], at[35]); MULADD(at[26], at[34]); MULADD(at[27], at[33]); MULADD(at[28], at[32]);
596 COMBA_STORE(C->dp[28]);
597 /* 29 */
598 COMBA_FORWARD;
599 MULADD(at[0], at[61]); MULADD(at[1], at[60]); MULADD(at[2], at[59]); MULADD(at[3], at[58]); MULADD(at[4], at[57]); MULADD(at[5], at[56]); MULADD(at[6], at[55]); MULADD(at[7], at[54]); MULADD(at[8], at[53]); MULADD(at[9], at[52]); MULADD(at[10], at[51]); MULADD(at[11], at[50]); MULADD(at[12], at[49]); MULADD(at[13], at[48]); MULADD(at[14], at[47]); MULADD(at[15], at[46]); MULADD(at[16], at[45]); MULADD(at[17], at[44]); MULADD(at[18], at[43]); MULADD(at[19], at[42]); MULADD(at[20], at[41]); MULADD(at[21], at[40]); MULADD(at[22], at[39]); MULADD(at[23], at[38]); MULADD(at[24], at[37]); MULADD(at[25], at[36]); MULADD(at[26], at[35]); MULADD(at[27], at[34]); MULADD(at[28], at[33]); MULADD(at[29], at[32]);
600 COMBA_STORE(C->dp[29]);
601 /* 30 */
602 COMBA_FORWARD;
603 MULADD(at[0], at[62]); MULADD(at[1], at[61]); MULADD(at[2], at[60]); MULADD(at[3], at[59]); MULADD(at[4], at[58]); MULADD(at[5], at[57]); MULADD(at[6], at[56]); MULADD(at[7], at[55]); MULADD(at[8], at[54]); MULADD(at[9], at[53]); MULADD(at[10], at[52]); MULADD(at[11], at[51]); MULADD(at[12], at[50]); MULADD(at[13], at[49]); MULADD(at[14], at[48]); MULADD(at[15], at[47]); MULADD(at[16], at[46]); MULADD(at[17], at[45]); MULADD(at[18], at[44]); MULADD(at[19], at[43]); MULADD(at[20], at[42]); MULADD(at[21], at[41]); MULADD(at[22], at[40]); MULADD(at[23], at[39]); MULADD(at[24], at[38]); MULADD(at[25], at[37]); MULADD(at[26], at[36]); MULADD(at[27], at[35]); MULADD(at[28], at[34]); MULADD(at[29], at[33]); MULADD(at[30], at[32]);
604 COMBA_STORE(C->dp[30]);
605 /* 31 */
606 COMBA_FORWARD;
607 MULADD(at[0], at[63]); MULADD(at[1], at[62]); MULADD(at[2], at[61]); MULADD(at[3], at[60]); MULADD(at[4], at[59]); MULADD(at[5], at[58]); MULADD(at[6], at[57]); MULADD(at[7], at[56]); MULADD(at[8], at[55]); MULADD(at[9], at[54]); MULADD(at[10], at[53]); MULADD(at[11], at[52]); MULADD(at[12], at[51]); MULADD(at[13], at[50]); MULADD(at[14], at[49]); MULADD(at[15], at[48]); MULADD(at[16], at[47]); MULADD(at[17], at[46]); MULADD(at[18], at[45]); MULADD(at[19], at[44]); MULADD(at[20], at[43]); MULADD(at[21], at[42]); MULADD(at[22], at[41]); MULADD(at[23], at[40]); MULADD(at[24], at[39]); MULADD(at[25], at[38]); MULADD(at[26], at[37]); MULADD(at[27], at[36]); MULADD(at[28], at[35]); MULADD(at[29], at[34]); MULADD(at[30], at[33]); MULADD(at[31], at[32]);
608 COMBA_STORE(C->dp[31]);
609 /* 32 */
610 COMBA_FORWARD;
611 MULADD(at[1], at[63]); MULADD(at[2], at[62]); MULADD(at[3], at[61]); MULADD(at[4], at[60]); MULADD(at[5], at[59]); MULADD(at[6], at[58]); MULADD(at[7], at[57]); MULADD(at[8], at[56]); MULADD(at[9], at[55]); MULADD(at[10], at[54]); MULADD(at[11], at[53]); MULADD(at[12], at[52]); MULADD(at[13], at[51]); MULADD(at[14], at[50]); MULADD(at[15], at[49]); MULADD(at[16], at[48]); MULADD(at[17], at[47]); MULADD(at[18], at[46]); MULADD(at[19], at[45]); MULADD(at[20], at[44]); MULADD(at[21], at[43]); MULADD(at[22], at[42]); MULADD(at[23], at[41]); MULADD(at[24], at[40]); MULADD(at[25], at[39]); MULADD(at[26], at[38]); MULADD(at[27], at[37]); MULADD(at[28], at[36]); MULADD(at[29], at[35]); MULADD(at[30], at[34]); MULADD(at[31], at[33]);
612 COMBA_STORE(C->dp[32]);
613 /* 33 */
614 COMBA_FORWARD;
615 MULADD(at[2], at[63]); MULADD(at[3], at[62]); MULADD(at[4], at[61]); MULADD(at[5], at[60]); MULADD(at[6], at[59]); MULADD(at[7], at[58]); MULADD(at[8], at[57]); MULADD(at[9], at[56]); MULADD(at[10], at[55]); MULADD(at[11], at[54]); MULADD(at[12], at[53]); MULADD(at[13], at[52]); MULADD(at[14], at[51]); MULADD(at[15], at[50]); MULADD(at[16], at[49]); MULADD(at[17], at[48]); MULADD(at[18], at[47]); MULADD(at[19], at[46]); MULADD(at[20], at[45]); MULADD(at[21], at[44]); MULADD(at[22], at[43]); MULADD(at[23], at[42]); MULADD(at[24], at[41]); MULADD(at[25], at[40]); MULADD(at[26], at[39]); MULADD(at[27], at[38]); MULADD(at[28], at[37]); MULADD(at[29], at[36]); MULADD(at[30], at[35]); MULADD(at[31], at[34]);
616 COMBA_STORE(C->dp[33]);
617 /* 34 */
618 COMBA_FORWARD;
619 MULADD(at[3], at[63]); MULADD(at[4], at[62]); MULADD(at[5], at[61]); MULADD(at[6], at[60]); MULADD(at[7], at[59]); MULADD(at[8], at[58]); MULADD(at[9], at[57]); MULADD(at[10], at[56]); MULADD(at[11], at[55]); MULADD(at[12], at[54]); MULADD(at[13], at[53]); MULADD(at[14], at[52]); MULADD(at[15], at[51]); MULADD(at[16], at[50]); MULADD(at[17], at[49]); MULADD(at[18], at[48]); MULADD(at[19], at[47]); MULADD(at[20], at[46]); MULADD(at[21], at[45]); MULADD(at[22], at[44]); MULADD(at[23], at[43]); MULADD(at[24], at[42]); MULADD(at[25], at[41]); MULADD(at[26], at[40]); MULADD(at[27], at[39]); MULADD(at[28], at[38]); MULADD(at[29], at[37]); MULADD(at[30], at[36]); MULADD(at[31], at[35]);
620 COMBA_STORE(C->dp[34]);
621 /* 35 */
622 COMBA_FORWARD;
623 MULADD(at[4], at[63]); MULADD(at[5], at[62]); MULADD(at[6], at[61]); MULADD(at[7], at[60]); MULADD(at[8], at[59]); MULADD(at[9], at[58]); MULADD(at[10], at[57]); MULADD(at[11], at[56]); MULADD(at[12], at[55]); MULADD(at[13], at[54]); MULADD(at[14], at[53]); MULADD(at[15], at[52]); MULADD(at[16], at[51]); MULADD(at[17], at[50]); MULADD(at[18], at[49]); MULADD(at[19], at[48]); MULADD(at[20], at[47]); MULADD(at[21], at[46]); MULADD(at[22], at[45]); MULADD(at[23], at[44]); MULADD(at[24], at[43]); MULADD(at[25], at[42]); MULADD(at[26], at[41]); MULADD(at[27], at[40]); MULADD(at[28], at[39]); MULADD(at[29], at[38]); MULADD(at[30], at[37]); MULADD(at[31], at[36]);
624 COMBA_STORE(C->dp[35]);
625 /* 36 */
626 COMBA_FORWARD;
627 MULADD(at[5], at[63]); MULADD(at[6], at[62]); MULADD(at[7], at[61]); MULADD(at[8], at[60]); MULADD(at[9], at[59]); MULADD(at[10], at[58]); MULADD(at[11], at[57]); MULADD(at[12], at[56]); MULADD(at[13], at[55]); MULADD(at[14], at[54]); MULADD(at[15], at[53]); MULADD(at[16], at[52]); MULADD(at[17], at[51]); MULADD(at[18], at[50]); MULADD(at[19], at[49]); MULADD(at[20], at[48]); MULADD(at[21], at[47]); MULADD(at[22], at[46]); MULADD(at[23], at[45]); MULADD(at[24], at[44]); MULADD(at[25], at[43]); MULADD(at[26], at[42]); MULADD(at[27], at[41]); MULADD(at[28], at[40]); MULADD(at[29], at[39]); MULADD(at[30], at[38]); MULADD(at[31], at[37]);
628 COMBA_STORE(C->dp[36]);
629 /* 37 */
630 COMBA_FORWARD;
631 MULADD(at[6], at[63]); MULADD(at[7], at[62]); MULADD(at[8], at[61]); MULADD(at[9], at[60]); MULADD(at[10], at[59]); MULADD(at[11], at[58]); MULADD(at[12], at[57]); MULADD(at[13], at[56]); MULADD(at[14], at[55]); MULADD(at[15], at[54]); MULADD(at[16], at[53]); MULADD(at[17], at[52]); MULADD(at[18], at[51]); MULADD(at[19], at[50]); MULADD(at[20], at[49]); MULADD(at[21], at[48]); MULADD(at[22], at[47]); MULADD(at[23], at[46]); MULADD(at[24], at[45]); MULADD(at[25], at[44]); MULADD(at[26], at[43]); MULADD(at[27], at[42]); MULADD(at[28], at[41]); MULADD(at[29], at[40]); MULADD(at[30], at[39]); MULADD(at[31], at[38]);
632 COMBA_STORE(C->dp[37]);
633 /* 38 */
634 COMBA_FORWARD;
635 MULADD(at[7], at[63]); MULADD(at[8], at[62]); MULADD(at[9], at[61]); MULADD(at[10], at[60]); MULADD(at[11], at[59]); MULADD(at[12], at[58]); MULADD(at[13], at[57]); MULADD(at[14], at[56]); MULADD(at[15], at[55]); MULADD(at[16], at[54]); MULADD(at[17], at[53]); MULADD(at[18], at[52]); MULADD(at[19], at[51]); MULADD(at[20], at[50]); MULADD(at[21], at[49]); MULADD(at[22], at[48]); MULADD(at[23], at[47]); MULADD(at[24], at[46]); MULADD(at[25], at[45]); MULADD(at[26], at[44]); MULADD(at[27], at[43]); MULADD(at[28], at[42]); MULADD(at[29], at[41]); MULADD(at[30], at[40]); MULADD(at[31], at[39]);
636 COMBA_STORE(C->dp[38]);
637
638 /* early out at 40 digits, 40*32==1280, or two 640 bit operands */
639 if (out_size <= 40) { COMBA_STORE2(C->dp[39]); C->used = 40; C->sign = A->sign ^ B->sign; pstm_clamp(C); COMBA_FINI; return PSTM_OKAY; }
640
641 /* 39 */
642 COMBA_FORWARD;
643 MULADD(at[8], at[63]); MULADD(at[9], at[62]); MULADD(at[10], at[61]); MULADD(at[11], at[60]); MULADD(at[12], at[59]); MULADD(at[13], at[58]); MULADD(at[14], at[57]); MULADD(at[15], at[56]); MULADD(at[16], at[55]); MULADD(at[17], at[54]); MULADD(at[18], at[53]); MULADD(at[19], at[52]); MULADD(at[20], at[51]); MULADD(at[21], at[50]); MULADD(at[22], at[49]); MULADD(at[23], at[48]); MULADD(at[24], at[47]); MULADD(at[25], at[46]); MULADD(at[26], at[45]); MULADD(at[27], at[44]); MULADD(at[28], at[43]); MULADD(at[29], at[42]); MULADD(at[30], at[41]); MULADD(at[31], at[40]);
644 COMBA_STORE(C->dp[39]);
645 /* 40 */
646 COMBA_FORWARD;
647 MULADD(at[9], at[63]); MULADD(at[10], at[62]); MULADD(at[11], at[61]); MULADD(at[12], at[60]); MULADD(at[13], at[59]); MULADD(at[14], at[58]); MULADD(at[15], at[57]); MULADD(at[16], at[56]); MULADD(at[17], at[55]); MULADD(at[18], at[54]); MULADD(at[19], at[53]); MULADD(at[20], at[52]); MULADD(at[21], at[51]); MULADD(at[22], at[50]); MULADD(at[23], at[49]); MULADD(at[24], at[48]); MULADD(at[25], at[47]); MULADD(at[26], at[46]); MULADD(at[27], at[45]); MULADD(at[28], at[44]); MULADD(at[29], at[43]); MULADD(at[30], at[42]); MULADD(at[31], at[41]);
648 COMBA_STORE(C->dp[40]);
649 /* 41 */
650 COMBA_FORWARD;
651 MULADD(at[10], at[63]); MULADD(at[11], at[62]); MULADD(at[12], at[61]); MULADD(at[13], at[60]); MULADD(at[14], at[59]); MULADD(at[15], at[58]); MULADD(at[16], at[57]); MULADD(at[17], at[56]); MULADD(at[18], at[55]); MULADD(at[19], at[54]); MULADD(at[20], at[53]); MULADD(at[21], at[52]); MULADD(at[22], at[51]); MULADD(at[23], at[50]); MULADD(at[24], at[49]); MULADD(at[25], at[48]); MULADD(at[26], at[47]); MULADD(at[27], at[46]); MULADD(at[28], at[45]); MULADD(at[29], at[44]); MULADD(at[30], at[43]); MULADD(at[31], at[42]);
652 COMBA_STORE(C->dp[41]);
653 /* 42 */
654 COMBA_FORWARD;
655 MULADD(at[11], at[63]); MULADD(at[12], at[62]); MULADD(at[13], at[61]); MULADD(at[14], at[60]); MULADD(at[15], at[59]); MULADD(at[16], at[58]); MULADD(at[17], at[57]); MULADD(at[18], at[56]); MULADD(at[19], at[55]); MULADD(at[20], at[54]); MULADD(at[21], at[53]); MULADD(at[22], at[52]); MULADD(at[23], at[51]); MULADD(at[24], at[50]); MULADD(at[25], at[49]); MULADD(at[26], at[48]); MULADD(at[27], at[47]); MULADD(at[28], at[46]); MULADD(at[29], at[45]); MULADD(at[30], at[44]); MULADD(at[31], at[43]);
656 COMBA_STORE(C->dp[42]);
657 /* 43 */
658 COMBA_FORWARD;
659 MULADD(at[12], at[63]); MULADD(at[13], at[62]); MULADD(at[14], at[61]); MULADD(at[15], at[60]); MULADD(at[16], at[59]); MULADD(at[17], at[58]); MULADD(at[18], at[57]); MULADD(at[19], at[56]); MULADD(at[20], at[55]); MULADD(at[21], at[54]); MULADD(at[22], at[53]); MULADD(at[23], at[52]); MULADD(at[24], at[51]); MULADD(at[25], at[50]); MULADD(at[26], at[49]); MULADD(at[27], at[48]); MULADD(at[28], at[47]); MULADD(at[29], at[46]); MULADD(at[30], at[45]); MULADD(at[31], at[44]);
660 COMBA_STORE(C->dp[43]);
661 /* 44 */
662 COMBA_FORWARD;
663 MULADD(at[13], at[63]); MULADD(at[14], at[62]); MULADD(at[15], at[61]); MULADD(at[16], at[60]); MULADD(at[17], at[59]); MULADD(at[18], at[58]); MULADD(at[19], at[57]); MULADD(at[20], at[56]); MULADD(at[21], at[55]); MULADD(at[22], at[54]); MULADD(at[23], at[53]); MULADD(at[24], at[52]); MULADD(at[25], at[51]); MULADD(at[26], at[50]); MULADD(at[27], at[49]); MULADD(at[28], at[48]); MULADD(at[29], at[47]); MULADD(at[30], at[46]); MULADD(at[31], at[45]);
664 COMBA_STORE(C->dp[44]);
665 /* 45 */
666 COMBA_FORWARD;
667 MULADD(at[14], at[63]); MULADD(at[15], at[62]); MULADD(at[16], at[61]); MULADD(at[17], at[60]); MULADD(at[18], at[59]); MULADD(at[19], at[58]); MULADD(at[20], at[57]); MULADD(at[21], at[56]); MULADD(at[22], at[55]); MULADD(at[23], at[54]); MULADD(at[24], at[53]); MULADD(at[25], at[52]); MULADD(at[26], at[51]); MULADD(at[27], at[50]); MULADD(at[28], at[49]); MULADD(at[29], at[48]); MULADD(at[30], at[47]); MULADD(at[31], at[46]);
668 COMBA_STORE(C->dp[45]);
669 /* 46 */
670 COMBA_FORWARD;
671 MULADD(at[15], at[63]); MULADD(at[16], at[62]); MULADD(at[17], at[61]); MULADD(at[18], at[60]); MULADD(at[19], at[59]); MULADD(at[20], at[58]); MULADD(at[21], at[57]); MULADD(at[22], at[56]); MULADD(at[23], at[55]); MULADD(at[24], at[54]); MULADD(at[25], at[53]); MULADD(at[26], at[52]); MULADD(at[27], at[51]); MULADD(at[28], at[50]); MULADD(at[29], at[49]); MULADD(at[30], at[48]); MULADD(at[31], at[47]);
672 COMBA_STORE(C->dp[46]);
673
674 /* early out at 48 digits, 48*32==1536, or two 768 bit operands */
675 if (out_size <= 48) { COMBA_STORE2(C->dp[47]); C->used = 48; C->sign = A->sign ^ B->sign; pstm_clamp(C); COMBA_FINI; return PSTM_OKAY; }
676
677 /* 47 */
678 COMBA_FORWARD;
679 MULADD(at[16], at[63]); MULADD(at[17], at[62]); MULADD(at[18], at[61]); MULADD(at[19], at[60]); MULADD(at[20], at[59]); MULADD(at[21], at[58]); MULADD(at[22], at[57]); MULADD(at[23], at[56]); MULADD(at[24], at[55]); MULADD(at[25], at[54]); MULADD(at[26], at[53]); MULADD(at[27], at[52]); MULADD(at[28], at[51]); MULADD(at[29], at[50]); MULADD(at[30], at[49]); MULADD(at[31], at[48]);
680 COMBA_STORE(C->dp[47]);
681 /* 48 */
682 COMBA_FORWARD;
683 MULADD(at[17], at[63]); MULADD(at[18], at[62]); MULADD(at[19], at[61]); MULADD(at[20], at[60]); MULADD(at[21], at[59]); MULADD(at[22], at[58]); MULADD(at[23], at[57]); MULADD(at[24], at[56]); MULADD(at[25], at[55]); MULADD(at[26], at[54]); MULADD(at[27], at[53]); MULADD(at[28], at[52]); MULADD(at[29], at[51]); MULADD(at[30], at[50]); MULADD(at[31], at[49]);
684 COMBA_STORE(C->dp[48]);
685 /* 49 */
686 COMBA_FORWARD;
687 MULADD(at[18], at[63]); MULADD(at[19], at[62]); MULADD(at[20], at[61]); MULADD(at[21], at[60]); MULADD(at[22], at[59]); MULADD(at[23], at[58]); MULADD(at[24], at[57]); MULADD(at[25], at[56]); MULADD(at[26], at[55]); MULADD(at[27], at[54]); MULADD(at[28], at[53]); MULADD(at[29], at[52]); MULADD(at[30], at[51]); MULADD(at[31], at[50]);
688 COMBA_STORE(C->dp[49]);
689 /* 50 */
690 COMBA_FORWARD;
691 MULADD(at[19], at[63]); MULADD(at[20], at[62]); MULADD(at[21], at[61]); MULADD(at[22], at[60]); MULADD(at[23], at[59]); MULADD(at[24], at[58]); MULADD(at[25], at[57]); MULADD(at[26], at[56]); MULADD(at[27], at[55]); MULADD(at[28], at[54]); MULADD(at[29], at[53]); MULADD(at[30], at[52]); MULADD(at[31], at[51]);
692 COMBA_STORE(C->dp[50]);
693 /* 51 */
694 COMBA_FORWARD;
695 MULADD(at[20], at[63]); MULADD(at[21], at[62]); MULADD(at[22], at[61]); MULADD(at[23], at[60]); MULADD(at[24], at[59]); MULADD(at[25], at[58]); MULADD(at[26], at[57]); MULADD(at[27], at[56]); MULADD(at[28], at[55]); MULADD(at[29], at[54]); MULADD(at[30], at[53]); MULADD(at[31], at[52]);
696 COMBA_STORE(C->dp[51]);
697 /* 52 */
698 COMBA_FORWARD;
699 MULADD(at[21], at[63]); MULADD(at[22], at[62]); MULADD(at[23], at[61]); MULADD(at[24], at[60]); MULADD(at[25], at[59]); MULADD(at[26], at[58]); MULADD(at[27], at[57]); MULADD(at[28], at[56]); MULADD(at[29], at[55]); MULADD(at[30], at[54]); MULADD(at[31], at[53]);
700 COMBA_STORE(C->dp[52]);
701 /* 53 */
702 COMBA_FORWARD;
703 MULADD(at[22], at[63]); MULADD(at[23], at[62]); MULADD(at[24], at[61]); MULADD(at[25], at[60]); MULADD(at[26], at[59]); MULADD(at[27], at[58]); MULADD(at[28], at[57]); MULADD(at[29], at[56]); MULADD(at[30], at[55]); MULADD(at[31], at[54]);
704 COMBA_STORE(C->dp[53]);
705 /* 54 */
706 COMBA_FORWARD;
707 MULADD(at[23], at[63]); MULADD(at[24], at[62]); MULADD(at[25], at[61]); MULADD(at[26], at[60]); MULADD(at[27], at[59]); MULADD(at[28], at[58]); MULADD(at[29], at[57]); MULADD(at[30], at[56]); MULADD(at[31], at[55]);
708 COMBA_STORE(C->dp[54]);
709
710 /* early out at 56 digits, 56*32==1792, or two 896 bit operands */
711 if (out_size <= 56) { COMBA_STORE2(C->dp[55]); C->used = 56; C->sign = A->sign ^ B->sign; pstm_clamp(C); COMBA_FINI; return PSTM_OKAY; }
712
713 /* 55 */
714 COMBA_FORWARD;
715 MULADD(at[24], at[63]); MULADD(at[25], at[62]); MULADD(at[26], at[61]); MULADD(at[27], at[60]); MULADD(at[28], at[59]); MULADD(at[29], at[58]); MULADD(at[30], at[57]); MULADD(at[31], at[56]);
716 COMBA_STORE(C->dp[55]);
717 /* 56 */
718 COMBA_FORWARD;
719 MULADD(at[25], at[63]); MULADD(at[26], at[62]); MULADD(at[27], at[61]); MULADD(at[28], at[60]); MULADD(at[29], at[59]); MULADD(at[30], at[58]); MULADD(at[31], at[57]);
720 COMBA_STORE(C->dp[56]);
721 /* 57 */
722 COMBA_FORWARD;
723 MULADD(at[26], at[63]); MULADD(at[27], at[62]); MULADD(at[28], at[61]); MULADD(at[29], at[60]); MULADD(at[30], at[59]); MULADD(at[31], at[58]);
724 COMBA_STORE(C->dp[57]);
725 /* 58 */
726 COMBA_FORWARD;
727 MULADD(at[27], at[63]); MULADD(at[28], at[62]); MULADD(at[29], at[61]); MULADD(at[30], at[60]); MULADD(at[31], at[59]);
728 COMBA_STORE(C->dp[58]);
729 /* 59 */
730 COMBA_FORWARD;
731 MULADD(at[28], at[63]); MULADD(at[29], at[62]); MULADD(at[30], at[61]); MULADD(at[31], at[60]);
732 COMBA_STORE(C->dp[59]);
733 /* 60 */
734 COMBA_FORWARD;
735 MULADD(at[29], at[63]); MULADD(at[30], at[62]); MULADD(at[31], at[61]);
736 COMBA_STORE(C->dp[60]);
737 /* 61 */
738 COMBA_FORWARD;
739 MULADD(at[30], at[63]); MULADD(at[31], at[62]);
740 COMBA_STORE(C->dp[61]);
741 /* 62 */
742 COMBA_FORWARD;
743 MULADD(at[31], at[63]);
744 COMBA_STORE(C->dp[62]);
745 COMBA_STORE2(C->dp[63]);
746 C->used = 64;
747 C->sign = A->sign ^ B->sign;
748 pstm_clamp(C);
749 COMBA_FINI;
750 return PSTM_OKAY;
751}
752#endif /* USE_2048_KEY_SPEED_OPTIMIZATIONS */
753
754/******************************************************************************/
755
756int32 pstm_mul_comba(psPool_t *pool, pstm_int *A, pstm_int *B, pstm_int *C,
757 pstm_digit *paD, uint32 paDlen)
758{
759#ifdef USE_1024_KEY_SPEED_OPTIMIZATIONS
760 if (A->used == 16 && B->used == 16) {
761 return pstm_mul_comba16(A, B, C);
762 } else {
763#ifdef USE_2048_KEY_SPEED_OPTIMIZATIONS
764 if (A->used == 32 && B->used == 32) {
765 return pstm_mul_comba32(A, B, C);
766 }
767#endif /* USE_2048_KEY_SPEED_OPTIMIZATIONS */
768 return pstm_mul_comba_gen(pool, A, B, C, paD, paDlen);
769 }
770#else
771#ifdef USE_2048_KEY_SPEED_OPTIMIZATIONS
772 if (A->used == 32 && B->used == 32) {
773 return pstm_mul_comba32(A, B, C);
774 }
775#endif /* USE_2048_KEY_SPEED_OPTIMIZATIONS */
776 return pstm_mul_comba_gen(pool, A, B, C, paD, paDlen);
777#endif
778}
779
780#endif /* !DISABLE_PSTM */
781/******************************************************************************/
diff --git a/networking/tls_pstm_sqr_comba.c b/networking/tls_pstm_sqr_comba.c
new file mode 100644
index 000000000..36cb9ea97
--- /dev/null
+++ b/networking/tls_pstm_sqr_comba.c
@@ -0,0 +1,1111 @@
1/*
2 * Copyright (C) 2017 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6#include "tls.h"
7
8/* The file is taken almost verbatim from matrixssl-3-7-2b-open/crypto/math/.
9 * Changes are flagged with //bbox
10 */
11
12/**
13 * @file pstm_sqr_comba.c
14 * @version 33ef80f (HEAD, tag: MATRIXSSL-3-7-2-OPEN, tag: MATRIXSSL-3-7-2-COMM, origin/master, origin/HEAD, master)
15 *
16 * Multiprecision Squaring with Comba technique.
17 */
18/*
19 * Copyright (c) 2013-2015 INSIDE Secure Corporation
20 * Copyright (c) PeerSec Networks, 2002-2011
21 * All Rights Reserved
22 *
23 * The latest version of this code is available at http://www.matrixssl.org
24 *
25 * This software is open source; you can redistribute it and/or modify
26 * it under the terms of the GNU General Public License as published by
27 * the Free Software Foundation; either version 2 of the License, or
28 * (at your option) any later version.
29 *
30 * This General Public License does NOT permit incorporating this software
31 * into proprietary programs. If you are unable to comply with the GPL, a
32 * commercial license for this software may be purchased from INSIDE at
33 * http://www.insidesecure.com/eng/Company/Locations
34 *
35 * This program is distributed in WITHOUT ANY WARRANTY; without even the
36 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
37 * See the GNU General Public License for more details.
38 *
39 * You should have received a copy of the GNU General Public License
40 * along with this program; if not, write to the Free Software
41 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
42 * http://www.gnu.org/copyleft/gpl.html
43 */
44/******************************************************************************/
45
46//bbox
47//#include "../cryptoApi.h"
48#ifndef DISABLE_PSTM
49
50/******************************************************************************/
51#if defined(PSTM_X86)
52/* x86-32 optimized for 32 bit platforms. For 64 bit mode use X86_64 instead */
53#if !defined(__GNUC__) || !defined(__i386__)
54#error "PSTM_X86 option requires GCC and 32 bit mode x86 processor"
55#endif
56//#pragma message ("Using 32 bit x86 Assembly Optimizations")
57
58#define COMBA_START
59
60#define CLEAR_CARRY \
61 c0 = c1 = c2 = 0;
62
63#define COMBA_STORE(x) \
64 x = c0;
65
66#define COMBA_STORE2(x) \
67 x = c1;
68
69#define CARRY_FORWARD \
70 do { c0 = c1; c1 = c2; c2 = 0; } while (0);
71
72#define COMBA_FINI
73
74#define SQRADD(i, j) \
75asm( \
76 "movl %6,%%eax \n\t" \
77 "mull %%eax \n\t" \
78 "addl %%eax,%0 \n\t" \
79 "adcl %%edx,%1 \n\t" \
80 "adcl $0,%2 \n\t" \
81 :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i) :"%eax","%edx","%cc");
82
83#define SQRADD2(i, j) \
84asm( \
85 "movl %6,%%eax \n\t" \
86 "mull %7 \n\t" \
87 "addl %%eax,%0 \n\t" \
88 "adcl %%edx,%1 \n\t" \
89 "adcl $0,%2 \n\t" \
90 "addl %%eax,%0 \n\t" \
91 "adcl %%edx,%1 \n\t" \
92 "adcl $0,%2 \n\t" \
93 :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j) :"%eax","%edx","%cc");
94
95#define SQRADDSC(i, j) \
96asm( \
97 "movl %6,%%eax \n\t" \
98 "mull %7 \n\t" \
99 "movl %%eax,%0 \n\t" \
100 "movl %%edx,%1 \n\t" \
101 "xorl %2,%2 \n\t" \
102 :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%eax","%edx","%cc");
103
104#define SQRADDAC(i, j) \
105asm( \
106 "movl %6,%%eax \n\t" \
107 "mull %7 \n\t" \
108 "addl %%eax,%0 \n\t" \
109 "adcl %%edx,%1 \n\t" \
110 "adcl $0,%2 \n\t" \
111 :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%eax","%edx","%cc");
112
113#define SQRADDDB \
114asm( \
115 "addl %6,%0 \n\t" \
116 "adcl %7,%1 \n\t" \
117 "adcl %8,%2 \n\t" \
118 "addl %6,%0 \n\t" \
119 "adcl %7,%1 \n\t" \
120 "adcl %8,%2 \n\t" \
121 :"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(sc0), "r"(sc1), "r"(sc2) : "%cc");
122
123/******************************************************************************/
124#elif defined(PSTM_X86_64)
125/* x86-64 optimized */
126#if !defined(__GNUC__) || !defined(__x86_64__) || !defined(PSTM_64BIT)
127#error "PSTM_X86_64 option requires PSTM_64BIT, GCC and 64 bit mode x86 processor"
128#endif
129//#pragma message ("Using 64 bit x86_64 Assembly Optimizations")
130
131#define COMBA_START
132
133#define CLEAR_CARRY \
134c0 = c1 = c2 = 0;
135
136#define COMBA_STORE(x) \
137x = c0;
138
139#define COMBA_STORE2(x) \
140x = c1;
141
142#define CARRY_FORWARD \
143do { c0 = c1; c1 = c2; c2 = 0; } while (0);
144
145#define COMBA_FINI
146
147#define SQRADD(i, j) \
148asm( \
149 "movq %6,%%rax \n\t" \
150 "mulq %%rax \n\t" \
151 "addq %%rax,%0 \n\t" \
152 "adcq %%rdx,%1 \n\t" \
153 "adcq $0,%2 \n\t" \
154 :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "g"(i) :"%rax","%rdx","cc");
155
156#define SQRADD2(i, j) \
157asm( \
158 "movq %6,%%rax \n\t" \
159 "mulq %7 \n\t" \
160 "addq %%rax,%0 \n\t" \
161 "adcq %%rdx,%1 \n\t" \
162 "adcq $0,%2 \n\t" \
163 "addq %%rax,%0 \n\t" \
164 "adcq %%rdx,%1 \n\t" \
165 "adcq $0,%2 \n\t" \
166 :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "g"(i), "g"(j) :"%rax","%rdx","cc");
167
168#define SQRADDSC(i, j) \
169asm( \
170 "movq %6,%%rax \n\t" \
171 "mulq %7 \n\t" \
172 "movq %%rax,%0 \n\t" \
173 "movq %%rdx,%1 \n\t" \
174 "xorq %2,%2 \n\t" \
175 :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%rax","%rdx","cc");
176
177#define SQRADDAC(i, j) \
178asm( \
179 "movq %6,%%rax \n\t" \
180 "mulq %7 \n\t" \
181 "addq %%rax,%0 \n\t" \
182 "adcq %%rdx,%1 \n\t" \
183 "adcq $0,%2 \n\t" \
184 :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%rax","%rdx","cc");
185
186#define SQRADDDB \
187asm( \
188 "addq %6,%0 \n\t" \
189 "adcq %7,%1 \n\t" \
190 "adcq %8,%2 \n\t" \
191 "addq %6,%0 \n\t" \
192 "adcq %7,%1 \n\t" \
193 "adcq %8,%2 \n\t" \
194 :"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(sc0), "r"(sc1), "r"(sc2) : "cc");
195
196/******************************************************************************/
197#elif defined(PSTM_ARM)
198/* ARM code */
199//#pragma message ("Using 32 bit ARM Assembly Optimizations")
200
201#define COMBA_START
202
203#define CLEAR_CARRY \
204c0 = c1 = c2 = 0;
205
206#define COMBA_STORE(x) \
207x = c0;
208
209#define COMBA_STORE2(x) \
210x = c1;
211
212#define CARRY_FORWARD \
213do { c0 = c1; c1 = c2; c2 = 0; } while (0);
214
215#define COMBA_FINI
216
217/* multiplies point i and j, updates carry "c1" and digit c2 */
218#define SQRADD(i, j) \
219asm( \
220" UMULL r0,r1,%6,%6 \n\t" \
221" ADDS %0,%0,r0 \n\t" \
222" ADCS %1,%1,r1 \n\t" \
223" ADC %2,%2,#0 \n\t" \
224:"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i) : "r0", "r1", "%cc");
225
226/* for squaring some of the terms are doubled... */
227#define SQRADD2(i, j) \
228asm( \
229" UMULL r0,r1,%6,%7 \n\t" \
230" ADDS %0,%0,r0 \n\t" \
231" ADCS %1,%1,r1 \n\t" \
232" ADC %2,%2,#0 \n\t" \
233" ADDS %0,%0,r0 \n\t" \
234" ADCS %1,%1,r1 \n\t" \
235" ADC %2,%2,#0 \n\t" \
236:"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j) : "r0", "r1", "%cc");
237
238#define SQRADDSC(i, j) \
239asm( \
240" UMULL %0,%1,%6,%7 \n\t" \
241" SUB %2,%2,%2 \n\t" \
242:"=r"(sc0), "=r"(sc1), "=r"(sc2) : "0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j) : "%cc");
243
244#define SQRADDAC(i, j) \
245asm( \
246" UMULL r0,r1,%6,%7 \n\t" \
247" ADDS %0,%0,r0 \n\t" \
248" ADCS %1,%1,r1 \n\t" \
249" ADC %2,%2,#0 \n\t" \
250:"=r"(sc0), "=r"(sc1), "=r"(sc2) : "0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j) : "r0", "r1", "%cc");
251
252#define SQRADDDB \
253asm( \
254" ADDS %0,%0,%3 \n\t" \
255" ADCS %1,%1,%4 \n\t" \
256" ADC %2,%2,%5 \n\t" \
257" ADDS %0,%0,%3 \n\t" \
258" ADCS %1,%1,%4 \n\t" \
259" ADC %2,%2,%5 \n\t" \
260:"=r"(c0), "=r"(c1), "=r"(c2) : "r"(sc0), "r"(sc1), "r"(sc2), "0"(c0), "1"(c1), "2"(c2) : "%cc");
261
262/******************************************************************************/
263#elif defined(PSTM_MIPS)
264/* MIPS32 */
265//#pragma message ("Using 32 bit MIPS Assembly Optimizations")
266
267#define COMBA_START
268
269#define CLEAR_CARRY \
270c0 = c1 = c2 = 0;
271
272#define COMBA_STORE(x) \
273x = c0;
274
275#define COMBA_STORE2(x) \
276x = c1;
277
278#define CARRY_FORWARD \
279do { c0 = c1; c1 = c2; c2 = 0; } while (0);
280
281#define COMBA_FINI
282
283/* multiplies point i and j, updates carry "c1" and digit c2 */
284#define SQRADD(i, j) \
285asm( \
286 " multu %6,%6 \n\t" \
287 " mflo $12 \n\t" \
288 " mfhi $13 \n\t" \
289 " addu %0,%0,$12 \n\t" \
290 " sltu $12,%0,$12 \n\t" \
291 " addu %1,%1,$13 \n\t" \
292 " sltu $13,%1,$13 \n\t" \
293 " addu %1,%1,$12 \n\t" \
294 " sltu $12,%1,$12 \n\t" \
295 " addu %2,%2,$13 \n\t" \
296 " addu %2,%2,$12 \n\t" \
297 :"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i):"$12","$13");
298
299/* for squaring some of the terms are doubled... */
300#define SQRADD2(i, j) \
301asm( \
302 " multu %6,%7 \n\t" \
303 " mflo $12 \n\t" \
304 " mfhi $13 \n\t" \
305 \
306 " addu %0,%0,$12 \n\t" \
307 " sltu $14,%0,$12 \n\t" \
308 " addu %1,%1,$13 \n\t" \
309 " sltu $15,%1,$13 \n\t" \
310 " addu %1,%1,$14 \n\t" \
311 " sltu $14,%1,$14 \n\t" \
312 " addu %2,%2,$15 \n\t" \
313 " addu %2,%2,$14 \n\t" \
314 \
315 " addu %0,%0,$12 \n\t" \
316 " sltu $14,%0,$12 \n\t" \
317 " addu %1,%1,$13 \n\t" \
318 " sltu $15,%1,$13 \n\t" \
319 " addu %1,%1,$14 \n\t" \
320 " sltu $14,%1,$14 \n\t" \
321 " addu %2,%2,$15 \n\t" \
322 " addu %2,%2,$14 \n\t" \
323 :"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"$12", "$13", "$14", "$15");
324
325#define SQRADDSC(i, j) \
326asm( \
327 " multu %6,%7 \n\t" \
328 " mflo %0 \n\t" \
329 " mfhi %1 \n\t" \
330 " xor %2,%2,%2 \n\t" \
331 :"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i),"r"(j) : "%cc");
332
333#define SQRADDAC(i, j) \
334asm( \
335 " multu %6,%7 \n\t" \
336 " mflo $12 \n\t" \
337 " mfhi $13 \n\t" \
338 " addu %0,%0,$12 \n\t" \
339 " sltu $12,%0,$12 \n\t" \
340 " addu %1,%1,$13 \n\t" \
341 " sltu $13,%1,$13 \n\t" \
342 " addu %1,%1,$12 \n\t" \
343 " sltu $12,%1,$12 \n\t" \
344 " addu %2,%2,$13 \n\t" \
345 " addu %2,%2,$12 \n\t" \
346 :"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j):"$12", "$13", "$14");
347
348#define SQRADDDB \
349asm( \
350 " addu %0,%0,%3 \n\t" \
351 " sltu $10,%0,%3 \n\t" \
352 " addu %1,%1,$10 \n\t" \
353 " sltu $10,%1,$10 \n\t" \
354 " addu %1,%1,%4 \n\t" \
355 " sltu $11,%1,%4 \n\t" \
356 " addu %2,%2,$10 \n\t" \
357 " addu %2,%2,$11 \n\t" \
358 " addu %2,%2,%5 \n\t" \
359 \
360 " addu %0,%0,%3 \n\t" \
361 " sltu $10,%0,%3 \n\t" \
362 " addu %1,%1,$10 \n\t" \
363 " sltu $10,%1,$10 \n\t" \
364 " addu %1,%1,%4 \n\t" \
365 " sltu $11,%1,%4 \n\t" \
366 " addu %2,%2,$10 \n\t" \
367 " addu %2,%2,$11 \n\t" \
368 " addu %2,%2,%5 \n\t" \
369 :"=r"(c0), "=r"(c1), "=r"(c2) : "r"(sc0), "r"(sc1), "r"(sc2), "0"(c0), "1"(c1), "2"(c2) : "$10", "$11");
370
371#else
372/******************************************************************************/
373#define PSTM_ISO
374/* ISO C portable code */
375
376#define COMBA_START
377
378#define CLEAR_CARRY \
379 c0 = c1 = c2 = 0;
380
381#define COMBA_STORE(x) \
382 x = c0;
383
384#define COMBA_STORE2(x) \
385 x = c1;
386
387#define CARRY_FORWARD \
388 do { c0 = c1; c1 = c2; c2 = 0; } while (0);
389
390#define COMBA_FINI
391
392/* multiplies point i and j, updates carry "c1" and digit c2 */
393#define SQRADD(i, j) \
394 do { pstm_word t; \
395 t = c0 + ((pstm_word)i) * ((pstm_word)j); c0 = (pstm_digit)t; \
396 t = c1 + (t >> DIGIT_BIT); \
397 c1 = (pstm_digit)t; c2 += (pstm_digit)(t >> DIGIT_BIT); \
398 } while (0);
399
400
401/* for squaring some of the terms are doubled... */
402#define SQRADD2(i, j) \
403 do { pstm_word t; \
404 t = ((pstm_word)i) * ((pstm_word)j); \
405 tt = (pstm_word)c0 + t; c0 = (pstm_digit)tt; \
406 tt = (pstm_word)c1 + (tt >> DIGIT_BIT); \
407 c1 = (pstm_digit)tt; c2 += (pstm_digit)(tt >> DIGIT_BIT); \
408 tt = (pstm_word)c0 + t; c0 = (pstm_digit)tt; \
409 tt = (pstm_word)c1 + (tt >> DIGIT_BIT); \
410 c1 = (pstm_digit)tt; c2 += (pstm_digit)(tt >> DIGIT_BIT); \
411 } while (0);
412
413#define SQRADDSC(i, j) \
414 do { pstm_word t; \
415 t = ((pstm_word)i) * ((pstm_word)j); \
416 sc0 = (pstm_digit)t; sc1 = (pstm_digit)(t >> DIGIT_BIT); sc2 = 0; \
417 } while (0);
418
419#define SQRADDAC(i, j) \
420 do { pstm_word t; \
421 t = ((pstm_word)sc0) + ((pstm_word)i) * ((pstm_word)j); \
422 sc0 = (pstm_digit)t; \
423 t = ((pstm_word)sc1) + (t >> DIGIT_BIT); sc1 = (pstm_digit)t; \
424 sc2 += (pstm_digit)(t >> DIGIT_BIT); \
425 } while (0);
426
427#define SQRADDDB \
428 do { pstm_word t; \
429 t = ((pstm_word)sc0) + ((pstm_word)sc0) + ((pstm_word)c0); \
430 c0 = (pstm_digit)t; \
431 t = ((pstm_word)sc1) + ((pstm_word)sc1) + c1 + (t >> DIGIT_BIT); \
432 c1 = (pstm_digit)t; \
433 c2 = c2 + sc2 + sc2 + (pstm_digit)(t >> DIGIT_BIT); \
434 } while (0);
435
436#endif /* ISO_C */
437
438/******************************************************************************/
439/*
440 Non-unrolled comba squarer
441 */
442//bbox: pool unused
443#define pstm_sqr_comba_gen(pool, A, B, paD, paDlen) \
444 pstm_sqr_comba_gen( A, B, paD, paDlen)
445static int32 pstm_sqr_comba_gen(psPool_t *pool, pstm_int *A, pstm_int *B,
446 pstm_digit *paD, uint32 paDlen)
447{
448 int16 paDfail, pa;
449 int32 ix, iz;
450 pstm_digit c0, c1, c2, *dst;
451#ifdef PSTM_ISO
452 pstm_word tt;
453#endif
454
455 paDfail = 0;
456 /* get size of output and trim */
457 pa = A->used + A->used;
458
459 /* number of output digits to produce */
460 COMBA_START;
461 CLEAR_CARRY;
462/*
463 If b is not large enough grow it and continue
464*/
465 if (B->alloc < pa) {
466 if (pstm_grow(B, pa) != PSTM_OKAY) {
467 return PS_MEM_FAIL;
468 }
469 }
470 if (paD != NULL) {
471 if (paDlen < (sizeof(pstm_digit) * pa)) {
472 paDfail = 1; /* have a paD, but it's not big enough */
473 dst = xzalloc(sizeof(pstm_digit) * pa);//bbox
474 } else {
475 dst = paD;
476 memset(dst, 0x0, paDlen);
477 }
478 } else {
479 dst = xzalloc(sizeof(pstm_digit) * pa);//bbox
480 }
481
482 for (ix = 0; ix < pa; ix++) {
483 int32 tx, ty, iy;
484 pstm_digit *tmpy, *tmpx;
485
486 /* get offsets into the two bignums */
487 ty = min(A->used-1, ix);
488 tx = ix - ty;
489
490 /* setup temp aliases */
491 tmpx = A->dp + tx;
492 tmpy = A->dp + ty;
493
494/*
495 This is the number of times the loop will iterate,
496 while (tx++ < a->used && ty-- >= 0) { ... }
497*/
498 iy = min(A->used-tx, ty+1);
499
500/*
501 now for squaring tx can never equal ty. We halve the distance since
502 they approach at a rate of 2x and we have to round because odd cases
503 need to be executed
504*/
505 iy = min(iy, (ty-tx+1)>>1);
506
507 /* forward carries */
508 CARRY_FORWARD;
509
510 /* execute loop */
511 for (iz = 0; iz < iy; iz++) {
512 SQRADD2(*tmpx++, *tmpy--);
513 }
514
515 /* even columns have the square term in them */
516 if ((ix&1) == 0) {
517 SQRADD(A->dp[ix>>1], A->dp[ix>>1]);
518 }
519
520 /* store it */
521 COMBA_STORE(dst[ix]);
522 }
523
524 COMBA_FINI;
525/*
526 setup dest
527 */
528 iz = B->used;
529 B->used = pa;
530 {
531 pstm_digit *tmpc;
532 tmpc = B->dp;
533 for (ix = 0; ix < pa; ix++) {
534 *tmpc++ = dst[ix];
535 }
536 /* clear unused digits (that existed in the old copy of c) */
537 for (; ix < iz; ix++) {
538 *tmpc++ = 0;
539 }
540 }
541 pstm_clamp(B);
542
543 if ((paD == NULL) || paDfail == 1) {
544 psFree(dst, pool);
545 }
546 return PS_SUCCESS;
547}
548
549/******************************************************************************/
550/*
551 Unrolled Comba loop for 1024 bit keys
552 */
553#ifdef USE_1024_KEY_SPEED_OPTIMIZATIONS
554static int32 pstm_sqr_comba16(pstm_int *A, pstm_int *B)
555{
556 pstm_digit *a, b[32], c0, c1, c2, sc0, sc1, sc2;
557#ifdef PSTM_ISO
558 pstm_word tt;
559#endif
560
561 if (B->alloc < 32) {
562 if (pstm_grow(B, 32) != PSTM_OKAY) {
563 return PS_MEM_FAIL;
564 }
565 }
566 a = A->dp;
567 sc0 = sc1 = sc2 = 0;
568
569 COMBA_START;
570
571 /* clear carries */
572 CLEAR_CARRY;
573
574 /* output 0 */
575 SQRADD(a[0],a[0]);
576 COMBA_STORE(b[0]);
577
578 /* output 1 */
579 CARRY_FORWARD;
580 SQRADD2(a[0], a[1]);
581 COMBA_STORE(b[1]);
582
583 /* output 2 */
584 CARRY_FORWARD;
585 SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]);
586 COMBA_STORE(b[2]);
587
588 /* output 3 */
589 CARRY_FORWARD;
590 SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]);
591 COMBA_STORE(b[3]);
592
593 /* output 4 */
594 CARRY_FORWARD;
595 SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]);
596 COMBA_STORE(b[4]);
597
598 /* output 5 */
599 CARRY_FORWARD;
600 SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB;
601 COMBA_STORE(b[5]);
602
603 /* output 6 */
604 CARRY_FORWARD;
605 SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]);
606 COMBA_STORE(b[6]);
607
608 /* output 7 */
609 CARRY_FORWARD;
610 SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB;
611 COMBA_STORE(b[7]);
612
613 /* output 8 */
614 CARRY_FORWARD;
615 SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]);
616 COMBA_STORE(b[8]);
617
618 /* output 9 */
619 CARRY_FORWARD;
620 SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB;
621 COMBA_STORE(b[9]);
622
623 /* output 10 */
624 CARRY_FORWARD;
625 SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]);
626 COMBA_STORE(b[10]);
627
628 /* output 11 */
629 CARRY_FORWARD;
630 SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB;
631 COMBA_STORE(b[11]);
632
633 /* output 12 */
634 CARRY_FORWARD;
635 SQRADDSC(a[0], a[12]); SQRADDAC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]);
636 COMBA_STORE(b[12]);
637
638 /* output 13 */
639 CARRY_FORWARD;
640 SQRADDSC(a[0], a[13]); SQRADDAC(a[1], a[12]); SQRADDAC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB;
641 COMBA_STORE(b[13]);
642
643 /* output 14 */
644 CARRY_FORWARD;
645 SQRADDSC(a[0], a[14]); SQRADDAC(a[1], a[13]); SQRADDAC(a[2], a[12]); SQRADDAC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]);
646 COMBA_STORE(b[14]);
647
648 /* output 15 */
649 CARRY_FORWARD;
650 SQRADDSC(a[0], a[15]); SQRADDAC(a[1], a[14]); SQRADDAC(a[2], a[13]); SQRADDAC(a[3], a[12]); SQRADDAC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB;
651 COMBA_STORE(b[15]);
652
653 /* output 16 */
654 CARRY_FORWARD;
655 SQRADDSC(a[1], a[15]); SQRADDAC(a[2], a[14]); SQRADDAC(a[3], a[13]); SQRADDAC(a[4], a[12]); SQRADDAC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]);
656 COMBA_STORE(b[16]);
657
658 /* output 17 */
659 CARRY_FORWARD;
660 SQRADDSC(a[2], a[15]); SQRADDAC(a[3], a[14]); SQRADDAC(a[4], a[13]); SQRADDAC(a[5], a[12]); SQRADDAC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB;
661 COMBA_STORE(b[17]);
662
663 /* output 18 */
664 CARRY_FORWARD;
665 SQRADDSC(a[3], a[15]); SQRADDAC(a[4], a[14]); SQRADDAC(a[5], a[13]); SQRADDAC(a[6], a[12]); SQRADDAC(a[7], a[11]); SQRADDAC(a[8], a[10]); SQRADDDB; SQRADD(a[9], a[9]);
666 COMBA_STORE(b[18]);
667
668 /* output 19 */
669 CARRY_FORWARD;
670 SQRADDSC(a[4], a[15]); SQRADDAC(a[5], a[14]); SQRADDAC(a[6], a[13]); SQRADDAC(a[7], a[12]); SQRADDAC(a[8], a[11]); SQRADDAC(a[9], a[10]); SQRADDDB;
671 COMBA_STORE(b[19]);
672
673 /* output 20 */
674 CARRY_FORWARD;
675 SQRADDSC(a[5], a[15]); SQRADDAC(a[6], a[14]); SQRADDAC(a[7], a[13]); SQRADDAC(a[8], a[12]); SQRADDAC(a[9], a[11]); SQRADDDB; SQRADD(a[10], a[10]);
676 COMBA_STORE(b[20]);
677
678 /* output 21 */
679 CARRY_FORWARD;
680 SQRADDSC(a[6], a[15]); SQRADDAC(a[7], a[14]); SQRADDAC(a[8], a[13]); SQRADDAC(a[9], a[12]); SQRADDAC(a[10], a[11]); SQRADDDB;
681 COMBA_STORE(b[21]);
682
683 /* output 22 */
684 CARRY_FORWARD;
685 SQRADDSC(a[7], a[15]); SQRADDAC(a[8], a[14]); SQRADDAC(a[9], a[13]); SQRADDAC(a[10], a[12]); SQRADDDB; SQRADD(a[11], a[11]);
686 COMBA_STORE(b[22]);
687
688 /* output 23 */
689 CARRY_FORWARD;
690 SQRADDSC(a[8], a[15]); SQRADDAC(a[9], a[14]); SQRADDAC(a[10], a[13]); SQRADDAC(a[11], a[12]); SQRADDDB;
691 COMBA_STORE(b[23]);
692
693 /* output 24 */
694 CARRY_FORWARD;
695 SQRADDSC(a[9], a[15]); SQRADDAC(a[10], a[14]); SQRADDAC(a[11], a[13]); SQRADDDB; SQRADD(a[12], a[12]);
696 COMBA_STORE(b[24]);
697
698 /* output 25 */
699 CARRY_FORWARD;
700 SQRADDSC(a[10], a[15]); SQRADDAC(a[11], a[14]); SQRADDAC(a[12], a[13]); SQRADDDB;
701 COMBA_STORE(b[25]);
702
703 /* output 26 */
704 CARRY_FORWARD;
705 SQRADD2(a[11], a[15]); SQRADD2(a[12], a[14]); SQRADD(a[13], a[13]);
706 COMBA_STORE(b[26]);
707
708 /* output 27 */
709 CARRY_FORWARD;
710 SQRADD2(a[12], a[15]); SQRADD2(a[13], a[14]);
711 COMBA_STORE(b[27]);
712
713 /* output 28 */
714 CARRY_FORWARD;
715 SQRADD2(a[13], a[15]); SQRADD(a[14], a[14]);
716 COMBA_STORE(b[28]);
717
718 /* output 29 */
719 CARRY_FORWARD;
720 SQRADD2(a[14], a[15]);
721 COMBA_STORE(b[29]);
722
723 /* output 30 */
724 CARRY_FORWARD;
725 SQRADD(a[15], a[15]);
726 COMBA_STORE(b[30]);
727 COMBA_STORE2(b[31]);
728 COMBA_FINI;
729
730 B->used = 32;
731 B->sign = PSTM_ZPOS;
732 memcpy(B->dp, b, 32 * sizeof(pstm_digit));
733 pstm_clamp(B);
734 return PSTM_OKAY;
735}
736#endif /* USE_1024_KEY_SPEED_OPTIMIZATIONS */
737
738
739#ifdef USE_2048_KEY_SPEED_OPTIMIZATIONS
740static int32 pstm_sqr_comba32(pstm_int *A, pstm_int *B)
741{
742 pstm_digit *a, b[64], c0, c1, c2, sc0, sc1, sc2;
743#ifdef PSTM_ISO
744 pstm_word tt;
745#endif
746
747 if (B->alloc < 64) {
748 if (pstm_grow(B, 64) != PSTM_OKAY) {
749 return PS_MEM_FAIL;
750 }
751 }
752 sc0 = sc1 = sc2 = 0;
753 a = A->dp;
754 COMBA_START;
755
756 /* clear carries */
757 CLEAR_CARRY;
758
759 /* output 0 */
760 SQRADD(a[0],a[0]);
761 COMBA_STORE(b[0]);
762
763 /* output 1 */
764 CARRY_FORWARD;
765 SQRADD2(a[0], a[1]);
766 COMBA_STORE(b[1]);
767
768 /* output 2 */
769 CARRY_FORWARD;
770 SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]);
771 COMBA_STORE(b[2]);
772
773 /* output 3 */
774 CARRY_FORWARD;
775 SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]);
776 COMBA_STORE(b[3]);
777
778 /* output 4 */
779 CARRY_FORWARD;
780 SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]);
781 COMBA_STORE(b[4]);
782
783 /* output 5 */
784 CARRY_FORWARD;
785 SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB;
786 COMBA_STORE(b[5]);
787
788 /* output 6 */
789 CARRY_FORWARD;
790 SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]);
791 COMBA_STORE(b[6]);
792
793 /* output 7 */
794 CARRY_FORWARD;
795 SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB;
796 COMBA_STORE(b[7]);
797
798 /* output 8 */
799 CARRY_FORWARD;
800 SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]);
801 COMBA_STORE(b[8]);
802
803 /* output 9 */
804 CARRY_FORWARD;
805 SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB;
806 COMBA_STORE(b[9]);
807
808 /* output 10 */
809 CARRY_FORWARD;
810 SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]);
811 COMBA_STORE(b[10]);
812
813 /* output 11 */
814 CARRY_FORWARD;
815 SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB;
816 COMBA_STORE(b[11]);
817
818 /* output 12 */
819 CARRY_FORWARD;
820 SQRADDSC(a[0], a[12]); SQRADDAC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]);
821 COMBA_STORE(b[12]);
822
823 /* output 13 */
824 CARRY_FORWARD;
825 SQRADDSC(a[0], a[13]); SQRADDAC(a[1], a[12]); SQRADDAC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB;
826 COMBA_STORE(b[13]);
827
828 /* output 14 */
829 CARRY_FORWARD;
830 SQRADDSC(a[0], a[14]); SQRADDAC(a[1], a[13]); SQRADDAC(a[2], a[12]); SQRADDAC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]);
831 COMBA_STORE(b[14]);
832
833 /* output 15 */
834 CARRY_FORWARD;
835 SQRADDSC(a[0], a[15]); SQRADDAC(a[1], a[14]); SQRADDAC(a[2], a[13]); SQRADDAC(a[3], a[12]); SQRADDAC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB;
836 COMBA_STORE(b[15]);
837
838 /* output 16 */
839 CARRY_FORWARD;
840 SQRADDSC(a[0], a[16]); SQRADDAC(a[1], a[15]); SQRADDAC(a[2], a[14]); SQRADDAC(a[3], a[13]); SQRADDAC(a[4], a[12]); SQRADDAC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]);
841 COMBA_STORE(b[16]);
842
843 /* output 17 */
844 CARRY_FORWARD;
845 SQRADDSC(a[0], a[17]); SQRADDAC(a[1], a[16]); SQRADDAC(a[2], a[15]); SQRADDAC(a[3], a[14]); SQRADDAC(a[4], a[13]); SQRADDAC(a[5], a[12]); SQRADDAC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB;
846 COMBA_STORE(b[17]);
847
848 /* output 18 */
849 CARRY_FORWARD;
850 SQRADDSC(a[0], a[18]); SQRADDAC(a[1], a[17]); SQRADDAC(a[2], a[16]); SQRADDAC(a[3], a[15]); SQRADDAC(a[4], a[14]); SQRADDAC(a[5], a[13]); SQRADDAC(a[6], a[12]); SQRADDAC(a[7], a[11]); SQRADDAC(a[8], a[10]); SQRADDDB; SQRADD(a[9], a[9]);
851 COMBA_STORE(b[18]);
852
853 /* output 19 */
854 CARRY_FORWARD;
855 SQRADDSC(a[0], a[19]); SQRADDAC(a[1], a[18]); SQRADDAC(a[2], a[17]); SQRADDAC(a[3], a[16]); SQRADDAC(a[4], a[15]); SQRADDAC(a[5], a[14]); SQRADDAC(a[6], a[13]); SQRADDAC(a[7], a[12]); SQRADDAC(a[8], a[11]); SQRADDAC(a[9], a[10]); SQRADDDB;
856 COMBA_STORE(b[19]);
857
858 /* output 20 */
859 CARRY_FORWARD;
860 SQRADDSC(a[0], a[20]); SQRADDAC(a[1], a[19]); SQRADDAC(a[2], a[18]); SQRADDAC(a[3], a[17]); SQRADDAC(a[4], a[16]); SQRADDAC(a[5], a[15]); SQRADDAC(a[6], a[14]); SQRADDAC(a[7], a[13]); SQRADDAC(a[8], a[12]); SQRADDAC(a[9], a[11]); SQRADDDB; SQRADD(a[10], a[10]);
861 COMBA_STORE(b[20]);
862
863 /* output 21 */
864 CARRY_FORWARD;
865 SQRADDSC(a[0], a[21]); SQRADDAC(a[1], a[20]); SQRADDAC(a[2], a[19]); SQRADDAC(a[3], a[18]); SQRADDAC(a[4], a[17]); SQRADDAC(a[5], a[16]); SQRADDAC(a[6], a[15]); SQRADDAC(a[7], a[14]); SQRADDAC(a[8], a[13]); SQRADDAC(a[9], a[12]); SQRADDAC(a[10], a[11]); SQRADDDB;
866 COMBA_STORE(b[21]);
867
868 /* output 22 */
869 CARRY_FORWARD;
870 SQRADDSC(a[0], a[22]); SQRADDAC(a[1], a[21]); SQRADDAC(a[2], a[20]); SQRADDAC(a[3], a[19]); SQRADDAC(a[4], a[18]); SQRADDAC(a[5], a[17]); SQRADDAC(a[6], a[16]); SQRADDAC(a[7], a[15]); SQRADDAC(a[8], a[14]); SQRADDAC(a[9], a[13]); SQRADDAC(a[10], a[12]); SQRADDDB; SQRADD(a[11], a[11]);
871 COMBA_STORE(b[22]);
872
873 /* output 23 */
874 CARRY_FORWARD;
875 SQRADDSC(a[0], a[23]); SQRADDAC(a[1], a[22]); SQRADDAC(a[2], a[21]); SQRADDAC(a[3], a[20]); SQRADDAC(a[4], a[19]); SQRADDAC(a[5], a[18]); SQRADDAC(a[6], a[17]); SQRADDAC(a[7], a[16]); SQRADDAC(a[8], a[15]); SQRADDAC(a[9], a[14]); SQRADDAC(a[10], a[13]); SQRADDAC(a[11], a[12]); SQRADDDB;
876 COMBA_STORE(b[23]);
877
878 /* output 24 */
879 CARRY_FORWARD;
880 SQRADDSC(a[0], a[24]); SQRADDAC(a[1], a[23]); SQRADDAC(a[2], a[22]); SQRADDAC(a[3], a[21]); SQRADDAC(a[4], a[20]); SQRADDAC(a[5], a[19]); SQRADDAC(a[6], a[18]); SQRADDAC(a[7], a[17]); SQRADDAC(a[8], a[16]); SQRADDAC(a[9], a[15]); SQRADDAC(a[10], a[14]); SQRADDAC(a[11], a[13]); SQRADDDB; SQRADD(a[12], a[12]);
881 COMBA_STORE(b[24]);
882
883 /* output 25 */
884 CARRY_FORWARD;
885 SQRADDSC(a[0], a[25]); SQRADDAC(a[1], a[24]); SQRADDAC(a[2], a[23]); SQRADDAC(a[3], a[22]); SQRADDAC(a[4], a[21]); SQRADDAC(a[5], a[20]); SQRADDAC(a[6], a[19]); SQRADDAC(a[7], a[18]); SQRADDAC(a[8], a[17]); SQRADDAC(a[9], a[16]); SQRADDAC(a[10], a[15]); SQRADDAC(a[11], a[14]); SQRADDAC(a[12], a[13]); SQRADDDB;
886 COMBA_STORE(b[25]);
887
888 /* output 26 */
889 CARRY_FORWARD;
890 SQRADDSC(a[0], a[26]); SQRADDAC(a[1], a[25]); SQRADDAC(a[2], a[24]); SQRADDAC(a[3], a[23]); SQRADDAC(a[4], a[22]); SQRADDAC(a[5], a[21]); SQRADDAC(a[6], a[20]); SQRADDAC(a[7], a[19]); SQRADDAC(a[8], a[18]); SQRADDAC(a[9], a[17]); SQRADDAC(a[10], a[16]); SQRADDAC(a[11], a[15]); SQRADDAC(a[12], a[14]); SQRADDDB; SQRADD(a[13], a[13]);
891 COMBA_STORE(b[26]);
892
893 /* output 27 */
894 CARRY_FORWARD;
895 SQRADDSC(a[0], a[27]); SQRADDAC(a[1], a[26]); SQRADDAC(a[2], a[25]); SQRADDAC(a[3], a[24]); SQRADDAC(a[4], a[23]); SQRADDAC(a[5], a[22]); SQRADDAC(a[6], a[21]); SQRADDAC(a[7], a[20]); SQRADDAC(a[8], a[19]); SQRADDAC(a[9], a[18]); SQRADDAC(a[10], a[17]); SQRADDAC(a[11], a[16]); SQRADDAC(a[12], a[15]); SQRADDAC(a[13], a[14]); SQRADDDB;
896 COMBA_STORE(b[27]);
897
898 /* output 28 */
899 CARRY_FORWARD;
900 SQRADDSC(a[0], a[28]); SQRADDAC(a[1], a[27]); SQRADDAC(a[2], a[26]); SQRADDAC(a[3], a[25]); SQRADDAC(a[4], a[24]); SQRADDAC(a[5], a[23]); SQRADDAC(a[6], a[22]); SQRADDAC(a[7], a[21]); SQRADDAC(a[8], a[20]); SQRADDAC(a[9], a[19]); SQRADDAC(a[10], a[18]); SQRADDAC(a[11], a[17]); SQRADDAC(a[12], a[16]); SQRADDAC(a[13], a[15]); SQRADDDB; SQRADD(a[14], a[14]);
901 COMBA_STORE(b[28]);
902
903 /* output 29 */
904 CARRY_FORWARD;
905 SQRADDSC(a[0], a[29]); SQRADDAC(a[1], a[28]); SQRADDAC(a[2], a[27]); SQRADDAC(a[3], a[26]); SQRADDAC(a[4], a[25]); SQRADDAC(a[5], a[24]); SQRADDAC(a[6], a[23]); SQRADDAC(a[7], a[22]); SQRADDAC(a[8], a[21]); SQRADDAC(a[9], a[20]); SQRADDAC(a[10], a[19]); SQRADDAC(a[11], a[18]); SQRADDAC(a[12], a[17]); SQRADDAC(a[13], a[16]); SQRADDAC(a[14], a[15]); SQRADDDB;
906 COMBA_STORE(b[29]);
907
908 /* output 30 */
909 CARRY_FORWARD;
910 SQRADDSC(a[0], a[30]); SQRADDAC(a[1], a[29]); SQRADDAC(a[2], a[28]); SQRADDAC(a[3], a[27]); SQRADDAC(a[4], a[26]); SQRADDAC(a[5], a[25]); SQRADDAC(a[6], a[24]); SQRADDAC(a[7], a[23]); SQRADDAC(a[8], a[22]); SQRADDAC(a[9], a[21]); SQRADDAC(a[10], a[20]); SQRADDAC(a[11], a[19]); SQRADDAC(a[12], a[18]); SQRADDAC(a[13], a[17]); SQRADDAC(a[14], a[16]); SQRADDDB; SQRADD(a[15], a[15]);
911 COMBA_STORE(b[30]);
912
913 /* output 31 */
914 CARRY_FORWARD;
915 SQRADDSC(a[0], a[31]); SQRADDAC(a[1], a[30]); SQRADDAC(a[2], a[29]); SQRADDAC(a[3], a[28]); SQRADDAC(a[4], a[27]); SQRADDAC(a[5], a[26]); SQRADDAC(a[6], a[25]); SQRADDAC(a[7], a[24]); SQRADDAC(a[8], a[23]); SQRADDAC(a[9], a[22]); SQRADDAC(a[10], a[21]); SQRADDAC(a[11], a[20]); SQRADDAC(a[12], a[19]); SQRADDAC(a[13], a[18]); SQRADDAC(a[14], a[17]); SQRADDAC(a[15], a[16]); SQRADDDB;
916 COMBA_STORE(b[31]);
917
918 /* output 32 */
919 CARRY_FORWARD;
920 SQRADDSC(a[1], a[31]); SQRADDAC(a[2], a[30]); SQRADDAC(a[3], a[29]); SQRADDAC(a[4], a[28]); SQRADDAC(a[5], a[27]); SQRADDAC(a[6], a[26]); SQRADDAC(a[7], a[25]); SQRADDAC(a[8], a[24]); SQRADDAC(a[9], a[23]); SQRADDAC(a[10], a[22]); SQRADDAC(a[11], a[21]); SQRADDAC(a[12], a[20]); SQRADDAC(a[13], a[19]); SQRADDAC(a[14], a[18]); SQRADDAC(a[15], a[17]); SQRADDDB; SQRADD(a[16], a[16]);
921 COMBA_STORE(b[32]);
922
923 /* output 33 */
924 CARRY_FORWARD;
925 SQRADDSC(a[2], a[31]); SQRADDAC(a[3], a[30]); SQRADDAC(a[4], a[29]); SQRADDAC(a[5], a[28]); SQRADDAC(a[6], a[27]); SQRADDAC(a[7], a[26]); SQRADDAC(a[8], a[25]); SQRADDAC(a[9], a[24]); SQRADDAC(a[10], a[23]); SQRADDAC(a[11], a[22]); SQRADDAC(a[12], a[21]); SQRADDAC(a[13], a[20]); SQRADDAC(a[14], a[19]); SQRADDAC(a[15], a[18]); SQRADDAC(a[16], a[17]); SQRADDDB;
926 COMBA_STORE(b[33]);
927
928 /* output 34 */
929 CARRY_FORWARD;
930 SQRADDSC(a[3], a[31]); SQRADDAC(a[4], a[30]); SQRADDAC(a[5], a[29]); SQRADDAC(a[6], a[28]); SQRADDAC(a[7], a[27]); SQRADDAC(a[8], a[26]); SQRADDAC(a[9], a[25]); SQRADDAC(a[10], a[24]); SQRADDAC(a[11], a[23]); SQRADDAC(a[12], a[22]); SQRADDAC(a[13], a[21]); SQRADDAC(a[14], a[20]); SQRADDAC(a[15], a[19]); SQRADDAC(a[16], a[18]); SQRADDDB; SQRADD(a[17], a[17]);
931 COMBA_STORE(b[34]);
932
933 /* output 35 */
934 CARRY_FORWARD;
935 SQRADDSC(a[4], a[31]); SQRADDAC(a[5], a[30]); SQRADDAC(a[6], a[29]); SQRADDAC(a[7], a[28]); SQRADDAC(a[8], a[27]); SQRADDAC(a[9], a[26]); SQRADDAC(a[10], a[25]); SQRADDAC(a[11], a[24]); SQRADDAC(a[12], a[23]); SQRADDAC(a[13], a[22]); SQRADDAC(a[14], a[21]); SQRADDAC(a[15], a[20]); SQRADDAC(a[16], a[19]); SQRADDAC(a[17], a[18]); SQRADDDB;
936 COMBA_STORE(b[35]);
937
938 /* output 36 */
939 CARRY_FORWARD;
940 SQRADDSC(a[5], a[31]); SQRADDAC(a[6], a[30]); SQRADDAC(a[7], a[29]); SQRADDAC(a[8], a[28]); SQRADDAC(a[9], a[27]); SQRADDAC(a[10], a[26]); SQRADDAC(a[11], a[25]); SQRADDAC(a[12], a[24]); SQRADDAC(a[13], a[23]); SQRADDAC(a[14], a[22]); SQRADDAC(a[15], a[21]); SQRADDAC(a[16], a[20]); SQRADDAC(a[17], a[19]); SQRADDDB; SQRADD(a[18], a[18]);
941 COMBA_STORE(b[36]);
942
943 /* output 37 */
944 CARRY_FORWARD;
945 SQRADDSC(a[6], a[31]); SQRADDAC(a[7], a[30]); SQRADDAC(a[8], a[29]); SQRADDAC(a[9], a[28]); SQRADDAC(a[10], a[27]); SQRADDAC(a[11], a[26]); SQRADDAC(a[12], a[25]); SQRADDAC(a[13], a[24]); SQRADDAC(a[14], a[23]); SQRADDAC(a[15], a[22]); SQRADDAC(a[16], a[21]); SQRADDAC(a[17], a[20]); SQRADDAC(a[18], a[19]); SQRADDDB;
946 COMBA_STORE(b[37]);
947
948 /* output 38 */
949 CARRY_FORWARD;
950 SQRADDSC(a[7], a[31]); SQRADDAC(a[8], a[30]); SQRADDAC(a[9], a[29]); SQRADDAC(a[10], a[28]); SQRADDAC(a[11], a[27]); SQRADDAC(a[12], a[26]); SQRADDAC(a[13], a[25]); SQRADDAC(a[14], a[24]); SQRADDAC(a[15], a[23]); SQRADDAC(a[16], a[22]); SQRADDAC(a[17], a[21]); SQRADDAC(a[18], a[20]); SQRADDDB; SQRADD(a[19], a[19]);
951 COMBA_STORE(b[38]);
952
953 /* output 39 */
954 CARRY_FORWARD;
955 SQRADDSC(a[8], a[31]); SQRADDAC(a[9], a[30]); SQRADDAC(a[10], a[29]); SQRADDAC(a[11], a[28]); SQRADDAC(a[12], a[27]); SQRADDAC(a[13], a[26]); SQRADDAC(a[14], a[25]); SQRADDAC(a[15], a[24]); SQRADDAC(a[16], a[23]); SQRADDAC(a[17], a[22]); SQRADDAC(a[18], a[21]); SQRADDAC(a[19], a[20]); SQRADDDB;
956 COMBA_STORE(b[39]);
957
958 /* output 40 */
959 CARRY_FORWARD;
960 SQRADDSC(a[9], a[31]); SQRADDAC(a[10], a[30]); SQRADDAC(a[11], a[29]); SQRADDAC(a[12], a[28]); SQRADDAC(a[13], a[27]); SQRADDAC(a[14], a[26]); SQRADDAC(a[15], a[25]); SQRADDAC(a[16], a[24]); SQRADDAC(a[17], a[23]); SQRADDAC(a[18], a[22]); SQRADDAC(a[19], a[21]); SQRADDDB; SQRADD(a[20], a[20]);
961 COMBA_STORE(b[40]);
962
963 /* output 41 */
964 CARRY_FORWARD;
965 SQRADDSC(a[10], a[31]); SQRADDAC(a[11], a[30]); SQRADDAC(a[12], a[29]); SQRADDAC(a[13], a[28]); SQRADDAC(a[14], a[27]); SQRADDAC(a[15], a[26]); SQRADDAC(a[16], a[25]); SQRADDAC(a[17], a[24]); SQRADDAC(a[18], a[23]); SQRADDAC(a[19], a[22]); SQRADDAC(a[20], a[21]); SQRADDDB;
966 COMBA_STORE(b[41]);
967
968 /* output 42 */
969 CARRY_FORWARD;
970 SQRADDSC(a[11], a[31]); SQRADDAC(a[12], a[30]); SQRADDAC(a[13], a[29]); SQRADDAC(a[14], a[28]); SQRADDAC(a[15], a[27]); SQRADDAC(a[16], a[26]); SQRADDAC(a[17], a[25]); SQRADDAC(a[18], a[24]); SQRADDAC(a[19], a[23]); SQRADDAC(a[20], a[22]); SQRADDDB; SQRADD(a[21], a[21]);
971 COMBA_STORE(b[42]);
972
973 /* output 43 */
974 CARRY_FORWARD;
975 SQRADDSC(a[12], a[31]); SQRADDAC(a[13], a[30]); SQRADDAC(a[14], a[29]); SQRADDAC(a[15], a[28]); SQRADDAC(a[16], a[27]); SQRADDAC(a[17], a[26]); SQRADDAC(a[18], a[25]); SQRADDAC(a[19], a[24]); SQRADDAC(a[20], a[23]); SQRADDAC(a[21], a[22]); SQRADDDB;
976 COMBA_STORE(b[43]);
977
978 /* output 44 */
979 CARRY_FORWARD;
980 SQRADDSC(a[13], a[31]); SQRADDAC(a[14], a[30]); SQRADDAC(a[15], a[29]); SQRADDAC(a[16], a[28]); SQRADDAC(a[17], a[27]); SQRADDAC(a[18], a[26]); SQRADDAC(a[19], a[25]); SQRADDAC(a[20], a[24]); SQRADDAC(a[21], a[23]); SQRADDDB; SQRADD(a[22], a[22]);
981 COMBA_STORE(b[44]);
982
983 /* output 45 */
984 CARRY_FORWARD;
985 SQRADDSC(a[14], a[31]); SQRADDAC(a[15], a[30]); SQRADDAC(a[16], a[29]); SQRADDAC(a[17], a[28]); SQRADDAC(a[18], a[27]); SQRADDAC(a[19], a[26]); SQRADDAC(a[20], a[25]); SQRADDAC(a[21], a[24]); SQRADDAC(a[22], a[23]); SQRADDDB;
986 COMBA_STORE(b[45]);
987
988 /* output 46 */
989 CARRY_FORWARD;
990 SQRADDSC(a[15], a[31]); SQRADDAC(a[16], a[30]); SQRADDAC(a[17], a[29]); SQRADDAC(a[18], a[28]); SQRADDAC(a[19], a[27]); SQRADDAC(a[20], a[26]); SQRADDAC(a[21], a[25]); SQRADDAC(a[22], a[24]); SQRADDDB; SQRADD(a[23], a[23]);
991 COMBA_STORE(b[46]);
992
993 /* output 47 */
994 CARRY_FORWARD;
995 SQRADDSC(a[16], a[31]); SQRADDAC(a[17], a[30]); SQRADDAC(a[18], a[29]); SQRADDAC(a[19], a[28]); SQRADDAC(a[20], a[27]); SQRADDAC(a[21], a[26]); SQRADDAC(a[22], a[25]); SQRADDAC(a[23], a[24]); SQRADDDB;
996 COMBA_STORE(b[47]);
997
998 /* output 48 */
999 CARRY_FORWARD;
1000 SQRADDSC(a[17], a[31]); SQRADDAC(a[18], a[30]); SQRADDAC(a[19], a[29]); SQRADDAC(a[20], a[28]); SQRADDAC(a[21], a[27]); SQRADDAC(a[22], a[26]); SQRADDAC(a[23], a[25]); SQRADDDB; SQRADD(a[24], a[24]);
1001 COMBA_STORE(b[48]);
1002
1003 /* output 49 */
1004 CARRY_FORWARD;
1005 SQRADDSC(a[18], a[31]); SQRADDAC(a[19], a[30]); SQRADDAC(a[20], a[29]); SQRADDAC(a[21], a[28]); SQRADDAC(a[22], a[27]); SQRADDAC(a[23], a[26]); SQRADDAC(a[24], a[25]); SQRADDDB;
1006 COMBA_STORE(b[49]);
1007
1008 /* output 50 */
1009 CARRY_FORWARD;
1010 SQRADDSC(a[19], a[31]); SQRADDAC(a[20], a[30]); SQRADDAC(a[21], a[29]); SQRADDAC(a[22], a[28]); SQRADDAC(a[23], a[27]); SQRADDAC(a[24], a[26]); SQRADDDB; SQRADD(a[25], a[25]);
1011 COMBA_STORE(b[50]);
1012
1013 /* output 51 */
1014 CARRY_FORWARD;
1015 SQRADDSC(a[20], a[31]); SQRADDAC(a[21], a[30]); SQRADDAC(a[22], a[29]); SQRADDAC(a[23], a[28]); SQRADDAC(a[24], a[27]); SQRADDAC(a[25], a[26]); SQRADDDB;
1016 COMBA_STORE(b[51]);
1017
1018 /* output 52 */
1019 CARRY_FORWARD;
1020 SQRADDSC(a[21], a[31]); SQRADDAC(a[22], a[30]); SQRADDAC(a[23], a[29]); SQRADDAC(a[24], a[28]); SQRADDAC(a[25], a[27]); SQRADDDB; SQRADD(a[26], a[26]);
1021 COMBA_STORE(b[52]);
1022
1023 /* output 53 */
1024 CARRY_FORWARD;
1025 SQRADDSC(a[22], a[31]); SQRADDAC(a[23], a[30]); SQRADDAC(a[24], a[29]); SQRADDAC(a[25], a[28]); SQRADDAC(a[26], a[27]); SQRADDDB;
1026 COMBA_STORE(b[53]);
1027
1028 /* output 54 */
1029 CARRY_FORWARD;
1030 SQRADDSC(a[23], a[31]); SQRADDAC(a[24], a[30]); SQRADDAC(a[25], a[29]); SQRADDAC(a[26], a[28]); SQRADDDB; SQRADD(a[27], a[27]);
1031 COMBA_STORE(b[54]);
1032
1033 /* output 55 */
1034 CARRY_FORWARD;
1035 SQRADDSC(a[24], a[31]); SQRADDAC(a[25], a[30]); SQRADDAC(a[26], a[29]); SQRADDAC(a[27], a[28]); SQRADDDB;
1036 COMBA_STORE(b[55]);
1037
1038 /* output 56 */
1039 CARRY_FORWARD;
1040 SQRADDSC(a[25], a[31]); SQRADDAC(a[26], a[30]); SQRADDAC(a[27], a[29]); SQRADDDB; SQRADD(a[28], a[28]);
1041 COMBA_STORE(b[56]);
1042
1043 /* output 57 */
1044 CARRY_FORWARD;
1045 SQRADDSC(a[26], a[31]); SQRADDAC(a[27], a[30]); SQRADDAC(a[28], a[29]); SQRADDDB;
1046 COMBA_STORE(b[57]);
1047
1048 /* output 58 */
1049 CARRY_FORWARD;
1050 SQRADD2(a[27], a[31]); SQRADD2(a[28], a[30]); SQRADD(a[29], a[29]);
1051 COMBA_STORE(b[58]);
1052
1053 /* output 59 */
1054 CARRY_FORWARD;
1055 SQRADD2(a[28], a[31]); SQRADD2(a[29], a[30]);
1056 COMBA_STORE(b[59]);
1057
1058 /* output 60 */
1059 CARRY_FORWARD;
1060 SQRADD2(a[29], a[31]); SQRADD(a[30], a[30]);
1061 COMBA_STORE(b[60]);
1062
1063 /* output 61 */
1064 CARRY_FORWARD;
1065 SQRADD2(a[30], a[31]);
1066 COMBA_STORE(b[61]);
1067
1068 /* output 62 */
1069 CARRY_FORWARD;
1070 SQRADD(a[31], a[31]);
1071 COMBA_STORE(b[62]);
1072 COMBA_STORE2(b[63]);
1073 COMBA_FINI;
1074
1075 B->used = 64;
1076 B->sign = PSTM_ZPOS;
1077 memcpy(B->dp, b, 64 * sizeof(pstm_digit));
1078 pstm_clamp(B);
1079 return PSTM_OKAY;
1080}
1081#endif /* USE_2048_KEY_SPEED_OPTIMIZATIONS */
1082
1083/******************************************************************************/
1084/*
1085 */
1086int32 pstm_sqr_comba(psPool_t *pool, pstm_int *A, pstm_int *B, pstm_digit *paD,
1087 uint32 paDlen)
1088{
1089#ifdef USE_1024_KEY_SPEED_OPTIMIZATIONS
1090 if (A->used == 16) {
1091 return pstm_sqr_comba16(A, B);
1092 } else {
1093#ifdef USE_2048_KEY_SPEED_OPTIMIZATIONS
1094 if (A->used == 32) {
1095 return pstm_sqr_comba32(A, B);
1096 }
1097#endif /* USE_2048_KEY_SPEED_OPTIMIZATIONS */
1098 return pstm_sqr_comba_gen(pool, A, B, paD, paDlen);
1099 }
1100#else
1101#ifdef USE_2048_KEY_SPEED_OPTIMIZATIONS
1102 if (A->used == 32) {
1103 return pstm_sqr_comba32(A, B);
1104 }
1105#endif /* USE_2048_KEY_SPEED_OPTIMIZATIONS */
1106 return pstm_sqr_comba_gen(pool, A, B, paD, paDlen);
1107#endif
1108}
1109
1110#endif /* DISABLE_PSTM */
1111/******************************************************************************/
diff --git a/networking/tls_rsa.c b/networking/tls_rsa.c
new file mode 100644
index 000000000..60c54248e
--- /dev/null
+++ b/networking/tls_rsa.c
@@ -0,0 +1,211 @@
1/*
2 * Copyright (C) 2017 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6#include "tls.h"
7
8/* The code below is taken from parts of
9 * matrixssl-3-7-2b-open/crypto/pubkey/pkcs.c
10 * matrixssl-3-7-2b-open/crypto/pubkey/rsa.c
11 * and (so far) almost not modified. Changes are flagged with //bbox
12 */
13
14#define pkcs1Pad(in, inlen, out, outlen, cryptType, userPtr) \
15 pkcs1Pad(in, inlen, out, outlen, cryptType)
16static //bbox
17int32 pkcs1Pad(unsigned char *in, uint32 inlen, unsigned char *out,
18 uint32 outlen, int32 cryptType, void *userPtr)
19{
20 unsigned char *c;
21 int32 randomLen;
22
23 randomLen = outlen - 3 - inlen;
24 if (randomLen < 8) {
25 psTraceCrypto("pkcs1Pad failure\n");
26 return PS_LIMIT_FAIL;
27 }
28 c = out;
29 *c = 0x00;
30 c++;
31 *c = (unsigned char)cryptType;
32 c++;
33 if (cryptType == PUBKEY_TYPE) {
34 while (randomLen-- > 0) {
35 *c++ = 0xFF;
36 }
37 } else {
38 if (matrixCryptoGetPrngData(c, (uint32)randomLen, userPtr) < 0) {
39 return PS_PLATFORM_FAIL;
40 }
41/*
42 SECURITY: Read through the random data and change all 0x0 to 0x01.
43 This is per spec that no random bytes should be 0
44*/
45 while (randomLen-- > 0) {
46 if (*c == 0x0) {
47 *c = 0x01;
48 }
49 c++;
50 }
51 }
52 *c = 0x00;
53 c++;
54 memcpy(c, in, inlen);
55
56 return outlen;
57}
58
59#define psRsaCrypt(pool, in, inlen, out, outlen, key, type, data) \
60 psRsaCrypt( in, inlen, out, outlen, key, type)
61static //bbox
62int32 psRsaCrypt(psPool_t *pool, const unsigned char *in, uint32 inlen,
63 unsigned char *out, uint32 *outlen, psRsaKey_t *key, int32 type,
64 void *data)
65{
66 pstm_int tmp, tmpa, tmpb;
67 int32 res;
68 uint32 x;
69
70//bbox
71// if (in == NULL || out == NULL || outlen == NULL || key == NULL) {
72// psTraceCrypto("NULL parameter error in psRsaCrypt\n");
73// return PS_ARG_FAIL;
74// }
75
76 tmp.dp = tmpa.dp = tmpb.dp = NULL;
77
78 /* Init and copy into tmp */
79 if (pstm_init_for_read_unsigned_bin(pool, &tmp, inlen + sizeof(pstm_digit))
80 != PS_SUCCESS) {
81 return PS_FAILURE;
82 }
83 if (pstm_read_unsigned_bin(&tmp, (unsigned char *)in, inlen) != PS_SUCCESS){
84 pstm_clear(&tmp);
85 return PS_FAILURE;
86 }
87 /* Sanity check on the input */
88 if (pstm_cmp(&key->N, &tmp) == PSTM_LT) {
89 res = PS_LIMIT_FAIL;
90 goto done;
91 }
92 if (type == PRIVKEY_TYPE) {
93 if (key->optimized) {
94 if (pstm_init_size(pool, &tmpa, key->p.alloc) != PS_SUCCESS) {
95 res = PS_FAILURE;
96 goto done;
97 }
98 if (pstm_init_size(pool, &tmpb, key->q.alloc) != PS_SUCCESS) {
99 pstm_clear(&tmpa);
100 res = PS_FAILURE;
101 goto done;
102 }
103 if (pstm_exptmod(pool, &tmp, &key->dP, &key->p, &tmpa) !=
104 PS_SUCCESS) {
105 psTraceCrypto("decrypt error: pstm_exptmod dP, p\n");
106 goto error;
107 }
108 if (pstm_exptmod(pool, &tmp, &key->dQ, &key->q, &tmpb) !=
109 PS_SUCCESS) {
110 psTraceCrypto("decrypt error: pstm_exptmod dQ, q\n");
111 goto error;
112 }
113 if (pstm_sub(&tmpa, &tmpb, &tmp) != PS_SUCCESS) {
114 psTraceCrypto("decrypt error: sub tmpb, tmp\n");
115 goto error;
116 }
117 if (pstm_mulmod(pool, &tmp, &key->qP, &key->p, &tmp) != PS_SUCCESS) {
118 psTraceCrypto("decrypt error: pstm_mulmod qP, p\n");
119 goto error;
120 }
121 if (pstm_mul_comba(pool, &tmp, &key->q, &tmp, NULL, 0)
122 != PS_SUCCESS){
123 psTraceCrypto("decrypt error: pstm_mul q \n");
124 goto error;
125 }
126 if (pstm_add(&tmp, &tmpb, &tmp) != PS_SUCCESS) {
127 psTraceCrypto("decrypt error: pstm_add tmp \n");
128 goto error;
129 }
130 } else {
131 if (pstm_exptmod(pool, &tmp, &key->d, &key->N, &tmp) !=
132 PS_SUCCESS) {
133 psTraceCrypto("psRsaCrypt error: pstm_exptmod\n");
134 goto error;
135 }
136 }
137 } else if (type == PUBKEY_TYPE) {
138 if (pstm_exptmod(pool, &tmp, &key->e, &key->N, &tmp) != PS_SUCCESS) {
139 psTraceCrypto("psRsaCrypt error: pstm_exptmod\n");
140 goto error;
141 }
142 } else {
143 psTraceCrypto("psRsaCrypt error: invalid type param\n");
144 goto error;
145 }
146 /* Read it back */
147 x = pstm_unsigned_bin_size(&key->N);
148
149 if ((uint32)x > *outlen) {
150 res = -1;
151 psTraceCrypto("psRsaCrypt error: pstm_unsigned_bin_size\n");
152 goto done;
153 }
154 /* We want the encrypted value to always be the key size. Pad with 0x0 */
155 while ((uint32)x < (unsigned long)key->size) {
156 *out++ = 0x0;
157 x++;
158 }
159
160 *outlen = x;
161 /* Convert it */
162 memset(out, 0x0, x);
163
164 if (pstm_to_unsigned_bin(pool, &tmp, out+(x-pstm_unsigned_bin_size(&tmp)))
165 != PS_SUCCESS) {
166 psTraceCrypto("psRsaCrypt error: pstm_to_unsigned_bin\n");
167 goto error;
168 }
169 /* Clean up and return */
170 res = PS_SUCCESS;
171 goto done;
172error:
173 res = PS_FAILURE;
174done:
175 if (type == PRIVKEY_TYPE && key->optimized) {
176 pstm_clear_multi(&tmpa, &tmpb, NULL, NULL, NULL, NULL, NULL, NULL);
177 }
178 pstm_clear(&tmp);
179 return res;
180}
181
182int32 psRsaEncryptPub(psPool_t *pool, psRsaKey_t *key,
183 unsigned char *in, uint32 inlen,
184 unsigned char *out, uint32 outlen, void *data)
185{
186 int32 err;
187 uint32 size;
188
189 size = key->size;
190 if (outlen < size) {
191//bbox psTraceCrypto("Error on bad outlen parameter to psRsaEncryptPub\n");
192 bb_error_msg_and_die("RSA crypt outlen:%d < size:%d", outlen, size);
193 return PS_ARG_FAIL;
194 }
195
196 if ((err = pkcs1Pad(in, inlen, out, size, PRIVKEY_TYPE, data))
197 < PS_SUCCESS) {
198 psTraceCrypto("Error padding psRsaEncryptPub. Likely data too long\n");
199 return err;
200 }
201 if ((err = psRsaCrypt(pool, out, size, out, (uint32*)&outlen, key,
202 PUBKEY_TYPE, data)) < PS_SUCCESS) {
203 psTraceCrypto("Error performing psRsaEncryptPub\n");
204 return err;
205 }
206 if (outlen != size) {
207 psTraceCrypto("Encrypted size error in psRsaEncryptPub\n");
208 return PS_FAILURE;
209 }
210 return size;
211}
diff --git a/networking/tls_rsa.h b/networking/tls_rsa.h
new file mode 100644
index 000000000..c464ed552
--- /dev/null
+++ b/networking/tls_rsa.h
@@ -0,0 +1,20 @@
1/*
2 * Copyright (C) 2017 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 *
6 * Selected few declarations for RSA.
7 */
8
9typedef struct {
10 pstm_int e, d, N, qP, dP, dQ, p, q;
11 uint32 size; /* Size of the key in bytes */
12 int32 optimized; /* 1 for optimized */
13//bbox psPool_t *pool;
14} psRsaKey_t;
15
16#define psRsaEncryptPub(pool, key, in, inlen, out, outlen, data) \
17 psRsaEncryptPub( key, in, inlen, out, outlen)
18int32 psRsaEncryptPub(psPool_t *pool, psRsaKey_t *key,
19 unsigned char *in, uint32 inlen,
20 unsigned char *out, uint32 outlen, void *data);
diff --git a/networking/tls_symmetric.h b/networking/tls_symmetric.h
new file mode 100644
index 000000000..5e0e4b6d8
--- /dev/null
+++ b/networking/tls_symmetric.h
@@ -0,0 +1,511 @@
1/*
2 * Copyright (C) 2017 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6
7
8/* The part below is a section of matrixssl-3-7-2b-open/crypto/cryptolib.h
9 * Changes are flagged with //bbox
10 */
11
12/******************************************************************************/
13/* 32-bit Rotates */
14/******************************************************************************/
15#if defined(_MSC_VER)
16/******************************************************************************/
17
18/* instrinsic rotate */
19#include <stdlib.h>
20#pragma intrinsic(_lrotr,_lrotl)
21#define ROR(x,n) _lrotr(x,n)
22#define ROL(x,n) _lrotl(x,n)
23
24/******************************************************************************/
25#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && \
26 !defined(INTEL_CC) && !defined(PS_NO_ASM)
27
28static ALWAYS_INLINE unsigned ROL(unsigned word, int i)
29{
30 if (__builtin_constant_p(i)) { //box
31 // Rotates by constant use fewer registers,
32 // and on many Intel CPUs rotates by %cl take 2 cycles, not 1.
33 asm ("roll %2,%0"
34 :"=r" (word)
35 :"0" (word),"i" (i));
36 return word;
37 } //box
38 asm ("roll %%cl,%0"
39 :"=r" (word)
40 :"0" (word),"c" (i));
41 return word;
42}
43
44static ALWAYS_INLINE unsigned ROR(unsigned word, int i)
45{
46 if (__builtin_constant_p(i)) { //box
47 asm ("rorl %2,%0"
48 :"=r" (word)
49 :"0" (word),"i" (i));
50 return word;
51 } //box
52 asm ("rorl %%cl,%0"
53 :"=r" (word)
54 :"0" (word),"c" (i));
55 return word;
56}
57
58/******************************************************************************/
59#else
60
61/* rotates the hard way */
62#define ROL(x, y) \
63 ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | \
64 (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & \
65 0xFFFFFFFFUL)
66#define ROR(x, y) \
67 ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | \
68 ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
69
70#endif /* 32-bit Rotates */
71/******************************************************************************/
72
73#ifdef HAVE_NATIVE_INT64
74#ifdef _MSC_VER
75 #define CONST64(n) n ## ui64
76#else
77 #define CONST64(n) n ## ULL
78#endif
79#endif
80
81/******************************************************************************/
82/*
83 Endian helper macros
84 */
85#if defined (ENDIAN_NEUTRAL)
86#define STORE32L(x, y) { \
87(y)[3] = (unsigned char)(((x)>>24)&255); \
88(y)[2] = (unsigned char)(((x)>>16)&255); \
89(y)[1] = (unsigned char)(((x)>>8)&255); \
90(y)[0] = (unsigned char)((x)&255); \
91}
92
93#define LOAD32L(x, y) { \
94x = ((unsigned long)((y)[3] & 255)<<24) | \
95((unsigned long)((y)[2] & 255)<<16) | \
96((unsigned long)((y)[1] & 255)<<8) | \
97((unsigned long)((y)[0] & 255)); \
98}
99
100#define STORE64L(x, y) { \
101(y)[7] = (unsigned char)(((x)>>56)&255); \
102(y)[6] = (unsigned char)(((x)>>48)&255); \
103(y)[5] = (unsigned char)(((x)>>40)&255); \
104(y)[4] = (unsigned char)(((x)>>32)&255); \
105(y)[3] = (unsigned char)(((x)>>24)&255); \
106(y)[2] = (unsigned char)(((x)>>16)&255); \
107(y)[1] = (unsigned char)(((x)>>8)&255); \
108(y)[0] = (unsigned char)((x)&255); \
109}
110
111#define LOAD64L(x, y) { \
112x = (((uint64)((y)[7] & 255))<<56)|(((uint64)((y)[6] & 255))<<48)| \
113(((uint64)((y)[5] & 255))<<40)|(((uint64)((y)[4] & 255))<<32)| \
114(((uint64)((y)[3] & 255))<<24)|(((uint64)((y)[2] & 255))<<16)| \
115(((uint64)((y)[1] & 255))<<8)|(((uint64)((y)[0] & 255))); \
116}
117
118#define STORE32H(x, y) { \
119(y)[0] = (unsigned char)(((x)>>24)&255); \
120(y)[1] = (unsigned char)(((x)>>16)&255); \
121(y)[2] = (unsigned char)(((x)>>8)&255); \
122(y)[3] = (unsigned char)((x)&255); \
123}
124
125#define LOAD32H(x, y) { \
126x = ((unsigned long)((y)[0] & 255)<<24) | \
127((unsigned long)((y)[1] & 255)<<16) | \
128((unsigned long)((y)[2] & 255)<<8) | \
129((unsigned long)((y)[3] & 255)); \
130}
131
132#define STORE64H(x, y) { \
133(y)[0] = (unsigned char)(((x)>>56)&255); \
134(y)[1] = (unsigned char)(((x)>>48)&255); \
135(y)[2] = (unsigned char)(((x)>>40)&255); \
136(y)[3] = (unsigned char)(((x)>>32)&255); \
137(y)[4] = (unsigned char)(((x)>>24)&255); \
138(y)[5] = (unsigned char)(((x)>>16)&255); \
139(y)[6] = (unsigned char)(((x)>>8)&255); \
140(y)[7] = (unsigned char)((x)&255); \
141}
142
143#define LOAD64H(x, y) { \
144x = (((uint64)((y)[0] & 255))<<56)|(((uint64)((y)[1] & 255))<<48) | \
145(((uint64)((y)[2] & 255))<<40)|(((uint64)((y)[3] & 255))<<32) | \
146(((uint64)((y)[4] & 255))<<24)|(((uint64)((y)[5] & 255))<<16) | \
147(((uint64)((y)[6] & 255))<<8)|(((uint64)((y)[7] & 255))); \
148}
149
150#endif /* ENDIAN_NEUTRAL */
151
152#ifdef ENDIAN_LITTLE
153#define STORE32H(x, y) { \
154(y)[0] = (unsigned char)(((x)>>24)&255); \
155(y)[1] = (unsigned char)(((x)>>16)&255); \
156(y)[2] = (unsigned char)(((x)>>8)&255); \
157(y)[3] = (unsigned char)((x)&255); \
158}
159
160#define LOAD32H(x, y) { \
161x = ((unsigned long)((y)[0] & 255)<<24) | \
162((unsigned long)((y)[1] & 255)<<16) | \
163((unsigned long)((y)[2] & 255)<<8) | \
164((unsigned long)((y)[3] & 255)); \
165}
166
167#define STORE64H(x, y) { \
168(y)[0] = (unsigned char)(((x)>>56)&255); \
169(y)[1] = (unsigned char)(((x)>>48)&255); \
170(y)[2] = (unsigned char)(((x)>>40)&255); \
171(y)[3] = (unsigned char)(((x)>>32)&255); \
172(y)[4] = (unsigned char)(((x)>>24)&255); \
173(y)[5] = (unsigned char)(((x)>>16)&255); \
174(y)[6] = (unsigned char)(((x)>>8)&255); \
175(y)[7] = (unsigned char)((x)&255); \
176}
177
178#define LOAD64H(x, y) { \
179x = (((uint64)((y)[0] & 255))<<56)|(((uint64)((y)[1] & 255))<<48) | \
180(((uint64)((y)[2] & 255))<<40)|(((uint64)((y)[3] & 255))<<32) | \
181(((uint64)((y)[4] & 255))<<24)|(((uint64)((y)[5] & 255))<<16) | \
182(((uint64)((y)[6] & 255))<<8)|(((uint64)((y)[7] & 255))); }
183
184#ifdef ENDIAN_32BITWORD
185#define STORE32L(x, y) { \
186unsigned long __t = (x); memcpy(y, &__t, 4); \
187}
188
189#define LOAD32L(x, y) memcpy(&(x), y, 4);
190
191#define STORE64L(x, y) { \
192(y)[7] = (unsigned char)(((x)>>56)&255); \
193(y)[6] = (unsigned char)(((x)>>48)&255); \
194(y)[5] = (unsigned char)(((x)>>40)&255); \
195(y)[4] = (unsigned char)(((x)>>32)&255); \
196(y)[3] = (unsigned char)(((x)>>24)&255); \
197(y)[2] = (unsigned char)(((x)>>16)&255); \
198(y)[1] = (unsigned char)(((x)>>8)&255); \
199(y)[0] = (unsigned char)((x)&255); \
200}
201
202#define LOAD64L(x, y) { \
203x = (((uint64)((y)[7] & 255))<<56)|(((uint64)((y)[6] & 255))<<48)| \
204(((uint64)((y)[5] & 255))<<40)|(((uint64)((y)[4] & 255))<<32)| \
205(((uint64)((y)[3] & 255))<<24)|(((uint64)((y)[2] & 255))<<16)| \
206(((uint64)((y)[1] & 255))<<8)|(((uint64)((y)[0] & 255))); \
207}
208
209#else /* 64-bit words then */
210#define STORE32L(x, y) \
211{ unsigned long __t = (x); memcpy(y, &__t, 4); }
212
213#define LOAD32L(x, y) \
214{ memcpy(&(x), y, 4); x &= 0xFFFFFFFF; }
215
216#define STORE64L(x, y) \
217{ uint64 __t = (x); memcpy(y, &__t, 8); }
218
219#define LOAD64L(x, y) \
220{ memcpy(&(x), y, 8); }
221
222#endif /* ENDIAN_64BITWORD */
223#endif /* ENDIAN_LITTLE */
224
225#ifdef ENDIAN_BIG
226#define STORE32L(x, y) { \
227(y)[3] = (unsigned char)(((x)>>24)&255); \
228(y)[2] = (unsigned char)(((x)>>16)&255); \
229(y)[1] = (unsigned char)(((x)>>8)&255); \
230(y)[0] = (unsigned char)((x)&255); \
231}
232
233#define LOAD32L(x, y) { \
234x = ((unsigned long)((y)[3] & 255)<<24) | \
235((unsigned long)((y)[2] & 255)<<16) | \
236((unsigned long)((y)[1] & 255)<<8) | \
237((unsigned long)((y)[0] & 255)); \
238}
239
240#define STORE64L(x, y) { \
241(y)[7] = (unsigned char)(((x)>>56)&255); \
242(y)[6] = (unsigned char)(((x)>>48)&255); \
243(y)[5] = (unsigned char)(((x)>>40)&255); \
244(y)[4] = (unsigned char)(((x)>>32)&255); \
245(y)[3] = (unsigned char)(((x)>>24)&255); \
246(y)[2] = (unsigned char)(((x)>>16)&255); \
247(y)[1] = (unsigned char)(((x)>>8)&255); \
248(y)[0] = (unsigned char)((x)&255); \
249}
250
251#define LOAD64L(x, y) { \
252x = (((uint64)((y)[7] & 255))<<56)|(((uint64)((y)[6] & 255))<<48) | \
253(((uint64)((y)[5] & 255))<<40)|(((uint64)((y)[4] & 255))<<32) | \
254(((uint64)((y)[3] & 255))<<24)|(((uint64)((y)[2] & 255))<<16) | \
255(((uint64)((y)[1] & 255))<<8)|(((uint64)((y)[0] & 255))); \
256}
257
258#ifdef ENDIAN_32BITWORD
259#define STORE32H(x, y) \
260{ unsigned int __t = (x); memcpy(y, &__t, 4); }
261
262#define LOAD32H(x, y) memcpy(&(x), y, 4);
263
264#define STORE64H(x, y) { \
265(y)[0] = (unsigned char)(((x)>>56)&255); \
266(y)[1] = (unsigned char)(((x)>>48)&255); \
267(y)[2] = (unsigned char)(((x)>>40)&255); \
268(y)[3] = (unsigned char)(((x)>>32)&255); \
269(y)[4] = (unsigned char)(((x)>>24)&255); \
270(y)[5] = (unsigned char)(((x)>>16)&255); \
271(y)[6] = (unsigned char)(((x)>>8)&255); \
272(y)[7] = (unsigned char)((x)&255); \
273}
274
275#define LOAD64H(x, y) { \
276x = (((uint64)((y)[0] & 255))<<56)|(((uint64)((y)[1] & 255))<<48)| \
277(((uint64)((y)[2] & 255))<<40)|(((uint64)((y)[3] & 255))<<32)| \
278(((uint64)((y)[4] & 255))<<24)|(((uint64)((y)[5] & 255))<<16)| \
279(((uint64)((y)[6] & 255))<<8)| (((uint64)((y)[7] & 255))); \
280}
281
282#else /* 64-bit words then */
283
284#define STORE32H(x, y) \
285{ unsigned long __t = (x); memcpy(y, &__t, 4); }
286
287#define LOAD32H(x, y) \
288{ memcpy(&(x), y, 4); x &= 0xFFFFFFFF; }
289
290#define STORE64H(x, y) \
291{ uint64 __t = (x); memcpy(y, &__t, 8); }
292
293#define LOAD64H(x, y) \
294{ memcpy(&(x), y, 8); }
295
296#endif /* ENDIAN_64BITWORD */
297#endif /* ENDIAN_BIG */
298
299#ifdef HAVE_NATIVE_INT64
300#define ROL64c(x, y) \
301( (((x)<<((uint64)(y)&63)) | \
302(((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((uint64)64-((y)&63)))) & CONST64(0xFFFFFFFFFFFFFFFF))
303
304#define ROR64c(x, y) \
305( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((uint64)(y)&CONST64(63))) | \
306((x)<<((uint64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF))
307#endif /* HAVE_NATIVE_INT64 */
308/******************************************************************************/
309
310
311
312/* The part below is taken almost verbatim from matrixssl-3-7-2b-open/crypto/symmetric/.
313 * Changes are flagged with //bbox
314 */
315
316/**
317 * @file symmetric.h
318 * @version 33ef80f (HEAD, tag: MATRIXSSL-3-7-2-OPEN, tag: MATRIXSSL-3-7-2-COMM, origin/master, origin/HEAD, master)
319 *
320 * Header for internal symmetric key cryptography support.
321 */
322/*
323 * Copyright (c) 2013-2015 INSIDE Secure Corporation
324 * Copyright (c) PeerSec Networks, 2002-2011
325 * All Rights Reserved
326 *
327 * The latest version of this code is available at http://www.matrixssl.org
328 *
329 * This software is open source; you can redistribute it and/or modify
330 * it under the terms of the GNU General Public License as published by
331 * the Free Software Foundation; either version 2 of the License, or
332 * (at your option) any later version.
333 *
334 * This General Public License does NOT permit incorporating this software
335 * into proprietary programs. If you are unable to comply with the GPL, a
336 * commercial license for this software may be purchased from INSIDE at
337 * http://www.insidesecure.com/eng/Company/Locations
338 *
339 * This program is distributed in WITHOUT ANY WARRANTY; without even the
340 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
341 * See the GNU General Public License for more details.
342 *
343 * You should have received a copy of the GNU General Public License
344 * along with this program; if not, write to the Free Software
345 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
346 * http://www.gnu.org/copyleft/gpl.html
347 */
348/******************************************************************************/
349
350#ifndef _h_PS_SYMMETRIC
351#define _h_PS_SYMMETRIC
352
353/******************************************************************************/
354#ifdef USE_AES
355/******************************************************************************/
356
357
358#ifndef USE_AES_CBC_EXTERNAL
359typedef struct {
360 uint32 eK[64], dK[64];
361 int32 Nr;
362} psAesKey_t;
363
364typedef struct {
365 int32 blocklen;
366 unsigned char IV[16];
367 psAesKey_t key;
368#if defined(USE_AES_GCM) || defined(USE_AES_CCM)
369 unsigned char EncCtr[16];
370 unsigned char CtrBlock[16];
371#endif
372#ifdef USE_AES_GCM
373 unsigned char gInit[16];
374 uint32 TagTemp[4];
375 unsigned char Hash_SubKey[16];
376 uint32 ProcessedBitCount[4];
377 uint32 InputBufferCount;
378 uint32 OutputBufferCount;
379 union
380 {
381 unsigned char Buffer[128];
382 uint32 BufferAlignment;
383 } Input;
384#endif /* USE_AES_GCM */
385#ifdef USE_AES_CCM
386 uint32_t ccmTagTemp[16 / sizeof(uint32_t)]; /* 32 */
387 union
388 {
389 /* Used for formatting IV. */
390 uint8_t Temporary[16];
391 /* Used for processing Mac. */
392 uint8_t Y0[16];
393 } u; /* 48 */
394#endif /* USE_AES_CCM */
395} psAesCipher_t;
396#endif /* USE_AES_CBC_EXTERNAL */
397
398#endif /* USE_AES */
399
400#ifdef USE_IDEA
401#define SSL_IDEA_KEY_LEN 16
402#define SSL_IDEA_IV_LEN 8
403#define SSL_IDEA_BLOCK_LEN 8
404
405typedef struct {
406 uint16 key_schedule[52];
407} psIdeaKey_t;
408
409typedef struct {
410 psIdeaKey_t key;
411 uint32 IV[2];
412 short for_encryption;
413 short inverted;
414} idea_CBC;
415#endif
416/******************************************************************************/
417
418/******************************************************************************/
419#ifdef USE_SEED
420/******************************************************************************/
421#define SSL_SEED_KEY_LEN 16
422#define SSL_SEED_IV_LEN 16
423
424
425typedef struct {
426 uint32 K[32], dK[32];
427} psSeedKey_t;
428
429typedef struct {
430 int32 blocklen;
431 unsigned char IV[16];
432 psSeedKey_t key;
433} seed_CBC;
434
435#endif /* USE_SEED */
436/******************************************************************************/
437
438/******************************************************************************/
439#if defined(USE_3DES) || defined(USE_DES)
440/******************************************************************************/
441#define DES3_KEY_LEN 24
442#define DES3_IV_LEN 8
443#define DES_KEY_LEN 8
444
445typedef struct {
446 uint32 ek[3][32], dk[3][32];
447} psDes3Key_t;
448
449/*
450 A block cipher CBC structure
451 */
452typedef struct {
453 int32 blocklen;
454 unsigned char IV[8];
455 psDes3Key_t key;
456} des3_CBC;
457
458#endif /* USE_3DES || USE_DES */
459/******************************************************************************/
460
461/******************************************************************************/
462#ifdef USE_ARC4
463typedef struct {
464 unsigned char state[256];
465 uint32 byteCount;
466 unsigned char x;
467 unsigned char y;
468} psRc4Key_t;
469#endif /* USE_ARC4 */
470/******************************************************************************/
471#ifdef USE_RC2
472typedef struct {
473 unsigned xkey[64];
474} psRc2Key_t;
475
476typedef struct {
477 int32 blocklen;
478 unsigned char IV[8];
479 psRc2Key_t key;
480} rc2_CBC;
481#endif /* USE_RC2 */
482/******************************************************************************/
483/* Universal types and defines */
484/******************************************************************************/
485#define MAXBLOCKSIZE 24
486
487typedef union {
488#ifdef USE_RC2
489 rc2_CBC rc2;
490#endif
491#ifdef USE_ARC4
492 psRc4Key_t arc4;
493#endif
494#ifdef USE_3DES
495 des3_CBC des3;
496#endif
497#ifdef USE_AES
498 psAesCipher_t aes;
499#endif
500#ifdef USE_SEED
501 seed_CBC seed;
502#endif
503#ifdef USE_IDEA
504 idea_CBC idea;
505#endif
506} psCipherContext_t;
507
508#define byte(x, n) (((x) >> (8 * (n))) & 255)
509
510#endif /* _h_PS_SYMMETRIC */
511/******************************************************************************/
diff --git a/networking/traceroute.c b/networking/traceroute.c
index a463b0faa..6817861ef 100644
--- a/networking/traceroute.c
+++ b/networking/traceroute.c
@@ -235,8 +235,6 @@
235//config: bool "Enable -I option (use ICMP instead of UDP)" 235//config: bool "Enable -I option (use ICMP instead of UDP)"
236//config: default y 236//config: default y
237//config: depends on TRACEROUTE || TRACEROUTE6 237//config: depends on TRACEROUTE || TRACEROUTE6
238//config: help
239//config: Add option -I to use ICMP ECHO instead of UDP datagrams.
240 238
241/* Needs socket(AF_INET, SOCK_RAW, IPPROTO_ICMP), therefore BB_SUID_MAYBE: */ 239/* Needs socket(AF_INET, SOCK_RAW, IPPROTO_ICMP), therefore BB_SUID_MAYBE: */
242//applet:IF_TRACEROUTE(APPLET(traceroute, BB_DIR_USR_BIN, BB_SUID_MAYBE)) 240//applet:IF_TRACEROUTE(APPLET(traceroute, BB_DIR_USR_BIN, BB_SUID_MAYBE))
diff --git a/networking/udhcp/Config.src b/networking/udhcp/Config.src
index 7bc13a719..5c068441a 100644
--- a/networking/udhcp/Config.src
+++ b/networking/udhcp/Config.src
@@ -123,7 +123,7 @@ config UDHCP_DEBUG
123 are very verbose and useful for debugging only. 123 are very verbose and useful for debugging only.
124 124
125config FEATURE_UDHCP_RFC3397 125config FEATURE_UDHCP_RFC3397
126 bool "Support for RFC3397 domain search (experimental)" 126 bool "Support RFC3397 domain search (experimental)"
127 default y 127 default y
128 depends on UDHCPD || UDHCPC 128 depends on UDHCPD || UDHCPC
129 help 129 help
@@ -132,7 +132,7 @@ config FEATURE_UDHCP_RFC3397
132 and SIP servers option 120, specified in RFC 3361. 132 and SIP servers option 120, specified in RFC 3361.
133 133
134config FEATURE_UDHCP_8021Q 134config FEATURE_UDHCP_8021Q
135 bool "Support for 802.1Q VLAN parameters" 135 bool "Support 802.1Q VLAN parameters"
136 default y 136 default y
137 depends on UDHCPD || UDHCPC 137 depends on UDHCPD || UDHCPC
138 help 138 help
diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c
index 1aaf5255c..420695a20 100644
--- a/networking/udhcp/common.c
+++ b/networking/udhcp/common.c
@@ -86,7 +86,7 @@ const struct dhcp_optflag dhcp_optflags[] = {
86}; 86};
87 87
88/* Used for converting options from incoming packets to env variables 88/* Used for converting options from incoming packets to env variables
89 * for udhcpc stript, and for setting options for udhcpd via 89 * for udhcpc script, and for setting options for udhcpd via
90 * "opt OPTION_NAME OPTION_VALUE" directives in udhcpd.conf file. 90 * "opt OPTION_NAME OPTION_VALUE" directives in udhcpd.conf file.
91 */ 91 */
92/* Must match dhcp_optflags[] order */ 92/* Must match dhcp_optflags[] order */
diff --git a/networking/udhcp/dumpleases.c b/networking/udhcp/dumpleases.c
index d83344a8d..dce9084b3 100644
--- a/networking/udhcp/dumpleases.c
+++ b/networking/udhcp/dumpleases.c
@@ -11,7 +11,7 @@
11//usage:#define dumpleases_full_usage "\n\n" 11//usage:#define dumpleases_full_usage "\n\n"
12//usage: "Display DHCP leases granted by udhcpd\n" 12//usage: "Display DHCP leases granted by udhcpd\n"
13//usage: IF_LONG_OPTS( 13//usage: IF_LONG_OPTS(
14//usage: "\n -f,--file=FILE Lease file" 14//usage: "\n -f,--file FILE Lease file"
15//usage: "\n -r,--remaining Show remaining time" 15//usage: "\n -r,--remaining Show remaining time"
16//usage: "\n -a,--absolute Show expiration time" 16//usage: "\n -a,--absolute Show expiration time"
17//usage: "\n -d,--decimal Show time in seconds" 17//usage: "\n -d,--decimal Show time in seconds"
diff --git a/networking/wget.c b/networking/wget.c
index 460b4b833..b9d840328 100644
--- a/networking/wget.c
+++ b/networking/wget.c
@@ -16,12 +16,15 @@
16//config: wget is a utility for non-interactive download of files from HTTP 16//config: wget is a utility for non-interactive download of files from HTTP
17//config: and FTP servers. 17//config: and FTP servers.
18//config: 18//config:
19//config:config FEATURE_WGET_LONG_OPTIONS
20//config: bool "Enable long options"
21//config: default y
22//config: depends on WGET && LONG_OPTS
23//config:
19//config:config FEATURE_WGET_STATUSBAR 24//config:config FEATURE_WGET_STATUSBAR
20//config: bool "Enable a nifty process meter (+2k)" 25//config: bool "Enable progress bar (+2k)"
21//config: default y 26//config: default y
22//config: depends on WGET 27//config: depends on WGET
23//config: help
24//config: Enable the transfer progress bar for wget transfers.
25//config: 28//config:
26//config:config FEATURE_WGET_AUTHENTICATION 29//config:config FEATURE_WGET_AUTHENTICATION
27//config: bool "Enable HTTP authentication" 30//config: bool "Enable HTTP authentication"
@@ -30,13 +33,6 @@
30//config: help 33//config: help
31//config: Support authenticated HTTP transfers. 34//config: Support authenticated HTTP transfers.
32//config: 35//config:
33//config:config FEATURE_WGET_LONG_OPTIONS
34//config: bool "Enable long options"
35//config: default y
36//config: depends on WGET && LONG_OPTS
37//config: help
38//config: Support long options for the wget applet.
39//config:
40//config:config FEATURE_WGET_TIMEOUT 36//config:config FEATURE_WGET_TIMEOUT
41//config: bool "Enable timeout option -T SEC" 37//config: bool "Enable timeout option -T SEC"
42//config: default y 38//config: default y
@@ -51,18 +47,59 @@
51//config: FEATURE_WGET_LONG_OPTIONS is also enabled, the --timeout option 47//config: FEATURE_WGET_LONG_OPTIONS is also enabled, the --timeout option
52//config: will work in addition to -T. 48//config: will work in addition to -T.
53//config: 49//config:
50//config:config FEATURE_WGET_HTTPS
51//config: bool "Support HTTPS using internal TLS code"
52//config: default y
53//config: depends on WGET
54//config: select TLS
55//config: help
56//config: wget will use internal TLS code to connect to https:// URLs.
57//config: Note:
58//config: On NOMMU machines, ssl_helper applet should be available
59//config: in the $PATH for this to work. Make sure to select that applet.
60//config:
61//config: Note: currently, TLS code only makes TLS I/O work, it
62//config: does *not* check that the peer is who it claims to be, etc.
63//config: IOW: it uses peer-supplied public keys to establish encryption
64//config: and signing keys, then encrypts and signs outgoing data and
65//config: decrypts incoming data.
66//config: It does not check signature hashes on the incoming data:
67//config: this means that attackers manipulating TCP packets can
68//config: send altered data and we unknowingly receive garbage.
69//config: (This check might be relatively easy to add).
70//config: It does not check public key's certificate:
71//config: this means that the peer may be an attacker impersonating
72//config: the server we think we are talking to.
73//config:
74//config: If you think this is unacceptable, consider this. As more and more
75//config: servers switch to HTTPS-only operation, without such "crippled"
76//config: TLS code it is *impossible* to simply download a kernel source
77//config: from kernel.org. Which can in real world translate into
78//config: "my small automatic tooling to build cross-compilers from sources
79//config: no longer works, I need to additionally keep a local copy
80//config: of ~4 megabyte source tarball of a SSL library and ~2 megabyte
81//config: source of wget, need to compile and built both before I can
82//config: download anything. All this despite the fact that the build
83//config: is done in a QEMU sandbox on a machine with absolutely nothing
84//config: worth stealing, so I don't care if someone would go to a lot
85//config: of trouble to intercept my HTTPS download to send me an altered
86//config: kernel tarball".
87//config:
88//config: If you still think this is unacceptable, send patches.
89//config:
90//config: If you still think this is unacceptable, do not want to send
91//config: patches, but do want to waste bandwidth expaining how wrong
92//config: it is, you will be ignored.
93//config:
54//config:config FEATURE_WGET_OPENSSL 94//config:config FEATURE_WGET_OPENSSL
55//config: bool "Try to connect to HTTPS using openssl" 95//config: bool "Try to connect to HTTPS using openssl"
56//config: default y 96//config: default y
57//config: depends on WGET 97//config: depends on WGET
58//config: help 98//config: help
59//config: Choose how wget establishes SSL connection for https:// URLs. 99//config: Try to use openssl to handle HTTPS.
60//config:
61//config: Busybox itself contains no SSL code. wget will spawn
62//config: a helper program to talk over HTTPS.
63//config: 100//config:
64//config: OpenSSL has a simple SSL client for debug purposes. 101//config: OpenSSL has a simple SSL client for debug purposes.
65//config: If you select "openssl" helper, wget will effectively run: 102//config: If you select this option, wget will effectively run:
66//config: "openssl s_client -quiet -connect hostname:443 103//config: "openssl s_client -quiet -connect hostname:443
67//config: -servername hostname 2>/dev/null" and pipe its data 104//config: -servername hostname 2>/dev/null" and pipe its data
68//config: through it. -servername is not used if hostname is numeric. 105//config: through it. -servername is not used if hostname is numeric.
@@ -75,24 +112,9 @@
75//config: openssl is also a big binary, often dynamically linked 112//config: openssl is also a big binary, often dynamically linked
76//config: against ~15 libraries. 113//config: against ~15 libraries.
77//config: 114//config:
78//config:config FEATURE_WGET_SSL_HELPER 115//config: If openssl can't be executed, internal TLS code will be used
79//config: bool "Try to connect to HTTPS using ssl_helper" 116//config: (if you enabled it); if openssl can be executed but fails later,
80//config: default y 117//config: wget can't detect this, and download will fail.
81//config: depends on WGET
82//config: help
83//config: Choose how wget establishes SSL connection for https:// URLs.
84//config:
85//config: Busybox itself contains no SSL code. wget will spawn
86//config: a helper program to talk over HTTPS.
87//config:
88//config: ssl_helper is a tool which can be built statically
89//config: from busybox sources against a small embedded SSL library.
90//config: Please see networking/ssl_helper/README.
91//config: It does not require double host resolution and emits
92//config: error messages to stderr.
93//config:
94//config: Precompiled static binary may be available at
95//config: http://busybox.net/downloads/binaries/
96 118
97//applet:IF_WGET(APPLET(wget, BB_DIR_USR_BIN, BB_SUID_DROP)) 119//applet:IF_WGET(APPLET(wget, BB_DIR_USR_BIN, BB_SUID_DROP))
98 120
@@ -105,20 +127,21 @@
105/* Since we ignore these opts, we don't show them in --help */ 127/* Since we ignore these opts, we don't show them in --help */
106/* //usage: " [--no-check-certificate] [--no-cache] [--passive-ftp] [-t TRIES]" */ 128/* //usage: " [--no-check-certificate] [--no-cache] [--passive-ftp] [-t TRIES]" */
107/* //usage: " [-nv] [-nc] [-nH] [-np]" */ 129/* //usage: " [-nv] [-nc] [-nH] [-np]" */
108//usage: " [-U|--user-agent AGENT]" IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..." 130//usage: " [-S|--server-response] [-U|--user-agent AGENT]" IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..."
109//usage: ) 131//usage: )
110//usage: IF_NOT_FEATURE_WGET_LONG_OPTIONS( 132//usage: IF_NOT_FEATURE_WGET_LONG_OPTIONS(
111//usage: "[-cq] [-O FILE] [-Y on/off] [-P DIR] [-U AGENT]" 133//usage: "[-cq] [-O FILE] [-Y on/off] [-P DIR] [-S] [-U AGENT]"
112//usage: IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..." 134//usage: IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..."
113//usage: ) 135//usage: )
114//usage:#define wget_full_usage "\n\n" 136//usage:#define wget_full_usage "\n\n"
115//usage: "Retrieve files via HTTP or FTP\n" 137//usage: "Retrieve files via HTTP or FTP\n"
116//usage: IF_FEATURE_WGET_LONG_OPTIONS( 138//usage: IF_FEATURE_WGET_LONG_OPTIONS(
117//usage: "\n --spider Spider mode - only check file existence" 139//usage: "\n --spider Only check URL existence: $? is 0 if exists"
118//usage: ) 140//usage: )
119//usage: "\n -c Continue retrieval of aborted transfer" 141//usage: "\n -c Continue retrieval of aborted transfer"
120//usage: "\n -q Quiet" 142//usage: "\n -q Quiet"
121//usage: "\n -P DIR Save to DIR (default .)" 143//usage: "\n -P DIR Save to DIR (default .)"
144//usage: "\n -S Show server response"
122//usage: IF_FEATURE_WGET_TIMEOUT( 145//usage: IF_FEATURE_WGET_TIMEOUT(
123//usage: "\n -T SEC Network read timeout is SEC seconds" 146//usage: "\n -T SEC Network read timeout is SEC seconds"
124//usage: ) 147//usage: )
@@ -141,6 +164,8 @@
141#endif 164#endif
142 165
143 166
167#define SSL_SUPPORTED (ENABLE_FEATURE_WGET_OPENSSL || ENABLE_FEATURE_WGET_HTTPS)
168
144struct host_info { 169struct host_info {
145 char *allocated; 170 char *allocated;
146 const char *path; 171 const char *path;
@@ -151,7 +176,7 @@ struct host_info {
151}; 176};
152static const char P_FTP[] ALIGN1 = "ftp"; 177static const char P_FTP[] ALIGN1 = "ftp";
153static const char P_HTTP[] ALIGN1 = "http"; 178static const char P_HTTP[] ALIGN1 = "http";
154#if ENABLE_FEATURE_WGET_OPENSSL || ENABLE_FEATURE_WGET_SSL_HELPER 179#if SSL_SUPPORTED
155static const char P_HTTPS[] ALIGN1 = "https"; 180static const char P_HTTPS[] ALIGN1 = "https";
156#endif 181#endif
157 182
@@ -232,16 +257,17 @@ struct globals {
232enum { 257enum {
233 WGET_OPT_CONTINUE = (1 << 0), 258 WGET_OPT_CONTINUE = (1 << 0),
234 WGET_OPT_QUIET = (1 << 1), 259 WGET_OPT_QUIET = (1 << 1),
235 WGET_OPT_OUTNAME = (1 << 2), 260 WGET_OPT_SERVER_RESPONSE = (1 << 2),
236 WGET_OPT_PREFIX = (1 << 3), 261 WGET_OPT_OUTNAME = (1 << 3),
237 WGET_OPT_PROXY = (1 << 4), 262 WGET_OPT_PREFIX = (1 << 4),
238 WGET_OPT_USER_AGENT = (1 << 5), 263 WGET_OPT_PROXY = (1 << 5),
239 WGET_OPT_NETWORK_READ_TIMEOUT = (1 << 6), 264 WGET_OPT_USER_AGENT = (1 << 6),
240 WGET_OPT_RETRIES = (1 << 7), 265 WGET_OPT_NETWORK_READ_TIMEOUT = (1 << 7),
241 WGET_OPT_nsomething = (1 << 8), 266 WGET_OPT_RETRIES = (1 << 8),
242 WGET_OPT_HEADER = (1 << 9) * ENABLE_FEATURE_WGET_LONG_OPTIONS, 267 WGET_OPT_nsomething = (1 << 9),
243 WGET_OPT_POST_DATA = (1 << 10) * ENABLE_FEATURE_WGET_LONG_OPTIONS, 268 WGET_OPT_HEADER = (1 << 10) * ENABLE_FEATURE_WGET_LONG_OPTIONS,
244 WGET_OPT_SPIDER = (1 << 11) * ENABLE_FEATURE_WGET_LONG_OPTIONS, 269 WGET_OPT_POST_DATA = (1 << 11) * ENABLE_FEATURE_WGET_LONG_OPTIONS,
270 WGET_OPT_SPIDER = (1 << 12) * ENABLE_FEATURE_WGET_LONG_OPTIONS,
245}; 271};
246 272
247enum { 273enum {
@@ -395,7 +421,7 @@ static FILE *open_socket(len_and_sockaddr *lsa)
395} 421}
396 422
397/* Returns '\n' if it was seen, else '\0'. Trims at first '\r' or '\n' */ 423/* Returns '\n' if it was seen, else '\0'. Trims at first '\r' or '\n' */
398static char fgets_and_trim(FILE *fp) 424static char fgets_and_trim(FILE *fp, const char *fmt)
399{ 425{
400 char c; 426 char c;
401 char *buf_ptr; 427 char *buf_ptr;
@@ -413,6 +439,9 @@ static char fgets_and_trim(FILE *fp)
413 439
414 log_io("< %s", G.wget_buf); 440 log_io("< %s", G.wget_buf);
415 441
442 if (fmt && (option_mask32 & WGET_OPT_SERVER_RESPONSE))
443 fprintf(stderr, fmt, G.wget_buf);
444
416 return c; 445 return c;
417} 446}
418 447
@@ -423,6 +452,9 @@ static int ftpcmd(const char *s1, const char *s2, FILE *fp)
423 if (!s2) 452 if (!s2)
424 s2 = ""; 453 s2 = "";
425 fprintf(fp, "%s%s\r\n", s1, s2); 454 fprintf(fp, "%s%s\r\n", s1, s2);
455 /* With --server-response, wget also shows its ftp commands */
456 if (option_mask32 & WGET_OPT_SERVER_RESPONSE)
457 fprintf(stderr, "--> %s%s\n\n", s1, s2);
426 fflush(fp); 458 fflush(fp);
427 log_io("> %s%s", s1, s2); 459 log_io("> %s%s", s1, s2);
428#if ENABLE_PLATFORM_MINGW32 460#if ENABLE_PLATFORM_MINGW32
@@ -431,7 +463,7 @@ static int ftpcmd(const char *s1, const char *s2, FILE *fp)
431 } 463 }
432 464
433 do { 465 do {
434 fgets_and_trim(fp); 466 fgets_and_trim(fp, "%s\n");
435 } while (!isdigit(G.wget_buf[0]) || G.wget_buf[3] != ' '); 467 } while (!isdigit(G.wget_buf[0]) || G.wget_buf[3] != ' ');
436#if ENABLE_PLATFORM_MINGW32 468#if ENABLE_PLATFORM_MINGW32
437 fseek(fp, 0L, SEEK_CUR); 469 fseek(fp, 0L, SEEK_CUR);
@@ -458,7 +490,7 @@ static void parse_url(const char *src_url, struct host_info *h)
458 if (strcmp(url, P_FTP) == 0) { 490 if (strcmp(url, P_FTP) == 0) {
459 h->port = bb_lookup_port(P_FTP, "tcp", 21); 491 h->port = bb_lookup_port(P_FTP, "tcp", 21);
460 } else 492 } else
461#if ENABLE_FEATURE_WGET_OPENSSL || ENABLE_FEATURE_WGET_SSL_HELPER 493#if SSL_SUPPORTED
462 if (strcmp(url, P_HTTPS) == 0) { 494 if (strcmp(url, P_HTTPS) == 0) {
463 h->port = bb_lookup_port(P_HTTPS, "tcp", 443); 495 h->port = bb_lookup_port(P_HTTPS, "tcp", 443);
464 h->protocol = P_HTTPS; 496 h->protocol = P_HTTPS;
@@ -480,7 +512,7 @@ static void parse_url(const char *src_url, struct host_info *h)
480 512
481 // FYI: 513 // FYI:
482 // "Real" wget 'http://busybox.net?var=a/b' sends this request: 514 // "Real" wget 'http://busybox.net?var=a/b' sends this request:
483 // 'GET /?var=a/b HTTP 1.0' 515 // 'GET /?var=a/b HTTP/1.0'
484 // and saves 'index.html?var=a%2Fb' (we save 'b') 516 // and saves 'index.html?var=a%2Fb' (we save 'b')
485 // wget 'http://busybox.net?login=john@doe': 517 // wget 'http://busybox.net?login=john@doe':
486 // request: 'GET /?login=john@doe HTTP/1.0' 518 // request: 'GET /?login=john@doe HTTP/1.0'
@@ -531,7 +563,7 @@ static char *gethdr(FILE *fp)
531 int c; 563 int c;
532 564
533 /* retrieve header line */ 565 /* retrieve header line */
534 c = fgets_and_trim(fp); 566 c = fgets_and_trim(fp, " %s\n");
535 567
536 /* end of the headers? */ 568 /* end of the headers? */
537 if (G.wget_buf[0] == '\0') 569 if (G.wget_buf[0] == '\0')
@@ -665,7 +697,7 @@ static int spawn_https_helper_openssl(const char *host, unsigned port)
665 char *servername; 697 char *servername;
666 int sp[2]; 698 int sp[2];
667 int pid; 699 int pid;
668 IF_FEATURE_WGET_SSL_HELPER(volatile int child_failed = 0;) 700 IF_FEATURE_WGET_HTTPS(volatile int child_failed = 0;)
669 701
670 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) != 0) 702 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) != 0)
671 /* Kernel can have AF_UNIX support disabled */ 703 /* Kernel can have AF_UNIX support disabled */
@@ -710,7 +742,7 @@ static int spawn_https_helper_openssl(const char *host, unsigned port)
710 742
711 BB_EXECVP(argv[0], argv); 743 BB_EXECVP(argv[0], argv);
712 xmove_fd(3, 2); 744 xmove_fd(3, 2);
713# if ENABLE_FEATURE_WGET_SSL_HELPER 745# if ENABLE_FEATURE_WGET_HTTPS
714 child_failed = 1; 746 child_failed = 1;
715 xfunc_die(); 747 xfunc_die();
716# else 748# else
@@ -723,7 +755,7 @@ static int spawn_https_helper_openssl(const char *host, unsigned port)
723 free(servername); 755 free(servername);
724 free(allocated); 756 free(allocated);
725 close(sp[1]); 757 close(sp[1]);
726# if ENABLE_FEATURE_WGET_SSL_HELPER 758# if ENABLE_FEATURE_WGET_HTTPS
727 if (child_failed) { 759 if (child_failed) {
728 close(sp[0]); 760 close(sp[0]);
729 return -1; 761 return -1;
@@ -733,38 +765,51 @@ static int spawn_https_helper_openssl(const char *host, unsigned port)
733} 765}
734#endif 766#endif
735 767
736/* See networking/ssl_helper/README how to build one */ 768#if ENABLE_FEATURE_WGET_HTTPS
737#if ENABLE_FEATURE_WGET_SSL_HELPER 769static void spawn_ssl_client(const char *host, int network_fd)
738static void spawn_https_helper_small(int network_fd)
739{ 770{
740 int sp[2]; 771 int sp[2];
741 int pid; 772 int pid;
773 char *servername, *p;
774
775 servername = xstrdup(host);
776 p = strrchr(servername, ':');
777 if (p) *p = '\0';
742 778
743 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) != 0) 779 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) != 0)
744 /* Kernel can have AF_UNIX support disabled */ 780 /* Kernel can have AF_UNIX support disabled */
745 bb_perror_msg_and_die("socketpair"); 781 bb_perror_msg_and_die("socketpair");
746 782
783 fflush_all();
747 pid = BB_MMU ? xfork() : xvfork(); 784 pid = BB_MMU ? xfork() : xvfork();
748 if (pid == 0) { 785 if (pid == 0) {
749 /* Child */ 786 /* Child */
750 char *argv[3];
751
752 close(sp[0]); 787 close(sp[0]);
753 xmove_fd(sp[1], 0); 788 xmove_fd(sp[1], 0);
754 xdup2(0, 1); 789 xdup2(0, 1);
755 xmove_fd(network_fd, 3); 790 if (BB_MMU) {
756 /* 791 tls_state_t *tls = new_tls_state();
757 * A simple ssl/tls helper 792 tls->ifd = tls->ofd = network_fd;
758 */ 793 tls_handshake(tls, servername);
759 argv[0] = (char*)"ssl_helper"; 794 tls_run_copy_loop(tls);
760 argv[1] = (char*)"-d3"; 795 exit(0);
761 argv[2] = NULL; 796 } else {
762 BB_EXECVP(argv[0], argv); 797 char *argv[5];
763 bb_perror_msg_and_die("can't execute '%s'", argv[0]); 798 xmove_fd(network_fd, 3);
799 argv[0] = (char*)"ssl_client";
800 argv[1] = (char*)"-s3";
801 //TODO: if (!is_ip_address(servername))...
802 argv[2] = (char*)"-n";
803 argv[3] = servername;
804 argv[4] = NULL;
805 BB_EXECVP(argv[0], argv);
806 bb_perror_msg_and_die("can't execute '%s'", argv[0]);
807 }
764 /* notreached */ 808 /* notreached */
765 } 809 }
766 810
767 /* Parent */ 811 /* Parent */
812 free(servername);
768 close(sp[1]); 813 close(sp[1]);
769 xmove_fd(sp[0], network_fd); 814 xmove_fd(sp[0], network_fd);
770} 815}
@@ -886,9 +931,9 @@ static void NOINLINE retrieve_file_data(FILE *dfp)
886 if (!G.chunked) 931 if (!G.chunked)
887 break; 932 break;
888 933
889 fgets_and_trim(dfp); /* Eat empty line */ 934 fgets_and_trim(dfp, NULL); /* Eat empty line */
890 get_clen: 935 get_clen:
891 fgets_and_trim(dfp); 936 fgets_and_trim(dfp, NULL);
892 G.content_len = STRTOOFF(G.wget_buf, NULL, 16); 937 G.content_len = STRTOOFF(G.wget_buf, NULL, 16);
893 /* FIXME: error check? */ 938 /* FIXME: error check? */
894 if (G.content_len == 0) 939 if (G.content_len == 0)
@@ -1013,16 +1058,16 @@ static void download_one_url(const char *url)
1013 1058
1014 /* Open socket to http(s) server */ 1059 /* Open socket to http(s) server */
1015#if ENABLE_FEATURE_WGET_OPENSSL 1060#if ENABLE_FEATURE_WGET_OPENSSL
1016 /* openssl (and maybe ssl_helper) support is configured */ 1061 /* openssl (and maybe internal TLS) support is configured */
1017 if (target.protocol == P_HTTPS) { 1062 if (target.protocol == P_HTTPS) {
1018 /* openssl-based helper 1063 /* openssl-based helper
1019 * Inconvenient API since we can't give it an open fd 1064 * Inconvenient API since we can't give it an open fd
1020 */ 1065 */
1021 int fd = spawn_https_helper_openssl(server.host, server.port); 1066 int fd = spawn_https_helper_openssl(server.host, server.port);
1022# if ENABLE_FEATURE_WGET_SSL_HELPER 1067# if ENABLE_FEATURE_WGET_HTTPS
1023 if (fd < 0) { /* no openssl? try ssl_helper */ 1068 if (fd < 0) { /* no openssl? try internal */
1024 sfp = open_socket(lsa); 1069 sfp = open_socket(lsa);
1025 spawn_https_helper_small(fileno(sfp)); 1070 spawn_ssl_client(server.host, fileno(sfp));
1026 goto socket_opened; 1071 goto socket_opened;
1027 } 1072 }
1028# else 1073# else
@@ -1035,11 +1080,11 @@ static void download_one_url(const char *url)
1035 } 1080 }
1036 sfp = open_socket(lsa); 1081 sfp = open_socket(lsa);
1037 socket_opened: 1082 socket_opened:
1038#elif ENABLE_FEATURE_WGET_SSL_HELPER 1083#elif ENABLE_FEATURE_WGET_HTTPS
1039 /* Only ssl_helper support is configured */ 1084 /* Only internal TLS support is configured */
1040 sfp = open_socket(lsa); 1085 sfp = open_socket(lsa);
1041 if (target.protocol == P_HTTPS) 1086 if (target.protocol == P_HTTPS)
1042 spawn_https_helper_small(fileno(sfp)); 1087 spawn_ssl_client(server.host, fileno(sfp));
1043#else 1088#else
1044 /* ssl (https) support is not configured */ 1089 /* ssl (https) support is not configured */
1045 sfp = open_socket(lsa); 1090 sfp = open_socket(lsa);
@@ -1099,18 +1144,26 @@ static void download_one_url(const char *url)
1099 } 1144 }
1100 1145
1101 fflush(sfp); 1146 fflush(sfp);
1102 /* If we use SSL helper, keeping our end of the socket open for writing 1147
1103 * makes our end (i.e. the same fd!) readable (EAGAIN instead of EOF) 1148/* Tried doing this unconditionally.
1104 * even after child closes its copy of the fd. 1149 * Cloudflare and nginx/1.11.5 are shocked to see SHUT_WR on non-HTTPS.
1105 * This helps: 1150 */
1106 */ 1151#if SSL_SUPPORTED
1107 shutdown(fileno(sfp), SHUT_WR); 1152 if (target.protocol == P_HTTPS) {
1153 /* If we use SSL helper, keeping our end of the socket open for writing
1154 * makes our end (i.e. the same fd!) readable (EAGAIN instead of EOF)
1155 * even after child closes its copy of the fd.
1156 * This helps:
1157 */
1158 shutdown(fileno(sfp), SHUT_WR);
1159 }
1160#endif
1108 1161
1109 /* 1162 /*
1110 * Retrieve HTTP response line and check for "200" status code. 1163 * Retrieve HTTP response line and check for "200" status code.
1111 */ 1164 */
1112 read_response: 1165 read_response:
1113 fgets_and_trim(sfp); 1166 fgets_and_trim(sfp, " %s\n");
1114 1167
1115 str = G.wget_buf; 1168 str = G.wget_buf;
1116 str = skip_non_whitespace(str); 1169 str = skip_non_whitespace(str);
@@ -1295,6 +1348,7 @@ int wget_main(int argc UNUSED_PARAM, char **argv)
1295 /* name, has_arg, val */ 1348 /* name, has_arg, val */
1296 "continue\0" No_argument "c" 1349 "continue\0" No_argument "c"
1297 "quiet\0" No_argument "q" 1350 "quiet\0" No_argument "q"
1351 "server-response\0" No_argument "S"
1298 "output-document\0" Required_argument "O" 1352 "output-document\0" Required_argument "O"
1299 "directory-prefix\0" Required_argument "P" 1353 "directory-prefix\0" Required_argument "P"
1300 "proxy\0" Required_argument "Y" 1354 "proxy\0" Required_argument "Y"
@@ -1337,7 +1391,7 @@ IF_DESKTOP( "no-parent\0" No_argument "\xf0")
1337#endif 1391#endif
1338 opt_complementary = "-1" /* at least one URL */ 1392 opt_complementary = "-1" /* at least one URL */
1339 IF_FEATURE_WGET_LONG_OPTIONS(":\xff::"); /* --header is a list */ 1393 IF_FEATURE_WGET_LONG_OPTIONS(":\xff::"); /* --header is a list */
1340 getopt32(argv, "cqO:P:Y:U:T:+" 1394 getopt32(argv, "cqSO:P:Y:U:T:+"
1341 /*ignored:*/ "t:" 1395 /*ignored:*/ "t:"
1342 /*ignored:*/ "n::" 1396 /*ignored:*/ "n::"
1343 /* wget has exactly four -n<letter> opts, all of which we can ignore: 1397 /* wget has exactly four -n<letter> opts, all of which we can ignore:
diff --git a/printutils/lpr.c b/printutils/lpr.c
index ed6a84a93..8cc87d167 100644
--- a/printutils/lpr.c
+++ b/printutils/lpr.c
@@ -23,6 +23,7 @@
23//config: help 23//config: help
24//config: lpq is a print spool queue examination and manipulation program. 24//config: lpq is a print spool queue examination and manipulation program.
25 25
26// APPLET_ODDNAME:name main location suid_type help
26//applet:IF_LPQ(APPLET_ODDNAME(lpq, lpqr, BB_DIR_USR_BIN, BB_SUID_DROP, lpq)) 27//applet:IF_LPQ(APPLET_ODDNAME(lpq, lpqr, BB_DIR_USR_BIN, BB_SUID_DROP, lpq))
27//applet:IF_LPR(APPLET_ODDNAME(lpr, lpqr, BB_DIR_USR_BIN, BB_SUID_DROP, lpr)) 28//applet:IF_LPR(APPLET_ODDNAME(lpr, lpqr, BB_DIR_USR_BIN, BB_SUID_DROP, lpr))
28 29
diff --git a/procps/Config.src b/procps/Config.src
index eb4760752..35fef2eda 100644
--- a/procps/Config.src
+++ b/procps/Config.src
@@ -8,7 +8,7 @@ menu "Process Utilities"
8INSERT 8INSERT
9 9
10config FEATURE_SHOW_THREADS 10config FEATURE_SHOW_THREADS
11 bool "Support for showing threads in ps/pstree/top" 11 bool "Support thread display in ps/pstree/top"
12 default y 12 default y
13 depends on PS || TOP || PSTREE 13 depends on PS || TOP || PSTREE
14 help 14 help
diff --git a/procps/Kbuild.src b/procps/Kbuild.src
index e7adc7340..6b4fb7470 100644
--- a/procps/Kbuild.src
+++ b/procps/Kbuild.src
@@ -7,7 +7,3 @@
7lib-y:= 7lib-y:=
8 8
9INSERT 9INSERT
10
11lib-$(CONFIG_ASH) += kill.o # used for built-in kill by ash
12lib-$(CONFIG_SH_IS_ASH) += kill.o # used for built-in kill by ash
13lib-$(CONFIG_BASH_IS_ASH) += kill.o # used for built-in kill by ash
diff --git a/procps/kill.c b/procps/kill.c
index 57a33bcaa..7ae5beead 100644
--- a/procps/kill.c
+++ b/procps/kill.c
@@ -33,7 +33,8 @@
33//config: the script it was called from. 33//config: the script it was called from.
34 34
35//applet:IF_KILL(APPLET(kill, BB_DIR_BIN, BB_SUID_DROP)) 35//applet:IF_KILL(APPLET(kill, BB_DIR_BIN, BB_SUID_DROP))
36//applet:IF_KILLALL(APPLET_ODDNAME(killall, kill, BB_DIR_USR_BIN, BB_SUID_DROP, killall)) 36// APPLET_ODDNAME:name main location suid_type help
37//applet:IF_KILLALL( APPLET_ODDNAME(killall, kill, BB_DIR_USR_BIN, BB_SUID_DROP, killall))
37//applet:IF_KILLALL5(APPLET_ODDNAME(killall5, kill, BB_DIR_USR_SBIN, BB_SUID_DROP, killall5)) 38//applet:IF_KILLALL5(APPLET_ODDNAME(killall5, kill, BB_DIR_USR_SBIN, BB_SUID_DROP, killall5))
38 39
39//kbuild:lib-$(CONFIG_KILL) += kill.o 40//kbuild:lib-$(CONFIG_KILL) += kill.o
@@ -92,28 +93,34 @@
92 * This is needed to avoid collision with kill -9 ... syntax 93 * This is needed to avoid collision with kill -9 ... syntax
93 */ 94 */
94 95
96//kbuild:lib-$(CONFIG_ASH_JOB_CONTROL) += kill.o
97//kbuild:lib-$(CONFIG_HUSH_KILL) += kill.o
98
99#define SH_KILL (ENABLE_ASH_JOB_CONTROL || ENABLE_HUSH_KILL)
100/* If shells want to have "kill", for ifdefs it's like ENABLE_KILL=1 */
101#if SH_KILL
102# undef ENABLE_KILL
103# define ENABLE_KILL 1
104#endif
105#define KILL_APPLET_CNT (ENABLE_KILL + ENABLE_KILLALL + ENABLE_KILLALL5)
106
95int kill_main(int argc UNUSED_PARAM, char **argv) 107int kill_main(int argc UNUSED_PARAM, char **argv)
96{ 108{
97 char *arg; 109 char *arg;
98 pid_t pid; 110 pid_t pid;
99 int signo = SIGTERM, errors = 0, quiet = 0; 111 int signo = SIGTERM, errors = 0, quiet = 0;
100#if ENABLE_KILL && !ENABLE_KILLALL && !ENABLE_KILLALL5 112
101# define killall 0 113#if KILL_APPLET_CNT == 1
102# define killall5 0 114# define is_killall ENABLE_KILLALL
103#elif !ENABLE_KILL && ENABLE_KILLALL && !ENABLE_KILLALL5 115# define is_killall5 ENABLE_KILLALL5
104# define killall 1
105# define killall5 0
106#elif !ENABLE_KILL && !ENABLE_KILLALL && ENABLE_KILLALL5
107# define killall 0
108# define killall5 1
109#else 116#else
110/* How to determine who we are? find 3rd char from the end: 117/* How to determine who we are? find 3rd char from the end:
111 * kill, killall, killall5 118 * kill, killall, killall5
112 * ^i ^a ^l - it's unique 119 * ^i ^a ^l - it's unique
113 * (checking from the start is complicated by /bin/kill... case) */ 120 * (checking from the start is complicated by /bin/kill... case) */
114 const char char3 = argv[0][strlen(argv[0]) - 3]; 121 const char char3 = argv[0][strlen(argv[0]) - 3];
115# define killall (ENABLE_KILLALL && char3 == 'a') 122# define is_killall (ENABLE_KILLALL && char3 == 'a')
116# define killall5 (ENABLE_KILLALL5 && char3 == 'l') 123# define is_killall5 (ENABLE_KILLALL5 && char3 == 'l')
117#endif 124#endif
118 125
119 /* Parse any options */ 126 /* Parse any options */
@@ -162,7 +169,7 @@ int kill_main(int argc UNUSED_PARAM, char **argv)
162 } 169 }
163 170
164 /* The -q quiet option */ 171 /* The -q quiet option */
165 if (killall && arg[1] == 'q' && arg[2] == '\0') { 172 if (is_killall && arg[1] == 'q' && arg[2] == '\0') {
166 quiet = 1; 173 quiet = 1;
167 arg = *++argv; 174 arg = *++argv;
168 if (!arg) 175 if (!arg)
@@ -174,7 +181,7 @@ int kill_main(int argc UNUSED_PARAM, char **argv)
174 arg++; /* skip '-' */ 181 arg++; /* skip '-' */
175 182
176 /* -o PID? (if present, it always is at the end of command line) */ 183 /* -o PID? (if present, it always is at the end of command line) */
177 if (killall5 && arg[0] == 'o') 184 if (is_killall5 && arg[0] == 'o')
178 goto do_it_now; 185 goto do_it_now;
179 186
180 if (argv[1] && arg[0] == 's' && arg[1] == '\0') { /* -s SIG? */ 187 if (argv[1] && arg[0] == 's' && arg[1] == '\0') { /* -s SIG? */
@@ -190,7 +197,7 @@ int kill_main(int argc UNUSED_PARAM, char **argv)
190 do_it_now: 197 do_it_now:
191 pid = getpid(); 198 pid = getpid();
192 199
193 if (killall5) { 200 if (is_killall5) {
194 pid_t sid; 201 pid_t sid;
195 procps_status_t* p = NULL; 202 procps_status_t* p = NULL;
196 /* compat: exitcode 2 is "no one was signaled" */ 203 /* compat: exitcode 2 is "no one was signaled" */
@@ -248,13 +255,14 @@ int kill_main(int argc UNUSED_PARAM, char **argv)
248 return ret; 255 return ret;
249 } 256 }
250 257
258#if ENABLE_KILL || ENABLE_KILLALL
251 /* Pid or name is required for kill/killall */ 259 /* Pid or name is required for kill/killall */
252 if (!arg) { 260 if (!arg) {
253 bb_error_msg("you need to specify whom to kill"); 261 bb_error_msg("you need to specify whom to kill");
254 return EXIT_FAILURE; 262 return EXIT_FAILURE;
255 } 263 }
256 264
257 if (killall) { 265 if (!ENABLE_KILL || is_killall) {
258 /* Looks like they want to do a killall. Do that */ 266 /* Looks like they want to do a killall. Do that */
259 do { 267 do {
260 pid_t* pidList; 268 pid_t* pidList;
@@ -282,10 +290,12 @@ int kill_main(int argc UNUSED_PARAM, char **argv)
282 } while (arg); 290 } while (arg);
283 return errors; 291 return errors;
284 } 292 }
293#endif
285 294
295#if ENABLE_KILL
286 /* Looks like they want to do a kill. Do that */ 296 /* Looks like they want to do a kill. Do that */
287 while (arg) { 297 while (arg) {
288#if ENABLE_ASH || ENABLE_HUSH 298# if SH_KILL
289 /* 299 /*
290 * We need to support shell's "hack formats" of 300 * We need to support shell's "hack formats" of
291 * " -PRGP_ID" (yes, with a leading space) 301 * " -PRGP_ID" (yes, with a leading space)
@@ -307,7 +317,7 @@ int kill_main(int argc UNUSED_PARAM, char **argv)
307 } 317 }
308 arg = end; /* can only point to ' ' or '\0' now */ 318 arg = end; /* can only point to ' ' or '\0' now */
309 } 319 }
310#else 320# else /* ENABLE_KILL but !SH_KILL */
311 pid = bb_strtoi(arg, NULL, 10); 321 pid = bb_strtoi(arg, NULL, 10);
312 if (errno) { 322 if (errno) {
313 bb_error_msg("invalid number '%s'", arg); 323 bb_error_msg("invalid number '%s'", arg);
@@ -316,8 +326,9 @@ int kill_main(int argc UNUSED_PARAM, char **argv)
316 bb_perror_msg("can't kill pid %d", (int)pid); 326 bb_perror_msg("can't kill pid %d", (int)pid);
317 errors++; 327 errors++;
318 } 328 }
319#endif 329# endif
320 arg = *++argv; 330 arg = *++argv;
321 } 331 }
322 return errors; 332 return errors;
333#endif
323} 334}
diff --git a/procps/nmeter.c b/procps/nmeter.c
index 3eac2d3b2..05bf0a08c 100644
--- a/procps/nmeter.c
+++ b/procps/nmeter.c
@@ -24,7 +24,7 @@
24//usage: "\n -d MSEC Milliseconds between updates, default:1000, none:-1" 24//usage: "\n -d MSEC Milliseconds between updates, default:1000, none:-1"
25//usage: "\n" 25//usage: "\n"
26//usage: "\nFormat specifiers:" 26//usage: "\nFormat specifiers:"
27//usage: "\n %Nc or %[cN] CPU. N - bar size (default:10)" 27//usage: "\n %Nc or %[cN] CPU. N - bar size (default 10)"
28//usage: "\n (displays: S:system U:user N:niced D:iowait I:irq i:softirq)" 28//usage: "\n (displays: S:system U:user N:niced D:iowait I:irq i:softirq)"
29//usage: "\n %[nINTERFACE] Network INTERFACE" 29//usage: "\n %[nINTERFACE] Network INTERFACE"
30//usage: "\n %m Allocated memory" 30//usage: "\n %m Allocated memory"
diff --git a/procps/pgrep.c b/procps/pgrep.c
index ac82b5156..e932a32bc 100644
--- a/procps/pgrep.c
+++ b/procps/pgrep.c
@@ -19,6 +19,7 @@
19//config: Send signals to processes by name. 19//config: Send signals to processes by name.
20 20
21//applet:IF_PGREP(APPLET(pgrep, BB_DIR_USR_BIN, BB_SUID_DROP)) 21//applet:IF_PGREP(APPLET(pgrep, BB_DIR_USR_BIN, BB_SUID_DROP))
22// APPLET_ODDNAME:name main location suid_type help
22//applet:IF_PKILL(APPLET_ODDNAME(pkill, pgrep, BB_DIR_USR_BIN, BB_SUID_DROP, pkill)) 23//applet:IF_PKILL(APPLET_ODDNAME(pkill, pgrep, BB_DIR_USR_BIN, BB_SUID_DROP, pkill))
23 24
24//kbuild:lib-$(CONFIG_PGREP) += pgrep.o 25//kbuild:lib-$(CONFIG_PGREP) += pgrep.o
diff --git a/procps/pidof.c b/procps/pidof.c
index 069adb7a4..b64f0cbd6 100644
--- a/procps/pidof.c
+++ b/procps/pidof.c
@@ -14,18 +14,18 @@
14//config: those id's on the standard output. 14//config: those id's on the standard output.
15//config: 15//config:
16//config:config FEATURE_PIDOF_SINGLE 16//config:config FEATURE_PIDOF_SINGLE
17//config: bool "Enable argument for single shot (-s)" 17//config: bool "Enable single shot (-s)"
18//config: default y 18//config: default y
19//config: depends on PIDOF 19//config: depends on PIDOF
20//config: help 20//config: help
21//config: Support argument '-s' for returning only the first pid found. 21//config: Support '-s' for returning only the first pid found.
22//config: 22//config:
23//config:config FEATURE_PIDOF_OMIT 23//config:config FEATURE_PIDOF_OMIT
24//config: bool "Enable argument for omitting pids (-o)" 24//config: bool "Enable omitting pids (-o PID)"
25//config: default y 25//config: default y
26//config: depends on PIDOF 26//config: depends on PIDOF
27//config: help 27//config: help
28//config: Support argument '-o' for omitting the given pids in output. 28//config: Support '-o PID' for omitting the given pid(s) in output.
29//config: The special pid %PPID can be used to name the parent process 29//config: The special pid %PPID can be used to name the parent process
30//config: of the pidof, in other words the calling shell or shell script. 30//config: of the pidof, in other words the calling shell or shell script.
31 31
diff --git a/procps/powertop.c b/procps/powertop.c
index ce85f4191..413806836 100644
--- a/procps/powertop.c
+++ b/procps/powertop.c
@@ -18,6 +18,14 @@
18//config: default y 18//config: default y
19//config: help 19//config: help
20//config: Analyze power consumption on Intel-based laptops 20//config: Analyze power consumption on Intel-based laptops
21//config:
22//config:config FEATURE_POWERTOP_INTERACTIVE
23//config: bool "Accept keyboard commands"
24//config: default y
25//config: depends on POWERTOP
26//config: help
27//config: Without this, powertop will only refresh display every 10 seconds.
28//config: No keyboard commands will work, only ^C to terminate.
21 29
22// XXX This should be configurable 30// XXX This should be configurable
23#define ENABLE_FEATURE_POWERTOP_PROCIRQ 1 31#define ENABLE_FEATURE_POWERTOP_PROCIRQ 1
@@ -82,7 +90,7 @@ struct globals {
82 ullong last_usage[MAX_CSTATE_COUNT]; 90 ullong last_usage[MAX_CSTATE_COUNT];
83 ullong start_duration[MAX_CSTATE_COUNT]; 91 ullong start_duration[MAX_CSTATE_COUNT];
84 ullong last_duration[MAX_CSTATE_COUNT]; 92 ullong last_duration[MAX_CSTATE_COUNT];
85#if ENABLE_FEATURE_USE_TERMIOS 93#if ENABLE_FEATURE_POWERTOP_INTERACTIVE
86 struct termios init_settings; 94 struct termios init_settings;
87#endif 95#endif
88}; 96};
@@ -91,7 +99,7 @@ struct globals {
91 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ 99 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
92} while (0) 100} while (0)
93 101
94#if ENABLE_FEATURE_USE_TERMIOS 102#if ENABLE_FEATURE_POWERTOP_INTERACTIVE
95static void reset_term(void) 103static void reset_term(void)
96{ 104{
97 tcsetattr_stdin_TCSANOW(&G.init_settings); 105 tcsetattr_stdin_TCSANOW(&G.init_settings);
@@ -682,8 +690,7 @@ int powertop_main(int UNUSED_PARAM argc, char UNUSED_PARAM **argv)
682 ullong cur_usage[MAX_CSTATE_COUNT]; 690 ullong cur_usage[MAX_CSTATE_COUNT];
683 ullong cur_duration[MAX_CSTATE_COUNT]; 691 ullong cur_duration[MAX_CSTATE_COUNT];
684 char cstate_lines[MAX_CSTATE_COUNT + 2][64]; 692 char cstate_lines[MAX_CSTATE_COUNT + 2][64];
685#if ENABLE_FEATURE_USE_TERMIOS 693#if ENABLE_FEATURE_POWERTOP_INTERACTIVE
686 struct termios new_settings;
687 struct pollfd pfd[1]; 694 struct pollfd pfd[1];
688 695
689 pfd[0].fd = 0; 696 pfd[0].fd = 0;
@@ -706,15 +713,12 @@ int powertop_main(int UNUSED_PARAM argc, char UNUSED_PARAM **argv)
706 713
707 puts("Collecting data for "DEFAULT_SLEEP_STR" seconds"); 714 puts("Collecting data for "DEFAULT_SLEEP_STR" seconds");
708 715
709#if ENABLE_FEATURE_USE_TERMIOS 716#if ENABLE_FEATURE_POWERTOP_INTERACTIVE
710 tcgetattr(0, (void *)&G.init_settings); 717 /* Turn on unbuffered input; turn off echoing, ^C ^Z etc */
711 memcpy(&new_settings, &G.init_settings, sizeof(new_settings)); 718 set_termios_to_raw(STDIN_FILENO, &G.init_settings, TERMIOS_CLEAR_ISIG);
712 /* Turn on unbuffered input, turn off echoing */ 719 bb_signals(BB_FATAL_SIGS, sig_handler);
713 new_settings.c_lflag &= ~(ISIG | ICANON | ECHO | ECHONL);
714 /* So we don't forget to reset term settings */ 720 /* So we don't forget to reset term settings */
715 atexit(reset_term); 721 atexit(reset_term);
716 bb_signals(BB_FATAL_SIGS, sig_handler);
717 tcsetattr_stdin_TCSANOW(&new_settings);
718#endif 722#endif
719 723
720 /* Collect initial data */ 724 /* Collect initial data */
@@ -739,7 +743,7 @@ int powertop_main(int UNUSED_PARAM argc, char UNUSED_PARAM **argv)
739 int i; 743 int i;
740 744
741 G.cant_enable_timer_stats |= start_timer(); /* 1 on error */ 745 G.cant_enable_timer_stats |= start_timer(); /* 1 on error */
742#if !ENABLE_FEATURE_USE_TERMIOS 746#if !ENABLE_FEATURE_POWERTOP_INTERACTIVE
743 sleep(DEFAULT_SLEEP); 747 sleep(DEFAULT_SLEEP);
744#else 748#else
745 if (safe_poll(pfd, 1, DEFAULT_SLEEP * 1000) > 0) { 749 if (safe_poll(pfd, 1, DEFAULT_SLEEP * 1000) > 0) {
diff --git a/procps/ps.c b/procps/ps.c
index 902811f31..f7242f2d5 100644
--- a/procps/ps.c
+++ b/procps/ps.c
@@ -32,19 +32,10 @@
32//config: Adds fields PPID, RSS, START, TIME & TTY 32//config: Adds fields PPID, RSS, START, TIME & TTY
33//config: 33//config:
34//config:config FEATURE_PS_TIME 34//config:config FEATURE_PS_TIME
35//config: bool "Enable time and elapsed time output" 35//config: bool "Support -o time and -o etime output specifiers"
36//config: default y 36//config: default y
37//config: depends on PS && DESKTOP 37//config: depends on PS && DESKTOP
38//config: select PLATFORM_LINUX 38//config: select PLATFORM_LINUX
39//config: help
40//config: Support -o time and -o etime output specifiers.
41//config:
42//config:config FEATURE_PS_ADDITIONAL_COLUMNS
43//config: bool "Enable additional ps columns"
44//config: default y
45//config: depends on PS && DESKTOP
46//config: help
47//config: Support -o rgroup, -o ruser, -o nice output specifiers.
48//config: 39//config:
49//config:config FEATURE_PS_UNUSUAL_SYSTEMS 40//config:config FEATURE_PS_UNUSUAL_SYSTEMS
50//config: bool "Support Linux prior to 2.4.0 and non-ELF systems" 41//config: bool "Support Linux prior to 2.4.0 and non-ELF systems"
@@ -53,6 +44,11 @@
53//config: help 44//config: help
54//config: Include support for measuring HZ on old kernels and non-ELF systems 45//config: Include support for measuring HZ on old kernels and non-ELF systems
55//config: (if you are on Linux 2.4.0+ and use ELF, you don't need this) 46//config: (if you are on Linux 2.4.0+ and use ELF, you don't need this)
47//config:
48//config:config FEATURE_PS_ADDITIONAL_COLUMNS
49//config: bool "Support -o rgroup, -o ruser, -o nice specifiers"
50//config: default y
51//config: depends on PS && DESKTOP
56 52
57//applet:IF_PS(APPLET(ps, BB_DIR_BIN, BB_SUID_DROP)) 53//applet:IF_PS(APPLET(ps, BB_DIR_BIN, BB_SUID_DROP))
58 54
@@ -628,7 +624,9 @@ int ps_main(int argc UNUSED_PARAM, char **argv)
628 procps_status_t *p; 624 procps_status_t *p;
629 llist_t* opt_o = NULL; 625 llist_t* opt_o = NULL;
630 char default_o[sizeof(DEFAULT_O_STR)]; 626 char default_o[sizeof(DEFAULT_O_STR)];
627#if ENABLE_SELINUX || ENABLE_FEATURE_SHOW_THREADS
631 int opt; 628 int opt;
629#endif
632 enum { 630 enum {
633 OPT_Z = (1 << 0), 631 OPT_Z = (1 << 0),
634 OPT_o = (1 << 1), 632 OPT_o = (1 << 1),
@@ -658,7 +656,11 @@ int ps_main(int argc UNUSED_PARAM, char **argv)
658 * procps v3.2.7 supports -T and shows tids as SPID column, 656 * procps v3.2.7 supports -T and shows tids as SPID column,
659 * it also supports -L where it shows tids as LWP column. 657 * it also supports -L where it shows tids as LWP column.
660 */ 658 */
661 opt = getopt32(argv, "Zo:*aAdefl"IF_FEATURE_SHOW_THREADS("T"), &opt_o); 659#if ENABLE_SELINUX || ENABLE_FEATURE_SHOW_THREADS
660 opt =
661#endif
662 getopt32(argv, "Zo:*aAdefl"IF_FEATURE_SHOW_THREADS("T"), &opt_o);
663
662 if (opt_o) { 664 if (opt_o) {
663 do { 665 do {
664 parse_o(llist_pop(&opt_o)); 666 parse_o(llist_pop(&opt_o));
diff --git a/procps/pstree.c b/procps/pstree.c
index c5fb83688..f97e99639 100644
--- a/procps/pstree.c
+++ b/procps/pstree.c
@@ -357,7 +357,9 @@ static void handle_thread(const char *comm, pid_t pid, pid_t ppid, uid_t uid)
357static void mread_proc(void) 357static void mread_proc(void)
358{ 358{
359 procps_status_t *p = NULL; 359 procps_status_t *p = NULL;
360#if ENABLE_FEATURE_SHOW_THREADS
360 pid_t parent = 0; 361 pid_t parent = 0;
362#endif
361 int flags = PSSCAN_COMM | PSSCAN_PID | PSSCAN_PPID | PSSCAN_UIDGID | PSSCAN_TASKS; 363 int flags = PSSCAN_COMM | PSSCAN_PID | PSSCAN_PPID | PSSCAN_UIDGID | PSSCAN_TASKS;
362 364
363 while ((p = procps_scan(p, flags)) != NULL) { 365 while ((p = procps_scan(p, flags)) != NULL) {
@@ -368,7 +370,9 @@ static void mread_proc(void)
368#endif 370#endif
369 { 371 {
370 add_proc(p->comm, p->pid, p->ppid, p->uid/*, 0*/); 372 add_proc(p->comm, p->pid, p->ppid, p->uid/*, 0*/);
373#if ENABLE_FEATURE_SHOW_THREADS
371 parent = p->pid; 374 parent = p->pid;
375#endif
372 } 376 }
373 } 377 }
374} 378}
diff --git a/procps/top.c b/procps/top.c
index 71207bac1..ff2fddeea 100644
--- a/procps/top.c
+++ b/procps/top.c
@@ -56,6 +56,14 @@
56//config: The top program provides a dynamic real-time view of a running 56//config: The top program provides a dynamic real-time view of a running
57//config: system. 57//config: system.
58//config: 58//config:
59//config:config FEATURE_TOP_INTERACTIVE
60//config: bool "Accept keyboard commands"
61//config: default y
62//config: depends on TOP
63//config: help
64//config: Without this, top will only refresh display every 5 seconds.
65//config: No keyboard commands will work, only ^C to terminate.
66//config:
59//config:config FEATURE_TOP_CPU_USAGE_PERCENTAGE 67//config:config FEATURE_TOP_CPU_USAGE_PERCENTAGE
60//config: bool "Show CPU per-process usage percentage" 68//config: bool "Show CPU per-process usage percentage"
61//config: default y 69//config: default y
@@ -158,7 +166,7 @@ struct globals {
158 smallint smp_cpu_info; /* one/many cpu info lines? */ 166 smallint smp_cpu_info; /* one/many cpu info lines? */
159#endif 167#endif
160 unsigned lines; /* screen height */ 168 unsigned lines; /* screen height */
161#if ENABLE_FEATURE_USE_TERMIOS 169#if ENABLE_FEATURE_TOP_INTERACTIVE
162 struct termios initial_settings; 170 struct termios initial_settings;
163 int scroll_ofs; 171 int scroll_ofs;
164#define G_scroll_ofs G.scroll_ofs 172#define G_scroll_ofs G.scroll_ofs
@@ -181,7 +189,7 @@ struct globals {
181 jiffy_counts_t *cpu_jif, *cpu_prev_jif; 189 jiffy_counts_t *cpu_jif, *cpu_prev_jif;
182 int num_cpus; 190 int num_cpus;
183#endif 191#endif
184#if ENABLE_FEATURE_USE_TERMIOS 192#if ENABLE_FEATURE_TOP_INTERACTIVE
185 char kbd_input[KEYCODE_BUFFER_SIZE]; 193 char kbd_input[KEYCODE_BUFFER_SIZE];
186#endif 194#endif
187 char line_buf[80]; 195 char line_buf[80];
@@ -220,7 +228,7 @@ enum {
220#define OPT_BATCH_MODE (option_mask32 & OPT_b) 228#define OPT_BATCH_MODE (option_mask32 & OPT_b)
221 229
222 230
223#if ENABLE_FEATURE_USE_TERMIOS 231#if ENABLE_FEATURE_TOP_INTERACTIVE
224static int pid_sort(top_status_t *P, top_status_t *Q) 232static int pid_sort(top_status_t *P, top_status_t *Q)
225{ 233{
226 /* Buggy wrt pids with high bit set */ 234 /* Buggy wrt pids with high bit set */
@@ -725,8 +733,7 @@ static void clearmems(void)
725 top = NULL; 733 top = NULL;
726} 734}
727 735
728#if ENABLE_FEATURE_USE_TERMIOS 736#if ENABLE_FEATURE_TOP_INTERACTIVE
729
730static void reset_term(void) 737static void reset_term(void)
731{ 738{
732 if (!OPT_BATCH_MODE) 739 if (!OPT_BATCH_MODE)
@@ -738,8 +745,7 @@ static void sig_catcher(int sig)
738 reset_term(); 745 reset_term();
739 kill_myself_with_sig(sig); 746 kill_myself_with_sig(sig);
740} 747}
741 748#endif /* FEATURE_TOP_INTERACTIVE */
742#endif /* FEATURE_USE_TERMIOS */
743 749
744/* 750/*
745 * TOPMEM support 751 * TOPMEM support
@@ -894,7 +900,7 @@ enum {
894 EXIT_MASK = (unsigned)-1, 900 EXIT_MASK = (unsigned)-1,
895}; 901};
896 902
897#if ENABLE_FEATURE_USE_TERMIOS 903#if ENABLE_FEATURE_TOP_INTERACTIVE
898static unsigned handle_input(unsigned scan_mask, unsigned interval) 904static unsigned handle_input(unsigned scan_mask, unsigned interval)
899{ 905{
900 if (option_mask32 & OPT_EOF) { 906 if (option_mask32 & OPT_EOF) {
@@ -1043,7 +1049,7 @@ static unsigned handle_input(unsigned scan_mask, unsigned interval)
1043//usage: "\n""Read the status of all processes from /proc each SECONDS" 1049//usage: "\n""Read the status of all processes from /proc each SECONDS"
1044//usage: "\n""and display a screenful of them." 1050//usage: "\n""and display a screenful of them."
1045//usage: "\n" 1051//usage: "\n"
1046//usage: IF_FEATURE_USE_TERMIOS( 1052//usage: IF_FEATURE_TOP_INTERACTIVE(
1047//usage: "Keys:" 1053//usage: "Keys:"
1048//usage: "\n"" N/M" 1054//usage: "\n"" N/M"
1049//usage: IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE("/P") 1055//usage: IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE("/P")
@@ -1091,9 +1097,6 @@ int top_main(int argc UNUSED_PARAM, char **argv)
1091 unsigned interval; 1097 unsigned interval;
1092 char *str_interval, *str_iterations; 1098 char *str_interval, *str_iterations;
1093 unsigned scan_mask = TOP_MASK; 1099 unsigned scan_mask = TOP_MASK;
1094#if ENABLE_FEATURE_USE_TERMIOS
1095 struct termios new_settings;
1096#endif
1097 1100
1098 INIT_G(); 1101 INIT_G();
1099 1102
@@ -1141,13 +1144,10 @@ int top_main(int argc UNUSED_PARAM, char **argv)
1141 if (OPT_BATCH_MODE) { 1144 if (OPT_BATCH_MODE) {
1142 option_mask32 |= OPT_EOF; 1145 option_mask32 |= OPT_EOF;
1143 } 1146 }
1144#if ENABLE_FEATURE_USE_TERMIOS 1147#if ENABLE_FEATURE_TOP_INTERACTIVE
1145 else { 1148 else {
1146 tcgetattr(0, (void *) &initial_settings); 1149 /* Turn on unbuffered input; turn off echoing, ^C ^Z etc */
1147 memcpy(&new_settings, &initial_settings, sizeof(new_settings)); 1150 set_termios_to_raw(STDIN_FILENO, &initial_settings, TERMIOS_CLEAR_ISIG);
1148 /* unbuffered input, turn off echo */
1149 new_settings.c_lflag &= ~(ISIG | ICANON | ECHO | ECHONL);
1150 tcsetattr_stdin_TCSANOW(&new_settings);
1151 } 1151 }
1152 1152
1153 bb_signals(BB_FATAL_SIGS, sig_catcher); 1153 bb_signals(BB_FATAL_SIGS, sig_catcher);
@@ -1165,14 +1165,12 @@ int top_main(int argc UNUSED_PARAM, char **argv)
1165 } else { 1165 } else {
1166 G.lines = 24; /* default */ 1166 G.lines = 24; /* default */
1167 col = 79; 1167 col = 79;
1168#if ENABLE_FEATURE_USE_TERMIOS
1169 /* We output to stdout, we need size of stdout (not stdin)! */ 1168 /* We output to stdout, we need size of stdout (not stdin)! */
1170 get_terminal_width_height(STDOUT_FILENO, &col, &G.lines); 1169 get_terminal_width_height(STDOUT_FILENO, &col, &G.lines);
1171 if (G.lines < 5 || col < 10) { 1170 if (G.lines < 5 || col < 10) {
1172 sleep(interval); 1171 sleep(interval);
1173 continue; 1172 continue;
1174 } 1173 }
1175#endif
1176 if (col > LINE_BUF_SIZE - 2) 1174 if (col > LINE_BUF_SIZE - 2)
1177 col = LINE_BUF_SIZE - 2; 1175 col = LINE_BUF_SIZE - 2;
1178 } 1176 }
@@ -1247,7 +1245,7 @@ int top_main(int argc UNUSED_PARAM, char **argv)
1247 clearmems(); 1245 clearmems();
1248 if (iterations >= 0 && !--iterations) 1246 if (iterations >= 0 && !--iterations)
1249 break; 1247 break;
1250#if !ENABLE_FEATURE_USE_TERMIOS 1248#if !ENABLE_FEATURE_TOP_INTERACTIVE
1251 sleep(interval); 1249 sleep(interval);
1252#else 1250#else
1253 scan_mask = handle_input(scan_mask, interval); 1251 scan_mask = handle_input(scan_mask, interval);
@@ -1255,7 +1253,7 @@ int top_main(int argc UNUSED_PARAM, char **argv)
1255 } /* end of "while (not Q)" */ 1253 } /* end of "while (not Q)" */
1256 1254
1257 bb_putchar('\n'); 1255 bb_putchar('\n');
1258#if ENABLE_FEATURE_USE_TERMIOS 1256#if ENABLE_FEATURE_TOP_INTERACTIVE
1259 reset_term(); 1257 reset_term();
1260#endif 1258#endif
1261 if (ENABLE_FEATURE_CLEAN_UP) { 1259 if (ENABLE_FEATURE_CLEAN_UP) {
diff --git a/procps/uptime.c b/procps/uptime.c
index 436193925..8e8956c0f 100644
--- a/procps/uptime.c
+++ b/procps/uptime.c
@@ -21,11 +21,11 @@
21//config: on, and the system load averages for the past 1, 5, and 15 minutes. 21//config: on, and the system load averages for the past 1, 5, and 15 minutes.
22//config: 22//config:
23//config:config FEATURE_UPTIME_UTMP_SUPPORT 23//config:config FEATURE_UPTIME_UTMP_SUPPORT
24//config: bool "Support for showing the number of users" 24//config: bool "Show the number of users"
25//config: default y 25//config: default y
26//config: depends on UPTIME && FEATURE_UTMP 26//config: depends on UPTIME && FEATURE_UTMP
27//config: help 27//config: help
28//config: Makes uptime display the number of users currently logged on. 28//config: Display the number of users currently logged on.
29 29
30//applet:IF_UPTIME(APPLET(uptime, BB_DIR_USR_BIN, BB_SUID_DROP)) 30//applet:IF_UPTIME(APPLET(uptime, BB_DIR_USR_BIN, BB_SUID_DROP))
31 31
diff --git a/runit/chpst.c b/runit/chpst.c
index 3769af25e..846c846d3 100644
--- a/runit/chpst.c
+++ b/runit/chpst.c
@@ -60,7 +60,8 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
60//config: Sets soft resource limits as specified by options 60//config: Sets soft resource limits as specified by options
61 61
62//applet:IF_CHPST(APPLET(chpst, BB_DIR_USR_BIN, BB_SUID_DROP)) 62//applet:IF_CHPST(APPLET(chpst, BB_DIR_USR_BIN, BB_SUID_DROP))
63//applet:IF_ENVDIR(APPLET_ODDNAME(envdir, chpst, BB_DIR_USR_BIN, BB_SUID_DROP, envdir)) 63// APPLET_ODDNAME:name main location suid_type help
64//applet:IF_ENVDIR( APPLET_ODDNAME(envdir, chpst, BB_DIR_USR_BIN, BB_SUID_DROP, envdir))
64//applet:IF_ENVUIDGID(APPLET_ODDNAME(envuidgid, chpst, BB_DIR_USR_BIN, BB_SUID_DROP, envuidgid)) 65//applet:IF_ENVUIDGID(APPLET_ODDNAME(envuidgid, chpst, BB_DIR_USR_BIN, BB_SUID_DROP, envuidgid))
65//applet:IF_SETUIDGID(APPLET_ODDNAME(setuidgid, chpst, BB_DIR_USR_BIN, BB_SUID_DROP, setuidgid)) 66//applet:IF_SETUIDGID(APPLET_ODDNAME(setuidgid, chpst, BB_DIR_USR_BIN, BB_SUID_DROP, setuidgid))
66//applet:IF_SOFTLIMIT(APPLET_ODDNAME(softlimit, chpst, BB_DIR_USR_BIN, BB_SUID_DROP, softlimit)) 67//applet:IF_SOFTLIMIT(APPLET_ODDNAME(softlimit, chpst, BB_DIR_USR_BIN, BB_SUID_DROP, softlimit))
diff --git a/scripts/gen_build_files.sh b/scripts/gen_build_files.sh
index ebee17c64..f79fa2f83 100755
--- a/scripts/gen_build_files.sh
+++ b/scripts/gen_build_files.sh
@@ -20,7 +20,9 @@ chk() { status "CHK" "$@"; }
20generate() 20generate()
21{ 21{
22 # NB: data to be inserted at INSERT line is coming on stdin 22 # NB: data to be inserted at INSERT line is coming on stdin
23 local src="$1" dst="$2" header="$3" 23 src="$1"
24 dst="$2"
25 header="$3"
24 #chk "${dst}" 26 #chk "${dst}"
25 { 27 {
26 # Need to use printf: different shells have inconsistent 28 # Need to use printf: different shells have inconsistent
diff --git a/scripts/trylink b/scripts/trylink
index c2a431626..9f288c141 100755
--- a/scripts/trylink
+++ b/scripts/trylink
@@ -46,8 +46,7 @@ try() {
46} 46}
47 47
48check_cc() { 48check_cc() {
49 local tempname="$(mktemp tmp.XXXXXXXXXX)" 49 tempname="$(mktemp tmp.XXXXXXXXXX)"
50 local r
51 echo "int main(int argc,char**argv){return argv?argc:0;}" >"$tempname".c 50 echo "int main(int argc,char**argv){return argv?argc:0;}" >"$tempname".c
52 # Can use "-o /dev/null", but older gcc tend to *unlink it* on failure! :( 51 # Can use "-o /dev/null", but older gcc tend to *unlink it* on failure! :(
53 # Was using "-xc /dev/null", but we need a valid C program. 52 # Was using "-xc /dev/null", but we need a valid C program.
@@ -55,14 +54,13 @@ check_cc() {
55 # '... -D"BB_VER=KBUILD_STR(1.N.M)" ...' 54 # '... -D"BB_VER=KBUILD_STR(1.N.M)" ...'
56 # and we need shell to process quotes! 55 # and we need shell to process quotes!
57 $CC $CFLAGS $LDFLAGS $1 "$tempname".c -o "$tempname" >/dev/null 2>&1 56 $CC $CFLAGS $LDFLAGS $1 "$tempname".c -o "$tempname" >/dev/null 2>&1
58 r=$? 57 exitcode=$?
59 rm -f "$tempname" "$tempname".c "$tempname".o 58 rm -f "$tempname" "$tempname".c "$tempname".o
60 return $r 59 return $exitcode
61} 60}
62 61
63check_libc_is_glibc() { 62check_libc_is_glibc() {
64 local tempname="$(mktemp tmp.XXXXXXXXXX)" 63 tempname="$(mktemp tmp.XXXXXXXXXX)"
65 local r
66 echo "\ 64 echo "\
67 #include <stdlib.h> 65 #include <stdlib.h>
68 /* Apparently uclibc defines __GLIBC__ (compat trick?). Oh well. */ 66 /* Apparently uclibc defines __GLIBC__ (compat trick?). Oh well. */
@@ -71,9 +69,9 @@ check_libc_is_glibc() {
71 #endif 69 #endif
72 " >"$tempname".c 70 " >"$tempname".c
73 ! $CC $CFLAGS "$tempname".c -c -o "$tempname".o >/dev/null 2>&1 71 ! $CC $CFLAGS "$tempname".c -c -o "$tempname".o >/dev/null 2>&1
74 r=$? 72 exitcode=$?
75 rm -f "$tempname" "$tempname".c "$tempname".o 73 rm -f "$tempname" "$tempname".c "$tempname".o
76 return $r 74 return $exitcode
77} 75}
78 76
79EXE="$1" 77EXE="$1"
diff --git a/selinux/chcon.c b/selinux/chcon.c
index c743013ce..ba9b08638 100644
--- a/selinux/chcon.c
+++ b/selinux/chcon.c
@@ -18,8 +18,6 @@
18//config: bool "Enable long options" 18//config: bool "Enable long options"
19//config: default y 19//config: default y
20//config: depends on CHCON && LONG_OPTS 20//config: depends on CHCON && LONG_OPTS
21//config: help
22//config: Support long options for the chcon applet.
23 21
24//applet:IF_CHCON(APPLET(chcon, BB_DIR_USR_BIN, BB_SUID_DROP)) 22//applet:IF_CHCON(APPLET(chcon, BB_DIR_USR_BIN, BB_SUID_DROP))
25 23
@@ -38,11 +36,11 @@
38//usage: "\n -c,--changes Report changes made" 36//usage: "\n -c,--changes Report changes made"
39//usage: "\n -h,--no-dereference Affect symlinks instead of their targets" 37//usage: "\n -h,--no-dereference Affect symlinks instead of their targets"
40//usage: "\n -f,--silent,--quiet Suppress most error messages" 38//usage: "\n -f,--silent,--quiet Suppress most error messages"
41//usage: "\n --reference=RFILE Use RFILE's group instead of using a CONTEXT value" 39//usage: "\n --reference RFILE Use RFILE's group instead of using a CONTEXT value"
42//usage: "\n -u,--user=USER Set user/role/type/range in the target" 40//usage: "\n -u,--user USER Set user/role/type/range in the target"
43//usage: "\n -r,--role=ROLE security context" 41//usage: "\n -r,--role ROLE security context"
44//usage: "\n -t,--type=TYPE" 42//usage: "\n -t,--type TYPE"
45//usage: "\n -l,--range=RANGE" 43//usage: "\n -l,--range RANGE"
46//usage: "\n -R,--recursive Recurse" 44//usage: "\n -R,--recursive Recurse"
47//usage: ) 45//usage: )
48//usage: IF_NOT_FEATURE_CHCON_LONG_OPTIONS( 46//usage: IF_NOT_FEATURE_CHCON_LONG_OPTIONS(
diff --git a/selinux/runcon.c b/selinux/runcon.c
index 16f171101..82f4d50d3 100644
--- a/selinux/runcon.c
+++ b/selinux/runcon.c
@@ -39,8 +39,6 @@
39//config: bool "Enable long options" 39//config: bool "Enable long options"
40//config: default y 40//config: default y
41//config: depends on RUNCON && LONG_OPTS 41//config: depends on RUNCON && LONG_OPTS
42//config: help
43//config: Support long options for the runcon applet.
44 42
45//applet:IF_RUNCON(APPLET(runcon, BB_DIR_USR_BIN, BB_SUID_DROP)) 43//applet:IF_RUNCON(APPLET(runcon, BB_DIR_USR_BIN, BB_SUID_DROP))
46 44
@@ -54,10 +52,10 @@
54//usage: "\n CONTEXT Complete security context\n" 52//usage: "\n CONTEXT Complete security context\n"
55//usage: IF_FEATURE_RUNCON_LONG_OPTIONS( 53//usage: IF_FEATURE_RUNCON_LONG_OPTIONS(
56//usage: "\n -c,--compute Compute process transition context before modifying" 54//usage: "\n -c,--compute Compute process transition context before modifying"
57//usage: "\n -t,--type=TYPE Type (for same role as parent)" 55//usage: "\n -t,--type TYPE Type (for same role as parent)"
58//usage: "\n -u,--user=USER User identity" 56//usage: "\n -u,--user USER User identity"
59//usage: "\n -r,--role=ROLE Role" 57//usage: "\n -r,--role ROLE Role"
60//usage: "\n -l,--range=RNG Levelrange" 58//usage: "\n -l,--range RNG Levelrange"
61//usage: ) 59//usage: )
62//usage: IF_NOT_FEATURE_RUNCON_LONG_OPTIONS( 60//usage: IF_NOT_FEATURE_RUNCON_LONG_OPTIONS(
63//usage: "\n -c Compute process transition context before modifying" 61//usage: "\n -c Compute process transition context before modifying"
diff --git a/selinux/setfiles.c b/selinux/setfiles.c
index 9fa5d3f30..c14a67be5 100644
--- a/selinux/setfiles.c
+++ b/selinux/setfiles.c
@@ -30,6 +30,7 @@
30//config: the same as setfiles, but usage is a little different. 30//config: the same as setfiles, but usage is a little different.
31 31
32//applet:IF_SETFILES(APPLET(setfiles, BB_DIR_SBIN, BB_SUID_DROP)) 32//applet:IF_SETFILES(APPLET(setfiles, BB_DIR_SBIN, BB_SUID_DROP))
33// APPLET_ODDNAME:name main location suid_type help
33//applet:IF_RESTORECON(APPLET_ODDNAME(restorecon, setfiles, BB_DIR_SBIN, BB_SUID_DROP, restorecon)) 34//applet:IF_RESTORECON(APPLET_ODDNAME(restorecon, setfiles, BB_DIR_SBIN, BB_SUID_DROP, restorecon))
34 35
35//kbuild:lib-$(CONFIG_SETFILES) += setfiles.o 36//kbuild:lib-$(CONFIG_SETFILES) += setfiles.o
diff --git a/shell/Config.src b/shell/Config.src
index 3545f05dd..ccb1b15fe 100644
--- a/shell/Config.src
+++ b/shell/Config.src
@@ -121,23 +121,11 @@ config FEATURE_SH_STANDALONE
121 for use as a rescue shell, in the event that you screw up your system. 121 for use as a rescue shell, in the event that you screw up your system.
122 122
123 This is implemented by re-execing /proc/self/exe (typically) 123 This is implemented by re-execing /proc/self/exe (typically)
124 with right parameters. Some selected applets ("NOFORK" applets) 124 with right parameters.
125 can even be executed without creating new process. 125
126 Instead, busybox will call <applet>_main() internally. 126 However, there are drawbacks: it is problematic in chroot jails
127 127 without mounted /proc, and ps/top may show command name as 'exe'
128 However, this causes problems in chroot jails without mounted /proc 128 for applets started this way.
129 and with ps/top (command name can be shown as 'exe' for applets
130 started this way).
131# untrue?
132# Note that this will *also* cause applets to take precedence
133# over shell builtins of the same name. So turning this on will
134# eliminate any performance gained by turning on the builtin "echo"
135# and "test" commands in ash.
136# untrue?
137# Note that when using this option, the shell will attempt to directly
138# run '/bin/busybox'. If you do not have the busybox binary sitting in
139# that exact location with that exact name, this option will not work at
140# all.
141 129
142config FEATURE_SH_NOFORK 130config FEATURE_SH_NOFORK
143 bool "Run 'nofork' applets directly" 131 bool "Run 'nofork' applets directly"
diff --git a/shell/ash.c b/shell/ash.c
index e21c4433d..0325a325c 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -50,8 +50,6 @@
50//config: bool "Optimize for size instead of speed" 50//config: bool "Optimize for size instead of speed"
51//config: default y 51//config: default y
52//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH 52//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH
53//config: help
54//config: Compile ash for reduced size at the price of speed.
55//config: 53//config:
56//config:config ASH_INTERNAL_GLOB 54//config:config ASH_INTERNAL_GLOB
57//config: bool "Use internal glob() implementation" 55//config: bool "Use internal glob() implementation"
@@ -61,6 +59,23 @@
61//config: Do not use glob() function from libc, use internal implementation. 59//config: Do not use glob() function from libc, use internal implementation.
62//config: Use this if you are getting "glob.h: No such file or directory" 60//config: Use this if you are getting "glob.h: No such file or directory"
63//config: or similar build errors. 61//config: or similar build errors.
62//config: Note that as of now (2017-01), uclibc and musl glob() both have bugs
63//config: which would break ash if you select N here.
64//config:
65//config:config ASH_BASH_COMPAT
66//config: bool "bash-compatible extensions"
67//config: default y
68//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH
69//config:
70//config:config ASH_JOB_CONTROL
71//config: bool "Job control"
72//config: default y
73//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH
74//config:
75//config:config ASH_ALIAS
76//config: bool "Alias support"
77//config: default y
78//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH
64//config: 79//config:
65//config:config ASH_RANDOM_SUPPORT 80//config:config ASH_RANDOM_SUPPORT
66//config: bool "Pseudorandom generator and $RANDOM variable" 81//config: bool "Pseudorandom generator and $RANDOM variable"
@@ -78,88 +93,60 @@
78//config: default y 93//config: default y
79//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH 94//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH
80//config: help 95//config: help
81//config: "PS#" may contain volatile content, such as backquote commands. 96//config: $PS# may contain volatile content, such as backquote commands.
82//config: This option recreates the prompt string from the environment 97//config: This option recreates the prompt string from the environment
83//config: variable each time it is displayed. 98//config: variable each time it is displayed.
84//config: 99//config:
85//config:config ASH_BASH_COMPAT
86//config: bool "bash-compatible extensions"
87//config: default y
88//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH
89//config: help
90//config: Enable bash-compatible extensions.
91//config:
92//config:config ASH_IDLE_TIMEOUT 100//config:config ASH_IDLE_TIMEOUT
93//config: bool "Idle timeout variable" 101//config: bool "Idle timeout variable $TMOUT"
94//config: default n
95//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH
96//config: help
97//config: Enables bash-like auto-logout after $TMOUT seconds of idle time.
98//config:
99//config:config ASH_JOB_CONTROL
100//config: bool "Job control"
101//config: default y
102//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH
103//config: help
104//config: Enable job control in the ash shell.
105//config:
106//config:config ASH_ALIAS
107//config: bool "Alias support"
108//config: default y 102//config: default y
109//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH 103//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH
110//config: help 104//config: help
111//config: Enable alias support in the ash shell. 105//config: Enable bash-like auto-logout after $TMOUT seconds of idle time.
112//config: 106//config:
113//config:config ASH_GETOPTS 107//config:config ASH_MAIL
114//config: bool "Builtin getopt to parse positional parameters" 108//config: bool "Check for new mail in interactive shell"
115//config: default y 109//config: default y
116//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH 110//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH
117//config: help 111//config: help
118//config: Enable support for getopts builtin in ash. 112//config: Enable "check for new mail" function:
113//config: if set, $MAIL file and $MAILPATH list of files
114//config: are checked for mtime changes, and "you have mail"
115//config: message is printed if change is detected.
119//config: 116//config:
120//config:config ASH_BUILTIN_ECHO 117//config:config ASH_ECHO
121//config: bool "Builtin version of 'echo'" 118//config: bool "echo builtin"
122//config: default y 119//config: default y
123//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH 120//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH
124//config: help
125//config: Enable support for echo builtin in ash.
126//config: 121//config:
127//config:config ASH_BUILTIN_PRINTF 122//config:config ASH_PRINTF
128//config: bool "Builtin version of 'printf'" 123//config: bool "printf builtin"
129//config: default y 124//config: default y
130//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH 125//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH
131//config: help
132//config: Enable support for printf builtin in ash.
133//config: 126//config:
134//config:config ASH_BUILTIN_TEST 127//config:config ASH_TEST
135//config: bool "Builtin version of 'test'" 128//config: bool "test builtin"
136//config: default y 129//config: default y
137//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH 130//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH
138//config: help
139//config: Enable support for test builtin in ash.
140//config: 131//config:
141//config:config ASH_HELP 132//config:config ASH_HELP
142//config: bool "help builtin" 133//config: bool "help builtin"
143//config: default y 134//config: default y
144//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH 135//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH
145//config: help
146//config: Enable help builtin in ash.
147//config: 136//config:
148//config:config ASH_CMDCMD 137//config:config ASH_GETOPTS
149//config: bool "'command' command to override shell builtins" 138//config: bool "getopts builtin"
150//config: default y 139//config: default y
151//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH 140//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH
152//config: help
153//config: Enable support for the ash 'command' builtin, which allows
154//config: you to run the specified command with the specified arguments,
155//config: even when there is an ash builtin command with the same name.
156//config: 141//config:
157//config:config ASH_MAIL 142//config:config ASH_CMDCMD
158//config: bool "Check for new mail on interactive shells" 143//config: bool "command builtin"
159//config: default y 144//config: default y
160//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH 145//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH
161//config: help 146//config: help
162//config: Enable "check for new mail" function in the ash shell. 147//config: Enable support for the 'command' builtin, which allows
148//config: you to run the specified command or builtin,
149//config: even when there is a function with the same name.
163//config: 150//config:
164//config: 151//config:
165//config:config ASH_NOCONSOLE 152//config:config ASH_NOCONSOLE
@@ -176,7 +163,8 @@
176//config:endif # ash options 163//config:endif # ash options
177 164
178//applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP)) 165//applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
179//applet:IF_SH_IS_ASH(APPLET_ODDNAME(sh, ash, BB_DIR_BIN, BB_SUID_DROP, ash)) 166// APPLET_ODDNAME:name main location suid_type help
167//applet:IF_SH_IS_ASH( APPLET_ODDNAME(sh, ash, BB_DIR_BIN, BB_SUID_DROP, ash))
180//applet:IF_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, ash)) 168//applet:IF_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, ash))
181 169
182//kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o 170//kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
@@ -185,15 +173,10 @@
185//kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o 173//kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
186 174
187/* 175/*
188 * The following should be set to reflect the type of system you have: 176 * DEBUG=1 to compile in debugging ('set -o debug' turns on)
189 * JOBS -> 1 if you have Berkeley job control, 0 otherwise. 177 * DEBUG=2 to compile in and turn on debugging.
190 * define SYSV if you are running under System V. 178 * When debugging is on ("set -o debug" was executed, or DEBUG=2),
191 * define DEBUG=1 to compile in debugging ('set -o debug' to turn on) 179 * debugging info is written to ./trace, quit signal generates core dump.
192 * define DEBUG=2 to compile in and turn on debugging.
193 *
194 * When debugging is on (DEBUG is 1 and "set -o debug" was executed),
195 * debugging info will be written to ./trace and a quit signal
196 * will generate a core dump.
197 */ 180 */
198#define DEBUG 0 181#define DEBUG 0
199/* Tweak debug output verbosity here */ 182/* Tweak debug output verbosity here */
@@ -210,9 +193,30 @@
210#include <fnmatch.h> 193#include <fnmatch.h>
211#include <sys/times.h> 194#include <sys/times.h>
212#include <sys/utsname.h> /* for setting $HOSTNAME */ 195#include <sys/utsname.h> /* for setting $HOSTNAME */
213
214#include "busybox.h" /* for applet_names */ 196#include "busybox.h" /* for applet_names */
215 197
198/* So far, all bash compat is controlled by one config option */
199/* Separate defines document which part of code implements what */
200/* function keyword */
201#define BASH_FUNCTION ENABLE_ASH_BASH_COMPAT
202#define IF_BASH_FUNCTION IF_ASH_BASH_COMPAT
203/* &>file */
204#define BASH_REDIR_OUTPUT ENABLE_ASH_BASH_COMPAT
205#define IF_BASH_REDIR_OUTPUT IF_ASH_BASH_COMPAT
206/* $'...' */
207#define BASH_DOLLAR_SQUOTE ENABLE_ASH_BASH_COMPAT
208#define IF_BASH_DOLLAR_SQUOTE IF_ASH_BASH_COMPAT
209#define BASH_PATTERN_SUBST ENABLE_ASH_BASH_COMPAT
210#define IF_BASH_PATTERN_SUBST IF_ASH_BASH_COMPAT
211#define BASH_SUBSTR ENABLE_ASH_BASH_COMPAT
212#define IF_BASH_SUBSTR IF_ASH_BASH_COMPAT
213/* [[ EXPR ]] */
214#define BASH_TEST2 (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST)
215#define BASH_SOURCE ENABLE_ASH_BASH_COMPAT
216#define BASH_PIPEFAIL ENABLE_ASH_BASH_COMPAT
217#define BASH_HOSTNAME_VAR ENABLE_ASH_BASH_COMPAT
218#define BASH_SHLVL_VAR ENABLE_ASH_BASH_COMPAT
219
216#if defined(__ANDROID_API__) && __ANDROID_API__ <= 24 220#if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
217/* Bionic at least up to version 24 has no glob() */ 221/* Bionic at least up to version 24 has no glob() */
218# undef ENABLE_ASH_INTERNAL_GLOB 222# undef ENABLE_ASH_INTERNAL_GLOB
@@ -338,7 +342,7 @@ static const char *const optletters_optnames[] = {
338 "b" "notify", 342 "b" "notify",
339 "u" "nounset", 343 "u" "nounset",
340 "\0" "vi" 344 "\0" "vi"
341#if ENABLE_ASH_BASH_COMPAT 345#if BASH_PIPEFAIL
342 ,"\0" "pipefail" 346 ,"\0" "pipefail"
343#endif 347#endif
344#if DEBUG 348#if DEBUG
@@ -421,14 +425,14 @@ struct globals_misc {
421#define bflag optlist[11] 425#define bflag optlist[11]
422#define uflag optlist[12] 426#define uflag optlist[12]
423#define viflag optlist[13] 427#define viflag optlist[13]
424#if ENABLE_ASH_BASH_COMPAT 428#if BASH_PIPEFAIL
425# define pipefail optlist[14] 429# define pipefail optlist[14]
426#else 430#else
427# define pipefail 0 431# define pipefail 0
428#endif 432#endif
429#if DEBUG 433#if DEBUG
430# define nolog optlist[14 + ENABLE_ASH_BASH_COMPAT] 434# define nolog optlist[14 + BASH_PIPEFAIL]
431# define debug optlist[15 + ENABLE_ASH_BASH_COMPAT] 435# define debug optlist[15 + BASH_PIPEFAIL]
432#endif 436#endif
433#if ENABLE_PLATFORM_MINGW32 437#if ENABLE_PLATFORM_MINGW32
434# define winxp optlist[14 + ENABLE_ASH_BASH_COMPAT + 2*DEBUG] 438# define winxp optlist[14 + ENABLE_ASH_BASH_COMPAT + 2*DEBUG]
@@ -755,8 +759,10 @@ out2str(const char *p)
755#define VSTRIMLEFT 0x8 /* ${var#pattern} */ 759#define VSTRIMLEFT 0x8 /* ${var#pattern} */
756#define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */ 760#define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */
757#define VSLENGTH 0xa /* ${#var} */ 761#define VSLENGTH 0xa /* ${#var} */
758#if ENABLE_ASH_BASH_COMPAT 762#if BASH_SUBSTR
759#define VSSUBSTR 0xc /* ${var:position:length} */ 763#define VSSUBSTR 0xc /* ${var:position:length} */
764#endif
765#if BASH_PATTERN_SUBST
760#define VSREPLACE 0xd /* ${var/pattern/replacement} */ 766#define VSREPLACE 0xd /* ${var/pattern/replacement} */
761#define VSREPLACEALL 0xe /* ${var//pattern/replacement} */ 767#define VSREPLACEALL 0xe /* ${var//pattern/replacement} */
762#endif 768#endif
@@ -783,7 +789,7 @@ static const char dolatstr[] ALIGN1 = {
783#define NDEFUN 14 789#define NDEFUN 14
784#define NARG 15 790#define NARG 15
785#define NTO 16 791#define NTO 16
786#if ENABLE_ASH_BASH_COMPAT 792#if BASH_REDIR_OUTPUT
787#define NTO2 17 793#define NTO2 17
788#endif 794#endif
789#define NCLOBBER 18 795#define NCLOBBER 18
@@ -1193,7 +1199,7 @@ shcmd(union node *cmd, FILE *fp)
1193 case NTO: s = ">>"+1; dftfd = 1; break; 1199 case NTO: s = ">>"+1; dftfd = 1; break;
1194 case NCLOBBER: s = ">|"; dftfd = 1; break; 1200 case NCLOBBER: s = ">|"; dftfd = 1; break;
1195 case NAPPEND: s = ">>"; dftfd = 1; break; 1201 case NAPPEND: s = ">>"; dftfd = 1; break;
1196#if ENABLE_ASH_BASH_COMPAT 1202#if BASH_REDIR_OUTPUT
1197 case NTO2: 1203 case NTO2:
1198#endif 1204#endif
1199 case NTOFD: s = ">&"; dftfd = 1; break; 1205 case NTOFD: s = ">&"; dftfd = 1; break;
@@ -3599,12 +3605,13 @@ struct job {
3599#if JOBS 3605#if JOBS
3600 int stopstatus; /* status of a stopped job */ 3606 int stopstatus; /* status of a stopped job */
3601#endif 3607#endif
3602 uint32_t 3608 unsigned nprocs; /* number of processes */
3603 nprocs: 16, /* number of processes */ 3609
3604 state: 8,
3605#define JOBRUNNING 0 /* at least one proc running */ 3610#define JOBRUNNING 0 /* at least one proc running */
3606#define JOBSTOPPED 1 /* all procs are stopped */ 3611#define JOBSTOPPED 1 /* all procs are stopped */
3607#define JOBDONE 2 /* all procs are completed */ 3612#define JOBDONE 2 /* all procs are completed */
3613 unsigned
3614 state: 8,
3608#if JOBS 3615#if JOBS
3609 sigint: 1, /* job was killed by SIGINT */ 3616 sigint: 1, /* job was killed by SIGINT */
3610 jobctl: 1, /* job running under job control */ 3617 jobctl: 1, /* job running under job control */
@@ -3791,6 +3798,72 @@ static struct job *curjob; //lots
3791/* number of presumed living untracked jobs */ 3798/* number of presumed living untracked jobs */
3792static int jobless; //4 3799static int jobless; //4
3793 3800
3801#if 0
3802/* Bash has a feature: it restores termios after a successful wait for
3803 * a foreground job which had at least one stopped or sigkilled member.
3804 * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3805 * properly restoring tty state. Should we do this too?
3806 * A reproducer: ^Z an interactive python:
3807 *
3808 * # python
3809 * Python 2.7.12 (...)
3810 * >>> ^Z
3811 * { python leaves tty in -icanon -echo state. We do survive that... }
3812 * [1]+ Stopped python
3813 * { ...however, next program (python #2) does not survive it well: }
3814 * # python
3815 * Python 2.7.12 (...)
3816 * >>> Traceback (most recent call last):
3817 * { above, I typed "qwerty<CR>", but -echo state is still in effect }
3818 * File "<stdin>", line 1, in <module>
3819 * NameError: name 'qwerty' is not defined
3820 *
3821 * The implementation below is modeled on bash code and seems to work.
3822 * However, I'm not sure we should do this. For one: what if I'd fg
3823 * the stopped python instead? It'll be confused by "restored" tty state.
3824 */
3825static struct termios shell_tty_info;
3826static void
3827get_tty_state(void)
3828{
3829 if (rootshell && ttyfd >= 0)
3830 tcgetattr(ttyfd, &shell_tty_info);
3831}
3832static void
3833set_tty_state(void)
3834{
3835 /* if (rootshell) - caller ensures this */
3836 if (ttyfd >= 0)
3837 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3838}
3839static int
3840job_signal_status(struct job *jp)
3841{
3842 int status;
3843 unsigned i;
3844 struct procstat *ps = jp->ps;
3845 for (i = 0; i < jp->nprocs; i++) {
3846 status = ps[i].ps_status;
3847 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3848 return status;
3849 }
3850 return 0;
3851}
3852static void
3853restore_tty_if_stopped_or_signaled(struct job *jp)
3854{
3855//TODO: check what happens if we come from waitforjob() in expbackq()
3856 if (rootshell) {
3857 int s = job_signal_status(jp);
3858 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3859 set_tty_state();
3860 }
3861}
3862#else
3863# define get_tty_state() ((void)0)
3864# define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3865#endif
3866
3794static void 3867static void
3795set_curjob(struct job *jp, unsigned mode) 3868set_curjob(struct job *jp, unsigned mode)
3796{ 3869{
@@ -4122,8 +4195,10 @@ restartjob(struct job *jp, int mode)
4122 goto out; 4195 goto out;
4123 jp->state = JOBRUNNING; 4196 jp->state = JOBRUNNING;
4124 pgid = jp->ps[0].ps_pid; 4197 pgid = jp->ps[0].ps_pid;
4125 if (mode == FORK_FG) 4198 if (mode == FORK_FG) {
4199 get_tty_state();
4126 xtcsetpgrp(ttyfd, pgid); 4200 xtcsetpgrp(ttyfd, pgid);
4201 }
4127 killpg(pgid, SIGCONT); 4202 killpg(pgid, SIGCONT);
4128 ps = jp->ps; 4203 ps = jp->ps;
4129 i = jp->nprocs; 4204 i = jp->nprocs;
@@ -4754,7 +4829,7 @@ makejob(/*union node *node,*/ int nprocs)
4754 memset(jp, 0, sizeof(*jp)); 4829 memset(jp, 0, sizeof(*jp));
4755#if JOBS 4830#if JOBS
4756 /* jp->jobctl is a bitfield. 4831 /* jp->jobctl is a bitfield.
4757 * "jp->jobctl |= jobctl" likely to give awful code */ 4832 * "jp->jobctl |= doing_jobctl" likely to give awful code */
4758 if (doing_jobctl) 4833 if (doing_jobctl)
4759 jp->jobctl = 1; 4834 jp->jobctl = 1;
4760#endif 4835#endif
@@ -4783,7 +4858,8 @@ cmdputs(const char *s)
4783 static const char vstype[VSTYPE + 1][3] = { 4858 static const char vstype[VSTYPE + 1][3] = {
4784 "", "}", "-", "+", "?", "=", 4859 "", "}", "-", "+", "?", "=",
4785 "%", "%%", "#", "##" 4860 "%", "%%", "#", "##"
4786 IF_ASH_BASH_COMPAT(, ":", "/", "//") 4861 IF_BASH_SUBSTR(, ":")
4862 IF_BASH_PATTERN_SUBST(, "/", "//")
4787 }; 4863 };
4788 4864
4789 const char *p, *str; 4865 const char *p, *str;
@@ -5010,7 +5086,7 @@ cmdtxt(union node *n)
5010 case NAPPEND: 5086 case NAPPEND:
5011 p = ">>"; 5087 p = ">>";
5012 goto redir; 5088 goto redir;
5013#if ENABLE_ASH_BASH_COMPAT 5089#if BASH_REDIR_OUTPUT
5014 case NTO2: 5090 case NTO2:
5015#endif 5091#endif
5016 case NTOFD: 5092 case NTOFD:
@@ -5362,6 +5438,8 @@ waitforjob(struct job *jp)
5362#if JOBS 5438#if JOBS
5363 if (jp->jobctl) { 5439 if (jp->jobctl) {
5364 xtcsetpgrp(ttyfd, rootpid); 5440 xtcsetpgrp(ttyfd, rootpid);
5441 restore_tty_if_stopped_or_signaled(jp);
5442
5365 /* 5443 /*
5366 * This is truly gross. 5444 * This is truly gross.
5367 * If we're doing job control, then we did a TIOCSPGRP which 5445 * If we're doing job control, then we did a TIOCSPGRP which
@@ -5587,7 +5665,7 @@ openredirect(union node *redir)
5587 goto ecreate; 5665 goto ecreate;
5588 break; 5666 break;
5589 case NTO: 5667 case NTO:
5590#if ENABLE_ASH_BASH_COMPAT 5668#if BASH_REDIR_OUTPUT
5591 case NTO2: 5669 case NTO2:
5592#endif 5670#endif
5593 /* Take care of noclobber mode. */ 5671 /* Take care of noclobber mode. */
@@ -5751,7 +5829,7 @@ redirect(union node *redir, int flags)
5751 union node *tmp = redir; 5829 union node *tmp = redir;
5752 do { 5830 do {
5753 sv_pos++; 5831 sv_pos++;
5754#if ENABLE_ASH_BASH_COMPAT 5832#if BASH_REDIR_OUTPUT
5755 if (tmp->nfile.type == NTO2) 5833 if (tmp->nfile.type == NTO2)
5756 sv_pos++; 5834 sv_pos++;
5757#endif 5835#endif
@@ -5793,7 +5871,7 @@ redirect(union node *redir, int flags)
5793 continue; 5871 continue;
5794 } 5872 }
5795 } 5873 }
5796#if ENABLE_ASH_BASH_COMPAT 5874#if BASH_REDIR_OUTPUT
5797 redirect_more: 5875 redirect_more:
5798#endif 5876#endif
5799 if (need_to_remember(sv, fd)) { 5877 if (need_to_remember(sv, fd)) {
@@ -5846,12 +5924,12 @@ redirect(union node *redir, int flags)
5846 } 5924 }
5847 } else if (fd != newfd) { /* move newfd to fd */ 5925 } else if (fd != newfd) { /* move newfd to fd */
5848 dup2_or_raise(newfd, fd); 5926 dup2_or_raise(newfd, fd);
5849#if ENABLE_ASH_BASH_COMPAT 5927#if BASH_REDIR_OUTPUT
5850 if (!(redir->nfile.type == NTO2 && fd == 2)) 5928 if (!(redir->nfile.type == NTO2 && fd == 2))
5851#endif 5929#endif
5852 close(newfd); 5930 close(newfd);
5853 } 5931 }
5854#if ENABLE_ASH_BASH_COMPAT 5932#if BASH_REDIR_OUTPUT
5855 if (redir->nfile.type == NTO2 && fd == 1) { 5933 if (redir->nfile.type == NTO2 && fd == 1) {
5856 /* We already redirected it to fd 1, now copy it to 2 */ 5934 /* We already redirected it to fd 1, now copy it to 2 */
5857 newfd = 1; 5935 newfd = 1;
@@ -6168,15 +6246,15 @@ static char *
6168rmescapes(char *str, int flag) 6246rmescapes(char *str, int flag)
6169{ 6247{
6170 static const char qchars[] ALIGN1 = { 6248 static const char qchars[] ALIGN1 = {
6171 IF_ASH_BASH_COMPAT('/',) CTLESC, CTLQUOTEMARK, '\0' }; 6249 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
6172 6250
6173 char *p, *q, *r; 6251 char *p, *q, *r;
6174 unsigned inquotes; 6252 unsigned inquotes;
6175 unsigned protect_against_glob; 6253 unsigned protect_against_glob;
6176 unsigned globbing; 6254 unsigned globbing;
6177 IF_ASH_BASH_COMPAT(unsigned slash = flag & RMESCAPE_SLASH;) 6255 IF_BASH_PATTERN_SUBST(unsigned slash = flag & RMESCAPE_SLASH;)
6178 6256
6179 p = strpbrk(str, qchars IF_ASH_BASH_COMPAT(+ !slash)); 6257 p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash));
6180 if (!p) 6258 if (!p)
6181 return str; 6259 return str;
6182 6260
@@ -6228,7 +6306,7 @@ rmescapes(char *str, int flag)
6228 protect_against_glob = 0; 6306 protect_against_glob = 0;
6229 goto copy; 6307 goto copy;
6230 } 6308 }
6231#if ENABLE_ASH_BASH_COMPAT 6309#if BASH_PATTERN_SUBST
6232 else if (*p == '/' && slash) { 6310 else if (*p == '/' && slash) {
6233 /* stop handling globbing and mark location of slash */ 6311 /* stop handling globbing and mark location of slash */
6234 globbing = slash = 0; 6312 globbing = slash = 0;
@@ -6887,10 +6965,10 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
6887 char *loc; 6965 char *loc;
6888 char *rmesc, *rmescend; 6966 char *rmesc, *rmescend;
6889 char *str; 6967 char *str;
6890 IF_ASH_BASH_COMPAT(char *repl = NULL;) 6968 IF_BASH_SUBSTR(int pos, len, orig_len;)
6891 IF_ASH_BASH_COMPAT(int pos, len, orig_len;)
6892 int amount, resetloc; 6969 int amount, resetloc;
6893 IF_ASH_BASH_COMPAT(int workloc;) 6970 IF_BASH_PATTERN_SUBST(int workloc;)
6971 IF_BASH_PATTERN_SUBST(char *repl = NULL;)
6894 int zero; 6972 int zero;
6895 char *(*scan)(char*, char*, char*, char*, int, int); 6973 char *(*scan)(char*, char*, char*, char*, int, int);
6896 6974
@@ -6915,7 +6993,7 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
6915 varunset(p, varname, startp, varflags); 6993 varunset(p, varname, startp, varflags);
6916 /* NOTREACHED */ 6994 /* NOTREACHED */
6917 6995
6918#if ENABLE_ASH_BASH_COMPAT 6996#if BASH_SUBSTR
6919 case VSSUBSTR: 6997 case VSSUBSTR:
6920//TODO: support more general format ${v:EXPR:EXPR}, 6998//TODO: support more general format ${v:EXPR:EXPR},
6921// where EXPR follows $(()) rules 6999// where EXPR follows $(()) rules
@@ -6984,17 +7062,19 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
6984 amount = loc - expdest; 7062 amount = loc - expdest;
6985 STADJUST(amount, expdest); 7063 STADJUST(amount, expdest);
6986 return loc; 7064 return loc;
6987#endif 7065#endif /* BASH_SUBSTR */
6988 } 7066 }
6989 7067
6990 resetloc = expdest - (char *)stackblock(); 7068 resetloc = expdest - (char *)stackblock();
6991 7069
7070#if BASH_PATTERN_SUBST
6992 /* We'll comeback here if we grow the stack while handling 7071 /* We'll comeback here if we grow the stack while handling
6993 * a VSREPLACE or VSREPLACEALL, since our pointers into the 7072 * a VSREPLACE or VSREPLACEALL, since our pointers into the
6994 * stack will need rebasing, and we'll need to remove our work 7073 * stack will need rebasing, and we'll need to remove our work
6995 * areas each time 7074 * areas each time
6996 */ 7075 */
6997 IF_ASH_BASH_COMPAT(restart:) 7076 restart:
7077#endif
6998 7078
6999 amount = expdest - ((char *)stackblock() + resetloc); 7079 amount = expdest - ((char *)stackblock() + resetloc);
7000 STADJUST(-amount, expdest); 7080 STADJUST(-amount, expdest);
@@ -7019,11 +7099,11 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
7019 * RMESCAPE_SLASH causes preglob to work differently on the pattern 7099 * RMESCAPE_SLASH causes preglob to work differently on the pattern
7020 * and string. It's only used on the first call. 7100 * and string. It's only used on the first call.
7021 */ 7101 */
7022 preglob(str, IF_ASH_BASH_COMPAT( 7102 preglob(str, IF_BASH_PATTERN_SUBST(
7023 (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ? 7103 (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ?
7024 RMESCAPE_SLASH :) 0); 7104 RMESCAPE_SLASH : ) 0);
7025 7105
7026#if ENABLE_ASH_BASH_COMPAT 7106#if BASH_PATTERN_SUBST
7027 workloc = expdest - (char *)stackblock(); 7107 workloc = expdest - (char *)stackblock();
7028 if (subtype == VSREPLACE || subtype == VSREPLACEALL) { 7108 if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
7029 char *idx, *end; 7109 char *idx, *end;
@@ -7124,7 +7204,7 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
7124 STADJUST(-amount, expdest); 7204 STADJUST(-amount, expdest);
7125 return startp; 7205 return startp;
7126 } 7206 }
7127#endif /* ENABLE_ASH_BASH_COMPAT */ 7207#endif /* BASH_PATTERN_SUBST */
7128 7208
7129 subtype -= VSTRIMRIGHT; 7209 subtype -= VSTRIMRIGHT;
7130#if DEBUG 7210#if DEBUG
@@ -7392,8 +7472,10 @@ evalvar(char *p, int flag, struct strlist *var_str_list)
7392 case VSTRIMLEFTMAX: 7472 case VSTRIMLEFTMAX:
7393 case VSTRIMRIGHT: 7473 case VSTRIMRIGHT:
7394 case VSTRIMRIGHTMAX: 7474 case VSTRIMRIGHTMAX:
7395#if ENABLE_ASH_BASH_COMPAT 7475#if BASH_SUBSTR
7396 case VSSUBSTR: 7476 case VSSUBSTR:
7477#endif
7478#if BASH_PATTERN_SUBST
7397 case VSREPLACE: 7479 case VSREPLACE:
7398 case VSREPLACEALL: 7480 case VSREPLACEALL:
7399#endif 7481#endif
@@ -7458,6 +7540,57 @@ addfname(const char *name)
7458 exparg.lastp = &sp->next; 7540 exparg.lastp = &sp->next;
7459} 7541}
7460 7542
7543/* Avoid glob() (and thus, stat() et al) for words like "echo" */
7544static int
7545hasmeta(const char *p)
7546{
7547 static const char chars[] ALIGN1 = {
7548 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7549 };
7550
7551 for (;;) {
7552 p = strpbrk(p, chars);
7553 if (!p)
7554 break;
7555 switch ((unsigned char) *p) {
7556 case CTLQUOTEMARK:
7557 for (;;) {
7558 p++;
7559 if (*p == CTLQUOTEMARK)
7560 break;
7561 if (*p == CTLESC)
7562 p++;
7563 if (*p == '\0') /* huh? */
7564 return 0;
7565 }
7566 break;
7567 case '\\':
7568 case CTLESC:
7569 p++;
7570 if (*p == '\0')
7571 return 0;
7572 break;
7573 case '[':
7574 if (!strchr(p + 1, ']')) {
7575 /* It's not a properly closed [] pattern,
7576 * but other metas may follow. Continue checking.
7577 * my[file* _is_ globbed by bash
7578 * and matches filenames like "my[file1".
7579 */
7580 break;
7581 }
7582 /* fallthrough */
7583 default:
7584 /* case '*': */
7585 /* case '?': */
7586 return 1;
7587 }
7588 p++;
7589 }
7590
7591 return 0;
7592}
7593
7461/* If we want to use glob() from libc... */ 7594/* If we want to use glob() from libc... */
7462#if !ENABLE_ASH_INTERNAL_GLOB 7595#if !ENABLE_ASH_INTERNAL_GLOB
7463 7596
@@ -7484,20 +7617,9 @@ expandmeta(struct strlist *str /*, int flag*/)
7484 if (fflag) 7617 if (fflag)
7485 goto nometa; 7618 goto nometa;
7486 7619
7487 /* Avoid glob() (and thus, stat() et al) for words like "echo" */ 7620 if (!hasmeta(str->text))
7488 p = str->text; 7621 goto nometa;
7489 while (*p) {
7490 if (*p == '*')
7491 goto need_glob;
7492 if (*p == '?')
7493 goto need_glob;
7494 if (*p == '[')
7495 goto need_glob;
7496 p++;
7497 }
7498 goto nometa;
7499 7622
7500 need_glob:
7501 INT_OFF; 7623 INT_OFF;
7502 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP); 7624 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7503// GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match 7625// GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
@@ -7734,9 +7856,6 @@ expsort(struct strlist *str)
7734static void 7856static void
7735expandmeta(struct strlist *str /*, int flag*/) 7857expandmeta(struct strlist *str /*, int flag*/)
7736{ 7858{
7737 static const char metachars[] ALIGN1 = {
7738 '*', '?', '[', 0
7739 };
7740 /* TODO - EXP_REDIR */ 7859 /* TODO - EXP_REDIR */
7741 7860
7742 while (str) { 7861 while (str) {
@@ -7747,7 +7866,7 @@ expandmeta(struct strlist *str /*, int flag*/)
7747 7866
7748 if (fflag) 7867 if (fflag)
7749 goto nometa; 7868 goto nometa;
7750 if (!strpbrk(str->text, metachars)) 7869 if (!hasmeta(str->text))
7751 goto nometa; 7870 goto nometa;
7752 savelastp = exparg.lastp; 7871 savelastp = exparg.lastp;
7753 7872
@@ -8322,7 +8441,7 @@ enum {
8322 TESAC, 8441 TESAC,
8323 TFI, 8442 TFI,
8324 TFOR, 8443 TFOR,
8325#if ENABLE_ASH_BASH_COMPAT 8444#if BASH_FUNCTION
8326 TFUNCTION, 8445 TFUNCTION,
8327#endif 8446#endif
8328 TIF, 8447 TIF,
@@ -8360,7 +8479,7 @@ enum {
8360 /* 19 */ | (1u << TESAC) 8479 /* 19 */ | (1u << TESAC)
8361 /* 20 */ | (1u << TFI) 8480 /* 20 */ | (1u << TFI)
8362 /* 21 */ | (0u << TFOR) 8481 /* 21 */ | (0u << TFOR)
8363#if ENABLE_ASH_BASH_COMPAT 8482#if BASH_FUNCTION
8364 /* 22 */ | (0u << TFUNCTION) 8483 /* 22 */ | (0u << TFUNCTION)
8365#endif 8484#endif
8366 /* 23 */ | (0u << TIF) 8485 /* 23 */ | (0u << TIF)
@@ -8398,7 +8517,7 @@ static const char *const tokname_array[] = {
8398 "esac", 8517 "esac",
8399 "fi", 8518 "fi",
8400 "for", 8519 "for",
8401#if ENABLE_ASH_BASH_COMPAT 8520#if BASH_FUNCTION
8402 "function", 8521 "function",
8403#endif 8522#endif
8404 "if", 8523 "if",
@@ -8646,7 +8765,7 @@ static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8646 [NDEFUN ] = SHELL_ALIGN(sizeof(struct narg)), 8765 [NDEFUN ] = SHELL_ALIGN(sizeof(struct narg)),
8647 [NARG ] = SHELL_ALIGN(sizeof(struct narg)), 8766 [NARG ] = SHELL_ALIGN(sizeof(struct narg)),
8648 [NTO ] = SHELL_ALIGN(sizeof(struct nfile)), 8767 [NTO ] = SHELL_ALIGN(sizeof(struct nfile)),
8649#if ENABLE_ASH_BASH_COMPAT 8768#if BASH_REDIR_OUTPUT
8650 [NTO2 ] = SHELL_ALIGN(sizeof(struct nfile)), 8769 [NTO2 ] = SHELL_ALIGN(sizeof(struct nfile)),
8651#endif 8770#endif
8652 [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)), 8771 [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
@@ -8737,7 +8856,7 @@ calcsize(union node *n)
8737 IF_PLATFORM_MINGW32(nodeptrsize += 3); 8856 IF_PLATFORM_MINGW32(nodeptrsize += 3);
8738 break; 8857 break;
8739 case NTO: 8858 case NTO:
8740#if ENABLE_ASH_BASH_COMPAT 8859#if BASH_REDIR_OUTPUT
8741 case NTO2: 8860 case NTO2:
8742#endif 8861#endif
8743 case NCLOBBER: 8862 case NCLOBBER:
@@ -8881,7 +9000,7 @@ copynode(union node *n)
8881 SAVE_PTR3(new->narg.backquote,new->narg.text,new->narg.next); 9000 SAVE_PTR3(new->narg.backquote,new->narg.text,new->narg.next);
8882 break; 9001 break;
8883 case NTO: 9002 case NTO:
8884#if ENABLE_ASH_BASH_COMPAT 9003#if BASH_REDIR_OUTPUT
8885 case NTO2: 9004 case NTO2:
8886#endif 9005#endif
8887 case NCLOBBER: 9006 case NCLOBBER:
@@ -9277,13 +9396,15 @@ evalsubshell(union node *n, int flags)
9277{ 9396{
9278 IF_PLATFORM_MINGW32(struct forkshell fs;) 9397 IF_PLATFORM_MINGW32(struct forkshell fs;)
9279 struct job *jp; 9398 struct job *jp;
9280 int backgnd = (n->type == NBACKGND); 9399 int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
9281 int status; 9400 int status;
9282 9401
9283 expredir(n->nredir.redirect); 9402 expredir(n->nredir.redirect);
9284 if (!backgnd && (flags & EV_EXIT) && !may_have_traps) 9403 if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
9285 goto nofork; 9404 goto nofork;
9286 INT_OFF; 9405 INT_OFF;
9406 if (backgnd == FORK_FG)
9407 get_tty_state();
9287 jp = makejob(/*n,*/ 1); 9408 jp = makejob(/*n,*/ 1);
9288#if ENABLE_PLATFORM_MINGW32 9409#if ENABLE_PLATFORM_MINGW32
9289 memset(&fs, 0, sizeof(fs)); 9410 memset(&fs, 0, sizeof(fs));
@@ -9308,7 +9429,7 @@ evalsubshell(union node *n, int flags)
9308 } 9429 }
9309 /* parent */ 9430 /* parent */
9310 status = 0; 9431 status = 0;
9311 if (!backgnd) 9432 if (backgnd == FORK_FG)
9312 status = waitforjob(jp); 9433 status = waitforjob(jp);
9313 INT_ON; 9434 INT_ON;
9314 return status; 9435 return status;
@@ -9332,14 +9453,14 @@ expredir(union node *n)
9332 case NFROMTO: 9453 case NFROMTO:
9333 case NFROM: 9454 case NFROM:
9334 case NTO: 9455 case NTO:
9335#if ENABLE_ASH_BASH_COMPAT 9456#if BASH_REDIR_OUTPUT
9336 case NTO2: 9457 case NTO2:
9337#endif 9458#endif
9338 case NCLOBBER: 9459 case NCLOBBER:
9339 case NAPPEND: 9460 case NAPPEND:
9340 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR); 9461 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9341 TRACE(("expredir expanded to '%s'\n", fn.list->text)); 9462 TRACE(("expredir expanded to '%s'\n", fn.list->text));
9342#if ENABLE_ASH_BASH_COMPAT 9463#if BASH_REDIR_OUTPUT
9343 store_expfname: 9464 store_expfname:
9344#endif 9465#endif
9345#if 0 9466#if 0
@@ -9361,7 +9482,7 @@ expredir(union node *n)
9361 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE); 9482 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9362 if (fn.list == NULL) 9483 if (fn.list == NULL)
9363 ash_msg_and_raise_error("redir error"); 9484 ash_msg_and_raise_error("redir error");
9364#if ENABLE_ASH_BASH_COMPAT 9485#if BASH_REDIR_OUTPUT
9365//FIXME: we used expandarg with different args! 9486//FIXME: we used expandarg with different args!
9366 if (!isdigit_str9(fn.list->text)) { 9487 if (!isdigit_str9(fn.list->text)) {
9367 /* >&file, not >&fd */ 9488 /* >&file, not >&fd */
@@ -9401,6 +9522,8 @@ evalpipe(union node *n, int flags)
9401 pipelen++; 9522 pipelen++;
9402 flags |= EV_EXIT; 9523 flags |= EV_EXIT;
9403 INT_OFF; 9524 INT_OFF;
9525 if (n->npipe.pipe_backgnd == 0)
9526 get_tty_state();
9404 jp = makejob(/*n,*/ pipelen); 9527 jp = makejob(/*n,*/ pipelen);
9405 prevfd = -1; 9528 prevfd = -1;
9406 for (lp = n->npipe.cmdlist; lp; lp = lp->next) { 9529 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
@@ -9764,13 +9887,13 @@ static int ulimitcmd(int, char **) FAST_FUNC;
9764#define BUILTIN_SPEC_REG_ASSG "7" 9887#define BUILTIN_SPEC_REG_ASSG "7"
9765 9888
9766/* Stubs for calling non-FAST_FUNC's */ 9889/* Stubs for calling non-FAST_FUNC's */
9767#if ENABLE_ASH_BUILTIN_ECHO 9890#if ENABLE_ASH_ECHO
9768static int FAST_FUNC echocmd(int argc, char **argv) { return echo_main(argc, argv); } 9891static int FAST_FUNC echocmd(int argc, char **argv) { return echo_main(argc, argv); }
9769#endif 9892#endif
9770#if ENABLE_ASH_BUILTIN_PRINTF 9893#if ENABLE_ASH_PRINTF
9771static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); } 9894static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9772#endif 9895#endif
9773#if ENABLE_ASH_BUILTIN_TEST 9896#if ENABLE_ASH_TEST || BASH_TEST2
9774static int FAST_FUNC testcmd(int argc, char **argv) { return test_main(argc, argv); } 9897static int FAST_FUNC testcmd(int argc, char **argv) { return test_main(argc, argv); }
9775#endif 9898#endif
9776 9899
@@ -9778,11 +9901,11 @@ static int FAST_FUNC testcmd(int argc, char **argv) { return test_main(argc, a
9778static const struct builtincmd builtintab[] = { 9901static const struct builtincmd builtintab[] = {
9779 { BUILTIN_SPEC_REG "." , dotcmd }, 9902 { BUILTIN_SPEC_REG "." , dotcmd },
9780 { BUILTIN_SPEC_REG ":" , truecmd }, 9903 { BUILTIN_SPEC_REG ":" , truecmd },
9781#if ENABLE_ASH_BUILTIN_TEST 9904#if ENABLE_ASH_TEST
9782 { BUILTIN_REGULAR "[" , testcmd }, 9905 { BUILTIN_REGULAR "[" , testcmd },
9783# if ENABLE_ASH_BASH_COMPAT 9906#endif
9907#if BASH_TEST2
9784 { BUILTIN_REGULAR "[[" , testcmd }, 9908 { BUILTIN_REGULAR "[[" , testcmd },
9785# endif
9786#endif 9909#endif
9787#if ENABLE_ASH_ALIAS 9910#if ENABLE_ASH_ALIAS
9788 { BUILTIN_REG_ASSG "alias" , aliascmd }, 9911 { BUILTIN_REG_ASSG "alias" , aliascmd },
@@ -9797,7 +9920,7 @@ static const struct builtincmd builtintab[] = {
9797 { BUILTIN_REGULAR "command" , commandcmd }, 9920 { BUILTIN_REGULAR "command" , commandcmd },
9798#endif 9921#endif
9799 { BUILTIN_SPEC_REG "continue", breakcmd }, 9922 { BUILTIN_SPEC_REG "continue", breakcmd },
9800#if ENABLE_ASH_BUILTIN_ECHO 9923#if ENABLE_ASH_ECHO
9801 { BUILTIN_REGULAR "echo" , echocmd }, 9924 { BUILTIN_REGULAR "echo" , echocmd },
9802#endif 9925#endif
9803 { BUILTIN_SPEC_REG "eval" , NULL }, /*evalcmd() has a differing prototype*/ 9926 { BUILTIN_SPEC_REG "eval" , NULL }, /*evalcmd() has a differing prototype*/
@@ -9826,7 +9949,7 @@ static const struct builtincmd builtintab[] = {
9826 { BUILTIN_NOSPEC "let" , letcmd }, 9949 { BUILTIN_NOSPEC "let" , letcmd },
9827#endif 9950#endif
9828 { BUILTIN_ASSIGN "local" , localcmd }, 9951 { BUILTIN_ASSIGN "local" , localcmd },
9829#if ENABLE_ASH_BUILTIN_PRINTF 9952#if ENABLE_ASH_PRINTF
9830 { BUILTIN_REGULAR "printf" , printfcmd }, 9953 { BUILTIN_REGULAR "printf" , printfcmd },
9831#endif 9954#endif
9832 { BUILTIN_NOSPEC "pwd" , pwdcmd }, 9955 { BUILTIN_NOSPEC "pwd" , pwdcmd },
@@ -9835,10 +9958,10 @@ static const struct builtincmd builtintab[] = {
9835 { BUILTIN_SPEC_REG "return" , returncmd }, 9958 { BUILTIN_SPEC_REG "return" , returncmd },
9836 { BUILTIN_SPEC_REG "set" , setcmd }, 9959 { BUILTIN_SPEC_REG "set" , setcmd },
9837 { BUILTIN_SPEC_REG "shift" , shiftcmd }, 9960 { BUILTIN_SPEC_REG "shift" , shiftcmd },
9838#if ENABLE_ASH_BASH_COMPAT 9961#if BASH_SOURCE
9839 { BUILTIN_SPEC_REG "source" , dotcmd }, 9962 { BUILTIN_SPEC_REG "source" , dotcmd },
9840#endif 9963#endif
9841#if ENABLE_ASH_BUILTIN_TEST 9964#if ENABLE_ASH_TEST
9842 { BUILTIN_REGULAR "test" , testcmd }, 9965 { BUILTIN_REGULAR "test" , testcmd },
9843#endif 9966#endif
9844 { BUILTIN_SPEC_REG "times" , timescmd }, 9967 { BUILTIN_SPEC_REG "times" , timescmd },
@@ -9857,15 +9980,15 @@ static const struct builtincmd builtintab[] = {
9857/* Should match the above table! */ 9980/* Should match the above table! */
9858#define COMMANDCMD (builtintab + \ 9981#define COMMANDCMD (builtintab + \
9859 /* . : */ 2 + \ 9982 /* . : */ 2 + \
9860 /* [ */ 1 * ENABLE_ASH_BUILTIN_TEST + \ 9983 /* [ */ 1 * ENABLE_ASH_TEST + \
9861 /* [[ */ 1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \ 9984 /* [[ */ 1 * BASH_TEST2 + \
9862 /* alias */ 1 * ENABLE_ASH_ALIAS + \ 9985 /* alias */ 1 * ENABLE_ASH_ALIAS + \
9863 /* bg */ 1 * ENABLE_ASH_JOB_CONTROL + \ 9986 /* bg */ 1 * ENABLE_ASH_JOB_CONTROL + \
9864 /* break cd cddir */ 3) 9987 /* break cd cddir */ 3)
9865#define EVALCMD (COMMANDCMD + \ 9988#define EVALCMD (COMMANDCMD + \
9866 /* command */ 1 * ENABLE_ASH_CMDCMD + \ 9989 /* command */ 1 * ENABLE_ASH_CMDCMD + \
9867 /* continue */ 1 + \ 9990 /* continue */ 1 + \
9868 /* echo */ 1 * ENABLE_ASH_BUILTIN_ECHO + \ 9991 /* echo */ 1 * ENABLE_ASH_ECHO + \
9869 0) 9992 0)
9870#define EXECCMD (EVALCMD + \ 9993#define EXECCMD (EVALCMD + \
9871 /* eval */ 1) 9994 /* eval */ 1)
@@ -10117,6 +10240,7 @@ evalcommand(union node *cmd, int flags)
10117 if (!(flags & EV_EXIT) || may_have_traps) { 10240 if (!(flags & EV_EXIT) || may_have_traps) {
10118 /* No, forking off a child is necessary */ 10241 /* No, forking off a child is necessary */
10119 INT_OFF; 10242 INT_OFF;
10243 get_tty_state();
10120 jp = makejob(/*cmd,*/ 1); 10244 jp = makejob(/*cmd,*/ 1);
10121 if (forkshell(jp, cmd, FORK_FG) != 0) { 10245 if (forkshell(jp, cmd, FORK_FG) != 0) {
10122 /* parent */ 10246 /* parent */
@@ -11505,10 +11629,10 @@ simplecmd(void)
11505 union node *vars, **vpp; 11629 union node *vars, **vpp;
11506 union node **rpp, *redir; 11630 union node **rpp, *redir;
11507 int savecheckkwd; 11631 int savecheckkwd;
11508#if ENABLE_ASH_BASH_COMPAT 11632#if BASH_TEST2
11509 smallint double_brackets_flag = 0; 11633 smallint double_brackets_flag = 0;
11510 smallint function_flag = 0;
11511#endif 11634#endif
11635 IF_BASH_FUNCTION(smallint function_flag = 0;)
11512 11636
11513 args = NULL; 11637 args = NULL;
11514 app = &args; 11638 app = &args;
@@ -11523,12 +11647,14 @@ simplecmd(void)
11523 checkkwd = savecheckkwd; 11647 checkkwd = savecheckkwd;
11524 t = readtoken(); 11648 t = readtoken();
11525 switch (t) { 11649 switch (t) {
11526#if ENABLE_ASH_BASH_COMPAT 11650#if BASH_FUNCTION
11527 case TFUNCTION: 11651 case TFUNCTION:
11528 if (peektoken() != TWORD) 11652 if (peektoken() != TWORD)
11529 raise_error_unexpected_syntax(TWORD); 11653 raise_error_unexpected_syntax(TWORD);
11530 function_flag = 1; 11654 function_flag = 1;
11531 break; 11655 break;
11656#endif
11657#if BASH_TEST2
11532 case TAND: /* "&&" */ 11658 case TAND: /* "&&" */
11533 case TOR: /* "||" */ 11659 case TOR: /* "||" */
11534 if (!double_brackets_flag) { 11660 if (!double_brackets_flag) {
@@ -11542,7 +11668,7 @@ simplecmd(void)
11542 n->type = NARG; 11668 n->type = NARG;
11543 /*n->narg.next = NULL; - stzalloc did it */ 11669 /*n->narg.next = NULL; - stzalloc did it */
11544 n->narg.text = wordtext; 11670 n->narg.text = wordtext;
11545#if ENABLE_ASH_BASH_COMPAT 11671#if BASH_TEST2
11546 if (strcmp("[[", wordtext) == 0) 11672 if (strcmp("[[", wordtext) == 0)
11547 double_brackets_flag = 1; 11673 double_brackets_flag = 1;
11548 else if (strcmp("]]", wordtext) == 0) 11674 else if (strcmp("]]", wordtext) == 0)
@@ -11557,7 +11683,7 @@ simplecmd(void)
11557 app = &n->narg.next; 11683 app = &n->narg.next;
11558 savecheckkwd = 0; 11684 savecheckkwd = 0;
11559 } 11685 }
11560#if ENABLE_ASH_BASH_COMPAT 11686#if BASH_FUNCTION
11561 if (function_flag) { 11687 if (function_flag) {
11562 checkkwd = CHKNL | CHKKWD; 11688 checkkwd = CHKNL | CHKKWD;
11563 switch (peektoken()) { 11689 switch (peektoken()) {
@@ -11587,7 +11713,7 @@ simplecmd(void)
11587 parsefname(); /* read name of redirection file */ 11713 parsefname(); /* read name of redirection file */
11588 break; 11714 break;
11589 case TLP: 11715 case TLP:
11590 IF_ASH_BASH_COMPAT(do_func:) 11716 IF_BASH_FUNCTION(do_func:)
11591 if (args && app == &args->narg.next 11717 if (args && app == &args->narg.next
11592 && !vars && !redir 11718 && !vars && !redir
11593 ) { 11719 ) {
@@ -11595,7 +11721,7 @@ simplecmd(void)
11595 const char *name; 11721 const char *name;
11596 11722
11597 /* We have a function */ 11723 /* We have a function */
11598 if (IF_ASH_BASH_COMPAT(!function_flag &&) readtoken() != TRP) 11724 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11599 raise_error_unexpected_syntax(TRP); 11725 raise_error_unexpected_syntax(TRP);
11600 name = n->narg.text; 11726 name = n->narg.text;
11601 if (!goodname(name) 11727 if (!goodname(name)
@@ -11608,7 +11734,7 @@ simplecmd(void)
11608 n->narg.next = parse_command(); 11734 n->narg.next = parse_command();
11609 return n; 11735 return n;
11610 } 11736 }
11611 IF_ASH_BASH_COMPAT(function_flag = 0;) 11737 IF_BASH_FUNCTION(function_flag = 0;)
11612 /* fall through */ 11738 /* fall through */
11613 default: 11739 default:
11614 tokpushback = 1; 11740 tokpushback = 1;
@@ -11789,7 +11915,7 @@ parse_command(void)
11789 n1 = list(0); 11915 n1 = list(0);
11790 t = TEND; 11916 t = TEND;
11791 break; 11917 break;
11792 IF_ASH_BASH_COMPAT(case TFUNCTION:) 11918 IF_BASH_FUNCTION(case TFUNCTION:)
11793 case TWORD: 11919 case TWORD:
11794 case TREDIR: 11920 case TREDIR:
11795 tokpushback = 1; 11921 tokpushback = 1;
@@ -11822,7 +11948,7 @@ parse_command(void)
11822 return n1; 11948 return n1;
11823} 11949}
11824 11950
11825#if ENABLE_ASH_BASH_COMPAT 11951#if BASH_DOLLAR_SQUOTE
11826static int 11952static int
11827decode_dollar_squote(void) 11953decode_dollar_squote(void)
11828{ 11954{
@@ -11907,7 +12033,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
11907 IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */ 12033 IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11908 int dqvarnest; /* levels of variables expansion within double quotes */ 12034 int dqvarnest; /* levels of variables expansion within double quotes */
11909 12035
11910 IF_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;) 12036 IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11911 12037
11912 startlinno = g_parsefile->linno; 12038 startlinno = g_parsefile->linno;
11913 bqlist = NULL; 12039 bqlist = NULL;
@@ -11942,7 +12068,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
11942 USTPUTC(c, out); 12068 USTPUTC(c, out);
11943 break; 12069 break;
11944 case CCTL: 12070 case CCTL:
11945#if ENABLE_ASH_BASH_COMPAT 12071#if BASH_DOLLAR_SQUOTE
11946 if (c == '\\' && bash_dollar_squote) { 12072 if (c == '\\' && bash_dollar_squote) {
11947 c = decode_dollar_squote(); 12073 c = decode_dollar_squote();
11948 if (c == '\0') { 12074 if (c == '\0') {
@@ -12003,7 +12129,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
12003 dblquote = 1; 12129 dblquote = 1;
12004 goto quotemark; 12130 goto quotemark;
12005 case CENDQUOTE: 12131 case CENDQUOTE:
12006 IF_ASH_BASH_COMPAT(bash_dollar_squote = 0;) 12132 IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
12007 if (eofmark != NULL && varnest == 0) { 12133 if (eofmark != NULL && varnest == 0) {
12008 USTPUTC(c, out); 12134 USTPUTC(c, out);
12009 } else { 12135 } else {
@@ -12062,7 +12188,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
12062 break; 12188 break;
12063 default: 12189 default:
12064 if (varnest == 0) { 12190 if (varnest == 0) {
12065#if ENABLE_ASH_BASH_COMPAT 12191#if BASH_REDIR_OUTPUT
12066 if (c == '&') { 12192 if (c == '&') {
12067//Can't call pgetc_eatbnl() here, this requires three-deep pungetc() 12193//Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
12068 if (pgetc() == '>') 12194 if (pgetc() == '>')
@@ -12094,7 +12220,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
12094 len = out - (char *)stackblock(); 12220 len = out - (char *)stackblock();
12095 out = stackblock(); 12221 out = stackblock();
12096 if (eofmark == NULL) { 12222 if (eofmark == NULL) {
12097 if ((c == '>' || c == '<' IF_ASH_BASH_COMPAT( || c == 0x100 + '>')) 12223 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
12098 && quotef == 0 12224 && quotef == 0
12099 ) { 12225 ) {
12100 if (isdigit_str9(out)) { 12226 if (isdigit_str9(out)) {
@@ -12182,7 +12308,7 @@ parseredir: {
12182 pungetc(); 12308 pungetc();
12183 } 12309 }
12184 } 12310 }
12185#if ENABLE_ASH_BASH_COMPAT 12311#if BASH_REDIR_OUTPUT
12186 else if (c == 0x100 + '>') { /* this flags &> redirection */ 12312 else if (c == 0x100 + '>') { /* this flags &> redirection */
12187 np->nfile.fd = 1; 12313 np->nfile.fd = 1;
12188 pgetc(); /* this is '>', no need to check */ 12314 pgetc(); /* this is '>', no need to check */
@@ -12248,7 +12374,7 @@ parsesub: {
12248 if (c > 255 /* PEOA or PEOF */ 12374 if (c > 255 /* PEOA or PEOF */
12249 || (c != '(' && c != '{' && !is_name(c) && !is_special(c)) 12375 || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
12250 ) { 12376 ) {
12251#if ENABLE_ASH_BASH_COMPAT 12377#if BASH_DOLLAR_SQUOTE
12252 if (syntax != DQSYNTAX && c == '\'') 12378 if (syntax != DQSYNTAX && c == '\'')
12253 bash_dollar_squote = 1; 12379 bash_dollar_squote = 1;
12254 else 12380 else
@@ -12324,7 +12450,7 @@ parsesub: {
12324 switch (c) { 12450 switch (c) {
12325 case ':': 12451 case ':':
12326 c = pgetc_eatbnl(); 12452 c = pgetc_eatbnl();
12327#if ENABLE_ASH_BASH_COMPAT 12453#if BASH_SUBSTR
12328 /* This check is only needed to not misinterpret 12454 /* This check is only needed to not misinterpret
12329 * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD} 12455 * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12330 * constructs. 12456 * constructs.
@@ -12354,7 +12480,7 @@ parsesub: {
12354 subtype++; 12480 subtype++;
12355 break; 12481 break;
12356 } 12482 }
12357#if ENABLE_ASH_BASH_COMPAT 12483#if BASH_PATTERN_SUBST
12358 case '/': 12484 case '/':
12359 /* ${v/[/]pattern/repl} */ 12485 /* ${v/[/]pattern/repl} */
12360//TODO: encode pattern and repl separately. 12486//TODO: encode pattern and repl separately.
@@ -12609,7 +12735,7 @@ xxreadtoken(void)
12609 p += xxreadtoken_doubles + 1; 12735 p += xxreadtoken_doubles + 1;
12610 } else { 12736 } else {
12611 pungetc(); 12737 pungetc();
12612#if ENABLE_ASH_BASH_COMPAT 12738#if BASH_REDIR_OUTPUT
12613 if (c == '&' && cc == '>') /* &> */ 12739 if (c == '&' && cc == '>') /* &> */
12614 break; /* return readtoken1(...) */ 12740 break; /* return readtoken1(...) */
12615#endif 12741#endif
@@ -12999,16 +13125,7 @@ find_dot_file(char *name)
12999 if (strchr(name, '/') || (ENABLE_PLATFORM_MINGW32 && strchr(name, '\\'))) 13125 if (strchr(name, '/') || (ENABLE_PLATFORM_MINGW32 && strchr(name, '\\')))
13000 return name; 13126 return name;
13001 13127
13002 /* IIRC standards do not say whether . is to be searched.
13003 * And it is even smaller this way, making it unconditional for now:
13004 */
13005 if (1) { /* ENABLE_ASH_BASH_COMPAT */
13006 fullname = name;
13007 goto try_cur_dir;
13008 }
13009
13010 while ((fullname = path_advance(&path, name)) != NULL) { 13128 while ((fullname = path_advance(&path, name)) != NULL) {
13011 try_cur_dir:
13012 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) { 13129 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
13013 /* 13130 /*
13014 * Don't bother freeing here, since it will 13131 * Don't bother freeing here, since it will
@@ -13032,6 +13149,7 @@ dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
13032 int status = 0; 13149 int status = 0;
13033 char *fullname; 13150 char *fullname;
13034 char **argv; 13151 char **argv;
13152 char *args_need_save;
13035 struct strlist *sp; 13153 struct strlist *sp;
13036 volatile struct shparam saveparam; 13154 volatile struct shparam saveparam;
13037 13155
@@ -13051,7 +13169,8 @@ dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
13051 */ 13169 */
13052 fullname = find_dot_file(argv[0]); 13170 fullname = find_dot_file(argv[0]);
13053 argv++; 13171 argv++;
13054 if (argv[0]) { /* . FILE ARGS, ARGS exist */ 13172 args_need_save = argv[0];
13173 if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
13055 int argc; 13174 int argc;
13056 saveparam = shellparam; 13175 saveparam = shellparam;
13057 shellparam.malloced = 0; 13176 shellparam.malloced = 0;
@@ -13070,7 +13189,7 @@ dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
13070 status = cmdloop(0); 13189 status = cmdloop(0);
13071 popfile(); 13190 popfile();
13072 13191
13073 if (argv[0]) { 13192 if (args_need_save) {
13074 freeparam(&shellparam); 13193 freeparam(&shellparam);
13075 shellparam = saveparam; 13194 shellparam = saveparam;
13076 }; 13195 };
@@ -13902,9 +14021,11 @@ init(void)
13902 setvareq((char*)defoptindvar, VTEXTFIXED); 14021 setvareq((char*)defoptindvar, VTEXTFIXED);
13903 14022
13904 setvar0("PPID", utoa(getppid())); 14023 setvar0("PPID", utoa(getppid()));
13905#if ENABLE_ASH_BASH_COMPAT 14024#if BASH_SHLVL_VAR
13906 p = lookupvar("SHLVL"); 14025 p = lookupvar("SHLVL");
13907 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT); 14026 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
14027#endif
14028#if BASH_HOSTNAME_VAR
13908 if (!lookupvar("HOSTNAME")) { 14029 if (!lookupvar("HOSTNAME")) {
13909 struct utsname uts; 14030 struct utsname uts;
13910 uname(&uts); 14031 uname(&uts);
@@ -13967,7 +14088,7 @@ procargs(char **argv)
13967#if DEBUG == 2 14088#if DEBUG == 2
13968 debug = 1; 14089 debug = 1;
13969#endif 14090#endif
13970 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */ 14091 /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13971 if (xminusc) { 14092 if (xminusc) {
13972 minusc = *xargv++; 14093 minusc = *xargv++;
13973 if (*xargv) 14094 if (*xargv)
@@ -14174,9 +14295,11 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
14174 if (!hp) { 14295 if (!hp) {
14175 hp = lookupvar("HOME"); 14296 hp = lookupvar("HOME");
14176 if (hp) { 14297 if (hp) {
14298 INT_OFF;
14177 hp = concat_path_file(hp, ".ash_history"); 14299 hp = concat_path_file(hp, ".ash_history");
14178 setvar0("HISTFILE", hp); 14300 setvar0("HISTFILE", hp);
14179 free((char*)hp); 14301 free((char*)hp);
14302 INT_ON;
14180 hp = lookupvar("HISTFILE"); 14303 hp = lookupvar("HISTFILE");
14181 } 14304 }
14182 } 14305 }
diff --git a/shell/ash_test/ash-misc/source_argv_and_shift.right b/shell/ash_test/ash-misc/source_argv_and_shift.right
new file mode 100644
index 000000000..b15cc96e7
--- /dev/null
+++ b/shell/ash_test/ash-misc/source_argv_and_shift.right
@@ -0,0 +1,4 @@
1sourced_arg1:1
2arg1:
3sourced_arg1:a
4arg1:1
diff --git a/shell/ash_test/ash-misc/source_argv_and_shift.tests b/shell/ash_test/ash-misc/source_argv_and_shift.tests
new file mode 100755
index 000000000..66353f3d7
--- /dev/null
+++ b/shell/ash_test/ash-misc/source_argv_and_shift.tests
@@ -0,0 +1,12 @@
1echo 'echo sourced_arg1:$1' >sourced1
2echo 'shift' >>sourced1
3
4set -- 1
5. ./sourced1
6echo arg1:$1
7
8set -- 1
9. ./sourced1 a
10echo arg1:$1
11
12rm sourced1
diff --git a/shell/hush.c b/shell/hush.c
index a56d3b280..4123cc19e 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -44,7 +44,6 @@
44 * special variables (done: PWD, PPID, RANDOM) 44 * special variables (done: PWD, PPID, RANDOM)
45 * tilde expansion 45 * tilde expansion
46 * aliases 46 * aliases
47 * kill %jobspec
48 * follow IFS rules more precisely, including update semantics 47 * follow IFS rules more precisely, including update semantics
49 * builtins mandated by standards we don't support: 48 * builtins mandated by standards we don't support:
50 * [un]alias, command, fc, getopts, newgrp, readonly, times 49 * [un]alias, command, fc, getopts, newgrp, readonly, times
@@ -100,8 +99,6 @@
100//config: bool "bash-compatible extensions" 99//config: bool "bash-compatible extensions"
101//config: default y 100//config: default y
102//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH 101//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
103//config: help
104//config: Enable bash-compatible extensions.
105//config: 102//config:
106//config:config HUSH_BRACE_EXPANSION 103//config:config HUSH_BRACE_EXPANSION
107//config: bool "Brace expansion" 104//config: bool "Brace expansion"
@@ -110,13 +107,6 @@
110//config: help 107//config: help
111//config: Enable {abc,def} extension. 108//config: Enable {abc,def} extension.
112//config: 109//config:
113//config:config HUSH_HELP
114//config: bool "help builtin"
115//config: default y
116//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
117//config: help
118//config: Enable help builtin in hush. Code size + ~1 kbyte.
119//config:
120//config:config HUSH_INTERACTIVE 110//config:config HUSH_INTERACTIVE
121//config: bool "Interactive mode" 111//config: bool "Interactive mode"
122//config: default y 112//config: default y
@@ -131,8 +121,6 @@
131//config: bool "Save command history to .hush_history" 121//config: bool "Save command history to .hush_history"
132//config: default y 122//config: default y
133//config: depends on HUSH_INTERACTIVE && FEATURE_EDITING_SAVEHISTORY 123//config: depends on HUSH_INTERACTIVE && FEATURE_EDITING_SAVEHISTORY
134//config: help
135//config: Enable history saving in hush.
136//config: 124//config:
137//config:config HUSH_JOB 125//config:config HUSH_JOB
138//config: bool "Job control" 126//config: bool "Job control"
@@ -146,42 +134,38 @@
146//config: but no separate process group is formed. 134//config: but no separate process group is formed.
147//config: 135//config:
148//config:config HUSH_TICK 136//config:config HUSH_TICK
149//config: bool "Process substitution" 137//config: bool "Support process substitution"
150//config: default y 138//config: default y
151//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH 139//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
152//config: help 140//config: help
153//config: Enable process substitution `command` and $(command) in hush. 141//config: Enable `command` and $(command).
154//config: 142//config:
155//config:config HUSH_IF 143//config:config HUSH_IF
156//config: bool "Support if/then/elif/else/fi" 144//config: bool "Support if/then/elif/else/fi"
157//config: default y 145//config: default y
158//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH 146//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
159//config: help
160//config: Enable if/then/elif/else/fi in hush.
161//config: 147//config:
162//config:config HUSH_LOOPS 148//config:config HUSH_LOOPS
163//config: bool "Support for, while and until loops" 149//config: bool "Support for, while and until loops"
164//config: default y 150//config: default y
165//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH 151//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
166//config: help
167//config: Enable for, while and until loops in hush.
168//config: 152//config:
169//config:config HUSH_CASE 153//config:config HUSH_CASE
170//config: bool "Support case ... esac statement" 154//config: bool "Support case ... esac statement"
171//config: default y 155//config: default y
172//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH 156//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
173//config: help 157//config: help
174//config: Enable case ... esac statement in hush. +400 bytes. 158//config: Enable case ... esac statement. +400 bytes.
175//config: 159//config:
176//config:config HUSH_FUNCTIONS 160//config:config HUSH_FUNCTIONS
177//config: bool "Support funcname() { commands; } syntax" 161//config: bool "Support funcname() { commands; } syntax"
178//config: default y 162//config: default y
179//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH 163//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
180//config: help 164//config: help
181//config: Enable support for shell functions in hush. +800 bytes. 165//config: Enable support for shell functions. +800 bytes.
182//config: 166//config:
183//config:config HUSH_LOCAL 167//config:config HUSH_LOCAL
184//config: bool "Support local builtin" 168//config: bool "local builtin"
185//config: default y 169//config: default y
186//config: depends on HUSH_FUNCTIONS 170//config: depends on HUSH_FUNCTIONS
187//config: help 171//config: help
@@ -195,20 +179,95 @@
195//config: Enable pseudorandom generator and dynamic variable "$RANDOM". 179//config: Enable pseudorandom generator and dynamic variable "$RANDOM".
196//config: Each read of "$RANDOM" will generate a new pseudorandom value. 180//config: Each read of "$RANDOM" will generate a new pseudorandom value.
197//config: 181//config:
182//config:config HUSH_MODE_X
183//config: bool "Support 'hush -x' option and 'set -x' command"
184//config: default y
185//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
186//config: help
187//config: This instructs hush to print commands before execution.
188//config: Adds ~300 bytes.
189//config:
190//config:config HUSH_ECHO
191//config: bool "echo builtin"
192//config: default y
193//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
194//config:
195//config:config HUSH_PRINTF
196//config: bool "printf builtin"
197//config: default y
198//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
199//config:
200//config:config HUSH_TEST
201//config: bool "test builtin"
202//config: default y
203//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
204//config:
205//config:config HUSH_HELP
206//config: bool "help builtin"
207//config: default y
208//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
209//config:
210//config:config HUSH_EXPORT
211//config: bool "export builtin"
212//config: default y
213//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
214//config:
198//config:config HUSH_EXPORT_N 215//config:config HUSH_EXPORT_N
199//config: bool "Support 'export -n' option" 216//config: bool "Support 'export -n' option"
200//config: default y 217//config: default y
201//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH 218//config: depends on HUSH_EXPORT
202//config: help 219//config: help
203//config: export -n unexports variables. It is a bash extension. 220//config: export -n unexports variables. It is a bash extension.
204//config: 221//config:
205//config:config HUSH_MODE_X 222//config:config HUSH_KILL
206//config: bool "Support 'hush -x' option and 'set -x' command" 223//config: bool "kill builtin (supports kill %jobspec)"
224//config: default y
225//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
226//config:
227//config:config HUSH_WAIT
228//config: bool "wait builtin"
229//config: default y
230//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
231//config:
232//config:config HUSH_TRAP
233//config: bool "trap builtin"
234//config: default y
235//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
236//config:
237//config:config HUSH_TYPE
238//config: bool "type builtin"
239//config: default y
240//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
241//config:
242//config:config HUSH_READ
243//config: bool "read builtin"
244//config: default y
245//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
246//config:
247//config:config HUSH_SET
248//config: bool "set builtin"
207//config: default y 249//config: default y
208//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH 250//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
209//config: help 251//config:
210//config: This instructs hush to print commands before execution. 252//config:config HUSH_UNSET
211//config: Adds ~300 bytes. 253//config: bool "unset builtin"
254//config: default y
255//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
256//config:
257//config:config HUSH_ULIMIT
258//config: bool "ulimit builtin"
259//config: default y
260//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
261//config:
262//config:config HUSH_UMASK
263//config: bool "umask builtin"
264//config: default y
265//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
266//config:
267//config:config HUSH_MEMLEAK
268//config: bool "memleak builtin (debugging)"
269//config: default n
270//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
212//config: 271//config:
213//config:config MSH 272//config:config MSH
214//config: bool "msh (deprecated: aliased to hush)" 273//config: bool "msh (deprecated: aliased to hush)"
@@ -218,8 +277,9 @@
218//config: msh is deprecated and will be removed, please migrate to hush. 277//config: msh is deprecated and will be removed, please migrate to hush.
219 278
220//applet:IF_HUSH(APPLET(hush, BB_DIR_BIN, BB_SUID_DROP)) 279//applet:IF_HUSH(APPLET(hush, BB_DIR_BIN, BB_SUID_DROP))
221//applet:IF_MSH(APPLET_ODDNAME(msh, hush, BB_DIR_BIN, BB_SUID_DROP, hush)) 280// APPLET_ODDNAME:name main location suid_type help
222//applet:IF_SH_IS_HUSH(APPLET_ODDNAME(sh, hush, BB_DIR_BIN, BB_SUID_DROP, hush)) 281//applet:IF_MSH( APPLET_ODDNAME(msh, hush, BB_DIR_BIN, BB_SUID_DROP, hush))
282//applet:IF_SH_IS_HUSH( APPLET_ODDNAME(sh, hush, BB_DIR_BIN, BB_SUID_DROP, hush))
223//applet:IF_BASH_IS_HUSH(APPLET_ODDNAME(bash, hush, BB_DIR_BIN, BB_SUID_DROP, hush)) 283//applet:IF_BASH_IS_HUSH(APPLET_ODDNAME(bash, hush, BB_DIR_BIN, BB_SUID_DROP, hush))
224 284
225//kbuild:lib-$(CONFIG_HUSH) += hush.o match.o shell_common.o 285//kbuild:lib-$(CONFIG_HUSH) += hush.o match.o shell_common.o
@@ -267,6 +327,15 @@
267#endif 327#endif
268 328
269 329
330/* So far, all bash compat is controlled by one config option */
331/* Separate defines document which part of code implements what */
332#define BASH_PATTERN_SUBST ENABLE_HUSH_BASH_COMPAT
333#define BASH_SUBSTR ENABLE_HUSH_BASH_COMPAT
334#define BASH_TEST2 ENABLE_HUSH_BASH_COMPAT
335#define BASH_SOURCE ENABLE_HUSH_BASH_COMPAT
336#define BASH_HOSTNAME_VAR ENABLE_HUSH_BASH_COMPAT
337
338
270/* Build knobs */ 339/* Build knobs */
271#define LEAK_HUNTING 0 340#define LEAK_HUNTING 0
272#define BUILD_AS_NOMMU 0 341#define BUILD_AS_NOMMU 0
@@ -347,12 +416,12 @@
347 416
348#define ERR_PTR ((void*)(long)1) 417#define ERR_PTR ((void*)(long)1)
349 418
350#define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n" 419#define JOB_STATUS_FORMAT "[%u] %-22s %.40s\n"
351 420
352#define _SPECIAL_VARS_STR "_*@$!?#" 421#define _SPECIAL_VARS_STR "_*@$!?#"
353#define SPECIAL_VARS_STR ("_*@$!?#" + 1) 422#define SPECIAL_VARS_STR ("_*@$!?#" + 1)
354#define NUMERIC_SPECVARS_STR ("_*@$!?#" + 3) 423#define NUMERIC_SPECVARS_STR ("_*@$!?#" + 3)
355#if ENABLE_HUSH_BASH_COMPAT 424#if BASH_PATTERN_SUBST
356/* Support / and // replace ops */ 425/* Support / and // replace ops */
357/* Note that // is stored as \ in "encoded" string representation */ 426/* Note that // is stored as \ in "encoded" string representation */
358# define VAR_ENCODED_SUBST_OPS "\\/%#:-=+?" 427# define VAR_ENCODED_SUBST_OPS "\\/%#:-=+?"
@@ -513,7 +582,7 @@ struct command {
513 smallint cmd_type; /* CMD_xxx */ 582 smallint cmd_type; /* CMD_xxx */
514#define CMD_NORMAL 0 583#define CMD_NORMAL 0
515#define CMD_SUBSHELL 1 584#define CMD_SUBSHELL 1
516#if ENABLE_HUSH_BASH_COMPAT 585#if BASH_TEST2
517/* used for "[[ EXPR ]]" */ 586/* used for "[[ EXPR ]]" */
518# define CMD_SINGLEWORD_NOGLOB 2 587# define CMD_SINGLEWORD_NOGLOB 2
519#endif 588#endif
@@ -563,7 +632,7 @@ struct pipe {
563 int alive_cmds; /* number of commands running (not exited) */ 632 int alive_cmds; /* number of commands running (not exited) */
564 int stopped_cmds; /* number of commands alive, but stopped */ 633 int stopped_cmds; /* number of commands alive, but stopped */
565#if ENABLE_HUSH_JOB 634#if ENABLE_HUSH_JOB
566 int jobid; /* job number */ 635 unsigned jobid; /* job number */
567 pid_t pgrp; /* process group ID for the job */ 636 pid_t pgrp; /* process group ID for the job */
568 char *cmdtext; /* name of job */ 637 char *cmdtext; /* name of job */
569#endif 638#endif
@@ -740,7 +809,7 @@ struct globals {
740#endif 809#endif
741#if ENABLE_HUSH_JOB 810#if ENABLE_HUSH_JOB
742 int run_list_level; 811 int run_list_level;
743 int last_jobid; 812 unsigned last_jobid;
744 pid_t saved_tty_pgrp; 813 pid_t saved_tty_pgrp;
745 struct pipe *job_list; 814 struct pipe *job_list;
746# define G_saved_tty_pgrp (G.saved_tty_pgrp) 815# define G_saved_tty_pgrp (G.saved_tty_pgrp)
@@ -770,8 +839,13 @@ struct globals {
770 smallint exiting; /* used to prevent EXIT trap recursion */ 839 smallint exiting; /* used to prevent EXIT trap recursion */
771 /* These four support $?, $#, and $1 */ 840 /* These four support $?, $#, and $1 */
772 smalluint last_exitcode; 841 smalluint last_exitcode;
842#if ENABLE_HUSH_SET
773 /* are global_argv and global_argv[1..n] malloced? (note: not [0]) */ 843 /* are global_argv and global_argv[1..n] malloced? (note: not [0]) */
774 smalluint global_args_malloced; 844 smalluint global_args_malloced;
845# define G_global_args_malloced (G.global_args_malloced)
846#else
847# define G_global_args_malloced 0
848#endif
775 /* how many non-NULL argv's we have. NB: $# + 1 */ 849 /* how many non-NULL argv's we have. NB: $# + 1 */
776 int global_argc; 850 int global_argc;
777 char **global_argv; 851 char **global_argv;
@@ -810,14 +884,21 @@ struct globals {
810 unsigned special_sig_mask; 884 unsigned special_sig_mask;
811#if ENABLE_HUSH_JOB 885#if ENABLE_HUSH_JOB
812 unsigned fatal_sig_mask; 886 unsigned fatal_sig_mask;
813# define G_fatal_sig_mask G.fatal_sig_mask 887# define G_fatal_sig_mask (G.fatal_sig_mask)
814#else 888#else
815# define G_fatal_sig_mask 0 889# define G_fatal_sig_mask 0
816#endif 890#endif
891#if ENABLE_HUSH_TRAP
817 char **traps; /* char *traps[NSIG] */ 892 char **traps; /* char *traps[NSIG] */
893# define G_traps G.traps
894#else
895# define G_traps ((char**)NULL)
896#endif
818 sigset_t pending_set; 897 sigset_t pending_set;
819#if HUSH_DEBUG 898#if ENABLE_HUSH_MEMLEAK
820 unsigned long memleak_value; 899 unsigned long memleak_value;
900#endif
901#if HUSH_DEBUG
821 int debug_indent; 902 int debug_indent;
822#endif 903#endif
823 struct sigaction sa; 904 struct sigaction sa;
@@ -839,11 +920,15 @@ struct globals {
839 920
840/* Function prototypes for builtins */ 921/* Function prototypes for builtins */
841static int builtin_cd(char **argv) FAST_FUNC; 922static int builtin_cd(char **argv) FAST_FUNC;
923#if ENABLE_HUSH_ECHO
842static int builtin_echo(char **argv) FAST_FUNC; 924static int builtin_echo(char **argv) FAST_FUNC;
925#endif
843static int builtin_eval(char **argv) FAST_FUNC; 926static int builtin_eval(char **argv) FAST_FUNC;
844static int builtin_exec(char **argv) FAST_FUNC; 927static int builtin_exec(char **argv) FAST_FUNC;
845static int builtin_exit(char **argv) FAST_FUNC; 928static int builtin_exit(char **argv) FAST_FUNC;
929#if ENABLE_HUSH_EXPORT
846static int builtin_export(char **argv) FAST_FUNC; 930static int builtin_export(char **argv) FAST_FUNC;
931#endif
847#if ENABLE_HUSH_JOB 932#if ENABLE_HUSH_JOB
848static int builtin_fg_bg(char **argv) FAST_FUNC; 933static int builtin_fg_bg(char **argv) FAST_FUNC;
849static int builtin_jobs(char **argv) FAST_FUNC; 934static int builtin_jobs(char **argv) FAST_FUNC;
@@ -857,24 +942,43 @@ static int builtin_history(char **argv) FAST_FUNC;
857#if ENABLE_HUSH_LOCAL 942#if ENABLE_HUSH_LOCAL
858static int builtin_local(char **argv) FAST_FUNC; 943static int builtin_local(char **argv) FAST_FUNC;
859#endif 944#endif
860#if HUSH_DEBUG 945#if ENABLE_HUSH_MEMLEAK
861static int builtin_memleak(char **argv) FAST_FUNC; 946static int builtin_memleak(char **argv) FAST_FUNC;
862#endif 947#endif
863#if ENABLE_PRINTF 948#if ENABLE_HUSH_PRINTF
864static int builtin_printf(char **argv) FAST_FUNC; 949static int builtin_printf(char **argv) FAST_FUNC;
865#endif 950#endif
866static int builtin_pwd(char **argv) FAST_FUNC; 951static int builtin_pwd(char **argv) FAST_FUNC;
952#if ENABLE_HUSH_READ
867static int builtin_read(char **argv) FAST_FUNC; 953static int builtin_read(char **argv) FAST_FUNC;
954#endif
955#if ENABLE_HUSH_SET
868static int builtin_set(char **argv) FAST_FUNC; 956static int builtin_set(char **argv) FAST_FUNC;
957#endif
869static int builtin_shift(char **argv) FAST_FUNC; 958static int builtin_shift(char **argv) FAST_FUNC;
870static int builtin_source(char **argv) FAST_FUNC; 959static int builtin_source(char **argv) FAST_FUNC;
960#if ENABLE_HUSH_TEST || BASH_TEST2
871static int builtin_test(char **argv) FAST_FUNC; 961static int builtin_test(char **argv) FAST_FUNC;
962#endif
963#if ENABLE_HUSH_TRAP
872static int builtin_trap(char **argv) FAST_FUNC; 964static int builtin_trap(char **argv) FAST_FUNC;
965#endif
966#if ENABLE_HUSH_TYPE
873static int builtin_type(char **argv) FAST_FUNC; 967static int builtin_type(char **argv) FAST_FUNC;
968#endif
874static int builtin_true(char **argv) FAST_FUNC; 969static int builtin_true(char **argv) FAST_FUNC;
970#if ENABLE_HUSH_UMASK
875static int builtin_umask(char **argv) FAST_FUNC; 971static int builtin_umask(char **argv) FAST_FUNC;
972#endif
973#if ENABLE_HUSH_UNSET
876static int builtin_unset(char **argv) FAST_FUNC; 974static int builtin_unset(char **argv) FAST_FUNC;
975#endif
976#if ENABLE_HUSH_KILL
977static int builtin_kill(char **argv) FAST_FUNC;
978#endif
979#if ENABLE_HUSH_WAIT
877static int builtin_wait(char **argv) FAST_FUNC; 980static int builtin_wait(char **argv) FAST_FUNC;
981#endif
878#if ENABLE_HUSH_LOOPS 982#if ENABLE_HUSH_LOOPS
879static int builtin_break(char **argv) FAST_FUNC; 983static int builtin_break(char **argv) FAST_FUNC;
880static int builtin_continue(char **argv) FAST_FUNC; 984static int builtin_continue(char **argv) FAST_FUNC;
@@ -901,13 +1005,13 @@ struct built_in_command {
901}; 1005};
902 1006
903static const struct built_in_command bltins1[] = { 1007static const struct built_in_command bltins1[] = {
904 BLTIN("." , builtin_source , "Run commands in a file"), 1008 BLTIN("." , builtin_source , "Run commands in file"),
905 BLTIN(":" , builtin_true , NULL), 1009 BLTIN(":" , builtin_true , NULL),
906#if ENABLE_HUSH_JOB 1010#if ENABLE_HUSH_JOB
907 BLTIN("bg" , builtin_fg_bg , "Resume a job in the background"), 1011 BLTIN("bg" , builtin_fg_bg , "Resume job in background"),
908#endif 1012#endif
909#if ENABLE_HUSH_LOOPS 1013#if ENABLE_HUSH_LOOPS
910 BLTIN("break" , builtin_break , "Exit from a loop"), 1014 BLTIN("break" , builtin_break , "Exit loop"),
911#endif 1015#endif
912 BLTIN("cd" , builtin_cd , "Change directory"), 1016 BLTIN("cd" , builtin_cd , "Change directory"),
913#if ENABLE_HUSH_LOOPS 1017#if ENABLE_HUSH_LOOPS
@@ -915,53 +1019,84 @@ static const struct built_in_command bltins1[] = {
915#endif 1019#endif
916 BLTIN("eval" , builtin_eval , "Construct and run shell command"), 1020 BLTIN("eval" , builtin_eval , "Construct and run shell command"),
917 BLTIN("exec" , builtin_exec , "Execute command, don't return to shell"), 1021 BLTIN("exec" , builtin_exec , "Execute command, don't return to shell"),
918 BLTIN("exit" , builtin_exit , "Exit"), 1022 BLTIN("exit" , builtin_exit , NULL),
1023#if ENABLE_HUSH_EXPORT
919 BLTIN("export" , builtin_export , "Set environment variables"), 1024 BLTIN("export" , builtin_export , "Set environment variables"),
1025#endif
920#if ENABLE_HUSH_JOB 1026#if ENABLE_HUSH_JOB
921 BLTIN("fg" , builtin_fg_bg , "Bring job into the foreground"), 1027 BLTIN("fg" , builtin_fg_bg , "Bring job into foreground"),
922#endif 1028#endif
923#if ENABLE_HUSH_HELP 1029#if ENABLE_HUSH_HELP
924 BLTIN("help" , builtin_help , NULL), 1030 BLTIN("help" , builtin_help , NULL),
925#endif 1031#endif
926#if MAX_HISTORY && ENABLE_FEATURE_EDITING 1032#if MAX_HISTORY && ENABLE_FEATURE_EDITING
927 BLTIN("history" , builtin_history , "Show command history"), 1033 BLTIN("history" , builtin_history , "Show history"),
928#endif 1034#endif
929#if ENABLE_HUSH_JOB 1035#if ENABLE_HUSH_JOB
930 BLTIN("jobs" , builtin_jobs , "List jobs"), 1036 BLTIN("jobs" , builtin_jobs , "List jobs"),
931#endif 1037#endif
1038#if ENABLE_HUSH_KILL
1039 BLTIN("kill" , builtin_kill , "Send signals to processes"),
1040#endif
932#if ENABLE_HUSH_LOCAL 1041#if ENABLE_HUSH_LOCAL
933 BLTIN("local" , builtin_local , "Set local variables"), 1042 BLTIN("local" , builtin_local , "Set local variables"),
934#endif 1043#endif
935#if HUSH_DEBUG 1044#if ENABLE_HUSH_MEMLEAK
936 BLTIN("memleak" , builtin_memleak , NULL), 1045 BLTIN("memleak" , builtin_memleak , NULL),
937#endif 1046#endif
1047#if ENABLE_HUSH_READ
938 BLTIN("read" , builtin_read , "Input into variable"), 1048 BLTIN("read" , builtin_read , "Input into variable"),
1049#endif
939#if ENABLE_HUSH_FUNCTIONS 1050#if ENABLE_HUSH_FUNCTIONS
940 BLTIN("return" , builtin_return , "Return from a function"), 1051 BLTIN("return" , builtin_return , "Return from function"),
1052#endif
1053#if ENABLE_HUSH_SET
1054 BLTIN("set" , builtin_set , "Set positional parameters"),
941#endif 1055#endif
942 BLTIN("set" , builtin_set , "Set/unset positional parameters"),
943 BLTIN("shift" , builtin_shift , "Shift positional parameters"), 1056 BLTIN("shift" , builtin_shift , "Shift positional parameters"),
944#if ENABLE_HUSH_BASH_COMPAT 1057#if BASH_SOURCE
945 BLTIN("source" , builtin_source , "Run commands in a file"), 1058 BLTIN("source" , builtin_source , NULL),
946#endif 1059#endif
1060#if ENABLE_HUSH_TRAP
947 BLTIN("trap" , builtin_trap , "Trap signals"), 1061 BLTIN("trap" , builtin_trap , "Trap signals"),
1062#endif
948 BLTIN("true" , builtin_true , NULL), 1063 BLTIN("true" , builtin_true , NULL),
1064#if ENABLE_HUSH_TYPE
949 BLTIN("type" , builtin_type , "Show command type"), 1065 BLTIN("type" , builtin_type , "Show command type"),
950 BLTIN("ulimit" , shell_builtin_ulimit , "Control resource limits"), 1066#endif
1067#if ENABLE_HUSH_ULIMIT
1068 BLTIN("ulimit" , shell_builtin_ulimit, "Control resource limits"),
1069#endif
1070#if ENABLE_HUSH_UMASK
951 BLTIN("umask" , builtin_umask , "Set file creation mask"), 1071 BLTIN("umask" , builtin_umask , "Set file creation mask"),
1072#endif
1073#if ENABLE_HUSH_UNSET
952 BLTIN("unset" , builtin_unset , "Unset variables"), 1074 BLTIN("unset" , builtin_unset , "Unset variables"),
1075#endif
1076#if ENABLE_HUSH_WAIT
953 BLTIN("wait" , builtin_wait , "Wait for process"), 1077 BLTIN("wait" , builtin_wait , "Wait for process"),
1078#endif
954}; 1079};
955/* For now, echo and test are unconditionally enabled. 1080/* These builtins won't be used if we are on NOMMU and need to re-exec
956 * Maybe make it configurable? */ 1081 * (it's cheaper to run an external program in this case):
1082 */
957static const struct built_in_command bltins2[] = { 1083static const struct built_in_command bltins2[] = {
1084#if ENABLE_HUSH_TEST
958 BLTIN("[" , builtin_test , NULL), 1085 BLTIN("[" , builtin_test , NULL),
1086#endif
1087#if BASH_TEST2
1088 BLTIN("[[" , builtin_test , NULL),
1089#endif
1090#if ENABLE_HUSH_ECHO
959 BLTIN("echo" , builtin_echo , NULL), 1091 BLTIN("echo" , builtin_echo , NULL),
960#if ENABLE_PRINTF 1092#endif
1093#if ENABLE_HUSH_PRINTF
961 BLTIN("printf" , builtin_printf , NULL), 1094 BLTIN("printf" , builtin_printf , NULL),
962#endif 1095#endif
963 BLTIN("pwd" , builtin_pwd , NULL), 1096 BLTIN("pwd" , builtin_pwd , NULL),
1097#if ENABLE_HUSH_TEST
964 BLTIN("test" , builtin_test , NULL), 1098 BLTIN("test" , builtin_test , NULL),
1099#endif
965}; 1100};
966 1101
967 1102
@@ -1346,7 +1481,7 @@ typedef struct save_arg_t {
1346 char *sv_argv0; 1481 char *sv_argv0;
1347 char **sv_g_argv; 1482 char **sv_g_argv;
1348 int sv_g_argc; 1483 int sv_g_argc;
1349 smallint sv_g_malloced; 1484 IF_HUSH_SET(smallint sv_g_malloced;)
1350} save_arg_t; 1485} save_arg_t;
1351 1486
1352static void save_and_replace_G_args(save_arg_t *sv, char **argv) 1487static void save_and_replace_G_args(save_arg_t *sv, char **argv)
@@ -1356,11 +1491,11 @@ static void save_and_replace_G_args(save_arg_t *sv, char **argv)
1356 sv->sv_argv0 = argv[0]; 1491 sv->sv_argv0 = argv[0];
1357 sv->sv_g_argv = G.global_argv; 1492 sv->sv_g_argv = G.global_argv;
1358 sv->sv_g_argc = G.global_argc; 1493 sv->sv_g_argc = G.global_argc;
1359 sv->sv_g_malloced = G.global_args_malloced; 1494 IF_HUSH_SET(sv->sv_g_malloced = G.global_args_malloced;)
1360 1495
1361 argv[0] = G.global_argv[0]; /* retain $0 */ 1496 argv[0] = G.global_argv[0]; /* retain $0 */
1362 G.global_argv = argv; 1497 G.global_argv = argv;
1363 G.global_args_malloced = 0; 1498 IF_HUSH_SET(G.global_args_malloced = 0;)
1364 1499
1365 n = 1; 1500 n = 1;
1366 while (*++argv) 1501 while (*++argv)
@@ -1370,19 +1505,19 @@ static void save_and_replace_G_args(save_arg_t *sv, char **argv)
1370 1505
1371static void restore_G_args(save_arg_t *sv, char **argv) 1506static void restore_G_args(save_arg_t *sv, char **argv)
1372{ 1507{
1373 char **pp; 1508#if ENABLE_HUSH_SET
1374
1375 if (G.global_args_malloced) { 1509 if (G.global_args_malloced) {
1376 /* someone ran "set -- arg1 arg2 ...", undo */ 1510 /* someone ran "set -- arg1 arg2 ...", undo */
1377 pp = G.global_argv; 1511 char **pp = G.global_argv;
1378 while (*++pp) /* note: does not free $0 */ 1512 while (*++pp) /* note: does not free $0 */
1379 free(*pp); 1513 free(*pp);
1380 free(G.global_argv); 1514 free(G.global_argv);
1381 } 1515 }
1516#endif
1382 argv[0] = sv->sv_argv0; 1517 argv[0] = sv->sv_argv0;
1383 G.global_argv = sv->sv_g_argv; 1518 G.global_argv = sv->sv_g_argv;
1384 G.global_argc = sv->sv_g_argc; 1519 G.global_argc = sv->sv_g_argc;
1385 G.global_args_malloced = sv->sv_g_malloced; 1520 IF_HUSH_SET(G.global_args_malloced = sv->sv_g_malloced;)
1386} 1521}
1387 1522
1388 1523
@@ -1670,13 +1805,13 @@ static void hush_exit(int exitcode)
1670#endif 1805#endif
1671 1806
1672 fflush_all(); 1807 fflush_all();
1673 if (G.exiting <= 0 && G.traps && G.traps[0] && G.traps[0][0]) { 1808 if (G.exiting <= 0 && G_traps && G_traps[0] && G_traps[0][0]) {
1674 char *argv[3]; 1809 char *argv[3];
1675 /* argv[0] is unused */ 1810 /* argv[0] is unused */
1676 argv[1] = G.traps[0]; 1811 argv[1] = G_traps[0];
1677 argv[2] = NULL; 1812 argv[2] = NULL;
1678 G.exiting = 1; /* prevent EXIT trap recursion */ 1813 G.exiting = 1; /* prevent EXIT trap recursion */
1679 /* Note: G.traps[0] is not cleared! 1814 /* Note: G_traps[0] is not cleared!
1680 * "trap" will still show it, if executed 1815 * "trap" will still show it, if executed
1681 * in the handler */ 1816 * in the handler */
1682 builtin_eval(argv); 1817 builtin_eval(argv);
@@ -1727,14 +1862,14 @@ static int check_and_run_traps(void)
1727 } while (sig < NSIG); 1862 } while (sig < NSIG);
1728 break; 1863 break;
1729 got_sig: 1864 got_sig:
1730 if (G.traps && G.traps[sig]) { 1865 if (G_traps && G_traps[sig]) {
1731 debug_printf_exec("%s: sig:%d handler:'%s'\n", __func__, sig, G.traps[sig]); 1866 debug_printf_exec("%s: sig:%d handler:'%s'\n", __func__, sig, G.traps[sig]);
1732 if (G.traps[sig][0]) { 1867 if (G_traps[sig][0]) {
1733 /* We have user-defined handler */ 1868 /* We have user-defined handler */
1734 smalluint save_rcode; 1869 smalluint save_rcode;
1735 char *argv[3]; 1870 char *argv[3];
1736 /* argv[0] is unused */ 1871 /* argv[0] is unused */
1737 argv[1] = G.traps[sig]; 1872 argv[1] = G_traps[sig];
1738 argv[2] = NULL; 1873 argv[2] = NULL;
1739 save_rcode = G.last_exitcode; 1874 save_rcode = G.last_exitcode;
1740 builtin_eval(argv); 1875 builtin_eval(argv);
@@ -2030,10 +2165,12 @@ static int unset_local_var_len(const char *name, int name_len)
2030 return EXIT_SUCCESS; 2165 return EXIT_SUCCESS;
2031} 2166}
2032 2167
2168#if ENABLE_HUSH_UNSET
2033static int unset_local_var(const char *name) 2169static int unset_local_var(const char *name)
2034{ 2170{
2035 return unset_local_var_len(name, strlen(name)); 2171 return unset_local_var_len(name, strlen(name));
2036} 2172}
2173#endif
2037 2174
2038static void unset_vars(char **strings) 2175static void unset_vars(char **strings)
2039{ 2176{
@@ -2050,11 +2187,13 @@ static void unset_vars(char **strings)
2050 free(strings); 2187 free(strings);
2051} 2188}
2052 2189
2190#if BASH_HOSTNAME_VAR || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_READ
2053static void FAST_FUNC set_local_var_from_halves(const char *name, const char *val) 2191static void FAST_FUNC set_local_var_from_halves(const char *name, const char *val)
2054{ 2192{
2055 char *var = xasprintf("%s=%s", name, val); 2193 char *var = xasprintf("%s=%s", name, val);
2056 set_local_var(var, /*flags:*/ 0, /*lvl:*/ 0, /*ro:*/ 0); 2194 set_local_var(var, /*flags:*/ 0, /*lvl:*/ 0, /*ro:*/ 0);
2057} 2195}
2196#endif
2058 2197
2059 2198
2060/* 2199/*
@@ -3507,7 +3646,7 @@ static int done_word(o_string *word, struct parse_context *ctx)
3507 (ctx->ctx_res_w == RES_SNTX)); 3646 (ctx->ctx_res_w == RES_SNTX));
3508 return (ctx->ctx_res_w == RES_SNTX); 3647 return (ctx->ctx_res_w == RES_SNTX);
3509 } 3648 }
3510# if ENABLE_HUSH_BASH_COMPAT 3649# if BASH_TEST2
3511 if (strcmp(word->data, "[[") == 0) { 3650 if (strcmp(word->data, "[[") == 0) {
3512 command->cmd_type = CMD_SINGLEWORD_NOGLOB; 3651 command->cmd_type = CMD_SINGLEWORD_NOGLOB;
3513 } 3652 }
@@ -4105,7 +4244,7 @@ static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsign
4105{ 4244{
4106 int ch; 4245 int ch;
4107 char dbl = end_ch & DOUBLE_CLOSE_CHAR_FLAG; 4246 char dbl = end_ch & DOUBLE_CLOSE_CHAR_FLAG;
4108# if ENABLE_HUSH_BASH_COMPAT 4247# if BASH_SUBSTR || BASH_PATTERN_SUBST
4109 char end_char2 = end_ch >> 8; 4248 char end_char2 = end_ch >> 8;
4110# endif 4249# endif
4111 end_ch &= (DOUBLE_CLOSE_CHAR_FLAG - 1); 4250 end_ch &= (DOUBLE_CLOSE_CHAR_FLAG - 1);
@@ -4116,7 +4255,11 @@ static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsign
4116 syntax_error_unterm_ch(end_ch); 4255 syntax_error_unterm_ch(end_ch);
4117 return 0; 4256 return 0;
4118 } 4257 }
4119 if (ch == end_ch IF_HUSH_BASH_COMPAT( || ch == end_char2)) { 4258 if (ch == end_ch
4259# if BASH_SUBSTR || BASH_PATTERN_SUBST
4260 || ch == end_char2
4261# endif
4262 ) {
4120 if (!dbl) 4263 if (!dbl)
4121 break; 4264 break;
4122 /* we look for closing )) of $((EXPR)) */ 4265 /* we look for closing )) of $((EXPR)) */
@@ -4269,14 +4412,14 @@ static int parse_dollar(o_string *as_string,
4269 4412
4270 /* Eat everything until closing '}' (or ':') */ 4413 /* Eat everything until closing '}' (or ':') */
4271 end_ch = '}'; 4414 end_ch = '}';
4272 if (ENABLE_HUSH_BASH_COMPAT 4415 if (BASH_SUBSTR
4273 && ch == ':' 4416 && ch == ':'
4274 && !strchr(MINUS_PLUS_EQUAL_QUESTION, i_peek(input)) 4417 && !strchr(MINUS_PLUS_EQUAL_QUESTION, i_peek(input))
4275 ) { 4418 ) {
4276 /* It's ${var:N[:M]} thing */ 4419 /* It's ${var:N[:M]} thing */
4277 end_ch = '}' * 0x100 + ':'; 4420 end_ch = '}' * 0x100 + ':';
4278 } 4421 }
4279 if (ENABLE_HUSH_BASH_COMPAT 4422 if (BASH_PATTERN_SUBST
4280 && ch == '/' 4423 && ch == '/'
4281 ) { 4424 ) {
4282 /* It's ${var/[/]pattern[/repl]} thing */ 4425 /* It's ${var/[/]pattern[/repl]} thing */
@@ -4303,7 +4446,9 @@ static int parse_dollar(o_string *as_string,
4303 o_addchr(as_string, last_ch); 4446 o_addchr(as_string, last_ch);
4304 } 4447 }
4305 4448
4306 if (ENABLE_HUSH_BASH_COMPAT && (end_ch & 0xff00)) { 4449 if ((BASH_SUBSTR || BASH_PATTERN_SUBST)
4450 && (end_ch & 0xff00)
4451 ) {
4307 /* close the first block: */ 4452 /* close the first block: */
4308 o_addchr(dest, SPECIAL_VAR_SYMBOL); 4453 o_addchr(dest, SPECIAL_VAR_SYMBOL);
4309 /* while parsing N from ${var:N[:M]} 4454 /* while parsing N from ${var:N[:M]}
@@ -4314,7 +4459,7 @@ static int parse_dollar(o_string *as_string,
4314 goto again; 4459 goto again;
4315 } 4460 }
4316 /* got '}' */ 4461 /* got '}' */
4317 if (end_ch == '}' * 0x100 + ':') { 4462 if (BASH_SUBSTR && end_ch == '}' * 0x100 + ':') {
4318 /* it's ${var:N} - emulate :999999999 */ 4463 /* it's ${var:N} - emulate :999999999 */
4319 o_addstr(dest, "999999999"); 4464 o_addstr(dest, "999999999");
4320 } /* else: it's ${var/[/]pattern} */ 4465 } /* else: it's ${var/[/]pattern} */
@@ -4389,7 +4534,7 @@ static int parse_dollar(o_string *as_string,
4389} 4534}
4390 4535
4391#if BB_MMU 4536#if BB_MMU
4392# if ENABLE_HUSH_BASH_COMPAT 4537# if BASH_PATTERN_SUBST
4393#define encode_string(as_string, dest, input, dquote_end, process_bkslash) \ 4538#define encode_string(as_string, dest, input, dquote_end, process_bkslash) \
4394 encode_string(dest, input, dquote_end, process_bkslash) 4539 encode_string(dest, input, dquote_end, process_bkslash)
4395# else 4540# else
@@ -4401,7 +4546,7 @@ static int parse_dollar(o_string *as_string,
4401 4546
4402#else /* !MMU */ 4547#else /* !MMU */
4403 4548
4404# if ENABLE_HUSH_BASH_COMPAT 4549# if BASH_PATTERN_SUBST
4405/* all parameters are needed, no macro tricks */ 4550/* all parameters are needed, no macro tricks */
4406# else 4551# else
4407#define encode_string(as_string, dest, input, dquote_end, process_bkslash) \ 4552#define encode_string(as_string, dest, input, dquote_end, process_bkslash) \
@@ -4414,7 +4559,7 @@ static int encode_string(o_string *as_string,
4414 int dquote_end, 4559 int dquote_end,
4415 int process_bkslash) 4560 int process_bkslash)
4416{ 4561{
4417#if !ENABLE_HUSH_BASH_COMPAT 4562#if !BASH_PATTERN_SUBST
4418 const int process_bkslash = 1; 4563 const int process_bkslash = 1;
4419#endif 4564#endif
4420 int ch; 4565 int ch;
@@ -5057,7 +5202,7 @@ static struct pipe *parse_stream(char **pstring,
5057/*** Execution routines ***/ 5202/*** Execution routines ***/
5058 5203
5059/* Expansion can recurse, need forward decls: */ 5204/* Expansion can recurse, need forward decls: */
5060#if !ENABLE_HUSH_BASH_COMPAT 5205#if !BASH_PATTERN_SUBST
5061/* only ${var/pattern/repl} (its pattern part) needs additional mode */ 5206/* only ${var/pattern/repl} (its pattern part) needs additional mode */
5062#define expand_string_to_string(str, do_unbackslash) \ 5207#define expand_string_to_string(str, do_unbackslash) \
5063 expand_string_to_string(str) 5208 expand_string_to_string(str)
@@ -5178,7 +5323,7 @@ static int expand_on_ifs(int *ended_with_ifs, o_string *output, int n, const cha
5178 * Returns malloced string. 5323 * Returns malloced string.
5179 * As an optimization, we return NULL if expansion is not needed. 5324 * As an optimization, we return NULL if expansion is not needed.
5180 */ 5325 */
5181#if !ENABLE_HUSH_BASH_COMPAT 5326#if !BASH_PATTERN_SUBST
5182/* only ${var/pattern/repl} (its pattern part) needs additional mode */ 5327/* only ${var/pattern/repl} (its pattern part) needs additional mode */
5183#define encode_then_expand_string(str, process_bkslash, do_unbackslash) \ 5328#define encode_then_expand_string(str, process_bkslash, do_unbackslash) \
5184 encode_then_expand_string(str) 5329 encode_then_expand_string(str)
@@ -5232,7 +5377,7 @@ static arith_t expand_and_evaluate_arith(const char *arg, const char **errmsg_p)
5232} 5377}
5233#endif 5378#endif
5234 5379
5235#if ENABLE_HUSH_BASH_COMPAT 5380#if BASH_PATTERN_SUBST
5236/* ${var/[/]pattern[/repl]} helpers */ 5381/* ${var/[/]pattern[/repl]} helpers */
5237static char *strstr_pattern(char *val, const char *pattern, int *size) 5382static char *strstr_pattern(char *val, const char *pattern, int *size)
5238{ 5383{
@@ -5284,7 +5429,7 @@ static char *replace_pattern(char *val, const char *pattern, const char *repl, c
5284 debug_printf_varexp("result:'%s'\n", result); 5429 debug_printf_varexp("result:'%s'\n", result);
5285 return result; 5430 return result;
5286} 5431}
5287#endif 5432#endif /* BASH_PATTERN_SUBST */
5288 5433
5289/* Helper: 5434/* Helper:
5290 * Handles <SPECIAL_VAR_SYMBOL>varname...<SPECIAL_VAR_SYMBOL> construct. 5435 * Handles <SPECIAL_VAR_SYMBOL>varname...<SPECIAL_VAR_SYMBOL> construct.
@@ -5332,7 +5477,7 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha
5332 if (exp_op == ':') { 5477 if (exp_op == ':') {
5333 exp_op = *exp_word++; 5478 exp_op = *exp_word++;
5334//TODO: try ${var:} and ${var:bogus} in non-bash config 5479//TODO: try ${var:} and ${var:bogus} in non-bash config
5335 if (ENABLE_HUSH_BASH_COMPAT 5480 if (BASH_SUBSTR
5336 && (!exp_op || !strchr(MINUS_PLUS_EQUAL_QUESTION, exp_op)) 5481 && (!exp_op || !strchr(MINUS_PLUS_EQUAL_QUESTION, exp_op))
5337 ) { 5482 ) {
5338 /* oops... it's ${var:N[:M]}, not ${var:?xxx} or some such */ 5483 /* oops... it's ${var:N[:M]}, not ${var:?xxx} or some such */
@@ -5414,7 +5559,7 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha
5414 } 5559 }
5415 } 5560 }
5416 } 5561 }
5417#if ENABLE_HUSH_BASH_COMPAT 5562#if BASH_PATTERN_SUBST
5418 else if (exp_op == '/' || exp_op == '\\') { 5563 else if (exp_op == '/' || exp_op == '\\') {
5419 /* It's ${var/[/]pattern[/repl]} thing. 5564 /* It's ${var/[/]pattern[/repl]} thing.
5420 * Note that in encoded form it has TWO parts: 5565 * Note that in encoded form it has TWO parts:
@@ -5461,9 +5606,9 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha
5461 free(repl); 5606 free(repl);
5462 } 5607 }
5463 } 5608 }
5464#endif 5609#endif /* BASH_PATTERN_SUBST */
5465 else if (exp_op == ':') { 5610 else if (exp_op == ':') {
5466#if ENABLE_HUSH_BASH_COMPAT && ENABLE_FEATURE_SH_MATH 5611#if BASH_SUBSTR && ENABLE_FEATURE_SH_MATH
5467 /* It's ${var:N[:M]} bashism. 5612 /* It's ${var:N[:M]} bashism.
5468 * Note that in encoded form it has TWO parts: 5613 * Note that in encoded form it has TWO parts:
5469 * var:N<SPECIAL_VAR_SYMBOL>M<SPECIAL_VAR_SYMBOL> 5614 * var:N<SPECIAL_VAR_SYMBOL>M<SPECIAL_VAR_SYMBOL>
@@ -5499,7 +5644,7 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha
5499 } 5644 }
5500 debug_printf_varexp("val:'%s'\n", val); 5645 debug_printf_varexp("val:'%s'\n", val);
5501 } else 5646 } else
5502#endif 5647#endif /* HUSH_SUBSTR_EXPANSION && FEATURE_SH_MATH */
5503 { 5648 {
5504 die_if_script("malformed ${%s:...}", var); 5649 die_if_script("malformed ${%s:...}", var);
5505 val = NULL; 5650 val = NULL;
@@ -5789,7 +5934,7 @@ static char **expand_strvec_to_strvec(char **argv)
5789 return expand_variables(argv, EXP_FLAG_GLOB | EXP_FLAG_ESC_GLOB_CHARS); 5934 return expand_variables(argv, EXP_FLAG_GLOB | EXP_FLAG_ESC_GLOB_CHARS);
5790} 5935}
5791 5936
5792#if ENABLE_HUSH_BASH_COMPAT 5937#if BASH_TEST2
5793static char **expand_strvec_to_strvec_singleword_noglob(char **argv) 5938static char **expand_strvec_to_strvec_singleword_noglob(char **argv)
5794{ 5939{
5795 return expand_variables(argv, EXP_FLAG_SINGLEWORD); 5940 return expand_variables(argv, EXP_FLAG_SINGLEWORD);
@@ -5804,7 +5949,7 @@ static char **expand_strvec_to_strvec_singleword_noglob(char **argv)
5804 */ 5949 */
5805static char *expand_string_to_string(const char *str, int do_unbackslash) 5950static char *expand_string_to_string(const char *str, int do_unbackslash)
5806{ 5951{
5807#if !ENABLE_HUSH_BASH_COMPAT 5952#if !BASH_PATTERN_SUBST
5808 const int do_unbackslash = 1; 5953 const int do_unbackslash = 1;
5809#endif 5954#endif
5810 char *argv[2], **list; 5955 char *argv[2], **list;
@@ -5882,13 +6027,15 @@ static void switch_off_special_sigs(unsigned mask)
5882 sig++; 6027 sig++;
5883 if (!(mask & 1)) 6028 if (!(mask & 1))
5884 continue; 6029 continue;
5885 if (G.traps) { 6030#if ENABLE_HUSH_TRAP
5886 if (G.traps[sig] && !G.traps[sig][0]) 6031 if (G_traps) {
6032 if (G_traps[sig] && !G_traps[sig][0])
5887 /* trap is '', has to remain SIG_IGN */ 6033 /* trap is '', has to remain SIG_IGN */
5888 continue; 6034 continue;
5889 free(G.traps[sig]); 6035 free(G_traps[sig]);
5890 G.traps[sig] = NULL; 6036 G_traps[sig] = NULL;
5891 } 6037 }
6038#endif
5892 /* We are here only if no trap or trap was not '' */ 6039 /* We are here only if no trap or trap was not '' */
5893 install_sighandler(sig, SIG_DFL); 6040 install_sighandler(sig, SIG_DFL);
5894 } 6041 }
@@ -5905,7 +6052,7 @@ static void reset_traps_to_defaults(void)
5905 /* This function is always called in a child shell 6052 /* This function is always called in a child shell
5906 * after fork (not vfork, NOMMU doesn't use this function). 6053 * after fork (not vfork, NOMMU doesn't use this function).
5907 */ 6054 */
5908 unsigned sig; 6055 IF_HUSH_TRAP(unsigned sig;)
5909 unsigned mask; 6056 unsigned mask;
5910 6057
5911 /* Child shells are not interactive. 6058 /* Child shells are not interactive.
@@ -5914,35 +6061,37 @@ static void reset_traps_to_defaults(void)
5914 * Same goes for SIGTERM, SIGHUP, SIGINT. 6061 * Same goes for SIGTERM, SIGHUP, SIGINT.
5915 */ 6062 */
5916 mask = (G.special_sig_mask & SPECIAL_INTERACTIVE_SIGS) | G_fatal_sig_mask; 6063 mask = (G.special_sig_mask & SPECIAL_INTERACTIVE_SIGS) | G_fatal_sig_mask;
5917 if (!G.traps && !mask) 6064 if (!G_traps && !mask)
5918 return; /* already no traps and no special sigs */ 6065 return; /* already no traps and no special sigs */
5919 6066
5920 /* Switch off special sigs */ 6067 /* Switch off special sigs */
5921 switch_off_special_sigs(mask); 6068 switch_off_special_sigs(mask);
5922#if ENABLE_HUSH_JOB 6069# if ENABLE_HUSH_JOB
5923 G_fatal_sig_mask = 0; 6070 G_fatal_sig_mask = 0;
5924#endif 6071# endif
5925 G.special_sig_mask &= ~SPECIAL_INTERACTIVE_SIGS; 6072 G.special_sig_mask &= ~SPECIAL_INTERACTIVE_SIGS;
5926 /* SIGQUIT,SIGCHLD and maybe SPECIAL_JOBSTOP_SIGS 6073 /* SIGQUIT,SIGCHLD and maybe SPECIAL_JOBSTOP_SIGS
5927 * remain set in G.special_sig_mask */ 6074 * remain set in G.special_sig_mask */
5928 6075
5929 if (!G.traps) 6076# if ENABLE_HUSH_TRAP
6077 if (!G_traps)
5930 return; 6078 return;
5931 6079
5932 /* Reset all sigs to default except ones with empty traps */ 6080 /* Reset all sigs to default except ones with empty traps */
5933 for (sig = 0; sig < NSIG; sig++) { 6081 for (sig = 0; sig < NSIG; sig++) {
5934 if (!G.traps[sig]) 6082 if (!G_traps[sig])
5935 continue; /* no trap: nothing to do */ 6083 continue; /* no trap: nothing to do */
5936 if (!G.traps[sig][0]) 6084 if (!G_traps[sig][0])
5937 continue; /* empty trap: has to remain SIG_IGN */ 6085 continue; /* empty trap: has to remain SIG_IGN */
5938 /* sig has non-empty trap, reset it: */ 6086 /* sig has non-empty trap, reset it: */
5939 free(G.traps[sig]); 6087 free(G_traps[sig]);
5940 G.traps[sig] = NULL; 6088 G_traps[sig] = NULL;
5941 /* There is no signal for trap 0 (EXIT) */ 6089 /* There is no signal for trap 0 (EXIT) */
5942 if (sig == 0) 6090 if (sig == 0)
5943 continue; 6091 continue;
5944 install_sighandler(sig, pick_sighandler(sig)); 6092 install_sighandler(sig, pick_sighandler(sig));
5945 } 6093 }
6094# endif
5946} 6095}
5947 6096
5948#else /* !BB_MMU */ 6097#else /* !BB_MMU */
@@ -5982,10 +6131,10 @@ static void re_execute_shell(char ***to_free, const char *s,
5982 cnt++; 6131 cnt++;
5983 6132
5984 empty_trap_mask = 0; 6133 empty_trap_mask = 0;
5985 if (G.traps) { 6134 if (G_traps) {
5986 int sig; 6135 int sig;
5987 for (sig = 1; sig < NSIG; sig++) { 6136 for (sig = 1; sig < NSIG; sig++) {
5988 if (G.traps[sig] && !G.traps[sig][0]) 6137 if (G_traps[sig] && !G_traps[sig][0])
5989 empty_trap_mask |= 1LL << sig; 6138 empty_trap_mask |= 1LL << sig;
5990 } 6139 }
5991 } 6140 }
@@ -6178,6 +6327,7 @@ static FILE *generate_stream_from_string(const char *s, pid_t *pid_p)
6178 xmove_fd(channel[1], 1); 6327 xmove_fd(channel[1], 1);
6179 /* Prevent it from trying to handle ctrl-z etc */ 6328 /* Prevent it from trying to handle ctrl-z etc */
6180 IF_HUSH_JOB(G.run_list_level = 1;) 6329 IF_HUSH_JOB(G.run_list_level = 1;)
6330# if ENABLE_HUSH_TRAP
6181 /* Awful hack for `trap` or $(trap). 6331 /* Awful hack for `trap` or $(trap).
6182 * 6332 *
6183 * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html 6333 * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
@@ -6221,6 +6371,7 @@ static FILE *generate_stream_from_string(const char *s, pid_t *pid_p)
6221 fflush_all(); /* important */ 6371 fflush_all(); /* important */
6222 _exit(0); 6372 _exit(0);
6223 } 6373 }
6374# endif
6224# if BB_MMU 6375# if BB_MMU
6225 reset_traps_to_defaults(); 6376 reset_traps_to_defaults();
6226 parse_and_run_string(s); 6377 parse_and_run_string(s);
@@ -6629,6 +6780,7 @@ static struct function *new_function(char *name)
6629 return funcp; 6780 return funcp;
6630} 6781}
6631 6782
6783# if ENABLE_HUSH_UNSET
6632static void unset_func(const char *name) 6784static void unset_func(const char *name)
6633{ 6785{
6634 struct function **funcpp = find_function_slot(name); 6786 struct function **funcpp = find_function_slot(name);
@@ -6644,13 +6796,14 @@ static void unset_func(const char *name)
6644 if (funcp->body) { 6796 if (funcp->body) {
6645 free_pipe_list(funcp->body); 6797 free_pipe_list(funcp->body);
6646 free(funcp->name); 6798 free(funcp->name);
6647# if !BB_MMU 6799# if !BB_MMU
6648 free(funcp->body_as_string); 6800 free(funcp->body_as_string);
6649# endif 6801# endif
6650 } 6802 }
6651 free(funcp); 6803 free(funcp);
6652 } 6804 }
6653} 6805}
6806# endif
6654 6807
6655# if BB_MMU 6808# if BB_MMU
6656#define exec_function(to_free, funcp, argv) \ 6809#define exec_function(to_free, funcp, argv) \
@@ -7043,7 +7196,7 @@ static void insert_bg_job(struct pipe *pi)
7043 job->cmdtext = xstrdup(get_cmdtext(pi)); 7196 job->cmdtext = xstrdup(get_cmdtext(pi));
7044 7197
7045 if (G_interactive_fd) 7198 if (G_interactive_fd)
7046 printf("[%d] %d %s\n", job->jobid, job->cmds[0].pid, job->cmdtext); 7199 printf("[%u] %u %s\n", job->jobid, (unsigned)job->cmds[0].pid, job->cmdtext);
7047 G.last_jobid = job->jobid; 7200 G.last_jobid = job->jobid;
7048} 7201}
7049 7202
@@ -7518,7 +7671,7 @@ static NOINLINE int run_pipe(struct pipe *pi)
7518 } 7671 }
7519 7672
7520 /* Expand the rest into (possibly) many strings each */ 7673 /* Expand the rest into (possibly) many strings each */
7521#if ENABLE_HUSH_BASH_COMPAT 7674#if BASH_TEST2
7522 if (command->cmd_type == CMD_SINGLEWORD_NOGLOB) { 7675 if (command->cmd_type == CMD_SINGLEWORD_NOGLOB) {
7523 argv_expanded = expand_strvec_to_strvec_singleword_noglob(argv + command->assignment_cnt); 7676 argv_expanded = expand_strvec_to_strvec_singleword_noglob(argv + command->assignment_cnt);
7524 } else 7677 } else
@@ -8118,10 +8271,12 @@ static void install_sighandlers(unsigned mask)
8118 if (old_handler == SIG_IGN) { 8271 if (old_handler == SIG_IGN) {
8119 /* oops... restore back to IGN, and record this fact */ 8272 /* oops... restore back to IGN, and record this fact */
8120 install_sighandler(sig, old_handler); 8273 install_sighandler(sig, old_handler);
8121 if (!G.traps) 8274#if ENABLE_HUSH_TRAP
8122 G.traps = xzalloc(sizeof(G.traps[0]) * NSIG); 8275 if (!G_traps)
8123 free(G.traps[sig]); 8276 G_traps = xzalloc(sizeof(G_traps[0]) * NSIG);
8124 G.traps[sig] = xzalloc(1); /* == xstrdup(""); */ 8277 free(G_traps[sig]);
8278 G_traps[sig] = xzalloc(1); /* == xstrdup(""); */
8279#endif
8125 } 8280 }
8126 } 8281 }
8127} 8282}
@@ -8272,7 +8427,7 @@ int hush_main(int argc, char **argv)
8272 /* Export PWD */ 8427 /* Export PWD */
8273 set_pwd_var(/*exp:*/ 1); 8428 set_pwd_var(/*exp:*/ 1);
8274 8429
8275#if ENABLE_HUSH_BASH_COMPAT 8430#if BASH_HOSTNAME_VAR
8276 /* Set (but not export) HOSTNAME unless already set */ 8431 /* Set (but not export) HOSTNAME unless already set */
8277 if (!get_local_var_value("HOSTNAME")) { 8432 if (!get_local_var_value("HOSTNAME")) {
8278 struct utsname uts; 8433 struct utsname uts;
@@ -8422,10 +8577,10 @@ int hush_main(int argc, char **argv)
8422 if (empty_trap_mask != 0) { 8577 if (empty_trap_mask != 0) {
8423 int sig; 8578 int sig;
8424 install_special_sighandlers(); 8579 install_special_sighandlers();
8425 G.traps = xzalloc(sizeof(G.traps[0]) * NSIG); 8580 G_traps = xzalloc(sizeof(G_traps[0]) * NSIG);
8426 for (sig = 1; sig < NSIG; sig++) { 8581 for (sig = 1; sig < NSIG; sig++) {
8427 if (empty_trap_mask & (1LL << sig)) { 8582 if (empty_trap_mask & (1LL << sig)) {
8428 G.traps[sig] = xzalloc(1); /* == xstrdup(""); */ 8583 G_traps[sig] = xzalloc(1); /* == xstrdup(""); */
8429 install_sighandler(sig, SIG_IGN); 8584 install_sighandler(sig, SIG_IGN);
8430 } 8585 }
8431 } 8586 }
@@ -8669,6 +8824,7 @@ static int FAST_FUNC builtin_true(char **argv UNUSED_PARAM)
8669 return 0; 8824 return 0;
8670} 8825}
8671 8826
8827#if ENABLE_HUSH_TEST || ENABLE_HUSH_ECHO || ENABLE_HUSH_PRINTF || ENABLE_HUSH_KILL
8672static int run_applet_main(char **argv, int (*applet_main_func)(int argc, char **argv)) 8828static int run_applet_main(char **argv, int (*applet_main_func)(int argc, char **argv))
8673{ 8829{
8674 int argc = 0; 8830 int argc = 0;
@@ -8678,24 +8834,50 @@ static int run_applet_main(char **argv, int (*applet_main_func)(int argc, char *
8678 } 8834 }
8679 return applet_main_func(argc, argv - argc); 8835 return applet_main_func(argc, argv - argc);
8680} 8836}
8681 8837#endif
8838#if ENABLE_HUSH_TEST || BASH_TEST2
8682static int FAST_FUNC builtin_test(char **argv) 8839static int FAST_FUNC builtin_test(char **argv)
8683{ 8840{
8684 return run_applet_main(argv, test_main); 8841 return run_applet_main(argv, test_main);
8685} 8842}
8686 8843#endif
8844#if ENABLE_HUSH_ECHO
8687static int FAST_FUNC builtin_echo(char **argv) 8845static int FAST_FUNC builtin_echo(char **argv)
8688{ 8846{
8689 return run_applet_main(argv, echo_main); 8847 return run_applet_main(argv, echo_main);
8690} 8848}
8691 8849#endif
8692#if ENABLE_PRINTF 8850#if ENABLE_HUSH_PRINTF
8693static int FAST_FUNC builtin_printf(char **argv) 8851static int FAST_FUNC builtin_printf(char **argv)
8694{ 8852{
8695 return run_applet_main(argv, printf_main); 8853 return run_applet_main(argv, printf_main);
8696} 8854}
8697#endif 8855#endif
8698 8856
8857#if ENABLE_HUSH_HELP
8858static int FAST_FUNC builtin_help(char **argv UNUSED_PARAM)
8859{
8860 const struct built_in_command *x;
8861
8862 printf(
8863 "Built-in commands:\n"
8864 "------------------\n");
8865 for (x = bltins1; x != &bltins1[ARRAY_SIZE(bltins1)]; x++) {
8866 if (x->b_descr)
8867 printf("%-10s%s\n", x->b_cmd, x->b_descr);
8868 }
8869 return EXIT_SUCCESS;
8870}
8871#endif
8872
8873#if MAX_HISTORY && ENABLE_FEATURE_EDITING
8874static int FAST_FUNC builtin_history(char **argv UNUSED_PARAM)
8875{
8876 show_history(G.line_input_state);
8877 return EXIT_SUCCESS;
8878}
8879#endif
8880
8699static char **skip_dash_dash(char **argv) 8881static char **skip_dash_dash(char **argv)
8700{ 8882{
8701 argv++; 8883 argv++;
@@ -8704,24 +8886,6 @@ static char **skip_dash_dash(char **argv)
8704 return argv; 8886 return argv;
8705} 8887}
8706 8888
8707static int FAST_FUNC builtin_eval(char **argv)
8708{
8709 int rcode = EXIT_SUCCESS;
8710
8711 argv = skip_dash_dash(argv);
8712 if (*argv) {
8713 char *str = expand_strvec_to_string(argv);
8714 /* bash:
8715 * eval "echo Hi; done" ("done" is syntax error):
8716 * "echo Hi" will not execute too.
8717 */
8718 parse_and_run_string(str);
8719 free(str);
8720 rcode = G.last_exitcode;
8721 }
8722 return rcode;
8723}
8724
8725static int FAST_FUNC builtin_cd(char **argv) 8889static int FAST_FUNC builtin_cd(char **argv)
8726{ 8890{
8727 const char *newdir; 8891 const char *newdir;
@@ -8749,6 +8913,30 @@ static int FAST_FUNC builtin_cd(char **argv)
8749 return EXIT_SUCCESS; 8913 return EXIT_SUCCESS;
8750} 8914}
8751 8915
8916static int FAST_FUNC builtin_pwd(char **argv UNUSED_PARAM)
8917{
8918 puts(get_cwd(0));
8919 return EXIT_SUCCESS;
8920}
8921
8922static int FAST_FUNC builtin_eval(char **argv)
8923{
8924 int rcode = EXIT_SUCCESS;
8925
8926 argv = skip_dash_dash(argv);
8927 if (*argv) {
8928 char *str = expand_strvec_to_string(argv);
8929 /* bash:
8930 * eval "echo Hi; done" ("done" is syntax error):
8931 * "echo Hi" will not execute too.
8932 */
8933 parse_and_run_string(str);
8934 free(str);
8935 rcode = G.last_exitcode;
8936 }
8937 return rcode;
8938}
8939
8752static int FAST_FUNC builtin_exec(char **argv) 8940static int FAST_FUNC builtin_exec(char **argv)
8753{ 8941{
8754 argv = skip_dash_dash(argv); 8942 argv = skip_dash_dash(argv);
@@ -8794,6 +8982,148 @@ static int FAST_FUNC builtin_exit(char **argv)
8794 hush_exit(xatoi(argv[0]) & 0xff); 8982 hush_exit(xatoi(argv[0]) & 0xff);
8795} 8983}
8796 8984
8985#if ENABLE_HUSH_TYPE
8986/* http://www.opengroup.org/onlinepubs/9699919799/utilities/type.html */
8987static int FAST_FUNC builtin_type(char **argv)
8988{
8989 int ret = EXIT_SUCCESS;
8990
8991 while (*++argv) {
8992 const char *type;
8993 char *path = NULL;
8994
8995 if (0) {} /* make conditional compile easier below */
8996 /*else if (find_alias(*argv))
8997 type = "an alias";*/
8998#if ENABLE_HUSH_FUNCTIONS
8999 else if (find_function(*argv))
9000 type = "a function";
9001#endif
9002 else if (find_builtin(*argv))
9003 type = "a shell builtin";
9004 else if ((path = find_in_path(*argv)) != NULL)
9005 type = path;
9006 else {
9007 bb_error_msg("type: %s: not found", *argv);
9008 ret = EXIT_FAILURE;
9009 continue;
9010 }
9011
9012 printf("%s is %s\n", *argv, type);
9013 free(path);
9014 }
9015
9016 return ret;
9017}
9018#endif
9019
9020#if ENABLE_HUSH_READ
9021/* Interruptibility of read builtin in bash
9022 * (tested on bash-4.2.8 by sending signals (not by ^C)):
9023 *
9024 * Empty trap makes read ignore corresponding signal, for any signal.
9025 *
9026 * SIGINT:
9027 * - terminates non-interactive shell;
9028 * - interrupts read in interactive shell;
9029 * if it has non-empty trap:
9030 * - executes trap and returns to command prompt in interactive shell;
9031 * - executes trap and returns to read in non-interactive shell;
9032 * SIGTERM:
9033 * - is ignored (does not interrupt) read in interactive shell;
9034 * - terminates non-interactive shell;
9035 * if it has non-empty trap:
9036 * - executes trap and returns to read;
9037 * SIGHUP:
9038 * - terminates shell (regardless of interactivity);
9039 * if it has non-empty trap:
9040 * - executes trap and returns to read;
9041 */
9042static int FAST_FUNC builtin_read(char **argv)
9043{
9044 const char *r;
9045 char *opt_n = NULL;
9046 char *opt_p = NULL;
9047 char *opt_t = NULL;
9048 char *opt_u = NULL;
9049 const char *ifs;
9050 int read_flags;
9051
9052 /* "!": do not abort on errors.
9053 * Option string must start with "sr" to match BUILTIN_READ_xxx
9054 */
9055 read_flags = getopt32(argv, "!srn:p:t:u:", &opt_n, &opt_p, &opt_t, &opt_u);
9056 if (read_flags == (uint32_t)-1)
9057 return EXIT_FAILURE;
9058 argv += optind;
9059 ifs = get_local_var_value("IFS"); /* can be NULL */
9060
9061 again:
9062 r = shell_builtin_read(set_local_var_from_halves,
9063 argv,
9064 ifs,
9065 read_flags,
9066 opt_n,
9067 opt_p,
9068 opt_t,
9069 opt_u
9070 );
9071
9072 if ((uintptr_t)r == 1 && errno == EINTR) {
9073 unsigned sig = check_and_run_traps();
9074 if (sig && sig != SIGINT)
9075 goto again;
9076 }
9077
9078 if ((uintptr_t)r > 1) {
9079 bb_error_msg("%s", r);
9080 r = (char*)(uintptr_t)1;
9081 }
9082
9083 return (uintptr_t)r;
9084}
9085#endif
9086
9087#if ENABLE_HUSH_UMASK
9088static int FAST_FUNC builtin_umask(char **argv)
9089{
9090 int rc;
9091 mode_t mask;
9092
9093 rc = 1;
9094 mask = umask(0);
9095 argv = skip_dash_dash(argv);
9096 if (argv[0]) {
9097 mode_t old_mask = mask;
9098
9099 /* numeric umasks are taken as-is */
9100 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
9101 if (!isdigit(argv[0][0]))
9102 mask ^= 0777;
9103 mask = bb_parse_mode(argv[0], mask);
9104 if (!isdigit(argv[0][0]))
9105 mask ^= 0777;
9106 if ((unsigned)mask > 0777) {
9107 mask = old_mask;
9108 /* bash messages:
9109 * bash: umask: 'q': invalid symbolic mode operator
9110 * bash: umask: 999: octal number out of range
9111 */
9112 bb_error_msg("%s: invalid mode '%s'", "umask", argv[0]);
9113 rc = 0;
9114 }
9115 } else {
9116 /* Mimic bash */
9117 printf("%04o\n", (unsigned) mask);
9118 /* fall through and restore mask which we set to 0 */
9119 }
9120 umask(mask);
9121
9122 return !rc; /* rc != 0 - success */
9123}
9124#endif
9125
9126#if ENABLE_HUSH_EXPORT || ENABLE_HUSH_TRAP
8797static void print_escaped(const char *s) 9127static void print_escaped(const char *s)
8798{ 9128{
8799 if (*s == '\'') 9129 if (*s == '\'')
@@ -8812,11 +9142,13 @@ static void print_escaped(const char *s)
8812 putchar('"'); 9142 putchar('"');
8813 } while (*s); 9143 } while (*s);
8814} 9144}
9145#endif
8815 9146
8816#if !ENABLE_HUSH_LOCAL 9147#if ENABLE_HUSH_EXPORT || ENABLE_HUSH_LOCAL
9148# if !ENABLE_HUSH_LOCAL
8817#define helper_export_local(argv, exp, lvl) \ 9149#define helper_export_local(argv, exp, lvl) \
8818 helper_export_local(argv, exp) 9150 helper_export_local(argv, exp)
8819#endif 9151# endif
8820static void helper_export_local(char **argv, int exp, int lvl) 9152static void helper_export_local(char **argv, int exp, int lvl)
8821{ 9153{
8822 do { 9154 do {
@@ -8849,14 +9181,14 @@ static void helper_export_local(char **argv, int exp, int lvl)
8849 continue; 9181 continue;
8850 } 9182 }
8851 } 9183 }
8852#if ENABLE_HUSH_LOCAL 9184# if ENABLE_HUSH_LOCAL
8853 if (exp == 0 /* local? */ 9185 if (exp == 0 /* local? */
8854 && var && var->func_nest_level == lvl 9186 && var && var->func_nest_level == lvl
8855 ) { 9187 ) {
8856 /* "local x=abc; ...; local x" - ignore second local decl */ 9188 /* "local x=abc; ...; local x" - ignore second local decl */
8857 continue; 9189 continue;
8858 } 9190 }
8859#endif 9191# endif
8860 /* Exporting non-existing variable. 9192 /* Exporting non-existing variable.
8861 * bash does not put it in environment, 9193 * bash does not put it in environment,
8862 * but remembers that it is exported, 9194 * but remembers that it is exported,
@@ -8872,7 +9204,9 @@ static void helper_export_local(char **argv, int exp, int lvl)
8872 set_local_var(name, /*exp:*/ exp, /*lvl:*/ lvl, /*ro:*/ 0); 9204 set_local_var(name, /*exp:*/ exp, /*lvl:*/ lvl, /*ro:*/ 0);
8873 } while (*++argv); 9205 } while (*++argv);
8874} 9206}
9207#endif
8875 9208
9209#if ENABLE_HUSH_EXPORT
8876static int FAST_FUNC builtin_export(char **argv) 9210static int FAST_FUNC builtin_export(char **argv)
8877{ 9211{
8878 unsigned opt_unexport; 9212 unsigned opt_unexport;
@@ -8918,6 +9252,7 @@ static int FAST_FUNC builtin_export(char **argv)
8918 9252
8919 return EXIT_SUCCESS; 9253 return EXIT_SUCCESS;
8920} 9254}
9255#endif
8921 9256
8922#if ENABLE_HUSH_LOCAL 9257#if ENABLE_HUSH_LOCAL
8923static int FAST_FUNC builtin_local(char **argv) 9258static int FAST_FUNC builtin_local(char **argv)
@@ -8931,6 +9266,7 @@ static int FAST_FUNC builtin_local(char **argv)
8931} 9266}
8932#endif 9267#endif
8933 9268
9269#if ENABLE_HUSH_UNSET
8934/* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#unset */ 9270/* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#unset */
8935static int FAST_FUNC builtin_unset(char **argv) 9271static int FAST_FUNC builtin_unset(char **argv)
8936{ 9272{
@@ -8958,16 +9294,18 @@ static int FAST_FUNC builtin_unset(char **argv)
8958 ret = EXIT_FAILURE; 9294 ret = EXIT_FAILURE;
8959 } 9295 }
8960 } 9296 }
8961#if ENABLE_HUSH_FUNCTIONS 9297# if ENABLE_HUSH_FUNCTIONS
8962 else { 9298 else {
8963 unset_func(*argv); 9299 unset_func(*argv);
8964 } 9300 }
8965#endif 9301# endif
8966 argv++; 9302 argv++;
8967 } 9303 }
8968 return ret; 9304 return ret;
8969} 9305}
9306#endif
8970 9307
9308#if ENABLE_HUSH_SET
8971/* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#set 9309/* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#set
8972 * built-in 'set' handler 9310 * built-in 'set' handler
8973 * SUSv3 says: 9311 * SUSv3 says:
@@ -9050,6 +9388,7 @@ static int FAST_FUNC builtin_set(char **argv)
9050 bb_error_msg("set: %s: invalid option", arg); 9388 bb_error_msg("set: %s: invalid option", arg);
9051 return EXIT_FAILURE; 9389 return EXIT_FAILURE;
9052} 9390}
9391#endif
9053 9392
9054static int FAST_FUNC builtin_shift(char **argv) 9393static int FAST_FUNC builtin_shift(char **argv)
9055{ 9394{
@@ -9059,7 +9398,7 @@ static int FAST_FUNC builtin_shift(char **argv)
9059 n = atoi(argv[0]); 9398 n = atoi(argv[0]);
9060 } 9399 }
9061 if (n >= 0 && n < G.global_argc) { 9400 if (n >= 0 && n < G.global_argc) {
9062 if (G.global_args_malloced) { 9401 if (G_global_args_malloced) {
9063 int m = 1; 9402 int m = 1;
9064 while (m <= n) 9403 while (m <= n)
9065 free(G.global_argv[m++]); 9404 free(G.global_argv[m++]);
@@ -9072,87 +9411,78 @@ static int FAST_FUNC builtin_shift(char **argv)
9072 return EXIT_FAILURE; 9411 return EXIT_FAILURE;
9073} 9412}
9074 9413
9075/* Interruptibility of read builtin in bash 9414static int FAST_FUNC builtin_source(char **argv)
9076 * (tested on bash-4.2.8 by sending signals (not by ^C)):
9077 *
9078 * Empty trap makes read ignore corresponding signal, for any signal.
9079 *
9080 * SIGINT:
9081 * - terminates non-interactive shell;
9082 * - interrupts read in interactive shell;
9083 * if it has non-empty trap:
9084 * - executes trap and returns to command prompt in interactive shell;
9085 * - executes trap and returns to read in non-interactive shell;
9086 * SIGTERM:
9087 * - is ignored (does not interrupt) read in interactive shell;
9088 * - terminates non-interactive shell;
9089 * if it has non-empty trap:
9090 * - executes trap and returns to read;
9091 * SIGHUP:
9092 * - terminates shell (regardless of interactivity);
9093 * if it has non-empty trap:
9094 * - executes trap and returns to read;
9095 */
9096static int FAST_FUNC builtin_read(char **argv)
9097{ 9415{
9098 const char *r; 9416 char *arg_path, *filename;
9099 char *opt_n = NULL; 9417 FILE *input;
9100 char *opt_p = NULL; 9418 save_arg_t sv;
9101 char *opt_t = NULL; 9419 char *args_need_save;
9102 char *opt_u = NULL; 9420#if ENABLE_HUSH_FUNCTIONS
9103 const char *ifs; 9421 smallint sv_flg;
9104 int read_flags; 9422#endif
9105 9423
9106 /* "!": do not abort on errors. 9424 argv = skip_dash_dash(argv);
9107 * Option string must start with "sr" to match BUILTIN_READ_xxx 9425 filename = argv[0];
9108 */ 9426 if (!filename) {
9109 read_flags = getopt32(argv, "!srn:p:t:u:", &opt_n, &opt_p, &opt_t, &opt_u); 9427 /* bash says: "bash: .: filename argument required" */
9110 if (read_flags == (uint32_t)-1) 9428 return 2; /* bash compat */
9429 }
9430 arg_path = NULL;
9431 if (!strchr(filename, '/')) {
9432 arg_path = find_in_path(filename);
9433 if (arg_path)
9434 filename = arg_path;
9435 }
9436 input = remember_FILE(fopen_or_warn(filename, "r"));
9437 free(arg_path);
9438 if (!input) {
9439 /* bb_perror_msg("%s", *argv); - done by fopen_or_warn */
9440 /* POSIX: non-interactive shell should abort here,
9441 * not merely fail. So far no one complained :)
9442 */
9111 return EXIT_FAILURE; 9443 return EXIT_FAILURE;
9112 argv += optind; 9444 }
9113 ifs = get_local_var_value("IFS"); /* can be NULL */
9114 9445
9115 again: 9446#if ENABLE_HUSH_FUNCTIONS
9116 r = shell_builtin_read(set_local_var_from_halves, 9447 sv_flg = G_flag_return_in_progress;
9117 argv, 9448 /* "we are inside sourced file, ok to use return" */
9118 ifs, 9449 G_flag_return_in_progress = -1;
9119 read_flags, 9450#endif
9120 opt_n, 9451 args_need_save = argv[1]; /* used as a boolean variable */
9121 opt_p, 9452 if (args_need_save)
9122 opt_t, 9453 save_and_replace_G_args(&sv, argv);
9123 opt_u
9124 );
9125 9454
9126 if ((uintptr_t)r == 1 && errno == EINTR) { 9455 /* "false; . ./empty_line; echo Zero:$?" should print 0 */
9127 unsigned sig = check_and_run_traps(); 9456 G.last_exitcode = 0;
9128 if (sig && sig != SIGINT) 9457 parse_and_run_file(input);
9129 goto again; 9458 fclose_and_forget(input);
9130 }
9131 9459
9132 if ((uintptr_t)r > 1) { 9460 if (args_need_save) /* can't use argv[1] instead: "shift" can mangle it */
9133 bb_error_msg("%s", r); 9461 restore_G_args(&sv, argv);
9134 r = (char*)(uintptr_t)1; 9462#if ENABLE_HUSH_FUNCTIONS
9135 } 9463 G_flag_return_in_progress = sv_flg;
9464#endif
9136 9465
9137 return (uintptr_t)r; 9466 return G.last_exitcode;
9138} 9467}
9139 9468
9469#if ENABLE_HUSH_TRAP
9140static int FAST_FUNC builtin_trap(char **argv) 9470static int FAST_FUNC builtin_trap(char **argv)
9141{ 9471{
9142 int sig; 9472 int sig;
9143 char *new_cmd; 9473 char *new_cmd;
9144 9474
9145 if (!G.traps) 9475 if (!G_traps)
9146 G.traps = xzalloc(sizeof(G.traps[0]) * NSIG); 9476 G_traps = xzalloc(sizeof(G_traps[0]) * NSIG);
9147 9477
9148 argv++; 9478 argv++;
9149 if (!*argv) { 9479 if (!*argv) {
9150 int i; 9480 int i;
9151 /* No args: print all trapped */ 9481 /* No args: print all trapped */
9152 for (i = 0; i < NSIG; ++i) { 9482 for (i = 0; i < NSIG; ++i) {
9153 if (G.traps[i]) { 9483 if (G_traps[i]) {
9154 printf("trap -- "); 9484 printf("trap -- ");
9155 print_escaped(G.traps[i]); 9485 print_escaped(G_traps[i]);
9156 /* note: bash adds "SIG", but only if invoked 9486 /* note: bash adds "SIG", but only if invoked
9157 * as "bash". If called as "sh", or if set -o posix, 9487 * as "bash". If called as "sh", or if set -o posix,
9158 * then it prints short signal names. 9488 * then it prints short signal names.
@@ -9182,11 +9512,11 @@ static int FAST_FUNC builtin_trap(char **argv)
9182 continue; 9512 continue;
9183 } 9513 }
9184 9514
9185 free(G.traps[sig]); 9515 free(G_traps[sig]);
9186 G.traps[sig] = xstrdup(new_cmd); 9516 G_traps[sig] = xstrdup(new_cmd);
9187 9517
9188 debug_printf("trap: setting SIG%s (%i) to '%s'\n", 9518 debug_printf("trap: setting SIG%s (%i) to '%s'\n",
9189 get_signame(sig), sig, G.traps[sig]); 9519 get_signame(sig), sig, G_traps[sig]);
9190 9520
9191 /* There is no signal for 0 (EXIT) */ 9521 /* There is no signal for 0 (EXIT) */
9192 if (sig == 0) 9522 if (sig == 0)
@@ -9226,59 +9556,54 @@ static int FAST_FUNC builtin_trap(char **argv)
9226 argv++; 9556 argv++;
9227 goto process_sig_list; 9557 goto process_sig_list;
9228} 9558}
9229
9230/* http://www.opengroup.org/onlinepubs/9699919799/utilities/type.html */
9231static int FAST_FUNC builtin_type(char **argv)
9232{
9233 int ret = EXIT_SUCCESS;
9234
9235 while (*++argv) {
9236 const char *type;
9237 char *path = NULL;
9238
9239 if (0) {} /* make conditional compile easier below */
9240 /*else if (find_alias(*argv))
9241 type = "an alias";*/
9242#if ENABLE_HUSH_FUNCTIONS
9243 else if (find_function(*argv))
9244 type = "a function";
9245#endif 9559#endif
9246 else if (find_builtin(*argv))
9247 type = "a shell builtin";
9248 else if ((path = find_in_path(*argv)) != NULL)
9249 type = path;
9250 else {
9251 bb_error_msg("type: %s: not found", *argv);
9252 ret = EXIT_FAILURE;
9253 continue;
9254 }
9255
9256 printf("%s is %s\n", *argv, type);
9257 free(path);
9258 }
9259
9260 return ret;
9261}
9262 9560
9263#if ENABLE_HUSH_JOB 9561#if ENABLE_HUSH_JOB
9264static struct pipe *parse_jobspec(const char *str) 9562static struct pipe *parse_jobspec(const char *str)
9265{ 9563{
9266 struct pipe *pi; 9564 struct pipe *pi;
9267 int jobnum; 9565 unsigned jobnum;
9268 9566
9269 if (sscanf(str, "%%%d", &jobnum) != 1) { 9567 if (sscanf(str, "%%%u", &jobnum) != 1) {
9270 bb_error_msg("bad argument '%s'", str); 9568 if (str[0] != '%'
9271 return NULL; 9569 || (str[1] != '%' && str[1] != '+' && str[1] != '\0')
9570 ) {
9571 bb_error_msg("bad argument '%s'", str);
9572 return NULL;
9573 }
9574 /* It is "%%", "%+" or "%" - current job */
9575 jobnum = G.last_jobid;
9576 if (jobnum == 0) {
9577 bb_error_msg("no current job");
9578 return NULL;
9579 }
9272 } 9580 }
9273 for (pi = G.job_list; pi; pi = pi->next) { 9581 for (pi = G.job_list; pi; pi = pi->next) {
9274 if (pi->jobid == jobnum) { 9582 if (pi->jobid == jobnum) {
9275 return pi; 9583 return pi;
9276 } 9584 }
9277 } 9585 }
9278 bb_error_msg("%d: no such job", jobnum); 9586 bb_error_msg("%u: no such job", jobnum);
9279 return NULL; 9587 return NULL;
9280} 9588}
9281 9589
9590static int FAST_FUNC builtin_jobs(char **argv UNUSED_PARAM)
9591{
9592 struct pipe *job;
9593 const char *status_string;
9594
9595 checkjobs(NULL, 0 /*(no pid to wait for)*/);
9596 for (job = G.job_list; job; job = job->next) {
9597 if (job->alive_cmds == job->stopped_cmds)
9598 status_string = "Stopped";
9599 else
9600 status_string = "Running";
9601
9602 printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->cmdtext);
9603 }
9604 return EXIT_SUCCESS;
9605}
9606
9282/* built-in 'fg' and 'bg' handler */ 9607/* built-in 'fg' and 'bg' handler */
9283static int FAST_FUNC builtin_fg_bg(char **argv) 9608static int FAST_FUNC builtin_fg_bg(char **argv)
9284{ 9609{
@@ -9334,188 +9659,81 @@ static int FAST_FUNC builtin_fg_bg(char **argv)
9334} 9659}
9335#endif 9660#endif
9336 9661
9337#if ENABLE_HUSH_HELP 9662#if ENABLE_HUSH_KILL
9338static int FAST_FUNC builtin_help(char **argv UNUSED_PARAM) 9663static int FAST_FUNC builtin_kill(char **argv)
9339{
9340 const struct built_in_command *x;
9341
9342 printf(
9343 "Built-in commands:\n"
9344 "------------------\n");
9345 for (x = bltins1; x != &bltins1[ARRAY_SIZE(bltins1)]; x++) {
9346 if (x->b_descr)
9347 printf("%-10s%s\n", x->b_cmd, x->b_descr);
9348 }
9349 return EXIT_SUCCESS;
9350}
9351#endif
9352
9353#if MAX_HISTORY && ENABLE_FEATURE_EDITING
9354static int FAST_FUNC builtin_history(char **argv UNUSED_PARAM)
9355{ 9664{
9356 show_history(G.line_input_state); 9665 int ret = 0;
9357 return EXIT_SUCCESS;
9358}
9359#endif
9360 9666
9361#if ENABLE_HUSH_JOB 9667# if ENABLE_HUSH_JOB
9362static int FAST_FUNC builtin_jobs(char **argv UNUSED_PARAM) 9668 if (argv[1] && strcmp(argv[1], "-l") != 0) {
9363{ 9669 int i = 1;
9364 struct pipe *job;
9365 const char *status_string;
9366 9670
9367 checkjobs(NULL, 0 /*(no pid to wait for)*/); 9671 do {
9368 for (job = G.job_list; job; job = job->next) { 9672 struct pipe *pi;
9369 if (job->alive_cmds == job->stopped_cmds) 9673 char *dst;
9370 status_string = "Stopped"; 9674 int j, n;
9371 else
9372 status_string = "Running";
9373 9675
9374 printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->cmdtext); 9676 if (argv[i][0] != '%')
9677 continue;
9678 /*
9679 * "kill %N" - job kill
9680 * Converting to pgrp / pid kill
9681 */
9682 pi = parse_jobspec(argv[i]);
9683 if (!pi) {
9684 /* Eat bad jobspec */
9685 j = i;
9686 do {
9687 j++;
9688 argv[j - 1] = argv[j];
9689 } while (argv[j]);
9690 ret = 1;
9691 i--;
9692 continue;
9693 }
9694 /*
9695 * In jobs started under job control, we signal
9696 * entire process group by kill -PGRP_ID.
9697 * This happens, f.e., in interactive shell.
9698 *
9699 * Otherwise, we signal each child via
9700 * kill PID1 PID2 PID3.
9701 * Testcases:
9702 * sh -c 'sleep 1|sleep 1 & kill %1'
9703 * sh -c 'true|sleep 2 & sleep 1; kill %1'
9704 * sh -c 'true|sleep 1 & sleep 2; kill %1'
9705 */
9706 n = G_interactive_fd ? 1 : pi->num_cmds;
9707 dst = alloca(n * sizeof(int)*4);
9708 argv[i] = dst;
9709 if (G_interactive_fd)
9710 dst += sprintf(dst, " -%u", (int)pi->pgrp);
9711 else for (j = 0; j < n; j++) {
9712 struct command *cmd = &pi->cmds[j];
9713 /* Skip exited members of the job */
9714 if (cmd->pid == 0)
9715 continue;
9716 /*
9717 * kill_main has matching code to expect
9718 * leading space. Needed to not confuse
9719 * negative pids with "kill -SIGNAL_NO" syntax
9720 */
9721 dst += sprintf(dst, " %u", (int)cmd->pid);
9722 }
9723 *dst = '\0';
9724 } while (argv[++i]);
9375 } 9725 }
9376 return EXIT_SUCCESS;
9377}
9378#endif
9379
9380#if HUSH_DEBUG
9381static int FAST_FUNC builtin_memleak(char **argv UNUSED_PARAM)
9382{
9383 void *p;
9384 unsigned long l;
9385
9386# ifdef M_TRIM_THRESHOLD
9387 /* Optional. Reduces probability of false positives */
9388 malloc_trim(0);
9389# endif 9726# endif
9390 /* Crude attempt to find where "free memory" starts,
9391 * sans fragmentation. */
9392 p = malloc(240);
9393 l = (unsigned long)p;
9394 free(p);
9395 p = malloc(3400);
9396 if (l < (unsigned long)p) l = (unsigned long)p;
9397 free(p);
9398 9727
9399 9728 if (argv[1] || ret == 0) {
9400# if 0 /* debug */ 9729 ret = run_applet_main(argv, kill_main);
9401 {
9402 struct mallinfo mi = mallinfo();
9403 printf("top alloc:0x%lx malloced:%d+%d=%d\n", l,
9404 mi.arena, mi.hblkhd, mi.arena + mi.hblkhd);
9405 } 9730 }
9406# endif 9731 /* else: ret = 1, "kill %bad_jobspec" case */
9407 9732 return ret;
9408 if (!G.memleak_value)
9409 G.memleak_value = l;
9410
9411 l -= G.memleak_value;
9412 if ((long)l < 0)
9413 l = 0;
9414 l /= 1024;
9415 if (l > 127)
9416 l = 127;
9417
9418 /* Exitcode is "how many kilobytes we leaked since 1st call" */
9419 return l;
9420}
9421#endif
9422
9423static int FAST_FUNC builtin_pwd(char **argv UNUSED_PARAM)
9424{
9425 puts(get_cwd(0));
9426 return EXIT_SUCCESS;
9427} 9733}
9428
9429static int FAST_FUNC builtin_source(char **argv)
9430{
9431 char *arg_path, *filename;
9432 FILE *input;
9433 save_arg_t sv;
9434#if ENABLE_HUSH_FUNCTIONS
9435 smallint sv_flg;
9436#endif
9437
9438 argv = skip_dash_dash(argv);
9439 filename = argv[0];
9440 if (!filename) {
9441 /* bash says: "bash: .: filename argument required" */
9442 return 2; /* bash compat */
9443 }
9444 arg_path = NULL;
9445 if (!strchr(filename, '/')) {
9446 arg_path = find_in_path(filename);
9447 if (arg_path)
9448 filename = arg_path;
9449 }
9450 input = remember_FILE(fopen_or_warn(filename, "r"));
9451 free(arg_path);
9452 if (!input) {
9453 /* bb_perror_msg("%s", *argv); - done by fopen_or_warn */
9454 /* POSIX: non-interactive shell should abort here,
9455 * not merely fail. So far no one complained :)
9456 */
9457 return EXIT_FAILURE;
9458 }
9459
9460#if ENABLE_HUSH_FUNCTIONS
9461 sv_flg = G_flag_return_in_progress;
9462 /* "we are inside sourced file, ok to use return" */
9463 G_flag_return_in_progress = -1;
9464#endif 9734#endif
9465 if (argv[1])
9466 save_and_replace_G_args(&sv, argv);
9467
9468 /* "false; . ./empty_line; echo Zero:$?" should print 0 */
9469 G.last_exitcode = 0;
9470 parse_and_run_file(input);
9471 fclose_and_forget(input);
9472
9473 if (argv[1])
9474 restore_G_args(&sv, argv);
9475#if ENABLE_HUSH_FUNCTIONS
9476 G_flag_return_in_progress = sv_flg;
9477#endif
9478
9479 return G.last_exitcode;
9480}
9481
9482static int FAST_FUNC builtin_umask(char **argv)
9483{
9484 int rc;
9485 mode_t mask;
9486
9487 rc = 1;
9488 mask = umask(0);
9489 argv = skip_dash_dash(argv);
9490 if (argv[0]) {
9491 mode_t old_mask = mask;
9492
9493 /* numeric umasks are taken as-is */
9494 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
9495 if (!isdigit(argv[0][0]))
9496 mask ^= 0777;
9497 mask = bb_parse_mode(argv[0], mask);
9498 if (!isdigit(argv[0][0]))
9499 mask ^= 0777;
9500 if ((unsigned)mask > 0777) {
9501 mask = old_mask;
9502 /* bash messages:
9503 * bash: umask: 'q': invalid symbolic mode operator
9504 * bash: umask: 999: octal number out of range
9505 */
9506 bb_error_msg("%s: invalid mode '%s'", "umask", argv[0]);
9507 rc = 0;
9508 }
9509 } else {
9510 /* Mimic bash */
9511 printf("%04o\n", (unsigned) mask);
9512 /* fall through and restore mask which we set to 0 */
9513 }
9514 umask(mask);
9515
9516 return !rc; /* rc != 0 - success */
9517}
9518 9735
9736#if ENABLE_HUSH_WAIT
9519/* http://www.opengroup.org/onlinepubs/9699919799/utilities/wait.html */ 9737/* http://www.opengroup.org/onlinepubs/9699919799/utilities/wait.html */
9520#if !ENABLE_HUSH_JOB 9738#if !ENABLE_HUSH_JOB
9521# define wait_for_child_or_signal(pipe,pid) wait_for_child_or_signal(pid) 9739# define wait_for_child_or_signal(pipe,pid) wait_for_child_or_signal(pid)
@@ -9622,13 +9840,15 @@ static int FAST_FUNC builtin_wait(char **argv)
9622#if ENABLE_HUSH_JOB 9840#if ENABLE_HUSH_JOB
9623 if (argv[0][0] == '%') { 9841 if (argv[0][0] == '%') {
9624 struct pipe *wait_pipe; 9842 struct pipe *wait_pipe;
9843 ret = 127; /* bash compat for bad jobspecs */
9625 wait_pipe = parse_jobspec(*argv); 9844 wait_pipe = parse_jobspec(*argv);
9626 if (wait_pipe) { 9845 if (wait_pipe) {
9627 ret = job_exited_or_stopped(wait_pipe); 9846 ret = job_exited_or_stopped(wait_pipe);
9628 if (ret < 0) 9847 if (ret < 0)
9629 ret = wait_for_child_or_signal(wait_pipe, 0); 9848 ret = wait_for_child_or_signal(wait_pipe, 0);
9630 continue;
9631 } 9849 }
9850 /* else: parse_jobspec() already emitted error msg */
9851 continue;
9632 } 9852 }
9633#endif 9853#endif
9634 /* mimic bash message */ 9854 /* mimic bash message */
@@ -9674,6 +9894,7 @@ static int FAST_FUNC builtin_wait(char **argv)
9674 9894
9675 return ret; 9895 return ret;
9676} 9896}
9897#endif
9677 9898
9678#if ENABLE_HUSH_LOOPS || ENABLE_HUSH_FUNCTIONS 9899#if ENABLE_HUSH_LOOPS || ENABLE_HUSH_FUNCTIONS
9679static unsigned parse_numeric_argv1(char **argv, unsigned def, unsigned def_min) 9900static unsigned parse_numeric_argv1(char **argv, unsigned def, unsigned def_min)
@@ -9740,3 +9961,46 @@ static int FAST_FUNC builtin_return(char **argv)
9740 return rc; 9961 return rc;
9741} 9962}
9742#endif 9963#endif
9964
9965#if ENABLE_HUSH_MEMLEAK
9966static int FAST_FUNC builtin_memleak(char **argv UNUSED_PARAM)
9967{
9968 void *p;
9969 unsigned long l;
9970
9971# ifdef M_TRIM_THRESHOLD
9972 /* Optional. Reduces probability of false positives */
9973 malloc_trim(0);
9974# endif
9975 /* Crude attempt to find where "free memory" starts,
9976 * sans fragmentation. */
9977 p = malloc(240);
9978 l = (unsigned long)p;
9979 free(p);
9980 p = malloc(3400);
9981 if (l < (unsigned long)p) l = (unsigned long)p;
9982 free(p);
9983
9984
9985# if 0 /* debug */
9986 {
9987 struct mallinfo mi = mallinfo();
9988 printf("top alloc:0x%lx malloced:%d+%d=%d\n", l,
9989 mi.arena, mi.hblkhd, mi.arena + mi.hblkhd);
9990 }
9991# endif
9992
9993 if (!G.memleak_value)
9994 G.memleak_value = l;
9995
9996 l -= G.memleak_value;
9997 if ((long)l < 0)
9998 l = 0;
9999 l /= 1024;
10000 if (l > 127)
10001 l = 127;
10002
10003 /* Exitcode is "how many kilobytes we leaked since 1st call" */
10004 return l;
10005}
10006#endif
diff --git a/shell/hush_test/hush-misc/source_argv_and_shift.right b/shell/hush_test/hush-misc/source_argv_and_shift.right
new file mode 100644
index 000000000..b15cc96e7
--- /dev/null
+++ b/shell/hush_test/hush-misc/source_argv_and_shift.right
@@ -0,0 +1,4 @@
1sourced_arg1:1
2arg1:
3sourced_arg1:a
4arg1:1
diff --git a/shell/hush_test/hush-misc/source_argv_and_shift.tests b/shell/hush_test/hush-misc/source_argv_and_shift.tests
new file mode 100755
index 000000000..66353f3d7
--- /dev/null
+++ b/shell/hush_test/hush-misc/source_argv_and_shift.tests
@@ -0,0 +1,12 @@
1echo 'echo sourced_arg1:$1' >sourced1
2echo 'shift' >>sourced1
3
4set -- 1
5. ./sourced1
6echo arg1:$1
7
8set -- 1
9. ./sourced1 a
10echo arg1:$1
11
12rm sourced1
diff --git a/shell/shell_common.c b/shell/shell_common.c
index 5a5b1780d..653154e34 100644
--- a/shell/shell_common.c
+++ b/shell/shell_common.c
@@ -147,7 +147,7 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val),
147 // Setting it to more than 1 breaks poll(): 147 // Setting it to more than 1 breaks poll():
148 // it blocks even if there's data. !?? 148 // it blocks even if there's data. !??
149 //tty.c_cc[VMIN] = nchars < 256 ? nchars : 255; 149 //tty.c_cc[VMIN] = nchars < 256 ? nchars : 255;
150 /* reads would block only if < 1 char is available */ 150 /* reads will block only if < 1 char is available */
151 tty.c_cc[VMIN] = 1; 151 tty.c_cc[VMIN] = 1;
152 /* no timeout (reads block forever) */ 152 /* no timeout (reads block forever) */
153 tty.c_cc[VTIME] = 0; 153 tty.c_cc[VTIME] = 0;
diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c
index ae0840bff..d64ff278f 100644
--- a/sysklogd/syslogd.c
+++ b/sysklogd/syslogd.c
@@ -135,8 +135,8 @@
135//usage: ) 135//usage: )
136//usage: "\n -O FILE Log to FILE (default: /var/log/messages, stdout if -)" 136//usage: "\n -O FILE Log to FILE (default: /var/log/messages, stdout if -)"
137//usage: IF_FEATURE_ROTATE_LOGFILE( 137//usage: IF_FEATURE_ROTATE_LOGFILE(
138//usage: "\n -s SIZE Max size (KB) before rotation (default:200KB, 0=off)" 138//usage: "\n -s SIZE Max size (KB) before rotation (default 200KB, 0=off)"
139//usage: "\n -b N N rotated logs to keep (default:1, max=99, 0=purge)" 139//usage: "\n -b N N rotated logs to keep (default 1, max 99, 0=purge)"
140//usage: ) 140//usage: )
141//usage: "\n -l N Log only messages more urgent than prio N (1-8)" 141//usage: "\n -l N Log only messages more urgent than prio N (1-8)"
142//usage: "\n -S Smaller output" 142//usage: "\n -S Smaller output"
@@ -146,7 +146,7 @@
146//usage: IF_FEATURE_SYSLOGD_CFG( 146//usage: IF_FEATURE_SYSLOGD_CFG(
147//usage: "\n -f FILE Use FILE as config (default:/etc/syslog.conf)" 147//usage: "\n -f FILE Use FILE as config (default:/etc/syslog.conf)"
148//usage: ) 148//usage: )
149/* //usage: "\n -m MIN Minutes between MARK lines (default:20, 0=off)" */ 149/* //usage: "\n -m MIN Minutes between MARK lines (default 20, 0=off)" */
150//usage: 150//usage:
151//usage:#define syslogd_example_usage 151//usage:#define syslogd_example_usage
152//usage: "$ syslogd -R masterlog:514\n" 152//usage: "$ syslogd -R masterlog:514\n"
diff --git a/testsuite/cryptpw.tests b/testsuite/cryptpw.tests
new file mode 100755
index 000000000..8ec476c9f
--- /dev/null
+++ b/testsuite/cryptpw.tests
@@ -0,0 +1,28 @@
1#!/bin/sh
2
3# Copyright 2017 by Denys Vlasenko <vda.linux@googlemail.com>
4# Licensed under GPLv2, see file LICENSE in this source tree.
5
6. ./testing.sh
7
8# testing "description" "command" "result" "infile" "stdin"
9
10optional USE_BB_CRYPT_SHA
11testing "cryptpw sha256" \
12 "cryptpw -m sha256 QWErty '123456789012345678901234567890'" \
13 '$5$1234567890123456$5DxfOCmU4vRhtzfsbdK.6wSGMwwVbac7ZkWwusb8Si7\n' "" ""
14
15testing "cryptpw sha256 rounds=99999" \
16 "cryptpw -m sha256 QWErty 'rounds=99999\$123456789012345678901234567890'" \
17 '$5$rounds=99999$1234567890123456$aYellycJGZM6AKyVzaQsSrDBdTixubtMnM6J.MN0xM8\n' "" ""
18
19testing "cryptpw sha512" \
20 "cryptpw -m sha512 QWErty '123456789012345678901234567890'" \
21 '$6$1234567890123456$KB7QqxFyqmJSWyQYcCuGeFukgz1bPQoipWZf7.9L7z3k8UNTXa6UikbKcUGDc2ANn7DOGmDaroxDgpK16w/RE0\n' "" ""
22
23testing "cryptpw sha512 rounds=99999" \
24 "cryptpw -m sha512 QWErty 'rounds=99999\$123456789012345678901234567890'" \
25 '$6$rounds=99999$1234567890123456$BfF6gD6ZjUmwawH5QaAglYAxtU./yvsz0fcQ464l49aMI2DZW3j5ri28CrxK7riPWNpLuUpfaIdY751SBYKUH.\n' "" ""
26SKIP=
27
28exit $FAILCOUNT
diff --git a/testsuite/mdev.tests b/testsuite/mdev.tests
index 59873011a..8515aff31 100755
--- a/testsuite/mdev.tests
+++ b/testsuite/mdev.tests
@@ -168,7 +168,7 @@ SKIP=
168# continuing to use directory structure from prev test 168# continuing to use directory structure from prev test
169rm -rf mdev.testdir/dev/* 169rm -rf mdev.testdir/dev/*
170echo "sda 0:0 644 @echo @echo TEST" >mdev.testdir/etc/mdev.conf 170echo "sda 0:0 644 @echo @echo TEST" >mdev.testdir/etc/mdev.conf
171optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_EXEC FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME FEATURE_SH_IS_ASH ASH_BUILTIN_ECHO 171optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_EXEC FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME FEATURE_SH_IS_ASH ASH_ECHO
172testing "mdev command" \ 172testing "mdev command" \
173 "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; 173 "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1;
174 ls -lnR mdev.testdir/dev | $FILTER_LS" \ 174 ls -lnR mdev.testdir/dev | $FILTER_LS" \
diff --git a/testsuite/runtest b/testsuite/runtest
index 51575d926..44f9cd1a1 100755
--- a/testsuite/runtest
+++ b/testsuite/runtest
@@ -12,12 +12,12 @@ total_failed=0
12# Option -e will make testcase stop on the first failed command. 12# Option -e will make testcase stop on the first failed command.
13run_applet_testcase() 13run_applet_testcase()
14{ 14{
15 local applet="$1" 15 applet="$1"
16 local testcase="$2" 16 testcase="$2"
17 17
18 local status=0 18 status=0
19 local uc_applet=$(echo "$applet" | tr a-z A-Z) 19 uc_applet=$(echo "$applet" | tr a-z A-Z)
20 local testname="$testcase" 20 testname="$testcase"
21 21
22 testname="${testname##*/}" # take basename 22 testname="${testname##*/}" # take basename
23 if grep "^# CONFIG_$uc_applet is not set$" "$bindir/.config" >/dev/null; then 23 if grep "^# CONFIG_$uc_applet is not set$" "$bindir/.config" >/dev/null; then
diff --git a/testsuite/unzip.tests b/testsuite/unzip.tests
index d9c45242c..2e4becdb8 100755
--- a/testsuite/unzip.tests
+++ b/testsuite/unzip.tests
@@ -34,7 +34,9 @@ rm foo.zip
34optional FEATURE_UNZIP_CDF 34optional FEATURE_UNZIP_CDF
35testing "unzip (bad archive)" "uudecode; unzip bad.zip 2>&1; echo \$?" \ 35testing "unzip (bad archive)" "uudecode; unzip bad.zip 2>&1; echo \$?" \
36"Archive: bad.zip 36"Archive: bad.zip
37unzip: short read 37 inflating: ]3j½r«IK-%Ix
38unzip: corrupted data
39unzip: inflate error
381 401
39" \ 41" \
40"" "\ 42"" "\
diff --git a/util-linux/Config.src b/util-linux/Config.src
index 3c522f948..0971d714a 100644
--- a/util-linux/Config.src
+++ b/util-linux/Config.src
@@ -40,7 +40,7 @@ config FEATURE_MOUNT_LOOP_CREATE
40 if it does not find a free one. 40 if it does not find a free one.
41 41
42config FEATURE_MTAB_SUPPORT 42config FEATURE_MTAB_SUPPORT
43 bool "Support for the old /etc/mtab file" 43 bool "Support old /etc/mtab file"
44 default n 44 default n
45 depends on MOUNT || UMOUNT 45 depends on MOUNT || UMOUNT
46 select FEATURE_MOUNT_FAKE 46 select FEATURE_MOUNT_FAKE
diff --git a/util-linux/dmesg.c b/util-linux/dmesg.c
index b7b2c6924..c3574f8f5 100644
--- a/util-linux/dmesg.c
+++ b/util-linux/dmesg.c
@@ -22,7 +22,7 @@
22//config: wish to enable the 'dmesg' utility. 22//config: wish to enable the 'dmesg' utility.
23//config: 23//config:
24//config:config FEATURE_DMESG_PRETTY 24//config:config FEATURE_DMESG_PRETTY
25//config: bool "Pretty dmesg output" 25//config: bool "Pretty output"
26//config: default y 26//config: default y
27//config: depends on DMESG 27//config: depends on DMESG
28//config: help 28//config: help
diff --git a/util-linux/fbset.c b/util-linux/fbset.c
index 8a78c1ef9..673bf9aa4 100644
--- a/util-linux/fbset.c
+++ b/util-linux/fbset.c
@@ -22,7 +22,7 @@
22//config: if you wish to enable the 'fbset' utility. 22//config: if you wish to enable the 'fbset' utility.
23//config: 23//config:
24//config:config FEATURE_FBSET_FANCY 24//config:config FEATURE_FBSET_FANCY
25//config: bool "Turn on extra fbset options" 25//config: bool "Enable extra options"
26//config: default y 26//config: default y
27//config: depends on FBSET 27//config: depends on FBSET
28//config: help 28//config: help
@@ -32,7 +32,7 @@
32//config: options. 32//config: options.
33//config: 33//config:
34//config:config FEATURE_FBSET_READMODE 34//config:config FEATURE_FBSET_READMODE
35//config: bool "Turn on fbset readmode support" 35//config: bool "Enable readmode support"
36//config: default y 36//config: default y
37//config: depends on FBSET 37//config: depends on FBSET
38//config: help 38//config: help
diff --git a/util-linux/fdisk.c b/util-linux/fdisk.c
index b988e65a9..916d4e30e 100644
--- a/util-linux/fdisk.c
+++ b/util-linux/fdisk.c
@@ -21,8 +21,6 @@
21//config: default y 21//config: default y
22//config: depends on FDISK 22//config: depends on FDISK
23//config: depends on !LFS # with LFS no special code is needed 23//config: depends on !LFS # with LFS no special code is needed
24//config: help
25//config: Enable this option to support large disks > 4GB.
26//config: 24//config:
27//config:config FEATURE_FDISK_WRITABLE 25//config:config FEATURE_FDISK_WRITABLE
28//config: bool "Write support" 26//config: bool "Write support"
@@ -105,8 +103,8 @@
105//usage: ) 103//usage: )
106//usage: "\n -b 2048 (for certain MO disks) use 2048-byte sectors" 104//usage: "\n -b 2048 (for certain MO disks) use 2048-byte sectors"
107//usage: "\n -C CYLINDERS Set number of cylinders/heads/sectors" 105//usage: "\n -C CYLINDERS Set number of cylinders/heads/sectors"
108//usage: "\n -H HEADS" 106//usage: "\n -H HEADS Typically 255"
109//usage: "\n -S SECTORS" 107//usage: "\n -S SECTORS Typically 63"
110 108
111#ifndef _LARGEFILE64_SOURCE 109#ifndef _LARGEFILE64_SOURCE
112/* For lseek64 */ 110/* For lseek64 */
diff --git a/util-linux/freeramdisk.c b/util-linux/freeramdisk.c
index 8bc2c443b..28148fcbe 100644
--- a/util-linux/freeramdisk.c
+++ b/util-linux/freeramdisk.c
@@ -33,6 +33,7 @@
33//config: ramdisk. If you have no use for freeing memory from a ramdisk, leave 33//config: ramdisk. If you have no use for freeing memory from a ramdisk, leave
34//config: this disabled. 34//config: this disabled.
35 35
36// APPLET_ODDNAME:name main location suid_type help
36//applet:IF_FDFLUSH(APPLET_ODDNAME(fdflush, freeramdisk, BB_DIR_BIN, BB_SUID_DROP, fdflush)) 37//applet:IF_FDFLUSH(APPLET_ODDNAME(fdflush, freeramdisk, BB_DIR_BIN, BB_SUID_DROP, fdflush))
37//applet:IF_FREERAMDISK(APPLET(freeramdisk, BB_DIR_SBIN, BB_SUID_DROP)) 38//applet:IF_FREERAMDISK(APPLET(freeramdisk, BB_DIR_SBIN, BB_SUID_DROP))
38 39
diff --git a/util-linux/fsck_minix.c b/util-linux/fsck_minix.c
index 0eaac17c0..2ab7530ea 100644
--- a/util-linux/fsck_minix.c
+++ b/util-linux/fsck_minix.c
@@ -1226,7 +1226,6 @@ void check2(void);
1226int fsck_minix_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 1226int fsck_minix_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1227int fsck_minix_main(int argc UNUSED_PARAM, char **argv) 1227int fsck_minix_main(int argc UNUSED_PARAM, char **argv)
1228{ 1228{
1229 struct termios tmp;
1230 int retcode = 0; 1229 int retcode = 0;
1231 1230
1232 xfunc_error_retval = 8; 1231 xfunc_error_retval = 8;
@@ -1271,10 +1270,7 @@ int fsck_minix_main(int argc UNUSED_PARAM, char **argv)
1271 read_tables(); 1270 read_tables();
1272 1271
1273 if (OPT_manual) { 1272 if (OPT_manual) {
1274 tcgetattr(0, &sv_termios); 1273 set_termios_to_raw(STDIN_FILENO, &sv_termios, 0);
1275 tmp = sv_termios;
1276 tmp.c_lflag &= ~(ICANON | ECHO);
1277 tcsetattr_stdin_TCSANOW(&tmp);
1278 termios_set = 1; 1274 termios_set = 1;
1279 } 1275 }
1280 1276
diff --git a/util-linux/fstrim.c b/util-linux/fstrim.c
index fc51878b6..563aa9720 100644
--- a/util-linux/fstrim.c
+++ b/util-linux/fstrim.c
@@ -23,9 +23,9 @@
23//usage: "[OPTIONS] MOUNTPOINT" 23//usage: "[OPTIONS] MOUNTPOINT"
24//usage:#define fstrim_full_usage "\n\n" 24//usage:#define fstrim_full_usage "\n\n"
25//usage: IF_LONG_OPTS( 25//usage: IF_LONG_OPTS(
26//usage: " -o,--offset=OFFSET Offset in bytes to discard from" 26//usage: " -o,--offset OFFSET Offset in bytes to discard from"
27//usage: "\n -l,--length=LEN Bytes to discard" 27//usage: "\n -l,--length LEN Bytes to discard"
28//usage: "\n -m,--minimum=MIN Minimum extent length" 28//usage: "\n -m,--minimum MIN Minimum extent length"
29//usage: "\n -v,--verbose Print number of discarded bytes" 29//usage: "\n -v,--verbose Print number of discarded bytes"
30//usage: ) 30//usage: )
31//usage: IF_NOT_LONG_OPTS( 31//usage: IF_NOT_LONG_OPTS(
diff --git a/util-linux/getopt.c b/util-linux/getopt.c
index f6ecc3dde..63294c520 100644
--- a/util-linux/getopt.c
+++ b/util-linux/getopt.c
@@ -57,13 +57,13 @@
57//usage: IF_LONG_OPTS( 57//usage: IF_LONG_OPTS(
58//usage: IF_FEATURE_GETOPT_LONG( 58//usage: IF_FEATURE_GETOPT_LONG(
59//usage: " -a,--alternative Allow long options starting with single -\n" 59//usage: " -a,--alternative Allow long options starting with single -\n"
60//usage: " -l,--longoptions=LOPT[,...] Long options to recognize\n" 60//usage: " -l,--longoptions LOPT[,...] Long options to recognize\n"
61//usage: ) 61//usage: )
62//usage: " -n,--name=PROGNAME The name under which errors are reported" 62//usage: " -n,--name PROGNAME The name under which errors are reported"
63//usage: "\n -o,--options=OPTSTRING Short options to recognize" 63//usage: "\n -o,--options OPTSTRING Short options to recognize"
64//usage: "\n -q,--quiet No error messages on unrecognized options" 64//usage: "\n -q,--quiet No error messages on unrecognized options"
65//usage: "\n -Q,--quiet-output No normal output" 65//usage: "\n -Q,--quiet-output No normal output"
66//usage: "\n -s,--shell=SHELL Set shell quoting conventions" 66//usage: "\n -s,--shell SHELL Set shell quoting conventions"
67//usage: "\n -T,--test Version test (exits with 4)" 67//usage: "\n -T,--test Version test (exits with 4)"
68//usage: "\n -u,--unquoted Don't quote output" 68//usage: "\n -u,--unquoted Don't quote output"
69//usage: ) 69//usage: )
diff --git a/util-linux/hexdump.c b/util-linux/hexdump.c
index 4a7f641db..25f771201 100644
--- a/util-linux/hexdump.c
+++ b/util-linux/hexdump.c
@@ -41,19 +41,21 @@
41//usage: "[-bcCdefnosvx" IF_FEATURE_HEXDUMP_REVERSE("R") "] [FILE]..." 41//usage: "[-bcCdefnosvx" IF_FEATURE_HEXDUMP_REVERSE("R") "] [FILE]..."
42//usage:#define hexdump_full_usage "\n\n" 42//usage:#define hexdump_full_usage "\n\n"
43//usage: "Display FILEs (or stdin) in a user specified format\n" 43//usage: "Display FILEs (or stdin) in a user specified format\n"
44//usage: "\n -b One-byte octal display" 44//usage: "\n -b 1-byte octal display"
45//usage: "\n -c One-byte character display" 45//usage: "\n -c 1-byte character display"
46//usage: "\n -C Canonical hex+ASCII, 16 bytes per line" 46//usage: "\n -d 2-byte decimal display"
47//usage: "\n -d Two-byte decimal display" 47//usage: "\n -o 2-byte octal display"
48//usage: "\n -e FORMAT_STRING" 48//usage: "\n -x 2-byte hex display"
49//usage: "\n -C hex+ASCII 16 bytes per line"
50//usage: "\n -v Show all (no dup folding)"
51//usage: "\n -e FORMAT_STR Example: '16/1 \"%02x|\"\"\\n\"'"
49//usage: "\n -f FORMAT_FILE" 52//usage: "\n -f FORMAT_FILE"
50//usage: "\n -n LENGTH Interpret only LENGTH bytes of input" 53// exactly the same help text lines in hexdump and xxd:
51//usage: "\n -o Two-byte octal display" 54//usage: "\n -n LENGTH Show only first LENGTH bytes"
52//usage: "\n -s OFFSET Skip OFFSET bytes" 55//usage: "\n -s OFFSET Skip OFFSET bytes"
53//usage: "\n -v Display all input data"
54//usage: "\n -x Two-byte hexadecimal display"
55//usage: IF_FEATURE_HEXDUMP_REVERSE( 56//usage: IF_FEATURE_HEXDUMP_REVERSE(
56//usage: "\n -R Reverse of 'hexdump -Cv'") 57//usage: "\n -R Reverse of 'hexdump -Cv'")
58// TODO: NONCOMPAT!!! move -R to xxd -r
57//usage: 59//usage:
58//usage:#define hd_trivial_usage 60//usage:#define hd_trivial_usage
59//usage: "FILE..." 61//usage: "FILE..."
@@ -83,11 +85,11 @@ static void bb_dump_addfile(dumper_t *dumper, char *name)
83} 85}
84 86
85static const char *const add_strings[] = { 87static const char *const add_strings[] = {
86 "\"%07.7_ax \" 16/1 \"%03o \" \"\\n\"", /* b */ 88 "\"%07.7_ax \"16/1 \"%03o \"\"\n\"", /* b */
87 "\"%07.7_ax \" 16/1 \"%3_c \" \"\\n\"", /* c */ 89 "\"%07.7_ax \"16/1 \"%3_c \"\"\n\"", /* c */
88 "\"%07.7_ax \" 8/2 \" %05u \" \"\\n\"", /* d */ 90 "\"%07.7_ax \"8/2 \" %05u \"\"\n\"", /* d */
89 "\"%07.7_ax \" 8/2 \" %06o \" \"\\n\"", /* o */ 91 "\"%07.7_ax \"8/2 \" %06o \"\"\n\"", /* o */
90 "\"%07.7_ax \" 8/2 \" %04x \" \"\\n\"", /* x */ 92 "\"%07.7_ax \"8/2 \" %04x \"\"\n\"", /* x */
91}; 93};
92 94
93static const char add_first[] ALIGN1 = "\"%07.7_Ax\n\""; 95static const char add_first[] ALIGN1 = "\"%07.7_Ax\n\"";
@@ -125,9 +127,11 @@ int hexdump_main(int argc, char **argv)
125 /* Save a little bit of space below by omitting the 'else's. */ 127 /* Save a little bit of space below by omitting the 'else's. */
126 if (ch == 'C') { 128 if (ch == 'C') {
127 hd_applet: 129 hd_applet:
128 bb_dump_add(dumper, "\"%08.8_Ax\n\""); 130 bb_dump_add(dumper, "\"%08.8_Ax\n\""); // final address line after dump
129 bb_dump_add(dumper, "\"%08.8_ax \" 8/1 \"%02x \" \" \" 8/1 \"%02x \" "); 131 //------------------- "address " 8 * "xx " " " 8 * "xx "
130 bb_dump_add(dumper, "\" |\" 16/1 \"%_p\" \"|\\n\""); 132 bb_dump_add(dumper, "\"%08.8_ax \"8/1 \"%02x \"\" \"8/1 \"%02x \"");
133 //------------------- " |ASCII...........|\n"
134 bb_dump_add(dumper, "\" |\"16/1 \"%_p\"\"|\n\"");
131 } 135 }
132 if (ch == 'e') { 136 if (ch == 'e') {
133 bb_dump_add(dumper, optarg); 137 bb_dump_add(dumper, optarg);
@@ -158,7 +162,7 @@ int hexdump_main(int argc, char **argv)
158 162
159 if (!dumper->fshead) { 163 if (!dumper->fshead) {
160 bb_dump_add(dumper, add_first); 164 bb_dump_add(dumper, add_first);
161 bb_dump_add(dumper, "\"%07.7_ax \" 8/2 \"%04x \" \"\\n\""); 165 bb_dump_add(dumper, "\"%07.7_ax \"8/2 \"%04x \"\"\n\"");
162 } 166 }
163 167
164 argv += optind; 168 argv += optind;
diff --git a/util-linux/hexdump_xxd.c b/util-linux/hexdump_xxd.c
new file mode 100644
index 000000000..be4b4f354
--- /dev/null
+++ b/util-linux/hexdump_xxd.c
@@ -0,0 +1,146 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * xxd implementation for busybox
4 *
5 * Copyright (c) 2017 Denys Vlasenko <vda.linux@gmail.com>
6 *
7 * Licensed under GPLv2, see file LICENSE in this source tree.
8 */
9//config:config XXD
10//config: bool "xxd"
11//config: default y
12//config: help
13//config: The xxd utility is used to display binary data in a readable
14//config: way that is comparable to the output from most hex editors.
15
16//applet:IF_XXD(APPLET_NOEXEC(xxd, xxd, BB_DIR_USR_BIN, BB_SUID_DROP, xxd))
17
18//kbuild:lib-$(CONFIG_XXD) += hexdump_xxd.o
19
20// $ xxd --version
21// xxd V1.10 27oct98 by Juergen Weigert
22// $ xxd --help
23// Usage:
24// xxd [options] [infile [outfile]]
25// or
26// xxd -r [-s [-]offset] [-c cols] [-ps] [infile [outfile]]
27// Options:
28// -a toggle autoskip: A single '*' replaces nul-lines. Default off.
29// -b binary digit dump (incompatible with -ps,-i,-r). Default hex.
30// -c cols format <cols> octets per line. Default 16 (-i: 12, -ps: 30).
31// -E show characters in EBCDIC. Default ASCII.
32// -e little-endian dump (incompatible with -ps,-i,-r).
33// -g number of octets per group in normal output. Default 2 (-e: 4).
34// -i output in C include file style.
35// -l len stop after <len> octets.
36// -o off add <off> to the displayed file position.
37// -ps output in postscript plain hexdump style.
38// -r reverse operation: convert (or patch) hexdump into binary.
39// -r -s off revert with <off> added to file positions found in hexdump.
40// -s [+][-]seek start at <seek> bytes abs. (or +: rel.) infile offset.
41// -u use upper case hex letters.
42
43//usage:#define xxd_trivial_usage
44//usage: "[OPTIONS] [FILE]"
45//usage:#define xxd_full_usage "\n\n"
46//usage: "Hex dump FILE (or stdin)\n"
47//usage: "\n -g N Bytes per group"
48//usage: "\n -c N Bytes per line"
49//usage: "\n -p Show only hex bytes, assumes -c30"
50// exactly the same help text lines in hexdump and xxd:
51//usage: "\n -l LENGTH Show only first LENGTH bytes"
52//usage: "\n -s OFFSET Skip OFFSET bytes"
53// TODO: implement -r (see hexdump -R)
54
55#include "libbb.h"
56#include "dump.h"
57
58/* This is a NOEXEC applet. Be very careful! */
59
60int xxd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
61int xxd_main(int argc UNUSED_PARAM, char **argv)
62{
63 char buf[80];
64 dumper_t *dumper;
65 char *opt_l, *opt_s;
66 unsigned bytes = 2;
67 unsigned cols = 0;
68 unsigned opt;
69
70 dumper = alloc_dumper();
71
72#define OPT_l (1 << 0)
73#define OPT_s (1 << 1)
74#define OPT_a (1 << 2)
75#define OPT_p (1 << 3)
76 opt_complementary = "?1"; /* 1 argument max */
77 opt = getopt32(argv, "l:s:apg:+c:+", &opt_l, &opt_s, &bytes, &cols);
78 argv += optind;
79
80 dumper->dump_vflag = ALL;
81// if (opt & OPT_a)
82// dumper->dump_vflag = SKIPNUL; ..does not exist
83 if (opt & OPT_l) {
84 dumper->dump_length = xstrtou_range(
85 opt_l,
86 /*base:*/ 0,
87 /*lo:*/ 0, /*hi:*/ INT_MAX
88 );
89 }
90 if (opt & OPT_s) {
91 dumper->dump_skip = xstrtoull_range(
92 opt_s,
93 /*base:*/ 0,
94 /*lo:*/ 0, /*hi:*/ OFF_T_MAX
95 );
96 //BUGGY for /proc/version (unseekable?)
97 }
98
99 if (opt & OPT_p) {
100 if (cols == 0)
101 cols = 30;
102 bytes = cols; /* -p ignores -gN */
103 } else {
104 if (cols == 0)
105 cols = 16;
106 bb_dump_add(dumper, "\"%08.8_ax: \""); // "address: "
107 }
108
109 if (bytes < 1 || bytes >= cols) {
110 sprintf(buf, "%u/1 \"%%02x\"", cols); // cols * "xx"
111 bb_dump_add(dumper, buf);
112 }
113 else if (bytes == 1) {
114 sprintf(buf, "%u/1 \"%%02x \"", cols); // cols * "xx "
115 bb_dump_add(dumper, buf);
116 }
117 else {
118/* Format "print byte" with and without trailing space */
119#define BS "/1 \"%02x \""
120#define B "/1 \"%02x\""
121 unsigned i;
122 char *bigbuf = xmalloc(cols * (sizeof(BS)-1));
123 char *p = bigbuf;
124 for (i = 1; i <= cols; i++) {
125 if (i == cols || i % bytes)
126 p = stpcpy(p, B);
127 else
128 p = stpcpy(p, BS);
129 }
130 // for -g3, this results in B B BS B B BS... B = "xxxxxx xxxxxx .....xx"
131 // todo: can be more clever and use
132 // one 'bytes-1/1 "%02x"' format instead of many "B B B..." formats
133 //bb_error_msg("ADDED:'%s'", bigbuf);
134 bb_dump_add(dumper, bigbuf);
135 free(bigbuf);
136 }
137
138 if (!(opt & OPT_p)) {
139 sprintf(buf, "\" \"%u/1 \"%%_p\"\"\n\"", cols); // " ASCII\n"
140 bb_dump_add(dumper, buf);
141 } else {
142 bb_dump_add(dumper, "\"\n\"");
143 }
144
145 return bb_dump_dump(dumper, argv);
146}
diff --git a/util-linux/hwclock.c b/util-linux/hwclock.c
index 084a7f1e9..d65011a71 100644
--- a/util-linux/hwclock.c
+++ b/util-linux/hwclock.c
@@ -20,10 +20,6 @@
20//config: bool "Support long options (--hctosys,...)" 20//config: bool "Support long options (--hctosys,...)"
21//config: default y 21//config: default y
22//config: depends on HWCLOCK && LONG_OPTS 22//config: depends on HWCLOCK && LONG_OPTS
23//config: help
24//config: By default, the hwclock utility only uses short options. If you
25//config: are overly fond of its long options, such as --hctosys, --utc, etc)
26//config: then enable this option.
27//config: 23//config:
28//config:config FEATURE_HWCLOCK_ADJTIME_FHS 24//config:config FEATURE_HWCLOCK_ADJTIME_FHS
29//config: bool "Use FHS /var/lib/hwclock/adjtime" 25//config: bool "Use FHS /var/lib/hwclock/adjtime"
diff --git a/util-linux/mkfs_ext2.c b/util-linux/mkfs_ext2.c
index 5816a208e..4a7a878ac 100644
--- a/util-linux/mkfs_ext2.c
+++ b/util-linux/mkfs_ext2.c
@@ -21,7 +21,8 @@
21//config: help 21//config: help
22//config: Alias to "mke2fs". 22//config: Alias to "mke2fs".
23 23
24//applet:IF_MKE2FS(APPLET_ODDNAME(mke2fs, mkfs_ext2, BB_DIR_SBIN, BB_SUID_DROP, mkfs_ext2)) 24// APPLET_ODDNAME:name main location suid_type help
25//applet:IF_MKE2FS( APPLET_ODDNAME(mke2fs, mkfs_ext2, BB_DIR_SBIN, BB_SUID_DROP, mkfs_ext2))
25//applet:IF_MKFS_EXT2(APPLET_ODDNAME(mkfs.ext2, mkfs_ext2, BB_DIR_SBIN, BB_SUID_DROP, mkfs_ext2)) 26//applet:IF_MKFS_EXT2(APPLET_ODDNAME(mkfs.ext2, mkfs_ext2, BB_DIR_SBIN, BB_SUID_DROP, mkfs_ext2))
26////////:IF_MKFS_EXT3(APPLET_ODDNAME(mkfs.ext3, mkfs_ext2, BB_DIR_SBIN, BB_SUID_DROP, mkfs_ext2)) 27////////:IF_MKFS_EXT3(APPLET_ODDNAME(mkfs.ext3, mkfs_ext2, BB_DIR_SBIN, BB_SUID_DROP, mkfs_ext2))
27 28
diff --git a/util-linux/mkfs_minix.c b/util-linux/mkfs_minix.c
index 912246b93..0dfe34705 100644
--- a/util-linux/mkfs_minix.c
+++ b/util-linux/mkfs_minix.c
@@ -80,6 +80,7 @@
80//config: this. If you enabled 'mkfs_minix' then you almost certainly want to 80//config: this. If you enabled 'mkfs_minix' then you almost certainly want to
81//config: be using the version 2 filesystem support. 81//config: be using the version 2 filesystem support.
82 82
83// APPLET_ODDNAME:name main location suid_type help
83//applet:IF_MKFS_MINIX(APPLET_ODDNAME(mkfs.minix, mkfs_minix, BB_DIR_SBIN, BB_SUID_DROP, mkfs_minix)) 84//applet:IF_MKFS_MINIX(APPLET_ODDNAME(mkfs.minix, mkfs_minix, BB_DIR_SBIN, BB_SUID_DROP, mkfs_minix))
84 85
85//kbuild:lib-$(CONFIG_MKFS_MINIX) += mkfs_minix.o 86//kbuild:lib-$(CONFIG_MKFS_MINIX) += mkfs_minix.o
diff --git a/util-linux/mkfs_vfat.c b/util-linux/mkfs_vfat.c
index ab70853a1..1fc943430 100644
--- a/util-linux/mkfs_vfat.c
+++ b/util-linux/mkfs_vfat.c
@@ -21,7 +21,8 @@
21//config: help 21//config: help
22//config: Alias to "mkdosfs". 22//config: Alias to "mkdosfs".
23 23
24//applet:IF_MKDOSFS(APPLET_ODDNAME(mkdosfs, mkfs_vfat, BB_DIR_SBIN, BB_SUID_DROP, mkfs_vfat)) 24// APPLET_ODDNAME:name main location suid_type help
25//applet:IF_MKDOSFS( APPLET_ODDNAME(mkdosfs, mkfs_vfat, BB_DIR_SBIN, BB_SUID_DROP, mkfs_vfat))
25//applet:IF_MKFS_VFAT(APPLET_ODDNAME(mkfs.vfat, mkfs_vfat, BB_DIR_SBIN, BB_SUID_DROP, mkfs_vfat)) 26//applet:IF_MKFS_VFAT(APPLET_ODDNAME(mkfs.vfat, mkfs_vfat, BB_DIR_SBIN, BB_SUID_DROP, mkfs_vfat))
26 27
27//kbuild:lib-$(CONFIG_MKDOSFS) += mkfs_vfat.o 28//kbuild:lib-$(CONFIG_MKDOSFS) += mkfs_vfat.o
diff --git a/util-linux/more.c b/util-linux/more.c
index d04c17f90..a032a1e7f 100644
--- a/util-linux/more.c
+++ b/util-linux/more.c
@@ -41,32 +41,33 @@
41#include "libbb.h" 41#include "libbb.h"
42#include "common_bufsiz.h" 42#include "common_bufsiz.h"
43 43
44/* Support for FEATURE_USE_TERMIOS */
45
46struct globals { 44struct globals {
47 int cin_fileno; 45 int tty_fileno;
46 unsigned terminal_width;
47 unsigned terminal_height;
48 struct termios initial_settings; 48 struct termios initial_settings;
49 struct termios new_settings;
50} FIX_ALIASING; 49} FIX_ALIASING;
51#define G (*(struct globals*)bb_common_bufsiz1) 50#define G (*(struct globals*)bb_common_bufsiz1)
52#define initial_settings (G.initial_settings)
53#define new_settings (G.new_settings )
54#define cin_fileno (G.cin_fileno )
55#define INIT_G() do { setup_common_bufsiz(); } while (0) 51#define INIT_G() do { setup_common_bufsiz(); } while (0)
56 52
57#define setTermSettings(fd, argp) \ 53static void get_wh(void)
58do { \ 54{
59 if (ENABLE_FEATURE_USE_TERMIOS) \ 55 /* never returns w, h <= 1 */
60 tcsetattr(fd, TCSANOW, argp); \ 56 get_terminal_width_height(G.tty_fileno, &G.terminal_width, &G.terminal_height);
61} while (0) 57 G.terminal_height -= 1;
62#define getTermSettings(fd, argp) tcgetattr(fd, argp) 58}
59
60static void tcsetattr_tty_TCSANOW(struct termios *settings)
61{
62 tcsetattr(G.tty_fileno, TCSANOW, settings);
63}
63 64
64static void gotsig(int sig UNUSED_PARAM) 65static void gotsig(int sig UNUSED_PARAM)
65{ 66{
66 /* bb_putchar_stderr doesn't use stdio buffering, 67 /* bb_putchar_stderr doesn't use stdio buffering,
67 * therefore it is safe in signal handler */ 68 * therefore it is safe in signal handler */
68 bb_putchar_stderr('\n'); 69 bb_putchar_stderr('\n');
69 setTermSettings(cin_fileno, &initial_settings); 70 tcsetattr_tty_TCSANOW(&G.initial_settings);
70 _exit(EXIT_FAILURE); 71 _exit(EXIT_FAILURE);
71} 72}
72 73
@@ -76,22 +77,16 @@ int more_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
76int more_main(int argc UNUSED_PARAM, char **argv) 77int more_main(int argc UNUSED_PARAM, char **argv)
77{ 78{
78 int c = c; /* for compiler */ 79 int c = c; /* for compiler */
79 int lines;
80 int input = 0; 80 int input = 0;
81 int spaces = 0; 81 int spaces = 0;
82 int please_display_more_prompt; 82 int please_display_more_prompt;
83 struct stat st; 83 FILE *tty;
84 FILE *file;
85 FILE *cin;
86 int len;
87 unsigned terminal_width;
88 unsigned terminal_height;
89 84
90 INIT_G(); 85 INIT_G();
91 86
92 /* Parse options */ 87 /* Parse options */
93 /* Accepted but ignored: */ 88 /* Accepted but ignored: */
94 /* -d Display help instead of ringing bell is pressed */ 89 /* -d Display help instead of ringing bell */
95 /* -f Count logical lines (IOW: long lines are not folded) */ 90 /* -f Count logical lines (IOW: long lines are not folded) */
96 /* -l Do not pause after any line containing a ^L (form feed) */ 91 /* -l Do not pause after any line containing a ^L (form feed) */
97 /* -s Squeeze blank lines into one */ 92 /* -s Squeeze blank lines into one */
@@ -104,29 +99,25 @@ int more_main(int argc UNUSED_PARAM, char **argv)
104 if (!isatty(STDOUT_FILENO)) 99 if (!isatty(STDOUT_FILENO))
105 return bb_cat(argv); 100 return bb_cat(argv);
106#if !ENABLE_PLATFORM_MINGW32 101#if !ENABLE_PLATFORM_MINGW32
107 cin = fopen_for_read(CURRENT_TTY); 102 tty = fopen_for_read(CURRENT_TTY);
108 if (!cin) 103 if (!tty)
109 return bb_cat(argv); 104 return bb_cat(argv);
110#else 105#else
111 cin = stdin; 106 tty = stdin;
112#endif 107#endif
113 108
114 if (ENABLE_FEATURE_USE_TERMIOS) { 109 G.tty_fileno = fileno(tty);
115 cin_fileno = fileno(cin); 110
116 getTermSettings(cin_fileno, &initial_settings); 111 /* Turn on unbuffered input; turn off echoing */
117 new_settings = initial_settings; 112 set_termios_to_raw(G.tty_fileno, &G.initial_settings, 0);
118 new_settings.c_lflag &= ~(ICANON | ECHO); 113 bb_signals(BB_FATAL_SIGS, gotsig);
119 new_settings.c_cc[VMIN] = 1;
120 new_settings.c_cc[VTIME] = 0;
121 setTermSettings(cin_fileno, &new_settings);
122 bb_signals(0
123 + (1 << SIGINT)
124 + (1 << SIGQUIT)
125 + (1 << SIGTERM)
126 , gotsig);
127 }
128 114
129 do { 115 do {
116 struct stat st;
117 FILE *file;
118 int len;
119 int lines;
120
130 file = stdin; 121 file = stdin;
131 if (*argv) { 122 if (*argv) {
132 file = fopen_or_warn(*argv, "r"); 123 file = fopen_or_warn(*argv, "r");
@@ -136,17 +127,20 @@ int more_main(int argc UNUSED_PARAM, char **argv)
136 st.st_size = 0; 127 st.st_size = 0;
137 fstat(fileno(file), &st); 128 fstat(fileno(file), &st);
138 129
139 please_display_more_prompt = 0; 130 get_wh();
140 /* never returns w, h <= 1 */
141 get_terminal_width_height(fileno(cin), &terminal_width, &terminal_height);
142 terminal_height -= 1;
143 131
132 please_display_more_prompt = 0;
144 len = 0; 133 len = 0;
145 lines = 0; 134 lines = 0;
146 while (spaces || (c = getc(file)) != EOF) { 135 for (;;) {
147 int wrap; 136 int wrap;
137
148 if (spaces) 138 if (spaces)
149 spaces--; 139 spaces--;
140 else {
141 c = getc(file);
142 if (c == EOF) break;
143 }
150 loop_top: 144 loop_top:
151 if (input != 'r' && please_display_more_prompt) { 145 if (input != 'r' && please_display_more_prompt) {
152 len = printf("--More-- "); 146 len = printf("--More-- ");
@@ -158,7 +152,6 @@ int more_main(int argc UNUSED_PARAM, char **argv)
158 (int) ((uoff_t)ftello(file) / d), 152 (int) ((uoff_t)ftello(file) / d),
159 st.st_size); 153 st.st_size);
160 } 154 }
161 fflush_all();
162 155
163 /* 156 /*
164 * We've just displayed the "--More--" prompt, so now we need 157 * We've just displayed the "--More--" prompt, so now we need
@@ -166,22 +159,23 @@ int more_main(int argc UNUSED_PARAM, char **argv)
166 */ 159 */
167 for (;;) { 160 for (;;) {
168#if !ENABLE_PLATFORM_MINGW32 161#if !ENABLE_PLATFORM_MINGW32
169 input = getc(cin); 162 fflush_all();
163 input = getc(tty);
170#else 164#else
171 input = _getch(); 165 input = _getch();
172#endif 166#endif
173 input = tolower(input); 167 input = tolower(input);
174 if (!ENABLE_FEATURE_USE_TERMIOS)
175 printf("\033[A"); /* cursor up */
176 /* Erase the last message */ 168 /* Erase the last message */
177 printf("\r%*s\r", len, ""); 169 printf("\r%*s\r", len, "");
178 170
171 if (input == 'q')
172 goto end;
179 /* Due to various multibyte escape 173 /* Due to various multibyte escape
180 * sequences, it's not ok to accept 174 * sequences, it's not ok to accept
181 * any input as a command to scroll 175 * any input as a command to scroll
182 * the screen. We only allow known 176 * the screen. We only allow known
183 * commands, else we show help msg. */ 177 * commands, else we show help msg. */
184 if (input == ' ' || input == '\n' || input == 'q' || input == 'r') 178 if (input == ' ' || input == '\n' || input == 'r')
185 break; 179 break;
186#if ENABLE_PLATFORM_MINGW32 180#if ENABLE_PLATFORM_MINGW32
187 if (input == '\r') 181 if (input == '\r')
@@ -193,15 +187,9 @@ int more_main(int argc UNUSED_PARAM, char **argv)
193 lines = 0; 187 lines = 0;
194 please_display_more_prompt = 0; 188 please_display_more_prompt = 0;
195 189
196 if (input == 'q')
197 goto end;
198
199 /* The user may have resized the terminal. 190 /* The user may have resized the terminal.
200 * Re-read the dimensions. */ 191 * Re-read the dimensions. */
201 if (ENABLE_FEATURE_USE_TERMIOS) { 192 get_wh();
202 get_terminal_width_height(cin_fileno, &terminal_width, &terminal_height);
203 terminal_height -= 1;
204 }
205 } 193 }
206 194
207 /* Crudely convert tabs into spaces, which are 195 /* Crudely convert tabs into spaces, which are
@@ -221,11 +209,11 @@ int more_main(int argc UNUSED_PARAM, char **argv)
221 * see if any characters have been hit in the _input_ stream. This 209 * see if any characters have been hit in the _input_ stream. This
222 * allows the user to quit while in the middle of a file. 210 * allows the user to quit while in the middle of a file.
223 */ 211 */
224 wrap = (++len > terminal_width); 212 wrap = (++len > G.terminal_width);
225 if (c == '\n' || wrap) { 213 if (c == '\n' || wrap) {
226 /* Then outputting this character 214 /* Then outputting this character
227 * will move us to a new line. */ 215 * will move us to a new line. */
228 if (++lines >= terminal_height || input == '\n') 216 if (++lines >= G.terminal_height || input == '\n')
229 please_display_more_prompt = 1; 217 please_display_more_prompt = 1;
230#if ENABLE_PLATFORM_MINGW32 218#if ENABLE_PLATFORM_MINGW32
231 if (input == '\r') 219 if (input == '\r')
@@ -249,6 +237,6 @@ int more_main(int argc UNUSED_PARAM, char **argv)
249 fflush_all(); 237 fflush_all();
250 } while (*argv && *++argv); 238 } while (*argv && *++argv);
251 end: 239 end:
252 setTermSettings(cin_fileno, &initial_settings); 240 tcsetattr_tty_TCSANOW(&G.initial_settings);
253 return 0; 241 return 0;
254} 242}
diff --git a/util-linux/mount.c b/util-linux/mount.c
index 42962b859..f0245f714 100644
--- a/util-linux/mount.c
+++ b/util-linux/mount.c
@@ -90,7 +90,7 @@
90//config: 90//config:
91//config:config FEATURE_MOUNT_FLAGS 91//config:config FEATURE_MOUNT_FLAGS
92//config: depends on MOUNT 92//config: depends on MOUNT
93//config: bool "Support lots of -o flags in mount" 93//config: bool "Support lots of -o flags"
94//config: default y 94//config: default y
95//config: help 95//config: help
96//config: Without this, mount only supports ro/rw/remount. With this, it 96//config: Without this, mount only supports ro/rw/remount. With this, it
@@ -2312,7 +2312,7 @@ int mount_main(int argc UNUSED_PARAM, char **argv)
2312 bb_error_msg_and_die(bb_msg_you_must_be_root); 2312 bb_error_msg_and_die(bb_msg_you_must_be_root);
2313 2313
2314 // Does type match? (NULL matches always) 2314 // Does type match? (NULL matches always)
2315 if (!match_fstype(mtcur, fstype)) 2315 if (!fstype_matches(mtcur->mnt_type, fstype))
2316 continue; 2316 continue;
2317 2317
2318 // Skip noauto and swap anyway 2318 // Skip noauto and swap anyway
diff --git a/util-linux/nsenter.c b/util-linux/nsenter.c
index 6834292da..57b218dab 100644
--- a/util-linux/nsenter.c
+++ b/util-linux/nsenter.c
@@ -30,19 +30,19 @@
30//usage: "[OPTIONS] [PROG [ARGS]]" 30//usage: "[OPTIONS] [PROG [ARGS]]"
31//usage:#if ENABLE_FEATURE_NSENTER_LONG_OPTS 31//usage:#if ENABLE_FEATURE_NSENTER_LONG_OPTS
32//usage:#define nsenter_full_usage "\n" 32//usage:#define nsenter_full_usage "\n"
33//usage: "\n -t, --target=PID Target process to get namespaces from" 33//usage: "\n -t,--target PID Target process to get namespaces from"
34//usage: "\n -m, --mount[=FILE] Enter mount namespace" 34//usage: "\n -m,--mount[=FILE] Enter mount namespace"
35//usage: "\n -u, --uts[=FILE] Enter UTS namespace (hostname etc)" 35//usage: "\n -u,--uts[=FILE] Enter UTS namespace (hostname etc)"
36//usage: "\n -i, --ipc[=FILE] Enter System V IPC namespace" 36//usage: "\n -i,--ipc[=FILE] Enter System V IPC namespace"
37//usage: "\n -n, --net[=FILE] Enter network namespace" 37//usage: "\n -n,--net[=FILE] Enter network namespace"
38//usage: "\n -p, --pid[=FILE] Enter pid namespace" 38//usage: "\n -p,--pid[=FILE] Enter pid namespace"
39//usage: "\n -U, --user[=FILE] Enter user namespace" 39//usage: "\n -U,--user[=FILE] Enter user namespace"
40//usage: "\n -S, --setuid=UID Set uid in entered namespace" 40//usage: "\n -S,--setuid UID Set uid in entered namespace"
41//usage: "\n -G, --setgid=GID Set gid in entered namespace" 41//usage: "\n -G,--setgid GID Set gid in entered namespace"
42//usage: "\n --preserve-credentials Don't touch uids or gids" 42//usage: "\n --preserve-credentials Don't touch uids or gids"
43//usage: "\n -r, --root[=DIR] Set root directory" 43//usage: "\n -r,--root[=DIR] Set root directory"
44//usage: "\n -w, --wd[=DIR] Set working directory" 44//usage: "\n -w,--wd[=DIR] Set working directory"
45//usage: "\n -F, --no-fork Don't fork before exec'ing PROG" 45//usage: "\n -F,--no-fork Don't fork before exec'ing PROG"
46//usage:#else 46//usage:#else
47//usage:#define nsenter_full_usage "\n" 47//usage:#define nsenter_full_usage "\n"
48//usage: "\n -t PID Target process to get namespaces from" 48//usage: "\n -t PID Target process to get namespaces from"
diff --git a/util-linux/rdate.c b/util-linux/rdate.c
index 8dd784d3d..960df25d2 100644
--- a/util-linux/rdate.c
+++ b/util-linux/rdate.c
@@ -21,11 +21,11 @@
21//kbuild:lib-$(CONFIG_RDATE) += rdate.o 21//kbuild:lib-$(CONFIG_RDATE) += rdate.o
22 22
23//usage:#define rdate_trivial_usage 23//usage:#define rdate_trivial_usage
24//usage: "[-sp] HOST" 24//usage: "[-s/-p] HOST"
25//usage:#define rdate_full_usage "\n\n" 25//usage:#define rdate_full_usage "\n\n"
26//usage: "Get and possibly set system time from a remote HOST\n" 26//usage: "Set and print time from HOST using RFC 868\n"
27//usage: "\n -s Set system time (default)" 27//usage: "\n -s Only set system time"
28//usage: "\n -p Print time" 28//usage: "\n -p Only print time"
29 29
30#include "libbb.h" 30#include "libbb.h"
31 31
@@ -58,8 +58,22 @@ static time_t askremotedate(const char *host)
58 * the RFC 868 time 2,208,988,800 corresponds to 00:00 1 Jan 1970 GMT 58 * the RFC 868 time 2,208,988,800 corresponds to 00:00 1 Jan 1970 GMT
59 * Subtract the RFC 868 time to get Linux epoch. 59 * Subtract the RFC 868 time to get Linux epoch.
60 */ 60 */
61 61 nett = ntohl(nett) - RFC_868_BIAS;
62 return ntohl(nett) - RFC_868_BIAS; 62
63 if (sizeof(time_t) > 4) {
64 /* Now we have 32-bit lsb of a wider time_t
65 * Imagine that nett = 0x00000001,
66 * current time cur = 0x123ffffffff.
67 * Assuming our time is not some 40 years off,
68 * remote time must be 0x12400000001.
69 * Need to adjust out time by (int32_t)(nett - cur).
70 */
71 time_t cur = time(NULL);
72 int32_t adjust = (int32_t)(nett - (uint32_t)cur);
73 return cur + adjust;
74 }
75 /* This is not going to work, but what can we do */
76 return (time_t)nett;
63} 77}
64 78
65int rdate_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 79int rdate_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
@@ -73,11 +87,15 @@ int rdate_main(int argc UNUSED_PARAM, char **argv)
73 87
74 remote_time = askremotedate(argv[optind]); 88 remote_time = askremotedate(argv[optind]);
75 89
76 if (!(flags & 2)) { /* no -p (-s may be present) */ 90 /* Manpages of various Unixes are confusing. What happens is:
77 time_t current_time; 91 * (no opts) set and print time
92 * -s: set time ("do not print the time")
93 * -p: print time ("do not set, just print the remote time")
94 * -sp: print time (that's what we do, not sure this is right)
95 */
78 96
79 time(&current_time); 97 if (!(flags & 2)) { /* no -p (-s may be present) */
80 if (current_time == remote_time) 98 if (time(NULL) == remote_time)
81 bb_error_msg("current time matches remote time"); 99 bb_error_msg("current time matches remote time");
82 else 100 else
83 if (stime(&remote_time) < 0) 101 if (stime(&remote_time) < 0)
diff --git a/util-linux/rtcwake.c b/util-linux/rtcwake.c
index 54fc70583..b63164588 100644
--- a/util-linux/rtcwake.c
+++ b/util-linux/rtcwake.c
@@ -41,10 +41,10 @@
41//usage: "\n -a,--auto Read clock mode from adjtime" 41//usage: "\n -a,--auto Read clock mode from adjtime"
42//usage: "\n -l,--local Clock is set to local time" 42//usage: "\n -l,--local Clock is set to local time"
43//usage: "\n -u,--utc Clock is set to UTC time" 43//usage: "\n -u,--utc Clock is set to UTC time"
44//usage: "\n -d,--device=DEV Specify the RTC device" 44//usage: "\n -d,--device DEV Specify the RTC device"
45//usage: "\n -m,--mode=MODE Set sleep state (default: standby)" 45//usage: "\n -m,--mode MODE Set sleep state (default: standby)"
46//usage: "\n -s,--seconds=SEC Set timeout in SEC seconds from now" 46//usage: "\n -s,--seconds SEC Set timeout in SEC seconds from now"
47//usage: "\n -t,--time=TIME Set timeout to TIME seconds from epoch" 47//usage: "\n -t,--time TIME Set timeout to TIME seconds from epoch"
48//usage: ) 48//usage: )
49//usage: IF_NOT_LONG_OPTS( 49//usage: IF_NOT_LONG_OPTS(
50//usage: "\n -a Read clock mode from adjtime" 50//usage: "\n -a Read clock mode from adjtime"
diff --git a/util-linux/setarch.c b/util-linux/setarch.c
index ec473e9cb..e4124b044 100644
--- a/util-linux/setarch.c
+++ b/util-linux/setarch.c
@@ -31,6 +31,7 @@
31//config: Alias to "setarch linux64". 31//config: Alias to "setarch linux64".
32 32
33//applet:IF_SETARCH(APPLET(setarch, BB_DIR_BIN, BB_SUID_DROP)) 33//applet:IF_SETARCH(APPLET(setarch, BB_DIR_BIN, BB_SUID_DROP))
34// APPLET_ODDNAME:name main location suid_type help
34//applet:IF_LINUX32(APPLET_ODDNAME(linux32, setarch, BB_DIR_BIN, BB_SUID_DROP, linux32)) 35//applet:IF_LINUX32(APPLET_ODDNAME(linux32, setarch, BB_DIR_BIN, BB_SUID_DROP, linux32))
35//applet:IF_LINUX64(APPLET_ODDNAME(linux64, setarch, BB_DIR_BIN, BB_SUID_DROP, linux64)) 36//applet:IF_LINUX64(APPLET_ODDNAME(linux64, setarch, BB_DIR_BIN, BB_SUID_DROP, linux64))
36 37
diff --git a/util-linux/swaponoff.c b/util-linux/swaponoff.c
index b8f4e9447..313ea0ef9 100644
--- a/util-linux/swaponoff.c
+++ b/util-linux/swaponoff.c
@@ -41,7 +41,8 @@
41//config: help 41//config: help
42//config: This option enables the 'swapoff' utility. 42//config: This option enables the 'swapoff' utility.
43 43
44//applet:IF_SWAPON(APPLET_ODDNAME(swapon, swap_on_off, BB_DIR_SBIN, BB_SUID_DROP, swapon)) 44// APPLET_ODDNAME:name main location suid_type help
45//applet:IF_SWAPON( APPLET_ODDNAME(swapon, swap_on_off, BB_DIR_SBIN, BB_SUID_DROP, swapon))
45//applet:IF_SWAPOFF(APPLET_ODDNAME(swapoff, swap_on_off, BB_DIR_SBIN, BB_SUID_DROP, swapoff)) 46//applet:IF_SWAPOFF(APPLET_ODDNAME(swapoff, swap_on_off, BB_DIR_SBIN, BB_SUID_DROP, swapoff))
46 47
47//kbuild:lib-$(CONFIG_SWAPON) += swaponoff.o 48//kbuild:lib-$(CONFIG_SWAPON) += swaponoff.o
diff --git a/util-linux/umount.c b/util-linux/umount.c
index 78eef57a5..c958fd552 100644
--- a/util-linux/umount.c
+++ b/util-linux/umount.c
@@ -125,8 +125,8 @@ int umount_main(int argc UNUSED_PARAM, char **argv)
125 } else { 125 } else {
126 setup_common_bufsiz(); 126 setup_common_bufsiz();
127 while (getmntent_r(fp, &me, bb_common_bufsiz1, COMMON_BUFSIZE)) { 127 while (getmntent_r(fp, &me, bb_common_bufsiz1, COMMON_BUFSIZE)) {
128 /* Match fstype if passed */ 128 /* Match fstype (fstype==NULL matches always) */
129 if (!match_fstype(&me, fstype)) 129 if (!fstype_matches(me.mnt_type, fstype))
130 continue; 130 continue;
131 m = xzalloc(sizeof(*m)); 131 m = xzalloc(sizeof(*m));
132 m->next = mtl; 132 m->next = mtl;
diff --git a/util-linux/unshare.c b/util-linux/unshare.c
index bbabeef55..52e8f1421 100644
--- a/util-linux/unshare.c
+++ b/util-linux/unshare.c
@@ -25,14 +25,14 @@
25//usage:#define unshare_trivial_usage 25//usage:#define unshare_trivial_usage
26//usage: "[OPTIONS] [PROG [ARGS]]" 26//usage: "[OPTIONS] [PROG [ARGS]]"
27//usage:#define unshare_full_usage "\n" 27//usage:#define unshare_full_usage "\n"
28//usage: "\n -m, --mount[=FILE] Unshare mount namespace" 28//usage: "\n -m,--mount[=FILE] Unshare mount namespace"
29//usage: "\n -u, --uts[=FILE] Unshare UTS namespace (hostname etc.)" 29//usage: "\n -u,--uts[=FILE] Unshare UTS namespace (hostname etc.)"
30//usage: "\n -i, --ipc[=FILE] Unshare System V IPC namespace" 30//usage: "\n -i,--ipc[=FILE] Unshare System V IPC namespace"
31//usage: "\n -n, --net[=FILE] Unshare network namespace" 31//usage: "\n -n,--net[=FILE] Unshare network namespace"
32//usage: "\n -p, --pid[=FILE] Unshare PID namespace" 32//usage: "\n -p,--pid[=FILE] Unshare PID namespace"
33//usage: "\n -U, --user[=FILE} Unshare user namespace" 33//usage: "\n -U,--user[=FILE] Unshare user namespace"
34//usage: "\n -f, --fork Fork before execing PROG" 34//usage: "\n -f,--fork Fork before execing PROG"
35//usage: "\n -r, --map-root-user Map current user to root (implies -u)" 35//usage: "\n -r,--map-root-user Map current user to root (implies -u)"
36//usage: "\n --mount-proc[=DIR] Mount /proc filesystem first (implies -m)" 36//usage: "\n --mount-proc[=DIR] Mount /proc filesystem first (implies -m)"
37//usage: "\n --propagation slave|shared|private|unchanged" 37//usage: "\n --propagation slave|shared|private|unchanged"
38//usage: "\n Modify mount propagation in mount namespace" 38//usage: "\n Modify mount propagation in mount namespace"
diff --git a/util-linux/volume_id/bcache.c b/util-linux/volume_id/bcache.c
index fd40eb081..334a341c3 100644
--- a/util-linux/volume_id/bcache.c
+++ b/util-linux/volume_id/bcache.c
@@ -10,14 +10,10 @@
10 10
11//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_BCACHE) += bcache.o 11//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_BCACHE) += bcache.o
12 12
13//config:
14//config:config FEATURE_VOLUMEID_BCACHE 13//config:config FEATURE_VOLUMEID_BCACHE
15//config: bool "bcache filesystem" 14//config: bool "bcache filesystem"
16//config: default y 15//config: default y
17//config: depends on VOLUMEID 16//config: depends on VOLUMEID
18//config: help
19//config: TODO
20//config:
21 17
22#include "volume_id_internal.h" 18#include "volume_id_internal.h"
23 19
diff --git a/util-linux/volume_id/btrfs.c b/util-linux/volume_id/btrfs.c
index e4dddf26d..338a48762 100644
--- a/util-linux/volume_id/btrfs.c
+++ b/util-linux/volume_id/btrfs.c
@@ -21,14 +21,10 @@
21 21
22//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_BTRFS) += btrfs.o 22//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_BTRFS) += btrfs.o
23 23
24//config:
25//config:config FEATURE_VOLUMEID_BTRFS 24//config:config FEATURE_VOLUMEID_BTRFS
26//config: bool "btrfs filesystem" 25//config: bool "btrfs filesystem"
27//config: default y 26//config: default y
28//config: depends on VOLUMEID 27//config: depends on VOLUMEID
29//config: help
30//config: TODO
31//config:
32 28
33#include "volume_id_internal.h" 29#include "volume_id_internal.h"
34 30
diff --git a/util-linux/volume_id/cramfs.c b/util-linux/volume_id/cramfs.c
index aeb7f20ac..c63223e2b 100644
--- a/util-linux/volume_id/cramfs.c
+++ b/util-linux/volume_id/cramfs.c
@@ -20,14 +20,10 @@
20 20
21//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_CRAMFS) += cramfs.o 21//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_CRAMFS) += cramfs.o
22 22
23//config:
24//config:config FEATURE_VOLUMEID_CRAMFS 23//config:config FEATURE_VOLUMEID_CRAMFS
25//config: bool "cramfs filesystem" 24//config: bool "cramfs filesystem"
26//config: default y 25//config: default y
27//config: depends on VOLUMEID 26//config: depends on VOLUMEID
28//config: help
29//config: TODO
30//config:
31 27
32#include "volume_id_internal.h" 28#include "volume_id_internal.h"
33 29
diff --git a/util-linux/volume_id/exfat.c b/util-linux/volume_id/exfat.c
index c3aa36804..7ed13a70e 100644
--- a/util-linux/volume_id/exfat.c
+++ b/util-linux/volume_id/exfat.c
@@ -20,7 +20,6 @@
20 20
21//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_EXFAT) += exfat.o 21//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_EXFAT) += exfat.o
22 22
23//config:
24//config:config FEATURE_VOLUMEID_EXFAT 23//config:config FEATURE_VOLUMEID_EXFAT
25//config: bool "exFAT filesystem" 24//config: bool "exFAT filesystem"
26//config: default y 25//config: default y
@@ -29,7 +28,6 @@
29//config: exFAT (extended FAT) is a proprietary file system designed especially 28//config: exFAT (extended FAT) is a proprietary file system designed especially
30//config: for flash drives. It has many features from NTFS, but with less 29//config: for flash drives. It has many features from NTFS, but with less
31//config: overhead. exFAT is used on most SDXC cards for consumer electronics. 30//config: overhead. exFAT is used on most SDXC cards for consumer electronics.
32//config:
33 31
34#include "volume_id_internal.h" 32#include "volume_id_internal.h"
35 33
diff --git a/util-linux/volume_id/ext.c b/util-linux/volume_id/ext.c
index df39d9342..473b3229a 100644
--- a/util-linux/volume_id/ext.c
+++ b/util-linux/volume_id/ext.c
@@ -20,14 +20,10 @@
20 20
21//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_EXT) += ext.o 21//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_EXT) += ext.o
22 22
23//config:
24//config:config FEATURE_VOLUMEID_EXT 23//config:config FEATURE_VOLUMEID_EXT
25//config: bool "Ext filesystem" 24//config: bool "Ext filesystem"
26//config: default y 25//config: default y
27//config: depends on VOLUMEID 26//config: depends on VOLUMEID
28//config: help
29//config: TODO
30//config:
31 27
32#include "volume_id_internal.h" 28#include "volume_id_internal.h"
33#include "bb_e2fs_defs.h" 29#include "bb_e2fs_defs.h"
diff --git a/util-linux/volume_id/f2fs.c b/util-linux/volume_id/f2fs.c
index bf0b66278..1d3bdae36 100644
--- a/util-linux/volume_id/f2fs.c
+++ b/util-linux/volume_id/f2fs.c
@@ -8,7 +8,6 @@
8 8
9//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_F2FS) += f2fs.o 9//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_F2FS) += f2fs.o
10 10
11//config:
12//config:config FEATURE_VOLUMEID_F2FS 11//config:config FEATURE_VOLUMEID_F2FS
13//config: bool "f2fs filesystem" 12//config: bool "f2fs filesystem"
14//config: default y 13//config: default y
@@ -18,7 +17,6 @@
18//config: which is adapted to newer forms of storage. F2FS also remedies some 17//config: which is adapted to newer forms of storage. F2FS also remedies some
19//config: known issues of the older log structured file systems, such as high 18//config: known issues of the older log structured file systems, such as high
20//config: cleaning overhead. 19//config: cleaning overhead.
21//config:
22 20
23#include "volume_id_internal.h" 21#include "volume_id_internal.h"
24 22
diff --git a/util-linux/volume_id/fat.c b/util-linux/volume_id/fat.c
index 476d500a6..bc3433daf 100644
--- a/util-linux/volume_id/fat.c
+++ b/util-linux/volume_id/fat.c
@@ -20,14 +20,10 @@
20 20
21//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_FAT) += fat.o 21//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_FAT) += fat.o
22 22
23//config:
24//config:config FEATURE_VOLUMEID_FAT 23//config:config FEATURE_VOLUMEID_FAT
25//config: bool "fat filesystem" 24//config: bool "fat filesystem"
26//config: default y 25//config: default y
27//config: depends on VOLUMEID 26//config: depends on VOLUMEID
28//config: help
29//config: TODO
30//config:
31 27
32#include "volume_id_internal.h" 28#include "volume_id_internal.h"
33 29
diff --git a/util-linux/volume_id/hfs.c b/util-linux/volume_id/hfs.c
index 8d34aaf68..78dae0790 100644
--- a/util-linux/volume_id/hfs.c
+++ b/util-linux/volume_id/hfs.c
@@ -20,14 +20,10 @@
20 20
21//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_HFS) += hfs.o 21//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_HFS) += hfs.o
22 22
23//config:
24//config:config FEATURE_VOLUMEID_HFS 23//config:config FEATURE_VOLUMEID_HFS
25//config: bool "hfs filesystem" 24//config: bool "hfs filesystem"
26//config: default y 25//config: default y
27//config: depends on VOLUMEID 26//config: depends on VOLUMEID
28//config: help
29//config: TODO
30//config:
31 27
32#include "volume_id_internal.h" 28#include "volume_id_internal.h"
33 29
diff --git a/util-linux/volume_id/iso9660.c b/util-linux/volume_id/iso9660.c
index 3848de453..23072f87c 100644
--- a/util-linux/volume_id/iso9660.c
+++ b/util-linux/volume_id/iso9660.c
@@ -20,14 +20,10 @@
20 20
21//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_ISO9660) += iso9660.o 21//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_ISO9660) += iso9660.o
22 22
23//config:
24//config:config FEATURE_VOLUMEID_ISO9660 23//config:config FEATURE_VOLUMEID_ISO9660
25//config: bool "iso9660 filesystem" 24//config: bool "iso9660 filesystem"
26//config: default y 25//config: default y
27//config: depends on VOLUMEID 26//config: depends on VOLUMEID
28//config: help
29//config: TODO
30//config:
31 27
32#include "volume_id_internal.h" 28#include "volume_id_internal.h"
33 29
diff --git a/util-linux/volume_id/jfs.c b/util-linux/volume_id/jfs.c
index a6eaff45b..543d90fe5 100644
--- a/util-linux/volume_id/jfs.c
+++ b/util-linux/volume_id/jfs.c
@@ -20,14 +20,10 @@
20 20
21//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_JFS) += jfs.o 21//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_JFS) += jfs.o
22 22
23//config:
24//config:config FEATURE_VOLUMEID_JFS 23//config:config FEATURE_VOLUMEID_JFS
25//config: bool "jfs filesystem" 24//config: bool "jfs filesystem"
26//config: default y 25//config: default y
27//config: depends on VOLUMEID 26//config: depends on VOLUMEID
28//config: help
29//config: TODO
30//config:
31 27
32#include "volume_id_internal.h" 28#include "volume_id_internal.h"
33 29
diff --git a/util-linux/volume_id/linux_raid.c b/util-linux/volume_id/linux_raid.c
index f20823a6e..0db6e8662 100644
--- a/util-linux/volume_id/linux_raid.c
+++ b/util-linux/volume_id/linux_raid.c
@@ -20,14 +20,10 @@
20 20
21//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_LINUXRAID) += linux_raid.o 21//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_LINUXRAID) += linux_raid.o
22 22
23//config:
24//config:config FEATURE_VOLUMEID_LINUXRAID 23//config:config FEATURE_VOLUMEID_LINUXRAID
25//config: bool "linuxraid" 24//config: bool "linuxraid"
26//config: default y 25//config: default y
27//config: depends on VOLUMEID 26//config: depends on VOLUMEID
28//config: help
29//config: TODO
30//config:
31 27
32#include "volume_id_internal.h" 28#include "volume_id_internal.h"
33 29
diff --git a/util-linux/volume_id/linux_swap.c b/util-linux/volume_id/linux_swap.c
index 39470d48c..a35769dfc 100644
--- a/util-linux/volume_id/linux_swap.c
+++ b/util-linux/volume_id/linux_swap.c
@@ -20,14 +20,10 @@
20 20
21//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_LINUXSWAP) += linux_swap.o 21//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_LINUXSWAP) += linux_swap.o
22 22
23//config:
24//config:config FEATURE_VOLUMEID_LINUXSWAP 23//config:config FEATURE_VOLUMEID_LINUXSWAP
25//config: bool "linux swap filesystem" 24//config: bool "linux swap filesystem"
26//config: default y 25//config: default y
27//config: depends on VOLUMEID 26//config: depends on VOLUMEID
28//config: help
29//config: TODO
30//config:
31 27
32#include "volume_id_internal.h" 28#include "volume_id_internal.h"
33 29
diff --git a/util-linux/volume_id/luks.c b/util-linux/volume_id/luks.c
index 21cb26f51..4b80b7a6d 100644
--- a/util-linux/volume_id/luks.c
+++ b/util-linux/volume_id/luks.c
@@ -20,14 +20,10 @@
20 20
21//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_LUKS) += luks.o 21//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_LUKS) += luks.o
22 22
23//config:
24//config:config FEATURE_VOLUMEID_LUKS 23//config:config FEATURE_VOLUMEID_LUKS
25//config: bool "luks filesystem" 24//config: bool "luks filesystem"
26//config: default y 25//config: default y
27//config: depends on VOLUMEID 26//config: depends on VOLUMEID
28//config: help
29//config: TODO
30//config:
31 27
32#include "volume_id_internal.h" 28#include "volume_id_internal.h"
33 29
diff --git a/util-linux/volume_id/nilfs.c b/util-linux/volume_id/nilfs.c
index f3a9ef58d..ffe919f36 100644
--- a/util-linux/volume_id/nilfs.c
+++ b/util-linux/volume_id/nilfs.c
@@ -21,7 +21,6 @@
21 21
22//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_NILFS) += nilfs.o 22//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_NILFS) += nilfs.o
23 23
24//config:
25//config:config FEATURE_VOLUMEID_NILFS 24//config:config FEATURE_VOLUMEID_NILFS
26//config: bool "nilfs filesystem" 25//config: bool "nilfs filesystem"
27//config: default y 26//config: default y
@@ -37,7 +36,6 @@
37//config: SOX compliance logging, and so forth. It can serve as an alternative 36//config: SOX compliance logging, and so forth. It can serve as an alternative
38//config: filesystem for Linux desktop environment, or as a basis of advanced 37//config: filesystem for Linux desktop environment, or as a basis of advanced
39//config: storage appliances. 38//config: storage appliances.
40//config:
41 39
42#include "volume_id_internal.h" 40#include "volume_id_internal.h"
43 41
diff --git a/util-linux/volume_id/ntfs.c b/util-linux/volume_id/ntfs.c
index 46f687a56..bf85f7ed3 100644
--- a/util-linux/volume_id/ntfs.c
+++ b/util-linux/volume_id/ntfs.c
@@ -20,14 +20,10 @@
20 20
21//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_NTFS) += ntfs.o 21//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_NTFS) += ntfs.o
22 22
23//config:
24//config:config FEATURE_VOLUMEID_NTFS 23//config:config FEATURE_VOLUMEID_NTFS
25//config: bool "ntfs filesystem" 24//config: bool "ntfs filesystem"
26//config: default y 25//config: default y
27//config: depends on VOLUMEID 26//config: depends on VOLUMEID
28//config: help
29//config: TODO
30//config:
31 27
32#include "volume_id_internal.h" 28#include "volume_id_internal.h"
33 29
diff --git a/util-linux/volume_id/ocfs2.c b/util-linux/volume_id/ocfs2.c
index 415e0bf61..2dedac98b 100644
--- a/util-linux/volume_id/ocfs2.c
+++ b/util-linux/volume_id/ocfs2.c
@@ -20,14 +20,10 @@
20 20
21//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_OCFS2) += ocfs2.o 21//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_OCFS2) += ocfs2.o
22 22
23//config:
24//config:config FEATURE_VOLUMEID_OCFS2 23//config:config FEATURE_VOLUMEID_OCFS2
25//config: bool "ocfs2 filesystem" 24//config: bool "ocfs2 filesystem"
26//config: default y 25//config: default y
27//config: depends on VOLUMEID 26//config: depends on VOLUMEID
28//config: help
29//config: TODO
30//config:
31 27
32#include "volume_id_internal.h" 28#include "volume_id_internal.h"
33 29
diff --git a/util-linux/volume_id/reiserfs.c b/util-linux/volume_id/reiserfs.c
index 24979fb1c..369d4d9bb 100644
--- a/util-linux/volume_id/reiserfs.c
+++ b/util-linux/volume_id/reiserfs.c
@@ -21,14 +21,10 @@
21 21
22//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_REISERFS) += reiserfs.o 22//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_REISERFS) += reiserfs.o
23 23
24//config:
25//config:config FEATURE_VOLUMEID_REISERFS 24//config:config FEATURE_VOLUMEID_REISERFS
26//config: bool "Reiser filesystem" 25//config: bool "Reiser filesystem"
27//config: default y 26//config: default y
28//config: depends on VOLUMEID 27//config: depends on VOLUMEID
29//config: help
30//config: TODO
31//config:
32 28
33#include "volume_id_internal.h" 29#include "volume_id_internal.h"
34 30
diff --git a/util-linux/volume_id/romfs.c b/util-linux/volume_id/romfs.c
index 4754fdb37..95a65f9ef 100644
--- a/util-linux/volume_id/romfs.c
+++ b/util-linux/volume_id/romfs.c
@@ -20,14 +20,10 @@
20 20
21//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_ROMFS) += romfs.o 21//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_ROMFS) += romfs.o
22 22
23//config:
24//config:config FEATURE_VOLUMEID_ROMFS 23//config:config FEATURE_VOLUMEID_ROMFS
25//config: bool "romfs filesystem" 24//config: bool "romfs filesystem"
26//config: default y 25//config: default y
27//config: depends on VOLUMEID 26//config: depends on VOLUMEID
28//config: help
29//config: TODO
30//config:
31 27
32#include "volume_id_internal.h" 28#include "volume_id_internal.h"
33 29
diff --git a/util-linux/volume_id/squashfs.c b/util-linux/volume_id/squashfs.c
index 079b6cc31..6bba199cd 100644
--- a/util-linux/volume_id/squashfs.c
+++ b/util-linux/volume_id/squashfs.c
@@ -8,7 +8,6 @@
8 8
9//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_SQUASHFS) += squashfs.o 9//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_SQUASHFS) += squashfs.o
10 10
11//config:
12//config:config FEATURE_VOLUMEID_SQUASHFS 11//config:config FEATURE_VOLUMEID_SQUASHFS
13//config: bool "SquashFS filesystem" 12//config: bool "SquashFS filesystem"
14//config: default y 13//config: default y
@@ -18,7 +17,6 @@
18//config: intended for general read-only filesystem use and in constrained block 17//config: intended for general read-only filesystem use and in constrained block
19//config: device/memory systems (e.g. embedded systems) where low overhead is 18//config: device/memory systems (e.g. embedded systems) where low overhead is
20//config: needed. 19//config: needed.
21//config:
22 20
23#include "volume_id_internal.h" 21#include "volume_id_internal.h"
24 22
diff --git a/util-linux/volume_id/sysv.c b/util-linux/volume_id/sysv.c
index 7b4b5360b..cd4cd906b 100644
--- a/util-linux/volume_id/sysv.c
+++ b/util-linux/volume_id/sysv.c
@@ -20,14 +20,10 @@
20 20
21//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_SYSV) += sysv.o 21//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_SYSV) += sysv.o
22 22
23//config:
24//config:config FEATURE_VOLUMEID_SYSV 23//config:config FEATURE_VOLUMEID_SYSV
25//config: bool "sysv filesystem" 24//config: bool "sysv filesystem"
26//config: default y 25//config: default y
27//config: depends on VOLUMEID 26//config: depends on VOLUMEID
28//config: help
29//config: TODO
30//config:
31 27
32#include "volume_id_internal.h" 28#include "volume_id_internal.h"
33 29
diff --git a/util-linux/volume_id/ubifs.c b/util-linux/volume_id/ubifs.c
index 13604ec35..99b0aa830 100644
--- a/util-linux/volume_id/ubifs.c
+++ b/util-linux/volume_id/ubifs.c
@@ -8,7 +8,6 @@
8 8
9//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_UBIFS) += ubifs.o 9//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_UBIFS) += ubifs.o
10 10
11//config:
12//config:config FEATURE_VOLUMEID_UBIFS 11//config:config FEATURE_VOLUMEID_UBIFS
13//config: bool "UBIFS filesystem" 12//config: bool "UBIFS filesystem"
14//config: default y 13//config: default y
@@ -16,7 +15,6 @@
16//config: help 15//config: help
17//config: UBIFS (Unsorted Block Image File System) is a file 16//config: UBIFS (Unsorted Block Image File System) is a file
18//config: system for use with raw flash memory media. 17//config: system for use with raw flash memory media.
19//config:
20 18
21#include "volume_id_internal.h" 19#include "volume_id_internal.h"
22 20
diff --git a/util-linux/volume_id/udf.c b/util-linux/volume_id/udf.c
index 921454503..613c80c86 100644
--- a/util-linux/volume_id/udf.c
+++ b/util-linux/volume_id/udf.c
@@ -20,14 +20,10 @@
20 20
21//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_UDF) += udf.o 21//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_UDF) += udf.o
22 22
23//config:
24//config:config FEATURE_VOLUMEID_UDF 23//config:config FEATURE_VOLUMEID_UDF
25//config: bool "udf filesystem" 24//config: bool "udf filesystem"
26//config: default y 25//config: default y
27//config: depends on VOLUMEID 26//config: depends on VOLUMEID
28//config: help
29//config: TODO
30//config:
31 27
32#include "volume_id_internal.h" 28#include "volume_id_internal.h"
33 29
diff --git a/util-linux/volume_id/unused_highpoint.c b/util-linux/volume_id/unused_highpoint.c
index 7231a1db2..4afa6d927 100644
--- a/util-linux/volume_id/unused_highpoint.c
+++ b/util-linux/volume_id/unused_highpoint.c
@@ -20,14 +20,10 @@
20 20
21//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_HIGHPOINTRAID) += highpoint.o 21//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_HIGHPOINTRAID) += highpoint.o
22 22
23//config:
24//config:### config FEATURE_VOLUMEID_HIGHPOINTRAID 23//config:### config FEATURE_VOLUMEID_HIGHPOINTRAID
25//config:### bool "highpoint raid" 24//config:### bool "highpoint raid"
26//config:### default y 25//config:### default y
27//config:### depends on VOLUMEID 26//config:### depends on VOLUMEID
28//config:### help
29//config:### TODO
30//config:
31 27
32#include "volume_id_internal.h" 28#include "volume_id_internal.h"
33 29
diff --git a/util-linux/volume_id/unused_hpfs.c b/util-linux/volume_id/unused_hpfs.c
index a87c89fb3..3e16dedbd 100644
--- a/util-linux/volume_id/unused_hpfs.c
+++ b/util-linux/volume_id/unused_hpfs.c
@@ -20,14 +20,10 @@
20 20
21//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_HPFS) += hpfs.o 21//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_HPFS) += hpfs.o
22 22
23//config:
24//config:### config FEATURE_VOLUMEID_HPFS 23//config:### config FEATURE_VOLUMEID_HPFS
25//config:### bool "hpfs filesystem" 24//config:### bool "hpfs filesystem"
26//config:### default y 25//config:### default y
27//config:### depends on VOLUMEID 26//config:### depends on VOLUMEID
28//config:### help
29//config:### TODO
30//config:
31 27
32#include "volume_id_internal.h" 28#include "volume_id_internal.h"
33 29
diff --git a/util-linux/volume_id/unused_isw_raid.c b/util-linux/volume_id/unused_isw_raid.c
index 851bd2f8f..fba99be58 100644
--- a/util-linux/volume_id/unused_isw_raid.c
+++ b/util-linux/volume_id/unused_isw_raid.c
@@ -20,14 +20,10 @@
20 20
21//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_ISWRAID) += isw_raid.o 21//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_ISWRAID) += isw_raid.o
22 22
23//config:
24//config:### config FEATURE_VOLUMEID_ISWRAID 23//config:### config FEATURE_VOLUMEID_ISWRAID
25//config:### bool "intel raid" 24//config:### bool "intel raid"
26//config:### default y 25//config:### default y
27//config:### depends on VOLUMEID 26//config:### depends on VOLUMEID
28//config:### help
29//config:### TODO
30//config:
31 27
32#include "volume_id_internal.h" 28#include "volume_id_internal.h"
33 29
diff --git a/util-linux/volume_id/unused_lsi_raid.c b/util-linux/volume_id/unused_lsi_raid.c
index 52d68deab..9dd2b409c 100644
--- a/util-linux/volume_id/unused_lsi_raid.c
+++ b/util-linux/volume_id/unused_lsi_raid.c
@@ -20,14 +20,10 @@
20 20
21//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_LSIRAID) += lsi_raid.o 21//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_LSIRAID) += lsi_raid.o
22 22
23//config:
24//config:### config FEATURE_VOLUMEID_LSIRAID 23//config:### config FEATURE_VOLUMEID_LSIRAID
25//config:### bool "lsi raid" 24//config:### bool "lsi raid"
26//config:### default y 25//config:### default y
27//config:### depends on VOLUMEID 26//config:### depends on VOLUMEID
28//config:### help
29//config:### TODO
30//config:
31 27
32#include "volume_id_internal.h" 28#include "volume_id_internal.h"
33 29
diff --git a/util-linux/volume_id/unused_lvm.c b/util-linux/volume_id/unused_lvm.c
index 08fa05243..5ad6d585c 100644
--- a/util-linux/volume_id/unused_lvm.c
+++ b/util-linux/volume_id/unused_lvm.c
@@ -20,14 +20,10 @@
20 20
21//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_LVM) += lvm.o 21//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_LVM) += lvm.o
22 22
23//config:
24//config:### config FEATURE_VOLUMEID_LVM 23//config:### config FEATURE_VOLUMEID_LVM
25//config:### bool "lvm" 24//config:### bool "lvm"
26//config:### default y 25//config:### default y
27//config:### depends on VOLUMEID 26//config:### depends on VOLUMEID
28//config:### help
29//config:### TODO
30//config:
31 27
32#include "volume_id_internal.h" 28#include "volume_id_internal.h"
33 29
diff --git a/util-linux/volume_id/unused_mac.c b/util-linux/volume_id/unused_mac.c
index a1a53d1fb..997d330a4 100644
--- a/util-linux/volume_id/unused_mac.c
+++ b/util-linux/volume_id/unused_mac.c
@@ -20,14 +20,10 @@
20 20
21//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_MAC) += mac.o 21//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_MAC) += mac.o
22 22
23//config:
24//config:### config FEATURE_VOLUMEID_MAC 23//config:### config FEATURE_VOLUMEID_MAC
25//config:### bool "mac filesystem" 24//config:### bool "mac filesystem"
26//config:### default y 25//config:### default y
27//config:### depends on VOLUMEID 26//config:### depends on VOLUMEID
28//config:### help
29//config:### TODO
30//config:
31 27
32#include "volume_id_internal.h" 28#include "volume_id_internal.h"
33 29
diff --git a/util-linux/volume_id/unused_minix.c b/util-linux/volume_id/unused_minix.c
index 50afd5c3e..443dbc272 100644
--- a/util-linux/volume_id/unused_minix.c
+++ b/util-linux/volume_id/unused_minix.c
@@ -20,14 +20,10 @@
20 20
21//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_MINIX) += minix.o 21//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_MINIX) += minix.o
22 22
23//config:
24//config:### config FEATURE_VOLUMEID_MINIX 23//config:### config FEATURE_VOLUMEID_MINIX
25//config:### bool "minix filesystem" 24//config:### bool "minix filesystem"
26//config:### default y 25//config:### default y
27//config:### depends on VOLUMEID 26//config:### depends on VOLUMEID
28//config:### help
29//config:### TODO
30//config:
31 27
32#include "volume_id_internal.h" 28#include "volume_id_internal.h"
33 29
diff --git a/util-linux/volume_id/unused_msdos.c b/util-linux/volume_id/unused_msdos.c
index 5ebaa3eef..f84c0f06f 100644
--- a/util-linux/volume_id/unused_msdos.c
+++ b/util-linux/volume_id/unused_msdos.c
@@ -20,14 +20,10 @@
20 20
21//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_MSDOS) += msdos.o 21//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_MSDOS) += msdos.o
22 22
23//config:
24//config:### config FEATURE_VOLUMEID_MSDOS 23//config:### config FEATURE_VOLUMEID_MSDOS
25//config:### bool "msdos filesystem" 24//config:### bool "msdos filesystem"
26//config:### default y 25//config:### default y
27//config:### depends on VOLUMEID 26//config:### depends on VOLUMEID
28//config:### help
29//config:### TODO
30//config:
31 27
32#include "volume_id_internal.h" 28#include "volume_id_internal.h"
33 29
diff --git a/util-linux/volume_id/unused_nvidia_raid.c b/util-linux/volume_id/unused_nvidia_raid.c
index d99a108f3..dfb54fa9d 100644
--- a/util-linux/volume_id/unused_nvidia_raid.c
+++ b/util-linux/volume_id/unused_nvidia_raid.c
@@ -20,14 +20,10 @@
20 20
21//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_NVIDIARAID) += nvidia_raid.o 21//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_NVIDIARAID) += nvidia_raid.o
22 22
23//config:
24//config:### config FEATURE_VOLUMEID_NVIDIARAID 23//config:### config FEATURE_VOLUMEID_NVIDIARAID
25//config:### bool "nvidia raid" 24//config:### bool "nvidia raid"
26//config:### default y 25//config:### default y
27//config:### depends on VOLUMEID 26//config:### depends on VOLUMEID
28//config:### help
29//config:### TODO
30//config:
31 27
32#include "volume_id_internal.h" 28#include "volume_id_internal.h"
33 29
diff --git a/util-linux/volume_id/unused_promise_raid.c b/util-linux/volume_id/unused_promise_raid.c
index cebebe35f..d594de39c 100644
--- a/util-linux/volume_id/unused_promise_raid.c
+++ b/util-linux/volume_id/unused_promise_raid.c
@@ -20,14 +20,10 @@
20 20
21//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_PROMISERAID) += promise_raid.o 21//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_PROMISERAID) += promise_raid.o
22 22
23//config:
24//config:### config FEATURE_VOLUMEID_PROMISERAID 23//config:### config FEATURE_VOLUMEID_PROMISERAID
25//config:### bool "promise raid" 24//config:### bool "promise raid"
26//config:### default y 25//config:### default y
27//config:### depends on VOLUMEID 26//config:### depends on VOLUMEID
28//config:### help
29//config:### TODO
30//config:
31 27
32#include "volume_id_internal.h" 28#include "volume_id_internal.h"
33 29
diff --git a/util-linux/volume_id/unused_silicon_raid.c b/util-linux/volume_id/unused_silicon_raid.c
index 40c8faa9e..886721b61 100644
--- a/util-linux/volume_id/unused_silicon_raid.c
+++ b/util-linux/volume_id/unused_silicon_raid.c
@@ -20,14 +20,10 @@
20 20
21//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_SILICONRAID) += silicon_raid.o 21//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_SILICONRAID) += silicon_raid.o
22 22
23//config:
24//config:### config FEATURE_VOLUMEID_SILICONRAID 23//config:### config FEATURE_VOLUMEID_SILICONRAID
25//config:### bool "silicon raid" 24//config:### bool "silicon raid"
26//config:### default y 25//config:### default y
27//config:### depends on VOLUMEID 26//config:### depends on VOLUMEID
28//config:### help
29//config:### TODO
30//config:
31 27
32#include "volume_id_internal.h" 28#include "volume_id_internal.h"
33 29
diff --git a/util-linux/volume_id/unused_ufs.c b/util-linux/volume_id/unused_ufs.c
index d33c10fc4..78ef26ad4 100644
--- a/util-linux/volume_id/unused_ufs.c
+++ b/util-linux/volume_id/unused_ufs.c
@@ -20,14 +20,10 @@
20 20
21//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_UFS) += ufs.o 21//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_UFS) += ufs.o
22 22
23//config:
24//config:### config FEATURE_VOLUMEID_UFS 23//config:### config FEATURE_VOLUMEID_UFS
25//config:### bool "ufs filesystem" 24//config:### bool "ufs filesystem"
26//config:### default y 25//config:### default y
27//config:### depends on VOLUMEID 26//config:### depends on VOLUMEID
28//config:### help
29//config:### TODO
30//config:
31 27
32#include "volume_id_internal.h" 28#include "volume_id_internal.h"
33 29
diff --git a/util-linux/volume_id/unused_via_raid.c b/util-linux/volume_id/unused_via_raid.c
index 258f93a4f..f82626655 100644
--- a/util-linux/volume_id/unused_via_raid.c
+++ b/util-linux/volume_id/unused_via_raid.c
@@ -20,14 +20,10 @@
20 20
21//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_VIARAID) += via_raid.o 21//kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_VIARAID) += via_raid.o
22 22
23//config:
24//config:### config FEATURE_VOLUMEID_VIARAID 23//config:### config FEATURE_VOLUMEID_VIARAID
25//config:### bool "via raid" 24//config:### bool "via raid"
26//config:### default y 25//config:### default y
27//config:### depends on VOLUMEID 26//config:### depends on VOLUMEID
28//config:### help
29//config:### TODO
30//config:
31 27
32#include "volume_id_internal.h" 28#include "volume_id_internal.h"
33 29
diff --git a/util-linux/volume_id/xfs.c b/util-linux/volume_id/xfs.c
index 5eefc201d..656d5bfcf 100644
--- a/util-linux/volume_id/xfs.c
+++ b/util-linux/volume_id/xfs.c
@@ -20,14 +20,10 @@
20 20
21//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_XFS) += xfs.o 21//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_XFS) += xfs.o
22 22
23//config:
24//config:config FEATURE_VOLUMEID_XFS 23//config:config FEATURE_VOLUMEID_XFS
25//config: bool "xfs filesystem" 24//config: bool "xfs filesystem"
26//config: default y 25//config: default y
27//config: depends on VOLUMEID 26//config: depends on VOLUMEID
28//config: help
29//config: TODO
30//config:
31 27
32#include "volume_id_internal.h" 28#include "volume_id_internal.h"
33 29