aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS3
-rw-r--r--archival/dpkg.c26
-rw-r--r--archival/libarchive/Kbuild.src8
-rw-r--r--archival/libarchive/decompress_bunzip2.c2
-rw-r--r--archival/libarchive/unxz/xz_dec_lzma2.c4
-rw-r--r--archival/tar.c4
-rw-r--r--archival/unzip.c2
-rw-r--r--console-tools/reset.c2
-rw-r--r--coreutils/cat.c156
-rw-r--r--coreutils/catv.c96
-rw-r--r--coreutils/cksum.c4
-rw-r--r--coreutils/dd.c8
-rw-r--r--coreutils/dos2unix.c2
-rw-r--r--coreutils/factor.c219
-rw-r--r--coreutils/ls.c14
-rw-r--r--coreutils/mktemp.c (renamed from debianutils/mktemp.c)0
-rw-r--r--coreutils/nl.c101
-rw-r--r--coreutils/nproc.c51
-rw-r--r--coreutils/paste.c140
-rw-r--r--coreutils/shred.c106
-rw-r--r--coreutils/timeout.c (renamed from miscutils/timeout.c)0
-rw-r--r--coreutils/uniq.c11
-rw-r--r--coreutils/who.c51
-rw-r--r--docs/posix_conformance.txt8
-rw-r--r--docs/sigint.htm10
-rw-r--r--docs/style-guide.txt2
-rw-r--r--editors/diff.c37
-rw-r--r--editors/sed.c8
-rw-r--r--editors/vi.c68
-rwxr-xr-xexamples/udhcp/sample.bound9
-rwxr-xr-xexamples/udhcp/sample.renew11
-rwxr-xr-xexamples/udhcp/simple.script10
-rwxr-xr-xexamples/var_service/dhcp_if/dhcp_handler2
-rw-r--r--findutils/find.c2
-rw-r--r--findutils/grep.c6
-rw-r--r--include/libbb.h51
-rw-r--r--init/init.c40
-rw-r--r--libbb/Kbuild.src1
-rw-r--r--libbb/bb_cat.c33
-rw-r--r--libbb/correct_password.c8
-rw-r--r--libbb/getopt32.c10
-rw-r--r--libbb/isqrt.c60
-rw-r--r--libbb/loop.c49
-rw-r--r--libbb/print_numbered_lines.c29
-rw-r--r--libbb/recursive_action.c46
-rw-r--r--libbb/securetty.c26
-rw-r--r--libbb/vfork_daemon_rexec.c28
-rw-r--r--libpwdgrp/pwd_grp.c4
-rw-r--r--loginutils/add-remove-shell.c20
-rw-r--r--loginutils/cryptpw.c2
-rw-r--r--loginutils/login.c21
-rw-r--r--loginutils/su.c27
-rw-r--r--mailutils/sendmail.c2
-rw-r--r--miscutils/inotifyd.c2
-rw-r--r--miscutils/less.c2
-rw-r--r--miscutils/lsscsi.c123
-rw-r--r--miscutils/partprobe.c56
-rw-r--r--miscutils/time.c49
-rw-r--r--modutils/Config.src2
-rw-r--r--modutils/modinfo.c2
-rw-r--r--modutils/modprobe-small.c41
-rw-r--r--modutils/modprobe.c23
-rw-r--r--networking/dnsd.c2
-rw-r--r--networking/ifenslave.c2
-rw-r--r--networking/ip.c66
-rw-r--r--networking/isrv.c2
-rw-r--r--networking/libiproute/ipaddress.c10
-rw-r--r--networking/libiproute/iplink.c300
-rw-r--r--networking/libiproute/iproute.c236
-rw-r--r--networking/libiproute/utils.c34
-rw-r--r--networking/libiproute/utils.h46
-rw-r--r--networking/nc.c33
-rw-r--r--networking/nc_bloaty.c59
-rw-r--r--networking/ntpd.c6
-rw-r--r--networking/ping.c4
-rw-r--r--networking/tcpudp.c2
-rw-r--r--networking/tls.c102
-rw-r--r--networking/tls_aes.c2104
-rw-r--r--networking/tls_pstm.c78
-rw-r--r--networking/tls_pstm.h18
-rw-r--r--networking/udhcp/common.h4
-rw-r--r--networking/udhcp/d6_common.h12
-rw-r--r--networking/udhcp/d6_dhcpc.c128
-rw-r--r--networking/udhcp/d6_packet.c4
-rw-r--r--networking/udhcp/d6_socket.c61
-rw-r--r--networking/udhcp/dhcpc.c32
-rw-r--r--networking/udhcp/dhcpd.c21
-rw-r--r--networking/udhcp/dhcprelay.c2
-rw-r--r--networking/udhcp/signalpipe.c23
-rw-r--r--networking/vconfig.c2
-rw-r--r--procps/kill.c10
-rw-r--r--runit/chpst.c13
-rw-r--r--runit/runsv.c95
-rw-r--r--runit/sv.c170
-rw-r--r--runit/svlogd.c13
-rw-r--r--shell/ash.c78
-rwxr-xr-xshell/ash_test/ash-misc/unicode1.tests2
-rw-r--r--shell/ash_test/ash-read/read_SIGCHLD.right2
-rwxr-xr-xshell/ash_test/ash-read/read_SIGCHLD.tests4
-rw-r--r--shell/hush.c17
-rwxr-xr-xshell/hush_test/hush-misc/unicode1.tests2
-rw-r--r--shell/hush_test/hush-read/read_SIGCHLD.right2
-rwxr-xr-xshell/hush_test/hush-read/read_SIGCHLD.tests4
-rw-r--r--shell/shell_common.c28
-rw-r--r--sysklogd/logread.c4
-rwxr-xr-xtestsuite/factor.tests48
-rw-r--r--testsuite/paste/paste20
-rw-r--r--testsuite/paste/paste-back-cuted-lines9
-rw-r--r--testsuite/paste/paste-multi-stdin16
-rw-r--r--testsuite/paste/paste-pairs16
-rw-r--r--testsuite/paste/paste-separate19
-rwxr-xr-xtestsuite/readlink.tests2
-rw-r--r--util-linux/cal.c (renamed from coreutils/cal.c)2
-rw-r--r--util-linux/chrt.c (renamed from miscutils/chrt.c)0
-rw-r--r--util-linux/eject.c (renamed from miscutils/eject.c)0
-rw-r--r--util-linux/fallocate.c104
-rw-r--r--util-linux/fsfreeze.c54
-rw-r--r--util-linux/getopt.c7
-rw-r--r--util-linux/hwclock.c2
-rw-r--r--util-linux/ionice.c (renamed from miscutils/ionice.c)0
-rw-r--r--util-linux/last.c (renamed from miscutils/last.c)0
-rw-r--r--util-linux/last_fancy.c (renamed from miscutils/last_fancy.c)0
-rw-r--r--util-linux/losetup.c27
-rw-r--r--util-linux/mesg.c (renamed from init/mesg.c)0
-rw-r--r--util-linux/mount.c21
-rw-r--r--util-linux/mountpoint.c (renamed from miscutils/mountpoint.c)0
-rw-r--r--util-linux/renice.c (renamed from procps/renice.c)2
-rw-r--r--util-linux/setsid.c (renamed from miscutils/setsid.c)0
-rw-r--r--util-linux/switch_root.c12
-rw-r--r--util-linux/taskset.c (renamed from miscutils/taskset.c)0
-rw-r--r--util-linux/umount.c24
-rw-r--r--util-linux/volume_id/udf.c2
-rw-r--r--util-linux/wall.c (renamed from miscutils/wall.c)0
133 files changed, 3349 insertions, 2815 deletions
diff --git a/AUTHORS b/AUTHORS
index fa58697f7..5c9a634c9 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -178,3 +178,6 @@ Mike Frysinger <vapier@gentoo.org>
178 178
179Jie Zhang <jie.zhang@analog.com> 179Jie Zhang <jie.zhang@analog.com>
180 fixed two bugs in msh and hush (exitcode of killed processes) 180 fixed two bugs in msh and hush (exitcode of killed processes)
181
182Maxime Coste <mawww@kakoune.org>
183 paste implementation
diff --git a/archival/dpkg.c b/archival/dpkg.c
index f133299e3..1cd45eda4 100644
--- a/archival/dpkg.c
+++ b/archival/dpkg.c
@@ -18,7 +18,7 @@
18 * known difference between busybox dpkg and the official dpkg that i don't 18 * known difference between busybox dpkg and the official dpkg that i don't
19 * consider important, its worth keeping a note of differences anyway, just to 19 * consider important, its worth keeping a note of differences anyway, just to
20 * make it easier to maintain. 20 * make it easier to maintain.
21 * - the first value for the confflile: field isnt placed on a new line. 21 * - the first value for the confflile: field isn't placed on a new line.
22 * - when installing a package the status: field is placed at the end of the 22 * - when installing a package the status: field is placed at the end of the
23 * section, rather than just after the package: field. 23 * section, rather than just after the package: field.
24 * 24 *
@@ -110,7 +110,7 @@ typedef struct common_node_s {
110 edge_t **edge; 110 edge_t **edge;
111} common_node_t; 111} common_node_t;
112 112
113/* Currently it doesnt store packages that have state-status of not-installed 113/* Currently it doesn't store packages that have state-status of not-installed
114 * So it only really has to be the size of the maximum number of packages 114 * So it only really has to be the size of the maximum number of packages
115 * likely to be installed at any one time, so there is a bit of leeway here */ 115 * likely to be installed at any one time, so there is a bit of leeway here */
116#define STATUS_HASH_PRIME 8191 116#define STATUS_HASH_PRIME 8191
@@ -205,7 +205,7 @@ static int search_name_hashtable(const char *key)
205 return probe_address; 205 return probe_address;
206} 206}
207 207
208/* this DOESNT add the key to the hashtable 208/* this DOESN'T add the key to the hashtable
209 * TODO make it consistent with search_name_hashtable 209 * TODO make it consistent with search_name_hashtable
210 */ 210 */
211static unsigned search_status_hashtable(const char *key) 211static unsigned search_status_hashtable(const char *key)
@@ -467,7 +467,7 @@ static void add_split_dependencies(common_node_t *parent_node, const char *whole
467 version = strchr(field2, '('); 467 version = strchr(field2, '(');
468 if (version == NULL) { 468 if (version == NULL) {
469 edge->operator = VER_ANY; 469 edge->operator = VER_ANY;
470 /* Get the versions hash number, adding it if the number isnt already in there */ 470 /* Get the versions hash number, adding it if the number isn't already in there */
471 edge->version = search_name_hashtable("ANY"); 471 edge->version = search_name_hashtable("ANY");
472 } else { 472 } else {
473 /* Skip leading ' ' or '(' */ 473 /* Skip leading ' ' or '(' */
@@ -496,7 +496,7 @@ static void add_split_dependencies(common_node_t *parent_node, const char *whole
496 496
497 /* Truncate version at trailing ' ' or ')' */ 497 /* Truncate version at trailing ' ' or ')' */
498 version[strcspn(version, " )")] = '\0'; 498 version[strcspn(version, " )")] = '\0';
499 /* Get the versions hash number, adding it if the number isnt already in there */ 499 /* Get the versions hash number, adding it if the number isn't already in there */
500 edge->version = search_name_hashtable(version); 500 edge->version = search_name_hashtable(version);
501 } 501 }
502 502
@@ -562,7 +562,7 @@ static int read_package_field(const char *package_buffer, char **field_name, cha
562 offset_name_end = offset; 562 offset_name_end = offset;
563 offset_value_start = next_offset; 563 offset_value_start = next_offset;
564 } 564 }
565 /* TODO: Name might still have trailing spaces if ':' isnt 565 /* TODO: Name might still have trailing spaces if ':' isn't
566 * immediately after name */ 566 * immediately after name */
567 break; 567 break;
568 case '\n': 568 case '\n':
@@ -776,7 +776,7 @@ static void index_status_file(const char *filename)
776 const unsigned package_num = fill_package_struct(control_buffer); 776 const unsigned package_num = fill_package_struct(control_buffer);
777 if (package_num != -1) { 777 if (package_num != -1) {
778 status_node = xmalloc(sizeof(status_node_t)); 778 status_node = xmalloc(sizeof(status_node_t));
779 /* fill_package_struct doesnt handle the status field */ 779 /* fill_package_struct doesn't handle the status field */
780 status_line = strstr(control_buffer, "Status:"); 780 status_line = strstr(control_buffer, "Status:");
781 if (status_line != NULL) { 781 if (status_line != NULL) {
782 status_line += 7; 782 status_line += 7;
@@ -850,7 +850,7 @@ static void write_status_file(deb_file_t **deb_file)
850 if (status_hashtable[status_num] != NULL) { 850 if (status_hashtable[status_num] != NULL) {
851 const char *status_from_hashtable = name_hashtable[status_hashtable[status_num]->status]; 851 const char *status_from_hashtable = name_hashtable[status_hashtable[status_num]->status];
852 if (strcmp(status_from_file, status_from_hashtable) != 0) { 852 if (strcmp(status_from_file, status_from_hashtable) != 0) {
853 /* New status isnt exactly the same as old status */ 853 /* New status isn't exactly the same as old status */
854 const int state_status = get_status(status_num, 3); 854 const int state_status = get_status(status_num, 3);
855 if ((strcmp("installed", name_hashtable[state_status]) == 0) 855 if ((strcmp("installed", name_hashtable[state_status]) == 0)
856 || (strcmp("unpacked", name_hashtable[state_status]) == 0) 856 || (strcmp("unpacked", name_hashtable[state_status]) == 0)
@@ -919,7 +919,7 @@ static void write_status_file(deb_file_t **deb_file)
919 } 919 }
920 } 920 }
921 } 921 }
922 /* If the package from the status file wasnt handle above, do it now*/ 922 /* If the package from the status file wasn't handle above, do it now*/
923 if (!write_flag) { 923 if (!write_flag) {
924 fprintf(new_status_file, "%s\n\n", control_buffer); 924 fprintf(new_status_file, "%s\n\n", control_buffer);
925 } 925 }
@@ -946,7 +946,7 @@ static void write_status_file(deb_file_t **deb_file)
946 if (errno != ENOENT) 946 if (errno != ENOENT)
947 bb_error_msg_and_die("can't create backup status file"); 947 bb_error_msg_and_die("can't create backup status file");
948 /* Its ok if renaming the status file fails because status 948 /* Its ok if renaming the status file fails because status
949 * file doesnt exist, maybe we are starting from scratch */ 949 * file doesn't exist, maybe we are starting from scratch */
950 bb_error_msg("no status file found, creating new one"); 950 bb_error_msg("no status file found, creating new one");
951 } 951 }
952 952
@@ -1061,7 +1061,7 @@ static int check_deps(deb_file_t **deb_file, int deb_start /*, int dep_max_count
1061 } 1061 }
1062 1062
1063 1063
1064 /* Check dependendcies */ 1064 /* Check dependentcies */
1065 for (i = 0; i < PACKAGE_HASH_PRIME; i++) { 1065 for (i = 0; i < PACKAGE_HASH_PRIME; i++) {
1066 int status_num = 0; 1066 int status_num = 0;
1067 int number_of_alternatives = 0; 1067 int number_of_alternatives = 0;
@@ -1244,7 +1244,7 @@ static void run_package_script_or_die(const char *package_name, const char *scri
1244 1244
1245 script_path = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, script_type); 1245 script_path = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, script_type);
1246 1246
1247 /* If the file doesnt exist is isnt fatal */ 1247 /* If the file doesn't exist it isn't fatal */
1248 result = access(script_path, F_OK) ? EXIT_SUCCESS : system(script_path); 1248 result = access(script_path, F_OK) ? EXIT_SUCCESS : system(script_path);
1249 free(script_path); 1249 free(script_path);
1250 if (result) 1250 if (result)
@@ -1839,7 +1839,7 @@ int dpkg_main(int argc UNUSED_PARAM, char **argv)
1839 ) { 1839 ) {
1840 status_node = xmalloc(sizeof(status_node_t)); 1840 status_node = xmalloc(sizeof(status_node_t));
1841 status_node->package = deb_file[deb_count]->package; 1841 status_node->package = deb_file[deb_count]->package;
1842 /* reinstreq isnt changed to "ok" until the package control info 1842 /* reinstreq isn't changed to "ok" until the package control info
1843 * is written to the status file*/ 1843 * is written to the status file*/
1844 status_node->status = search_name_hashtable("install reinstreq not-installed"); 1844 status_node->status = search_name_hashtable("install reinstreq not-installed");
1845 status_hashtable[status_num] = status_node; 1845 status_hashtable[status_num] = status_node;
diff --git a/archival/libarchive/Kbuild.src b/archival/libarchive/Kbuild.src
index eaf67451f..942e755b9 100644
--- a/archival/libarchive/Kbuild.src
+++ b/archival/libarchive/Kbuild.src
@@ -51,8 +51,8 @@ lib-$(CONFIG_LZOP) += lzo1x_1.o lzo1x_1o.o lzo1x_d.o
51lib-$(CONFIG_UNLZOP) += lzo1x_1.o lzo1x_1o.o lzo1x_d.o 51lib-$(CONFIG_UNLZOP) += lzo1x_1.o lzo1x_1o.o lzo1x_d.o
52lib-$(CONFIG_LZOPCAT) += lzo1x_1.o lzo1x_1o.o lzo1x_d.o 52lib-$(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 54# 'bzip2 -d', bunzip2 or bzcat selects FEATURE_BZIP2_DECOMPRESS
55lib-$(CONFIG_BZCAT) += open_transformer.o decompress_bunzip2.o 55lib-$(CONFIG_FEATURE_BZIP2_DECOMPRESS) += open_transformer.o decompress_bunzip2.o
56lib-$(CONFIG_FEATURE_UNZIP_BZIP2) += open_transformer.o decompress_bunzip2.o 56lib-$(CONFIG_FEATURE_UNZIP_BZIP2) += open_transformer.o decompress_bunzip2.o
57lib-$(CONFIG_UNLZMA) += open_transformer.o decompress_unlzma.o 57lib-$(CONFIG_UNLZMA) += open_transformer.o decompress_unlzma.o
58lib-$(CONFIG_LZCAT) += open_transformer.o decompress_unlzma.o 58lib-$(CONFIG_LZCAT) += open_transformer.o decompress_unlzma.o
@@ -62,8 +62,8 @@ lib-$(CONFIG_UNXZ) += open_transformer.o decompress_unxz.o
62lib-$(CONFIG_XZCAT) += open_transformer.o decompress_unxz.o 62lib-$(CONFIG_XZCAT) += open_transformer.o decompress_unxz.o
63lib-$(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 64lib-$(CONFIG_FEATURE_UNZIP_XZ) += open_transformer.o decompress_unxz.o
65lib-$(CONFIG_GUNZIP) += open_transformer.o decompress_gunzip.o 65# 'gzip -d', gunzip or zcat selects FEATURE_GZIP_DECOMPRESS
66lib-$(CONFIG_ZCAT) += open_transformer.o decompress_gunzip.o 66lib-$(CONFIG_FEATURE_GZIP_DECOMPRESS) += open_transformer.o decompress_gunzip.o
67lib-$(CONFIG_UNCOMPRESS) += open_transformer.o decompress_uncompress.o 67lib-$(CONFIG_UNCOMPRESS) += open_transformer.o decompress_uncompress.o
68lib-$(CONFIG_UNZIP) += open_transformer.o decompress_gunzip.o unsafe_prefix.o 68lib-$(CONFIG_UNZIP) += open_transformer.o decompress_gunzip.o unsafe_prefix.o
69lib-$(CONFIG_RPM2CPIO) += open_transformer.o decompress_gunzip.o get_header_cpio.o 69lib-$(CONFIG_RPM2CPIO) += open_transformer.o decompress_gunzip.o get_header_cpio.o
diff --git a/archival/libarchive/decompress_bunzip2.c b/archival/libarchive/decompress_bunzip2.c
index 4fb989c29..803702f75 100644
--- a/archival/libarchive/decompress_bunzip2.c
+++ b/archival/libarchive/decompress_bunzip2.c
@@ -308,7 +308,7 @@ static int get_next_block(bunzip_data *bd)
308 base = hufGroup->base - 1; 308 base = hufGroup->base - 1;
309 limit = hufGroup->limit - 1; 309 limit = hufGroup->limit - 1;
310 310
311 /* Calculate permute[]. Concurently, initialize temp[] and limit[]. */ 311 /* Calculate permute[]. Concurrently, initialize temp[] and limit[]. */
312 pp = 0; 312 pp = 0;
313 for (i = minLen; i <= maxLen; i++) { 313 for (i = minLen; i <= maxLen; i++) {
314 int k; 314 int k;
diff --git a/archival/libarchive/unxz/xz_dec_lzma2.c b/archival/libarchive/unxz/xz_dec_lzma2.c
index 351251f7c..bca41e705 100644
--- a/archival/libarchive/unxz/xz_dec_lzma2.c
+++ b/archival/libarchive/unxz/xz_dec_lzma2.c
@@ -486,11 +486,11 @@ static __always_inline void XZ_FUNC rc_normalize(struct rc_dec *rc)
486} 486}
487 487
488/* 488/*
489 * Decode one bit. In some versions, this function has been splitted in three 489 * Decode one bit. In some versions, this function has been split in three
490 * functions so that the compiler is supposed to be able to more easily avoid 490 * functions so that the compiler is supposed to be able to more easily avoid
491 * an extra branch. In this particular version of the LZMA decoder, this 491 * an extra branch. In this particular version of the LZMA decoder, this
492 * doesn't seem to be a good idea (tested with GCC 3.3.6, 3.4.6, and 4.3.3 492 * doesn't seem to be a good idea (tested with GCC 3.3.6, 3.4.6, and 4.3.3
493 * on x86). Using a non-splitted version results in nicer looking code too. 493 * on x86). Using a non-split version results in nicer looking code too.
494 * 494 *
495 * NOTE: This must return an int. Do not make it return a bool or the speed 495 * NOTE: This must return an int. Do not make it return a bool or the speed
496 * of the code generated by GCC 3.x decreases 10-15 %. (GCC 4.3 doesn't care, 496 * of the code generated by GCC 3.x decreases 10-15 %. (GCC 4.3 doesn't care,
diff --git a/archival/tar.c b/archival/tar.c
index 34e3052ce..be5838d0d 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -529,8 +529,8 @@ static int FAST_FUNC writeFileToTarball(const char *fileName, struct stat *statb
529 /* 529 /*
530 * Check to see if we are dealing with a hard link. 530 * Check to see if we are dealing with a hard link.
531 * If so - 531 * If so -
532 * Treat the first occurance of a given dev/inode as a file while 532 * Treat the first occurrence of a given dev/inode as a file while
533 * treating any additional occurances as hard links. This is done 533 * treating any additional occurrences as hard links. This is done
534 * by adding the file information to the HardLinkInfo linked list. 534 * by adding the file information to the HardLinkInfo linked list.
535 */ 535 */
536 tbInfo->hlInfo = NULL; 536 tbInfo->hlInfo = NULL;
diff --git a/archival/unzip.c b/archival/unzip.c
index 56989fa0b..986145d0f 100644
--- a/archival/unzip.c
+++ b/archival/unzip.c
@@ -242,7 +242,7 @@ static uint32_t find_cdf_offset(void)
242 end = 0; 242 end = 0;
243 243
244 dbg("Looking for cdf_offset starting from 0x%"OFF_FMT"x", end); 244 dbg("Looking for cdf_offset starting from 0x%"OFF_FMT"x", end);
245 xlseek(zip_fd, end, SEEK_SET); 245 xlseek(zip_fd, end, SEEK_SET);
246 buf = xzalloc(PEEK_FROM_END); 246 buf = xzalloc(PEEK_FROM_END);
247 full_read(zip_fd, buf, PEEK_FROM_END); 247 full_read(zip_fd, buf, PEEK_FROM_END);
248 248
diff --git a/console-tools/reset.c b/console-tools/reset.c
index 57cebb4ea..587c0d11a 100644
--- a/console-tools/reset.c
+++ b/console-tools/reset.c
@@ -56,6 +56,8 @@ int reset_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
56#if ENABLE_STTY 56#if ENABLE_STTY
57 return stty_main(2, (char**)args); 57 return stty_main(2, (char**)args);
58#else 58#else
59 /* Make sure stdout gets drained before we execvp */
60 fflush_all();
59 execvp("stty", (char**)args); 61 execvp("stty", (char**)args);
60#endif 62#endif
61 } 63 }
diff --git a/coreutils/cat.c b/coreutils/cat.c
index 65978887e..4d9147f8a 100644
--- a/coreutils/cat.c
+++ b/coreutils/cat.c
@@ -12,56 +12,168 @@
12//config: help 12//config: help
13//config: cat is used to concatenate files and print them to the standard 13//config: cat is used to concatenate files and print them to the standard
14//config: output. Enable this option if you wish to enable the 'cat' utility. 14//config: output. Enable this option if you wish to enable the 'cat' utility.
15//config:
16//config:config FEATURE_CATV
17//config: bool "cat -v[etA]"
18//config: default y
19//config: depends on CAT
20//config: help
21//config: Display nonprinting characters as escape sequences
15 22
16//applet:IF_CAT(APPLET_NOFORK(cat, cat, BB_DIR_BIN, BB_SUID_DROP, cat)) 23//applet:IF_CAT(APPLET(cat, BB_DIR_BIN, BB_SUID_DROP))
17 24
18//kbuild:lib-$(CONFIG_CAT) += cat.o 25//kbuild:lib-$(CONFIG_CAT) += cat.o
19 26
20/* BB_AUDIT SUSv3 compliant */ 27/* BB_AUDIT SUSv3 compliant */
21/* http://www.opengroup.org/onlinepubs/007904975/utilities/cat.html */ 28/* http://www.opengroup.org/onlinepubs/007904975/utilities/cat.html */
22 29
23//usage:#define cat_trivial_usage 30//usage:#define cat_trivial_usage
24//usage: "[FILE]..." 31//usage: "[-nb"IF_FEATURE_CATV("vteA")"] [FILE]..."
25//usage:#define cat_full_usage "\n\n" 32//usage:#define cat_full_usage "\n\n"
26//usage: "Concatenate FILEs and print them to stdout" 33//usage: "Print FILEs to stdout\n"
34//usage: "\n -n Number output lines"
35//usage: "\n -b Number nonempty lines"
36//usage: IF_FEATURE_CATV(
37//usage: "\n -v Show nonprinting characters as ^x or M-x"
38//usage: "\n -t ...and tabs as ^I"
39//usage: "\n -e ...and end lines with $"
40//usage: "\n -A Same as -vte"
41//usage: )
42/*
43 Longopts not implemented yet:
44 --number-nonblank number nonempty output lines, overrides -n
45 --number number all output lines
46 --show-nonprinting use ^ and M- notation, except for LFD and TAB
47 --show-all equivalent to -vet
48 Not implemented yet:
49 -E, --show-ends display $ at end of each line (-e sans -v)
50 -T, --show-tabs display TAB characters as ^I (-t sans -v)
51 -s, --squeeze-blank suppress repeated empty output lines
52*/
27//usage: 53//usage:
28//usage:#define cat_example_usage 54//usage:#define cat_example_usage
29//usage: "$ cat /proc/uptime\n" 55//usage: "$ cat /proc/uptime\n"
30//usage: "110716.72 17.67" 56//usage: "110716.72 17.67"
31 57
32#include "libbb.h" 58#include "libbb.h"
59#include "common_bufsiz.h"
33 60
34/* This is a NOFORK applet. Be very careful! */ 61#if ENABLE_FEATURE_CATV
35 62/*
36 63 * cat -v implementation for busybox
37int bb_cat(char **argv) 64 *
65 * Copyright (C) 2006 Rob Landley <rob@landley.net>
66 *
67 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
68 */
69/* Rob had "cat -v" implemented as a separate applet, catv.
70 * See "cat -v considered harmful" at
71 * http://cm.bell-labs.com/cm/cs/doc/84/kp.ps.gz
72 * From USENIX Summer Conference Proceedings, 1983
73 * """
74 * The talk reviews reasons for UNIX's popularity and shows, using UCB cat
75 * as a primary example, how UNIX has grown fat. cat isn't for printing
76 * files with line numbers, it isn't for compressing multiple blank lines,
77 * it's not for looking at non-printing ASCII characters, it's for
78 * concatenating files.
79 * We are reminded that ls isn't the place for code to break a single column
80 * into multiple ones, and that mailnews shouldn't have its own more
81 * processing or joke encryption code.
82 * """
83 *
84 * I agree with the argument. Unfortunately, this ship has sailed (1983...).
85 * There are dozens of Linux distros and each of them has "cat" which supports -v.
86 * It's unrealistic for us to "reeducate" them to use our, incompatible way
87 * to achieve "cat -v" effect. The actuall effect would be "users pissed off
88 * by gratuitous incompatibility".
89 */
90#define CATV_OPT_e (1<<0)
91#define CATV_OPT_t (1<<1)
92#define CATV_OPT_v (1<<2)
93static int catv(unsigned opts, char **argv)
38{ 94{
39 int fd;
40 int retval = EXIT_SUCCESS; 95 int retval = EXIT_SUCCESS;
96 int fd;
41 97
42 if (!*argv) 98 BUILD_BUG_ON(CATV_OPT_e != VISIBLE_ENDLINE);
43 argv = (char**) &bb_argv_dash; 99 BUILD_BUG_ON(CATV_OPT_t != VISIBLE_SHOW_TABS);
100#if 0 /* These consts match, we can just pass "opts" to visible() */
101 if (opts & CATV_OPT_e)
102 flags |= VISIBLE_ENDLINE;
103 if (opts & CATV_OPT_t)
104 flags |= VISIBLE_SHOW_TABS;
105#endif
106
107 /* Read from stdin if there's nothing else to do. */
108 if (!argv[0])
109 *--argv = (char*)"-";
44 110
111#define read_buf bb_common_bufsiz1
112 setup_common_bufsiz();
45 do { 113 do {
46 fd = open_or_warn_stdin(*argv); 114 fd = open_or_warn_stdin(*argv);
47 if (fd >= 0) { 115 if (fd < 0) {
48 /* This is not a xfunc - never exits */ 116 retval = EXIT_FAILURE;
49 off_t r = bb_copyfd_eof(fd, STDOUT_FILENO); 117 continue;
50 if (fd != STDIN_FILENO)
51 close(fd);
52 if (r >= 0)
53 continue;
54 } 118 }
55 retval = EXIT_FAILURE; 119 for (;;) {
120 int i, res;
121
122 res = read(fd, read_buf, COMMON_BUFSIZE);
123 if (res < 0)
124 retval = EXIT_FAILURE;
125 if (res <= 0)
126 break;
127 for (i = 0; i < res; i++) {
128 unsigned char c = read_buf[i];
129 char buf[sizeof("M-^c")];
130 visible(c, buf, opts);
131 fputs(buf, stdout);
132 }
133 }
134 if (ENABLE_FEATURE_CLEAN_UP && fd)
135 close(fd);
56 } while (*++argv); 136 } while (*++argv);
57 137
58 return retval; 138 fflush_stdout_and_exit(retval);
59} 139}
140#endif
60 141
61int cat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 142int cat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
62int cat_main(int argc UNUSED_PARAM, char **argv) 143int cat_main(int argc UNUSED_PARAM, char **argv)
63{ 144{
64 getopt32(argv, "u"); 145 struct number_state ns;
146 unsigned opts;
147
148 IF_FEATURE_CATV(opt_complementary = "Aetv"; /* -A == -vet */)
149 /* -u is ignored ("unbuffered") */
150 opts = getopt32(argv, IF_FEATURE_CATV("etvA")"nbu");
65 argv += optind; 151 argv += optind;
66 return bb_cat(argv); 152
153#if ENABLE_FEATURE_CATV
154 if (opts & 7)
155 return catv(opts, argv);
156//BUG: -v,-e,-t,-A ignore -nb
157 opts >>= 4;
158#endif
159
160#define CAT_OPT_n (1<<0)
161#define CAT_OPT_b (1<<1)
162#define CAT_OPT_u (1<<2)
163 if (!(opts & (CAT_OPT_n|CAT_OPT_b))) /* no -n or -b */
164 return bb_cat(argv);
165
166 if (!*argv)
167 *--argv = (char*)"-";
168 ns.width = 6;
169 ns.start = 1;
170 ns.inc = 1;
171 ns.sep = "\t";
172 ns.empty_str = "\n";
173 ns.all = !(opts & CAT_OPT_b); /* -n without -b */
174 ns.nonempty = (opts & CAT_OPT_b); /* -b (with or without -n) */
175 do {
176 print_numbered_lines(&ns, *argv);
177 } while (*++argv);
178 fflush_stdout_and_exit(EXIT_SUCCESS);
67} 179}
diff --git a/coreutils/catv.c b/coreutils/catv.c
deleted file mode 100644
index 1aeebe1d9..000000000
--- a/coreutils/catv.c
+++ /dev/null
@@ -1,96 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * cat -v implementation for busybox
4 *
5 * Copyright (C) 2006 Rob Landley <rob@landley.net>
6 *
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */
9
10/* See "Cat -v considered harmful" at
11 * http://cm.bell-labs.com/cm/cs/doc/84/kp.ps.gz */
12
13//config:config CATV
14//config: bool "catv"
15//config: default y
16//config: help
17//config: Display nonprinting characters as escape sequences (like some
18//config: implementations' cat -v option).
19
20//applet:IF_CATV(APPLET(catv, BB_DIR_BIN, BB_SUID_DROP))
21
22//kbuild:lib-$(CONFIG_CATV) += catv.o
23
24//usage:#define catv_trivial_usage
25//usage: "[-etv] [FILE]..."
26//usage:#define catv_full_usage "\n\n"
27//usage: "Display nonprinting characters as ^x or M-x\n"
28//usage: "\n -e End each line with $"
29//usage: "\n -t Show tabs as ^I"
30//usage: "\n -v Don't use ^x or M-x escapes"
31
32#include "libbb.h"
33#include "common_bufsiz.h"
34
35#define CATV_OPT_e (1<<0)
36#define CATV_OPT_t (1<<1)
37#define CATV_OPT_v (1<<2)
38struct BUG_const_mismatch {
39 char BUG_const_mismatch[
40 CATV_OPT_e == VISIBLE_ENDLINE && CATV_OPT_t == VISIBLE_SHOW_TABS
41 ? 1 : -1
42 ];
43};
44
45int catv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
46int catv_main(int argc UNUSED_PARAM, char **argv)
47{
48 int retval = EXIT_SUCCESS;
49 int fd;
50 unsigned opts;
51 opts = getopt32(argv, "etv");
52 argv += optind;
53#if 0 /* These consts match, we can just pass "opts" to visible() */
54 if (opts & CATV_OPT_e)
55 flags |= VISIBLE_ENDLINE;
56 if (opts & CATV_OPT_t)
57 flags |= VISIBLE_SHOW_TABS;
58#endif
59
60 /* Read from stdin if there's nothing else to do. */
61 if (!argv[0])
62 *--argv = (char*)"-";
63
64#define read_buf bb_common_bufsiz1
65 setup_common_bufsiz();
66 do {
67 fd = open_or_warn_stdin(*argv);
68 if (fd < 0) {
69 retval = EXIT_FAILURE;
70 continue;
71 }
72 for (;;) {
73 int i, res;
74
75 res = read(fd, read_buf, COMMON_BUFSIZE);
76 if (res < 0)
77 retval = EXIT_FAILURE;
78 if (res <= 0)
79 break;
80 for (i = 0; i < res; i++) {
81 unsigned char c = read_buf[i];
82 if (opts & CATV_OPT_v) {
83 putchar(c);
84 } else {
85 char buf[sizeof("M-^c")];
86 visible(c, buf, opts);
87 fputs(buf, stdout);
88 }
89 }
90 }
91 if (ENABLE_FEATURE_CLEAN_UP && fd)
92 close(fd);
93 } while (*++argv);
94
95 fflush_stdout_and_exit(retval);
96}
diff --git a/coreutils/cksum.c b/coreutils/cksum.c
index aeec0188d..9034fc19a 100644
--- a/coreutils/cksum.c
+++ b/coreutils/cksum.c
@@ -17,9 +17,9 @@
17//kbuild:lib-$(CONFIG_CKSUM) += cksum.o 17//kbuild:lib-$(CONFIG_CKSUM) += cksum.o
18 18
19//usage:#define cksum_trivial_usage 19//usage:#define cksum_trivial_usage
20//usage: "FILES..." 20//usage: "FILE..."
21//usage:#define cksum_full_usage "\n\n" 21//usage:#define cksum_full_usage "\n\n"
22//usage: "Calculate the CRC32 checksums of FILES" 22//usage: "Calculate the CRC32 checksums of FILEs"
23 23
24#include "libbb.h" 24#include "libbb.h"
25#include "common_bufsiz.h" 25#include "common_bufsiz.h"
diff --git a/coreutils/dd.c b/coreutils/dd.c
index 85152d8ce..2fccf9d8e 100644
--- a/coreutils/dd.c
+++ b/coreutils/dd.c
@@ -543,11 +543,11 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
543 if (write_and_stats(ibuf, n, obs, outfile)) 543 if (write_and_stats(ibuf, n, obs, outfile))
544 goto out_status; 544 goto out_status;
545 } 545 }
546 }
546 547
547 if (G.flags & FLAG_FSYNC) { 548 if (G.flags & FLAG_FSYNC) {
548 if (fsync(ofd) < 0) 549 if (fsync(ofd) < 0)
549 goto die_outfile; 550 goto die_outfile;
550 }
551 } 551 }
552 552
553 if (ENABLE_FEATURE_DD_IBS_OBS && oc) { 553 if (ENABLE_FEATURE_DD_IBS_OBS && oc) {
diff --git a/coreutils/dos2unix.c b/coreutils/dos2unix.c
index 6d2347163..9d81ccca6 100644
--- a/coreutils/dos2unix.c
+++ b/coreutils/dos2unix.c
@@ -2,7 +2,7 @@
2/* 2/*
3 * dos2unix for BusyBox 3 * dos2unix for BusyBox
4 * 4 *
5 * dos2unix '\n' convertor 0.5.0 5 * dos2unix '\n' converter 0.5.0
6 * based on Unix2Dos 0.9.0 by Peter Hanecak (made 19.2.1997) 6 * based on Unix2Dos 0.9.0 by Peter Hanecak (made 19.2.1997)
7 * Copyright 1997,.. by Peter Hanecak <hanecak@megaloman.sk>. 7 * Copyright 1997,.. by Peter Hanecak <hanecak@megaloman.sk>.
8 * All rights reserved. 8 * All rights reserved.
diff --git a/coreutils/factor.c b/coreutils/factor.c
new file mode 100644
index 000000000..205cdc053
--- /dev/null
+++ b/coreutils/factor.c
@@ -0,0 +1,219 @@
1/*
2 * Copyright (C) 2017 Denys Vlasenko <vda.linux@googlemail.com>
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6//config:config FACTOR
7//config: bool "factor"
8//config: default y
9//config: help
10//config: factor factorizes integers
11
12//applet:IF_FACTOR(APPLET(factor, BB_DIR_USR_BIN, BB_SUID_DROP))
13
14//kbuild:lib-$(CONFIG_FACTOR) += factor.o
15
16//usage:#define factor_trivial_usage
17//usage: "[NUMBER]..."
18//usage:#define factor_full_usage "\n\n"
19//usage: "Print prime factors"
20
21#include "libbb.h"
22
23#if 0
24# define dbg(...) bb_error_msg(__VA_ARGS__)
25#else
26# define dbg(...) ((void)0)
27#endif
28
29typedef unsigned long long wide_t;
30
31#if ULLONG_MAX == (UINT_MAX * UINT_MAX + 2 * UINT_MAX)
32/* "unsigned" is half as wide as ullong */
33typedef unsigned half_t;
34#define HALF_MAX UINT_MAX
35#define HALF_FMT ""
36#elif ULLONG_MAX == (ULONG_MAX * ULONG_MAX + 2 * ULONG_MAX)
37/* long is half as wide as ullong */
38typedef unsigned long half_t;
39#define HALF_MAX ULONG_MAX
40#define HALF_FMT "l"
41#else
42#error Cant find an integer type which is half as wide as ullong
43#endif
44
45static half_t isqrt_odd(wide_t N)
46{
47 half_t s = isqrt(N);
48 /* Subtract 1 from even s, odd s won't change: */
49 /* (doesnt work for zero, but we know that s != 0 here) */
50 s = (s - 1) | 1;
51 return s;
52}
53
54static NOINLINE void factorize(wide_t N)
55{
56 half_t factor;
57 half_t max_factor;
58 // unsigned count3;
59 // unsigned count5;
60 // unsigned count7;
61 // ^^^^^^^^^^^^^^^ commented-out simple sieving code (easier to grasp).
62 // Faster sieving, using one word for potentially up to 6 counters:
63 // count upwards in each mask, counter "triggers" when it sets its mask to "100[0]..."
64 // 10987654321098765432109876543210 - bits 31-0 in 32-bit word
65 // 17777713333311111777775555333 - bit masks for counters for primes 3,5,7,11,13,17
66 // 100000100001000010001001 - value for adding 1 to each mask
67 // 10000010000010000100001000100 - value for checking that any mask reached msb
68 enum {
69 SHIFT_3 = 1 << 0,
70 SHIFT_5 = 1 << 3,
71 SHIFT_7 = 1 << 7,
72 INCREMENT_EACH = SHIFT_3 | SHIFT_5 | SHIFT_7,
73 MULTIPLE_OF_3 = 1 << 2,
74 MULTIPLE_OF_5 = 1 << 6,
75 MULTIPLE_OF_7 = 1 << 11,
76 MULTIPLE_DETECTED = MULTIPLE_OF_3 | MULTIPLE_OF_5 | MULTIPLE_OF_7,
77 };
78 unsigned sieve_word;
79
80 if (N < 4)
81 goto end;
82
83 while (!(N & 1)) {
84 printf(" 2");
85 N >>= 1;
86 }
87
88 /* The code needs to be optimized for the case where
89 * there are large prime factors. For example,
90 * this is not hard:
91 * 8262075252869367027 = 3 7 17 23 47 101 113 127 131 137 823
92 * (the largest factor to test is only ~sqrt(823) = 28)
93 * but this is:
94 * 18446744073709551601 = 53 348051774975651917
95 * the last factor requires testing up to
96 * 589959129 - about 100 million iterations.
97 * The slowest case (largest prime) for N < 2^64 is
98 * factor 18446744073709551557 (0xffffffffffffffc5).
99 */
100 max_factor = isqrt_odd(N);
101 // count3 = 3;
102 // count5 = 6;
103 // count7 = 9;
104 sieve_word = 0
105 /* initial count for SHIFT_n is (n-1)/2*3: */
106 + (MULTIPLE_OF_3 - 3 * SHIFT_3)
107 + (MULTIPLE_OF_5 - 6 * SHIFT_5)
108 + (MULTIPLE_OF_7 - 9 * SHIFT_7)
109 //+ (MULTIPLE_OF_11 - 15 * SHIFT_11)
110 //+ (MULTIPLE_OF_13 - 18 * SHIFT_13)
111 //+ (MULTIPLE_OF_17 - 24 * SHIFT_17)
112 ;
113 factor = 3;
114 for (;;) {
115 /* The division is the most costly part of the loop.
116 * On 64bit CPUs, takes at best 12 cycles, often ~20.
117 */
118 while ((N % factor) == 0) { /* not likely */
119 N = N / factor;
120 printf(" %"HALF_FMT"u", factor);
121 max_factor = isqrt_odd(N);
122 }
123 next_factor:
124 if (factor >= max_factor)
125 break;
126 factor += 2;
127 /* Rudimentary wheel sieving: skip multiples of 3, 5 and 7:
128 * Every third odd number is divisible by three and thus isn't a prime:
129 * 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47...
130 * ^ ^ ^ ^ ^ ^ ^ _ ^ ^ _ ^ ^ ^ ^
131 * (^ = primes, _ = would-be-primes-if-not-divisible-by-5)
132 * The numbers with space under them are excluded by sieve 3.
133 */
134 // count7--;
135 // count5--;
136 // count3--;
137 // if (count3 && count5 && count7)
138 // continue;
139 sieve_word += INCREMENT_EACH;
140 if (!(sieve_word & MULTIPLE_DETECTED))
141 continue;
142 /*
143 * "factor" is multiple of 3 33% of the time (count3 reached 0),
144 * else, multiple of 5 13% of the time,
145 * else, multiple of 7 7.6% of the time.
146 * Cumulatively, with 3,5,7 sieving we are here 54.3% of the time.
147 */
148 // if (count3 == 0)
149 // count3 = 3;
150 if (sieve_word & MULTIPLE_OF_3)
151 sieve_word -= SHIFT_3 * 3;
152 // if (count5 == 0)
153 // count5 = 5;
154 if (sieve_word & MULTIPLE_OF_5)
155 sieve_word -= SHIFT_5 * 5;
156 // if (count7 == 0)
157 // count7 = 7;
158 if (sieve_word & MULTIPLE_OF_7)
159 sieve_word -= SHIFT_7 * 7;
160 goto next_factor;
161 }
162 end:
163 if (N > 1)
164 printf(" %llu", N);
165 bb_putchar('\n');
166}
167
168static void factorize_numstr(const char *numstr)
169{
170 wide_t N;
171
172 /* Leading + is ok (coreutils compat) */
173 if (*numstr == '+')
174 numstr++;
175 N = bb_strtoull(numstr, NULL, 10);
176 if (errno)
177 bb_show_usage();
178 printf("%llu:", N);
179 factorize(N);
180}
181
182int factor_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
183int factor_main(int argc UNUSED_PARAM, char **argv)
184{
185 //// coreutils has undocumented option ---debug (three dashes)
186 //getopt32(argv, "");
187 //argv += optind;
188 argv++;
189
190 if (!*argv) {
191 /* Read from stdin, several numbers per line are accepted */
192 for (;;) {
193 char *numstr, *line;
194 line = xmalloc_fgetline(stdin);
195 if (!line)
196 return EXIT_SUCCESS;
197 numstr = line;
198 for (;;) {
199 char *end;
200 numstr = skip_whitespace(numstr);
201 if (!numstr[0])
202 break;
203 end = skip_non_whitespace(numstr);
204 if (*end != '\0')
205 *end++ = '\0';
206 factorize_numstr(numstr);
207 numstr = end;
208 }
209 free(line);
210 }
211 }
212
213 do {
214 /* Leading spaces are ok (coreutils compat) */
215 factorize_numstr(skip_whitespace(*argv));
216 } while (*++argv);
217
218 return EXIT_SUCCESS;
219}
diff --git a/coreutils/ls.c b/coreutils/ls.c
index 6e0a52d75..6780057da 100644
--- a/coreutils/ls.c
+++ b/coreutils/ls.c
@@ -1067,17 +1067,19 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1067 * 'auto', 'tty', 'if-tty' 1067 * 'auto', 'tty', 'if-tty'
1068 * (and substrings: "--color=alwa" work too) 1068 * (and substrings: "--color=alwa" work too)
1069 */ 1069 */
1070 static const char ls_longopts[] ALIGN1 =
1071 "full-time\0" No_argument "\xff"
1072 "group-directories-first\0" No_argument "\xfe"
1073 "color\0" Optional_argument "\xfd"
1074 ;
1075 static const char color_str[] ALIGN1 = 1070 static const char color_str[] ALIGN1 =
1076 "always\0""yes\0""force\0" 1071 "always\0""yes\0""force\0"
1077 "auto\0""tty\0""if-tty\0"; 1072 "auto\0""tty\0""if-tty\0";
1078 /* need to initialize since --color has _an optional_ argument */ 1073 /* need to initialize since --color has _an optional_ argument */
1079 const char *color_opt = color_str; /* "always" */ 1074 const char *color_opt = color_str; /* "always" */
1080#endif 1075#endif
1076#if ENABLE_LONG_OPTS
1077 static const char ls_longopts[] ALIGN1 =
1078 "full-time\0" No_argument "\xff"
1079 "group-directories-first\0" No_argument "\xfe"
1080 "color\0" Optional_argument "\xfd"
1081 ;
1082#endif
1081 1083
1082 INIT_G(); 1084 INIT_G();
1083 1085
@@ -1091,7 +1093,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1091#endif 1093#endif
1092 1094
1093 /* process options */ 1095 /* process options */
1094 IF_FEATURE_LS_COLOR(applet_long_options = ls_longopts;) 1096 IF_LONG_OPTS(applet_long_options = ls_longopts;)
1095 opt_complementary = 1097 opt_complementary =
1096 /* -n and -g imply -l */ 1098 /* -n and -g imply -l */
1097 "nl:gl" 1099 "nl:gl"
diff --git a/debianutils/mktemp.c b/coreutils/mktemp.c
index 65353697a..65353697a 100644
--- a/debianutils/mktemp.c
+++ b/coreutils/mktemp.c
diff --git a/coreutils/nl.c b/coreutils/nl.c
new file mode 100644
index 000000000..5c64923bb
--- /dev/null
+++ b/coreutils/nl.c
@@ -0,0 +1,101 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Copyright (C) 2017 Denys Vlasenko <vda.linux@googlemail.com>
4 *
5 * Licensed under GPLv2, see file LICENSE in this source tree.
6 */
7//config:config NL
8//config: bool "nl"
9//config: default y
10//config: help
11//config: nl is used to number lines of files.
12
13//applet:IF_NL(APPLET(nl, BB_DIR_USR_BIN, BB_SUID_DROP))
14
15//kbuild:lib-$(CONFIG_NL) += nl.o
16
17//usage:#define nl_trivial_usage
18//usage: "[OPTIONS] [FILE]..."
19//usage:#define nl_full_usage "\n\n"
20//usage: "Write FILEs to standard output with line numbers added\n"
21//usage: "\n -b STYLE Which lines to number - a: all, t: nonempty, n: none"
22//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^TODO: support "pBRE": number only lines thatmatch regexp BRE"
23////usage: "\n -f STYLE footer lines"
24////usage: "\n -h STYLE header lines"
25////usage: "\n -d CC use CC for separating logical pages"
26//usage: "\n -i N Line number increment"
27////usage: "\n -l NUMBER group of NUMBER empty lines counted as one"
28////usage: "\n -n FORMAT lneft justified, no leading zeros; rn or rz"
29////usage: "\n -p do not reset line numbers at logical pages (huh?)"
30//usage: "\n -s STRING Use STRING as line number separator"
31//usage: "\n -v N Start from N"
32//usage: "\n -w N Width of line numbers"
33
34/* By default, selects -v1 -i1 -l1 -sTAB -w6 -nrn -hn -bt -fn */
35
36#include "libbb.h"
37
38void FAST_FUNC print_numbered_lines(struct number_state *ns, const char *filename)
39{
40 FILE *fp = fopen_or_warn_stdin(filename);
41 unsigned N = ns->start;
42 char *line;
43
44 while ((line = xmalloc_fgetline(fp)) != NULL) {
45 if (ns->all
46 || (ns->nonempty && line[0])
47 ) {
48 printf("%*u%s%s\n", ns->width, N, ns->sep, line);
49 N += ns->inc;
50 } else if (ns->empty_str)
51 fputs(ns->empty_str, stdout);
52 free(line);
53 }
54
55 fclose(fp);
56}
57
58int nl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
59int nl_main(int argc UNUSED_PARAM, char **argv)
60{
61 struct number_state ns;
62 const char *opt_b = "t";
63 enum {
64 OPT_p = (1 << 0),
65 };
66#if ENABLE_LONG_OPTS
67 static const char nl_longopts[] ALIGN1 =
68 "body-numbering\0" Required_argument "b"
69 // "footer-numbering\0" Required_argument "f" - not implemented yet
70 // "header-numbering\0" Required_argument "h" - not implemented yet
71 // "section-delimiter\0" Required_argument "d" - not implemented yet
72 "line-increment\0" Required_argument "i"
73 // "join-blank-lines\0" Required_argument "l" - not implemented yet
74 // "number-format\0" Required_argument "n" - not implemented yet
75 "no-renumber\0" No_argument "p" // no-op so far
76 "number-separator\0" Required_argument "s"
77 "starting-line-number\0"Required_argument "v"
78 "number-width\0" Required_argument "w"
79 ;
80
81 applet_long_options = nl_longopts;
82#endif
83 ns.width = 6;
84 ns.start = 1;
85 ns.inc = 1;
86 ns.sep = "\t";
87 getopt32(argv, "pw:+s:v:+i:+b:", &ns.width, &ns.sep, &ns.start, &ns.inc, &opt_b);
88 ns.all = (opt_b[0] == 'a');
89 ns.nonempty = (opt_b[0] == 't');
90 ns.empty_str = xasprintf("%*s\n", ns.width + (int)strlen(ns.sep), "");
91
92 argv += optind;
93 if (!*argv)
94 *--argv = (char*)"-";
95
96 do {
97 print_numbered_lines(&ns, *argv);
98 } while (*++argv);
99
100 fflush_stdout_and_exit(EXIT_SUCCESS);
101}
diff --git a/coreutils/nproc.c b/coreutils/nproc.c
new file mode 100644
index 000000000..d7c6a4ba1
--- /dev/null
+++ b/coreutils/nproc.c
@@ -0,0 +1,51 @@
1/*
2 * Copyright (C) 2017 Denys Vlasenko <vda.linux@googlemail.com>
3 *
4 * Licensed under GPLv2, see LICENSE in this source tree
5 */
6//config:config NPROC
7//config: bool "nproc"
8//config: default y
9//config: help
10//config: Print number of CPUs
11
12//applet:IF_NPROC(APPLET(nproc, BB_DIR_USR_BIN, BB_SUID_DROP))
13
14//kbuild:lib-$(CONFIG_NPROC) += nproc.o
15
16//usage:#define nproc_trivial_usage
17//usage: ""
18//TODO: "[--all] [--ignore=N]"
19//usage:#define nproc_full_usage "\n\n"
20//usage: "Print number of CPUs"
21
22#include <sched.h>
23#include "libbb.h"
24
25int nproc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
26int nproc_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
27{
28 unsigned long mask[1024];
29 unsigned i, count = 0;
30
31 //applet_long_options = ...;
32 //getopt32(argv, "");
33
34 //if --all, count /sys/devices/system/cpu/cpuN dirs, else:
35
36 if (sched_getaffinity(0, sizeof(mask), (void*)mask) == 0) {
37 for (i = 0; i < ARRAY_SIZE(mask); i++) {
38 unsigned long m = mask[i];
39 while (m) {
40 if (m & 1)
41 count++;
42 m >>= 1;
43 }
44 }
45 }
46 if (count == 0)
47 count++;
48 printf("%u\n", count);
49
50 return 0;
51}
diff --git a/coreutils/paste.c b/coreutils/paste.c
new file mode 100644
index 000000000..3920859d6
--- /dev/null
+++ b/coreutils/paste.c
@@ -0,0 +1,140 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * paste.c - implementation of the posix paste command
4 *
5 * Written by Maxime Coste <mawww@kakoune.org>
6 *
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */
9//config:config PASTE
10//config: bool "paste"
11//config: default y
12//config: help
13//config: paste is used to paste lines of different files together
14//config: and write the result to stdout
15
16//applet:IF_PASTE(APPLET_NOEXEC(paste, paste, BB_DIR_USR_BIN, BB_SUID_DROP, paste))
17
18//kbuild:lib-$(CONFIG_PASTE) += paste.o
19
20//usage:#define paste_trivial_usage
21//usage: "[OPTIONS] [FILE]..."
22//usage:#define paste_full_usage "\n\n"
23//usage: "Paste lines from each input file, separated with tab\n"
24//usage: "\n -d LIST Use delimiters from LIST, not tab"
25//usage: "\n -s Serial: one file at a time"
26//usage:
27//usage:#define paste_example_usage
28//usage: "# write out directory in four columns\n"
29//usage: "$ ls | paste - - - -\n"
30//usage: "# combine pairs of lines from a file into single lines\n"
31//usage: "$ paste -s -d '\\t\\n' file\n"
32
33#include "libbb.h"
34
35static void paste_files(FILE** files, int file_cnt, char* delims, int del_cnt)
36{
37 char *line;
38 char delim;
39 int active_files = file_cnt;
40 int i;
41
42 while (active_files > 0) {
43 int del_idx = 0;
44
45 for (i = 0; i < file_cnt; ++i) {
46 if (files[i] == NULL)
47 continue;
48
49 line = xmalloc_fgetline(files[i]);
50 if (!line) {
51 fclose_if_not_stdin(files[i]);
52 files[i] = NULL;
53 --active_files;
54 continue;
55 }
56 fputs(line, stdout);
57 free(line);
58 delim = '\n';
59 if (i != file_cnt - 1) {
60 delim = delims[del_idx++];
61 if (del_idx == del_cnt)
62 del_idx = 0;
63 }
64 if (delim != '\0')
65 fputc(delim, stdout);
66 }
67 }
68}
69
70static void paste_files_separate(FILE** files, char* delims, int del_cnt)
71{
72 char *line, *next_line;
73 char delim;
74 int i;
75
76 for (i = 0; files[i]; ++i) {
77 int del_idx = 0;
78
79 line = NULL;
80 while ((next_line = xmalloc_fgetline(files[i])) != NULL) {
81 if (line) {
82 fputs(line, stdout);
83 free(line);
84 delim = delims[del_idx++];
85 if (del_idx == del_cnt)
86 del_idx = 0;
87 if (delim != '\0')
88 fputc(delim, stdout);
89 }
90 line = next_line;
91 }
92 if (line) {
93 /* coreutils adds \n even if this is a final line
94 * of the last file and it was not \n-terminated.
95 */
96 printf("%s\n", line);
97 free(line);
98 }
99 fclose_if_not_stdin(files[i]);
100 }
101}
102
103#define PASTE_OPT_DELIMITERS (1 << 0)
104#define PASTE_OPT_SEPARATE (1 << 1)
105
106int paste_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
107int paste_main(int argc UNUSED_PARAM, char **argv)
108{
109 char *delims = (char*)"\t";
110 int del_cnt = 1;
111 unsigned opt;
112 int i;
113
114 opt = getopt32(argv, "d:s", &delims);
115 argv += optind;
116
117 if (opt & PASTE_OPT_DELIMITERS) {
118 if (!delims[0])
119 bb_error_msg_and_die("-d '' is not supported");
120 /* unknown mappings are not changed: "\z" -> '\\' 'z' */
121 /* trailing backslash, if any, is preserved */
122 del_cnt = strcpy_and_process_escape_sequences(delims, delims) - delims;
123 /* note: handle NUL properly (do not stop at it!): try -d'\t\0\t' */
124 }
125
126 if (!argv[0])
127 (--argv)[0] = (char*) "-";
128 for (i = 0; argv[i]; ++i) {
129 argv[i] = (void*) fopen_or_warn_stdin(argv[i]);
130 if (!argv[i])
131 xfunc_die();
132 }
133
134 if (opt & PASTE_OPT_SEPARATE)
135 paste_files_separate((FILE**)argv, delims, del_cnt);
136 else
137 paste_files((FILE**)argv, i, delims, del_cnt);
138
139 fflush_stdout_and_exit(0);
140}
diff --git a/coreutils/shred.c b/coreutils/shred.c
new file mode 100644
index 000000000..b3c009539
--- /dev/null
+++ b/coreutils/shred.c
@@ -0,0 +1,106 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Copyright (C) 2017 Denys Vlasenko <vda.linux@googlemail.com>
4 *
5 * Licensed under GPLv2, see file LICENSE in this source tree.
6 */
7//config:config SHRED
8//config: bool "shred"
9//config: default y
10//config: help
11//config: Overwrite a file to hide its contents, and optionally delete it
12
13//applet:IF_SHRED(APPLET(shred, BB_DIR_USR_BIN, BB_SUID_DROP))
14
15//kbuild:lib-$(CONFIG_SHRED) += shred.o
16
17//usage:#define shred_trivial_usage
18//usage: "FILE..."
19//usage:#define shred_full_usage "\n\n"
20//usage: "Overwrite/delete FILEs\n"
21//usage: "\n -f Chmod to ensure writability"
22//usage: "\n -n N Overwrite N times (default 3)"
23//usage: "\n -z Final overwrite with zeros"
24//usage: "\n -u Remove file"
25//-x and -v are accepted but have no effect
26
27/* shred (GNU coreutils) 8.25:
28-f, --force change permissions to allow writing if necessary
29-u truncate and remove file after overwriting
30-z, --zero add a final overwrite with zeros to hide shredding
31-n, --iterations=N overwrite N times instead of the default (3)
32-v, --verbose show progress
33-x, --exact do not round file sizes up to the next full block; this is the default for non-regular files
34--random-source=FILE get random bytes from FILE
35-s, --size=N shred this many bytes (suffixes like K, M, G accepted)
36--remove[=HOW] like -u but give control on HOW to delete; See below
37*/
38
39#include "libbb.h"
40
41int shred_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
42int shred_main(int argc UNUSED_PARAM, char **argv)
43{
44 int rand_fd = rand_fd; /* for compiler */
45 int zero_fd;
46 unsigned num_iter = 3;
47 unsigned opt;
48 enum {
49 OPT_f = (1 << 0),
50 OPT_u = (1 << 1),
51 OPT_z = (1 << 2),
52 OPT_n = (1 << 3),
53 OPT_v = (1 << 4),
54 OPT_x = (1 << 5),
55 };
56
57 opt = getopt32(argv, "fuzn:+vx", &num_iter);
58 argv += optind;
59
60 zero_fd = xopen("/dev/zero", O_RDONLY);
61 if (num_iter != 0)
62 rand_fd = xopen("/dev/urandom", O_RDONLY);
63
64 if (!*argv)
65 bb_show_usage();
66
67 for (;;) {
68 struct stat sb;
69 const char *fname;
70 unsigned i;
71 int fd;
72
73 fname = *argv++;
74 if (!fname)
75 break;
76 fd = -1;
77 if (opt & OPT_f) {
78 fd = open(fname, O_WRONLY);
79 if (fd < 0)
80 chmod(fname, 0666);
81 }
82 if (fd < 0)
83 fd = xopen(fname, O_WRONLY);
84
85 if (fstat(fd, &sb) == 0 && sb.st_size > 0) {
86 off_t size = sb.st_size;
87
88 for (i = 0; i < num_iter; i++) {
89 bb_copyfd_size(rand_fd, fd, size);
90 fdatasync(fd);
91 xlseek(fd, 0, SEEK_SET);
92 }
93 if (opt & OPT_z) {
94 bb_copyfd_size(zero_fd, fd, size);
95 fdatasync(fd);
96 }
97 if (opt & OPT_u) {
98 ftruncate(fd, 0);
99 xunlink(fname);
100 }
101 xclose(fd);
102 }
103 }
104
105 return EXIT_SUCCESS;
106}
diff --git a/miscutils/timeout.c b/coreutils/timeout.c
index f29dc8a9c..f29dc8a9c 100644
--- a/miscutils/timeout.c
+++ b/coreutils/timeout.c
diff --git a/coreutils/uniq.c b/coreutils/uniq.c
index be550b5cd..2b62ad3ae 100644
--- a/coreutils/uniq.c
+++ b/coreutils/uniq.c
@@ -26,6 +26,7 @@
26//usage: "\n -c Prefix lines by the number of occurrences" 26//usage: "\n -c Prefix lines by the number of occurrences"
27//usage: "\n -d Only print duplicate lines" 27//usage: "\n -d Only print duplicate lines"
28//usage: "\n -u Only print unique lines" 28//usage: "\n -u Only print unique lines"
29//usage: "\n -i Ignore case"
29//usage: "\n -f N Skip first N fields" 30//usage: "\n -f N Skip first N fields"
30//usage: "\n -s N Skip first N chars (after any skipped fields)" 31//usage: "\n -s N Skip first N chars (after any skipped fields)"
31//usage: "\n -w N Compare N characters in line" 32//usage: "\n -w N Compare N characters in line"
@@ -54,12 +55,13 @@ int uniq_main(int argc UNUSED_PARAM, char **argv)
54 OPT_f = 0x8, 55 OPT_f = 0x8,
55 OPT_s = 0x10, 56 OPT_s = 0x10,
56 OPT_w = 0x20, 57 OPT_w = 0x20,
58 OPT_i = 0x40,
57 }; 59 };
58 60
59 skip_fields = skip_chars = 0; 61 skip_fields = skip_chars = 0;
60 max_chars = INT_MAX; 62 max_chars = INT_MAX;
61 63
62 opt = getopt32(argv, "cduf:+s:+w:+", &skip_fields, &skip_chars, &max_chars); 64 opt = getopt32(argv, "cduf:+s:+w:+i", &skip_fields, &skip_chars, &max_chars);
63 argv += optind; 65 argv += optind;
64 66
65 input_filename = argv[0]; 67 input_filename = argv[0];
@@ -106,7 +108,12 @@ int uniq_main(int argc UNUSED_PARAM, char **argv)
106 ++cur_compare; 108 ++cur_compare;
107 } 109 }
108 110
109 if (!old_line || strncmp(old_compare, cur_compare, max_chars)) { 111 if (!old_line)
112 break;
113 if ((opt & OPT_i)
114 ? strncasecmp(old_compare, cur_compare, max_chars)
115 : strncmp(old_compare, cur_compare, max_chars)
116 ) {
110 break; 117 break;
111 } 118 }
112 119
diff --git a/coreutils/who.c b/coreutils/who.c
index e6179bb00..4adead77e 100644
--- a/coreutils/who.c
+++ b/coreutils/who.c
@@ -23,6 +23,14 @@
23//config: help 23//config: help
24//config: who is used to show who is logged on. 24//config: who is used to show who is logged on.
25//config: 25//config:
26// procps-ng has this variation of "who":
27//config:config W
28//config: bool "w"
29//config: default y
30//config: depends on FEATURE_UTMP
31//config: help
32//config: w is used to show who is logged on.
33//config:
26//config:config USERS 34//config:config USERS
27//config: bool "users" 35//config: bool "users"
28//config: default y 36//config: default y
@@ -32,10 +40,12 @@
32 40
33// APPLET_ODDNAME:name main location suid_type help 41// APPLET_ODDNAME:name main location suid_type help
34//applet:IF_USERS(APPLET_ODDNAME(users, who, BB_DIR_USR_BIN, BB_SUID_DROP, users)) 42//applet:IF_USERS(APPLET_ODDNAME(users, who, BB_DIR_USR_BIN, BB_SUID_DROP, users))
35//applet:IF_WHO(APPLET(who, BB_DIR_USR_BIN, BB_SUID_DROP)) 43//applet:IF_W( APPLET_ODDNAME(w, who, BB_DIR_USR_BIN, BB_SUID_DROP, w))
44//applet:IF_WHO( APPLET( who, BB_DIR_USR_BIN, BB_SUID_DROP))
36 45
37//kbuild:lib-$(CONFIG_USERS) += who.o 46//kbuild:lib-$(CONFIG_USERS) += who.o
38//kbuild:lib-$(CONFIG_WHO) += who.o 47//kbuild:lib-$(CONFIG_W) += who.o
48//kbuild:lib-$(CONFIG_WHO) += who.o
39 49
40/* BB_AUDIT SUSv3 _NOT_ compliant -- missing options -b, -d, -l, -m, -p, -q, -r, -s, -t, -T, -u; Missing argument 'file'. */ 50/* BB_AUDIT SUSv3 _NOT_ compliant -- missing options -b, -d, -l, -m, -p, -q, -r, -s, -t, -T, -u; Missing argument 'file'. */
41 51
@@ -44,6 +54,31 @@
44//usage:#define users_full_usage "\n\n" 54//usage:#define users_full_usage "\n\n"
45//usage: "Print the users currently logged on" 55//usage: "Print the users currently logged on"
46 56
57//usage:#define w_trivial_usage
58//usage: ""
59//usage:#define w_full_usage "\n\n"
60//usage: "Show who is logged on"
61//
62// procps-ng 3.3.10:
63// "\n -h, --no-header"
64// "\n -u, --no-current"
65// Ignores the username while figuring out the current process
66// and cpu times. To demonstrate this, do a "su" and do a "w" and a "w -u".
67// "\n -s, --short"
68// Short format. Don't print the login time, JCPU or PCPU times.
69// "\n -f, --from"
70// Toggle printing the from (remote hostname) field.
71// The default is for the from field to not be printed
72// "\n -i, --ip-addr"
73// Display IP address instead of hostname for from field.
74// "\n -o, --old-style"
75// Old style output. Prints blank space for idle times less than one minute.
76// Example output:
77// 17:28:00 up 4 days, 22:41, 4 users, load average: 0.84, 0.97, 0.90
78// USER TTY LOGIN@ IDLE JCPU PCPU WHAT
79// root tty1 Thu18 4days 4:33m 0.07s /bin/sh /etc/xdg/xfce4/xinitrc -- vt
80// root pts/1 Mon13 3:24m 1:01 0.01s w
81
47//usage:#define who_trivial_usage 82//usage:#define who_trivial_usage
48//usage: "[-a]" 83//usage: "[-a]"
49//usage:#define who_full_usage "\n\n" 84//usage:#define who_full_usage "\n\n"
@@ -74,14 +109,17 @@ static void idle_string(char *str6, time_t t)
74int who_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 109int who_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
75int who_main(int argc UNUSED_PARAM, char **argv) 110int who_main(int argc UNUSED_PARAM, char **argv)
76{ 111{
112#define CNT_APPLET (ENABLE_USERS + ENABLE_W + ENABLE_WHO)
113 int do_users = (ENABLE_USERS && (CNT_APPLET == 1 || applet_name[0] == 'u'));
114 int do_w = (ENABLE_W && (CNT_APPLET == 1 || applet_name[1] == '\0'));
115 int do_who = (ENABLE_WHO && (CNT_APPLET == 1 || applet_name[1] == 'h'));
77 struct utmpx *ut; 116 struct utmpx *ut;
78 unsigned opt; 117 unsigned opt;
79 int do_users = (ENABLE_USERS && (!ENABLE_WHO || applet_name[0] == 'u'));
80 const char *fmt = "%s"; 118 const char *fmt = "%s";
81 119
82 opt_complementary = "=0"; 120 opt_complementary = "=0";
83 opt = getopt32(argv, do_users ? "" : "aH"); 121 opt = getopt32(argv, do_who ? "aH" : "");
84 if (opt & 2) // -H 122 if ((opt & 2) || do_w) /* -H or we are w */
85 puts("USER\t\tTTY\t\tIDLE\tTIME\t\t HOST"); 123 puts("USER\t\tTTY\t\tIDLE\tTIME\t\t HOST");
86 124
87 setutxent(); 125 setutxent();
@@ -115,6 +153,9 @@ int who_main(int argc UNUSED_PARAM, char **argv)
115 (int)sizeof(ut->ut_user), ut->ut_user, 153 (int)sizeof(ut->ut_user), ut->ut_user,
116 (int)sizeof(ut->ut_line), ut->ut_line, 154 (int)sizeof(ut->ut_line), ut->ut_line,
117 str6, 155 str6,
156// TODO: with LANG=en_US.UTF-8, who from coreutils 8.25 shows
157// TIME col as "2017-04-06 18:47" (the default format is "Apr 6 18:47").
158// The former format looks saner to me. Switch to it unconditionally?
118 ctime(&seconds) + 4, 159 ctime(&seconds) + 4,
119 (int)sizeof(ut->ut_host), ut->ut_host 160 (int)sizeof(ut->ut_host), ut->ut_host
120 ); 161 );
diff --git a/docs/posix_conformance.txt b/docs/posix_conformance.txt
index c0582dc23..8b9112020 100644
--- a/docs/posix_conformance.txt
+++ b/docs/posix_conformance.txt
@@ -22,7 +22,7 @@ POSIX Tools supported only as shell built-ins (ash shell):
22POSIX Tools not supported: 22POSIX Tools not supported:
23 asa, at, batch, bc, c99, command, compress, csplit, ex, fc, file, 23 asa, at, batch, bc, c99, command, compress, csplit, ex, fc, file,
24 gencat, getconf, iconv, join, link, locale, localedef, lp, m4, 24 gencat, getconf, iconv, join, link, locale, localedef, lp, m4,
25 mailx, newgrp, nl, paste, pathchk, pax, pr, qalter, qdel, qhold, qmove, 25 mailx, newgrp, nl, pathchk, pax, pr, qalter, qdel, qhold, qmove,
26 qmsg, qrerun, qrls, qselect, qsig, qstat, qsub, tabs, talk, tput, 26 qmsg, qrerun, qrls, qselect, qsig, qstat, qsub, tabs, talk, tput,
27 tsort, unlink, uucp, uustat, uux 27 tsort, unlink, uucp, uustat, uux
28 28
@@ -469,6 +469,12 @@ od POSIX options
469 -x | no | no | 469 -x | no | no |
470od Busybox specific options: None 470od Busybox specific options: None
471 471
472paste POSIX options
473 option | exists | compliant | remarks
474 -d list | yes | yes |
475 -s | yes | yes |
476paste Busybox specific options: None
477
472patch POSIX options 478patch POSIX options
473 option | exists | compliant | remarks 479 option | exists | compliant | remarks
474 -D define | no | no | 480 -D define | no | no |
diff --git a/docs/sigint.htm b/docs/sigint.htm
index e230f4df7..d656aeb8c 100644
--- a/docs/sigint.htm
+++ b/docs/sigint.htm
@@ -45,7 +45,7 @@ intention.
45 45
46</td></tr><tr><th valign=top align=left>Required knowledge: </th> 46</td></tr><tr><th valign=top align=left>Required knowledge: </th>
47<td valign=top align=left>You have to know what it means to catch SIGINT or SIGQUIT and how 47<td valign=top align=left>You have to know what it means to catch SIGINT or SIGQUIT and how
48processes are waiting for other processes (childs) they spawned. 48processes are waiting for other processes (children) they spawned.
49 49
50 50
51</td></tr></table> 51</td></tr></table>
@@ -366,7 +366,7 @@ signal, it has to take care of communicating the signal status
366itself. 366itself.
367 367
368<p>Some programs don't do this. On SIGINT, they do cleanup and exit 368<p>Some programs don't do this. On SIGINT, they do cleanup and exit
369immediatly, but the calling shell isn't told about the non-normal exit 369immediately, but the calling shell isn't told about the non-normal exit
370and it will call the next program in the script. 370and it will call the next program in the script.
371 371
372<p>As a result, the user hits SIGINT and while one program exits, the 372<p>As a result, the user hits SIGINT and while one program exits, the
@@ -446,7 +446,7 @@ handlers, so it is portable.
446<code>trap</code> command. Here, the same as for C programs apply. If 446<code>trap</code> command. Here, the same as for C programs apply. If
447the intention of SIGINT is to end your program, you have to exit in a 447the intention of SIGINT is to end your program, you have to exit in a
448way that the calling programs "sees" that you have been killed. If 448way that the calling programs "sees" that you have been killed. If
449you don't catch SIGINT, this happend automatically, but of you catch 449you don't catch SIGINT, this happened automatically, but of you catch
450SIGINT, i.e. to do cleanup work, you have to end the program by 450SIGINT, i.e. to do cleanup work, you have to end the program by
451killing yourself, not by calling exit. 451killing yourself, not by calling exit.
452 452
@@ -466,7 +466,7 @@ files (which isn't really portable in C, though).
466bourne shell. Every language implementation that lets you catch SIGINT 466bourne shell. Every language implementation that lets you catch SIGINT
467should also give you the option to reset the signal and kill yourself. 467should also give you the option to reset the signal and kill yourself.
468 468
469<P>It is always desireable to exit the right way, even if you don't 469<P>It is always desirable to exit the right way, even if you don't
470expect your usual callers to depend on it, some unusual one will come 470expect your usual callers to depend on it, some unusual one will come
471along. This proper exit status will be needed for WCE and will not 471along. This proper exit status will be needed for WCE and will not
472hurt when the calling shell uses IUE or WUE. 472hurt when the calling shell uses IUE or WUE.
@@ -565,7 +565,7 @@ comments the scripts echo.
565<th>What happens when a shellscript called emacs, the user did not use 565<th>What happens when a shellscript called emacs, the user did not use
566<code>C-c</code> and the script has additional commands in it?</th> 566<code>C-c</code> and the script has additional commands in it?</th>
567<th>What happens if a non-interactive child catches SIGINT?</th> 567<th>What happens if a non-interactive child catches SIGINT?</th>
568<th>To behave properly, childs must do what?</th> 568<th>To behave properly, children must do what?</th>
569</tr> 569</tr>
570 570
571<tr valign=top align=left> 571<tr valign=top align=left>
diff --git a/docs/style-guide.txt b/docs/style-guide.txt
index 10ed893dc..9eed7f125 100644
--- a/docs/style-guide.txt
+++ b/docs/style-guide.txt
@@ -329,7 +329,7 @@ With "const int" compiler may fail to optimize it out and will reserve
329a real storage in rodata for it! (Hopefully, newer gcc will get better 329a real storage in rodata for it! (Hopefully, newer gcc will get better
330at it...). With "define", you have slight risk of polluting namespace 330at it...). With "define", you have slight risk of polluting namespace
331(#define doesn't allow you to redefine the name in the inner scopes), 331(#define doesn't allow you to redefine the name in the inner scopes),
332and complex "define" are evaluated each time they uesd, not once 332and complex "define" are evaluated each time they used, not once
333at declarations like enums. Also, the preprocessor does _no_ type checking 333at declarations like enums. Also, the preprocessor does _no_ type checking
334whatsoever, making it much more error prone. 334whatsoever, making it much more error prone.
335 335
diff --git a/editors/diff.c b/editors/diff.c
index f2eeb8257..975bc4603 100644
--- a/editors/diff.c
+++ b/editors/diff.c
@@ -295,17 +295,6 @@ static int search(const int *c, int k, int y, const struct cand *list)
295 } 295 }
296} 296}
297 297
298static unsigned isqrt(unsigned n)
299{
300 unsigned x = 1;
301 while (1) {
302 const unsigned y = x;
303 x = ((n / x) + x) >> 1;
304 if (x <= (y + 1) && x >= (y - 1))
305 return x;
306 }
307}
308
309static void stone(const int *a, int n, const int *b, int *J, int pref) 298static void stone(const int *a, int n, const int *b, int *J, int pref)
310{ 299{
311 const unsigned isq = isqrt(n); 300 const unsigned isq = isqrt(n);
@@ -730,9 +719,19 @@ static int diffreg(char *file[2])
730 fp[0] = stdin; 719 fp[0] = stdin;
731 fp[1] = stdin; 720 fp[1] = stdin;
732 for (i = 0; i < 2; i++) { 721 for (i = 0; i < 2; i++) {
733 int fd = open_or_warn_stdin(file[i]); 722 int fd = STDIN_FILENO;
734 if (fd == -1) 723 if (!LONE_DASH(file[i])) {
735 goto out; 724 if (!(option_mask32 & FLAG(N))) {
725 fd = open_or_warn(file[i], O_RDONLY);
726 if (fd == -1)
727 goto out;
728 } else {
729 /* -N: if some file does not exist compare it like empty */
730 fd = open(file[i], O_RDONLY);
731 if (fd == -1)
732 fd = xopen("/dev/null", O_RDONLY);
733 }
734 }
736 /* Our diff implementation is using seek. 735 /* Our diff implementation is using seek.
737 * When we meet non-seekable file, we must make a temp copy. 736 * When we meet non-seekable file, we must make a temp copy.
738 */ 737 */
@@ -1010,17 +1009,23 @@ int diff_main(int argc UNUSED_PARAM, char **argv)
1010 argv += optind; 1009 argv += optind;
1011 while (L_arg) 1010 while (L_arg)
1012 label[!!label[0]] = llist_pop(&L_arg); 1011 label[!!label[0]] = llist_pop(&L_arg);
1012
1013 /* Compat: "diff file name_which_doesnt_exist" exits with 2 */
1013 xfunc_error_retval = 2; 1014 xfunc_error_retval = 2;
1014 for (i = 0; i < 2; i++) { 1015 for (i = 0; i < 2; i++) {
1015 file[i] = argv[i]; 1016 file[i] = argv[i];
1016 /* Compat: "diff file name_which_doesnt_exist" exits with 2 */
1017 if (LONE_DASH(file[i])) { 1017 if (LONE_DASH(file[i])) {
1018 fstat(STDIN_FILENO, &stb[i]); 1018 fstat(STDIN_FILENO, &stb[i]);
1019 gotstdin++; 1019 gotstdin++;
1020 } else 1020 } else if (option_mask32 & FLAG(N)) {
1021 if (stat(file[i], &stb[i]))
1022 xstat("/dev/null", &stb[i]);
1023 } else {
1021 xstat(file[i], &stb[i]); 1024 xstat(file[i], &stb[i]);
1025 }
1022 } 1026 }
1023 xfunc_error_retval = 1; 1027 xfunc_error_retval = 1;
1028
1024 if (gotstdin && (S_ISDIR(stb[0].st_mode) || S_ISDIR(stb[1].st_mode))) 1029 if (gotstdin && (S_ISDIR(stb[0].st_mode) || S_ISDIR(stb[1].st_mode)))
1025 bb_error_msg_and_die("can't compare stdin to a directory"); 1030 bb_error_msg_and_die("can't compare stdin to a directory");
1026 1031
diff --git a/editors/sed.c b/editors/sed.c
index 86230ea42..b2c7ba829 100644
--- a/editors/sed.c
+++ b/editors/sed.c
@@ -337,7 +337,7 @@ static int get_address(const char *my_str, int *linenum, regex_t ** regex)
337 337
338 if (isdigit(*my_str)) { 338 if (isdigit(*my_str)) {
339 *linenum = strtol(my_str, (char**)&pos, 10); 339 *linenum = strtol(my_str, (char**)&pos, 10);
340 /* endstr shouldnt ever equal NULL */ 340 /* endstr shouldn't ever equal NULL */
341 } else if (*my_str == '$') { 341 } else if (*my_str == '$') {
342 *linenum = -1; 342 *linenum = -1;
343 pos++; 343 pos++;
@@ -444,7 +444,7 @@ static int parse_subst_cmd(sed_cmd_t *sed_cmd, const char *substr)
444 free(fname); 444 free(fname);
445 break; 445 break;
446 } 446 }
447 /* Ignore case (gnu exension) */ 447 /* Ignore case (gnu extension) */
448 case 'i': 448 case 'i':
449 case 'I': 449 case 'I':
450 cflags |= REG_ICASE; 450 cflags |= REG_ICASE;
@@ -587,7 +587,7 @@ static const char *parse_cmd_args(sed_cmd_t *sed_cmd, const char *cmdstr)
587 free(match); 587 free(match);
588 free(replace); 588 free(replace);
589 } 589 }
590 /* if it wasnt a single-letter command that takes no arguments 590 /* if it wasn't a single-letter command that takes no arguments
591 * then it must be an invalid command. 591 * then it must be an invalid command.
592 */ 592 */
593 else if (idx >= IDX_nul) { /* not d,D,g,G,h,H,l,n,N,p,P,q,x,=,{,} */ 593 else if (idx >= IDX_nul) { /* not d,D,g,G,h,H,l,n,N,p,P,q,x,=,{,} */
@@ -751,7 +751,7 @@ static void do_subst_w_backrefs(char *line, char *replace)
751 continue; 751 continue;
752 } 752 }
753 /* I _think_ it is impossible to get '\' to be 753 /* I _think_ it is impossible to get '\' to be
754 * the last char in replace string. Thus we dont check 754 * the last char in replace string. Thus we don't check
755 * for replace[i] == NUL. (counterexample anyone?) */ 755 * for replace[i] == NUL. (counterexample anyone?) */
756 /* if we find a backslash escaped character, print the character */ 756 /* if we find a backslash escaped character, print the character */
757 pipe_putc(replace[i]); 757 pipe_putc(replace[i]);
diff --git a/editors/vi.c b/editors/vi.c
index e5ca3adfa..900b41cb5 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -715,14 +715,6 @@ static int init_text_buffer(char *fn)
715{ 715{
716 int rc; 716 int rc;
717 717
718 flush_undo_data();
719 modified_count = 0;
720 last_modified_count = -1;
721#if ENABLE_FEATURE_VI_YANKMARK
722 /* init the marks */
723 memset(mark, 0, sizeof(mark));
724#endif
725
726 /* allocate/reallocate text buffer */ 718 /* allocate/reallocate text buffer */
727 free(text); 719 free(text);
728 text_size = 10240; 720 text_size = 10240;
@@ -737,6 +729,14 @@ static int init_text_buffer(char *fn)
737 // file doesnt exist. Start empty buf with dummy line 729 // file doesnt exist. Start empty buf with dummy line
738 char_insert(text, '\n', NO_UNDO); 730 char_insert(text, '\n', NO_UNDO);
739 } 731 }
732
733 flush_undo_data();
734 modified_count = 0;
735 last_modified_count = -1;
736#if ENABLE_FEATURE_VI_YANKMARK
737 /* init the marks */
738 memset(mark, 0, sizeof(mark));
739#endif
740 return rc; 740 return rc;
741} 741}
742 742
@@ -1034,7 +1034,9 @@ static void colon(char *buf)
1034 || strncmp(p, "wn", cnt) == 0 1034 || strncmp(p, "wn", cnt) == 0
1035 || (p[0] == 'x' && !p[1]) 1035 || (p[0] == 'x' && !p[1])
1036 ) { 1036 ) {
1037 cnt = file_write(current_filename, text, end - 1); 1037 if (modified_count != 0 || p[0] != 'x') {
1038 cnt = file_write(current_filename, text, end - 1);
1039 }
1038 if (cnt < 0) { 1040 if (cnt < 0) {
1039 if (cnt == -1) 1041 if (cnt == -1)
1040 status_line_bold("Write error: %s", strerror(errno)); 1042 status_line_bold("Write error: %s", strerror(errno));
@@ -1045,8 +1047,9 @@ static void colon(char *buf)
1045 current_filename, 1047 current_filename,
1046 count_lines(text, end - 1), cnt 1048 count_lines(text, end - 1), cnt
1047 ); 1049 );
1048 if (p[0] == 'x' || p[1] == 'q' || p[1] == 'n' 1050 if (p[0] == 'x'
1049 || p[0] == 'X' || p[1] == 'Q' || p[1] == 'N' 1051 || p[1] == 'q' || p[1] == 'n'
1052 || p[1] == 'Q' || p[1] == 'N'
1050 ) { 1053 ) {
1051 editing = 0; 1054 editing = 0;
1052 } 1055 }
@@ -1476,16 +1479,19 @@ static void colon(char *buf)
1476 goto ret; 1479 goto ret;
1477 } 1480 }
1478#endif 1481#endif
1479 // how many lines in text[]?
1480 li = count_lines(q, r);
1481 size = r - q + 1;
1482 //if (useforce) { 1482 //if (useforce) {
1483 // if "fn" is not write-able, chmod u+w 1483 // if "fn" is not write-able, chmod u+w
1484 // sprintf(syscmd, "chmod u+w %s", fn); 1484 // sprintf(syscmd, "chmod u+w %s", fn);
1485 // system(syscmd); 1485 // system(syscmd);
1486 // forced = TRUE; 1486 // forced = TRUE;
1487 //} 1487 //}
1488 l = file_write(fn, q, r); 1488 if (modified_count != 0 || cmd[0] != 'x') {
1489 size = r - q + 1;
1490 l = file_write(fn, q, r);
1491 } else {
1492 size = 0;
1493 l = 0;
1494 }
1489 //if (useforce && forced) { 1495 //if (useforce && forced) {
1490 // chmod u-w 1496 // chmod u-w
1491 // sprintf(syscmd, "chmod u-w %s", fn); 1497 // sprintf(syscmd, "chmod u-w %s", fn);
@@ -1496,17 +1502,20 @@ static void colon(char *buf)
1496 if (l == -1) 1502 if (l == -1)
1497 status_line_bold_errno(fn); 1503 status_line_bold_errno(fn);
1498 } else { 1504 } else {
1505 // how many lines written
1506 li = count_lines(q, q + l - 1);
1499 status_line("'%s' %dL, %dC", fn, li, l); 1507 status_line("'%s' %dL, %dC", fn, li, l);
1500 if (q == text && r == end - 1 && l == size) { 1508 if (l == size) {
1501 modified_count = 0; 1509 if (q == text && q + l == end) {
1502 last_modified_count = -1; 1510 modified_count = 0;
1503 } 1511 last_modified_count = -1;
1504 if ((cmd[0] == 'x' || cmd[1] == 'q' || cmd[1] == 'n' 1512 }
1505 || cmd[0] == 'X' || cmd[1] == 'Q' || cmd[1] == 'N' 1513 if (cmd[0] == 'x'
1506 ) 1514 || cmd[1] == 'q' || cmd[1] == 'n'
1507 && l == size 1515 || cmd[1] == 'Q' || cmd[1] == 'N'
1508 ) { 1516 ) {
1509 editing = 0; 1517 editing = 0;
1518 }
1510 } 1519 }
1511 } 1520 }
1512#if ENABLE_FEATURE_VI_YANKMARK 1521#if ENABLE_FEATURE_VI_YANKMARK
@@ -2816,8 +2825,15 @@ static int readit(void) // read (maybe cursor) key from stdin
2816 int c; 2825 int c;
2817 2826
2818 fflush_all(); 2827 fflush_all();
2819 c = read_key(STDIN_FILENO, readbuffer, /*timeout off:*/ -2); 2828
2829 // Wait for input. TIMEOUT = -1 makes read_key wait even
2830 // on nonblocking stdin.
2831 // Note: read_key sets errno to 0 on success.
2832 again:
2833 c = read_key(STDIN_FILENO, readbuffer, /*timeout:*/ -1);
2820 if (c == -1) { // EOF/error 2834 if (c == -1) { // EOF/error
2835 if (errno == EAGAIN) // paranoia
2836 goto again;
2821 go_bottom_and_clear_to_eol(); 2837 go_bottom_and_clear_to_eol();
2822 cookmode(); // terminal to "cooked" 2838 cookmode(); // terminal to "cooked"
2823 bb_error_msg_and_die("can't read user input"); 2839 bb_error_msg_and_die("can't read user input");
diff --git a/examples/udhcp/sample.bound b/examples/udhcp/sample.bound
index 7c9d857e0..efd98cf15 100755
--- a/examples/udhcp/sample.bound
+++ b/examples/udhcp/sample.bound
@@ -18,11 +18,18 @@ then
18 metric=0 18 metric=0
19 for i in $router 19 for i in $router
20 do 20 do
21 if [ "$subnet" = "255.255.255.255" ]; then
22 # special case for /32 subnets:
23 # /32 instructs kernel to always use routing for all outgoing packets
24 # (they can never be sent to local subnet - there is no local subnet for /32).
25 # Used in datacenters, avoids the need for private ip-addresses between two hops.
26 /sbin/ip route add $i dev $interface
27 fi
21 /sbin/route add default gw $i dev $interface metric $((metric++)) 28 /sbin/route add default gw $i dev $interface metric $((metric++))
22 done 29 done
23fi 30fi
24 31
25# Only replace resolv.conf is we have at least one DNS server 32# Only replace resolv.conf if we have at least one DNS server
26if [ -n "$dns" ] 33if [ -n "$dns" ]
27then 34then
28 echo -n > $RESOLV_CONF 35 echo -n > $RESOLV_CONF
diff --git a/examples/udhcp/sample.renew b/examples/udhcp/sample.renew
index 4dce8486a..efd98cf15 100755
--- a/examples/udhcp/sample.renew
+++ b/examples/udhcp/sample.renew
@@ -1,5 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# Sample udhcpc bound script 2# Sample udhcpc renew script
3 3
4RESOLV_CONF="/etc/udhcpc/resolv.conf" 4RESOLV_CONF="/etc/udhcpc/resolv.conf"
5 5
@@ -18,11 +18,18 @@ then
18 metric=0 18 metric=0
19 for i in $router 19 for i in $router
20 do 20 do
21 if [ "$subnet" = "255.255.255.255" ]; then
22 # special case for /32 subnets:
23 # /32 instructs kernel to always use routing for all outgoing packets
24 # (they can never be sent to local subnet - there is no local subnet for /32).
25 # Used in datacenters, avoids the need for private ip-addresses between two hops.
26 /sbin/ip route add $i dev $interface
27 fi
21 /sbin/route add default gw $i dev $interface metric $((metric++)) 28 /sbin/route add default gw $i dev $interface metric $((metric++))
22 done 29 done
23fi 30fi
24 31
25# Only replace resolv.conf is we have at least one DNS server 32# Only replace resolv.conf if we have at least one DNS server
26if [ -n "$dns" ] 33if [ -n "$dns" ]
27then 34then
28 echo -n > $RESOLV_CONF 35 echo -n > $RESOLV_CONF
diff --git a/examples/udhcp/simple.script b/examples/udhcp/simple.script
index 2a917eb6c..e4c1f2d76 100755
--- a/examples/udhcp/simple.script
+++ b/examples/udhcp/simple.script
@@ -29,8 +29,14 @@ case "$1" in
29 metric=0 29 metric=0
30 for i in $router ; do 30 for i in $router ; do
31 echo "Adding router $i" 31 echo "Adding router $i"
32 route add default gw $i dev $interface metric $metric 32 if [ "$subnet" = "255.255.255.255" ]; then
33 : $(( metric += 1 )) 33 # special case for /32 subnets:
34 # /32 instructs kernel to always use routing for all outgoing packets
35 # (they can never be sent to local subnet - there is no local subnet for /32).
36 # Used in datacenters, avoids the need for private ip-addresses between two hops.
37 ip route add $i dev $interface
38 fi
39 route add default gw $i dev $interface metric $((metric++))
34 done 40 done
35 fi 41 fi
36 42
diff --git a/examples/var_service/dhcp_if/dhcp_handler b/examples/var_service/dhcp_if/dhcp_handler
index 3d2a5cb79..3d44a6022 100755
--- a/examples/var_service/dhcp_if/dhcp_handler
+++ b/examples/var_service/dhcp_if/dhcp_handler
@@ -21,7 +21,7 @@
21# ntpsrv=10.34.32.125 10.34.255.7 21# ntpsrv=10.34.32.125 10.34.255.7
22# 22#
23# renew: lease is renewed. Environment is similar to "bound". 23# renew: lease is renewed. Environment is similar to "bound".
24# The IP address does not change, however, the other DHCP paramaters, 24# The IP address does not change, however, the other DHCP parameters,
25# such as the default gateway, subnet mask, and dns server may change. 25# such as the default gateway, subnet mask, and dns server may change.
26# 26#
27# nak: udhcpc received a NAK message. 27# nak: udhcpc received a NAK message.
diff --git a/findutils/find.c b/findutils/find.c
index 67aa40b21..0596c0059 100644
--- a/findutils/find.c
+++ b/findutils/find.c
@@ -182,7 +182,7 @@
182//config: default y 182//config: default y
183//config: depends on FIND 183//config: depends on FIND
184//config: help 184//config: help
185//config: If the file is a directory, dont descend into it. Useful for 185//config: If the file is a directory, don't descend into it. Useful for
186//config: exclusion .svn and CVS directories. 186//config: exclusion .svn and CVS directories.
187//config: 187//config:
188//config:config FEATURE_FIND_DELETE 188//config:config FEATURE_FIND_DELETE
diff --git a/findutils/grep.c b/findutils/grep.c
index 8b6e29874..b115d9a1d 100644
--- a/findutils/grep.c
+++ b/findutils/grep.c
@@ -39,7 +39,7 @@
39//config:config FEATURE_GREP_CONTEXT 39//config:config FEATURE_GREP_CONTEXT
40//config: bool "Enable before and after context flags (-A, -B and -C)" 40//config: bool "Enable before and after context flags (-A, -B and -C)"
41//config: default y 41//config: default y
42//config: depends on GREP || EGREP 42//config: depends on GREP || EGREP || FGREP
43//config: help 43//config: help
44//config: Print the specified number of leading (-B) and/or trailing (-A) 44//config: Print the specified number of leading (-B) and/or trailing (-A)
45//config: context surrounding our matching lines. 45//config: context surrounding our matching lines.
@@ -523,7 +523,7 @@ static int grep_file(FILE *file)
523 if (option_mask32 & OPT_o) { 523 if (option_mask32 & OPT_o) {
524 if (FGREP_FLAG) { 524 if (FGREP_FLAG) {
525 /* -Fo just prints the pattern 525 /* -Fo just prints the pattern
526 * (unless -v: -Fov doesnt print anything at all) */ 526 * (unless -v: -Fov doesn't print anything at all) */
527 if (found) 527 if (found)
528 print_line(gl->pattern, strlen(gl->pattern), linenum, ':'); 528 print_line(gl->pattern, strlen(gl->pattern), linenum, ':');
529 } else while (1) { 529 } else while (1) {
@@ -831,7 +831,7 @@ int grep_main(int argc UNUSED_PARAM, char **argv)
831 grep_done: ; 831 grep_done: ;
832 } while (*argv && *++argv); 832 } while (*argv && *++argv);
833 833
834 /* destroy all the elments in the pattern list */ 834 /* destroy all the elements in the pattern list */
835 if (ENABLE_FEATURE_CLEAN_UP) { 835 if (ENABLE_FEATURE_CLEAN_UP) {
836 while (pattern_head) { 836 while (pattern_head) {
837 llist_t *pattern_head_ptr = pattern_head; 837 llist_t *pattern_head_ptr = pattern_head;
diff --git a/include/libbb.h b/include/libbb.h
index 1f5b211c1..9313a557a 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -353,6 +353,8 @@ extern int *const bb_errno;
353uint64_t bb_bswap_64(uint64_t x) FAST_FUNC; 353uint64_t bb_bswap_64(uint64_t x) FAST_FUNC;
354#endif 354#endif
355 355
356unsigned long FAST_FUNC isqrt(unsigned long long N);
357
356unsigned long long monotonic_ns(void) FAST_FUNC; 358unsigned long long monotonic_ns(void) FAST_FUNC;
357unsigned long long monotonic_us(void) FAST_FUNC; 359unsigned long long monotonic_us(void) FAST_FUNC;
358unsigned long long monotonic_ms(void) FAST_FUNC; 360unsigned long long monotonic_ms(void) FAST_FUNC;
@@ -1193,6 +1195,26 @@ extern const char *applet_long_options;
1193#endif 1195#endif
1194extern uint32_t option_mask32; 1196extern uint32_t option_mask32;
1195extern uint32_t getopt32(char **argv, const char *applet_opts, ...) FAST_FUNC; 1197extern uint32_t getopt32(char **argv, const char *applet_opts, ...) FAST_FUNC;
1198/* BSD-derived getopt() functions require that optind be set to 1 in
1199 * order to reset getopt() state. This used to be generally accepted
1200 * way of resetting getopt(). However, glibc's getopt()
1201 * has additional getopt() state beyond optind (specifically, glibc
1202 * extensions such as '+' and '-' at the start of the string), and requires
1203 * that optind be set to zero to reset its state. BSD-derived versions
1204 * of getopt() misbehaved if optind is set to 0 in order to reset getopt(),
1205 * and glibc's getopt() used to coredump if optind is set 1 in order
1206 * to reset getopt().
1207 * Then BSD introduced additional variable "optreset" which should be
1208 * set to 1 in order to reset getopt(). Sigh. Standards, anyone?
1209 *
1210 * By ~2008, OpenBSD 3.4 was changed to survive glibc-like optind = 0
1211 * (to interpret it as if optreset was set).
1212 */
1213#if defined(__GLIBC__) || ENABLE_PLATFORM_MINGW32
1214#define GETOPT_RESET() (optind = 0)
1215#else /* BSD style */
1216#define GETOPT_RESET() (optind = 1)
1217#endif
1196 1218
1197 1219
1198/* Having next pointer as a first member allows easy creation 1220/* Having next pointer as a first member allows easy creation
@@ -1264,7 +1286,7 @@ extern void bb_logenv_override(void) FAST_FUNC;
1264 1286
1265 1287
1266/* Applets which are useful from another applets */ 1288/* Applets which are useful from another applets */
1267int bb_cat(char** argv); 1289int bb_cat(char** argv) FAST_FUNC;
1268/* If shell needs them, they exist even if not enabled as applets */ 1290/* If shell needs them, they exist even if not enabled as applets */
1269int echo_main(int argc, char** argv) IF_ECHO(MAIN_EXTERNALLY_VISIBLE); 1291int echo_main(int argc, char** argv) IF_ECHO(MAIN_EXTERNALLY_VISIBLE);
1270int printf_main(int argc, char **argv) IF_PRINTF(MAIN_EXTERNALLY_VISIBLE); 1292int printf_main(int argc, char **argv) IF_PRINTF(MAIN_EXTERNALLY_VISIBLE);
@@ -1290,6 +1312,16 @@ int bunzip2_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1290void bb_displayroutes(int noresolve, int netstatfmt) FAST_FUNC; 1312void bb_displayroutes(int noresolve, int netstatfmt) FAST_FUNC;
1291#endif 1313#endif
1292 1314
1315struct number_state {
1316 unsigned width;
1317 unsigned start;
1318 unsigned inc;
1319 const char *sep;
1320 const char *empty_str;
1321 smallint all, nonempty;
1322};
1323void print_numbered_lines(struct number_state *ns, const char *filename) FAST_FUNC;
1324
1293 1325
1294/* Networking */ 1326/* Networking */
1295/* This structure defines protocol families and their handlers. */ 1327/* This structure defines protocol families and their handlers. */
@@ -1348,10 +1380,15 @@ extern int get_linux_version_code(void) FAST_FUNC;
1348 1380
1349extern char *query_loop(const char *device) FAST_FUNC; 1381extern char *query_loop(const char *device) FAST_FUNC;
1350extern int del_loop(const char *device) FAST_FUNC; 1382extern int del_loop(const char *device) FAST_FUNC;
1351/* If *devname is not NULL, use that name, otherwise try to find free one, 1383/*
1384 * If *devname is not NULL, use that name, otherwise try to find free one,
1352 * malloc and return it in *devname. 1385 * malloc and return it in *devname.
1353 * return value: 1: read-only loopdev was setup, 0: rw, < 0: error */ 1386 * return value is the opened fd to the loop device, or < on error
1354extern int set_loop(char **devname, const char *file, unsigned long long offset, int ro) FAST_FUNC; 1387 */
1388extern int set_loop(char **devname, const char *file, unsigned long long offset, unsigned flags) FAST_FUNC;
1389/* These constants match linux/loop.h (without BB_ prefix): */
1390#define BB_LO_FLAGS_READ_ONLY 1
1391#define BB_LO_FLAGS_AUTOCLEAR 4
1355 1392
1356/* Like bb_ask below, but asks on stdin with no timeout. */ 1393/* Like bb_ask below, but asks on stdin with no timeout. */
1357char *bb_ask_stdin(const char * prompt) FAST_FUNC; 1394char *bb_ask_stdin(const char * prompt) FAST_FUNC;
@@ -1463,6 +1500,12 @@ extern void selinux_or_die(void) FAST_FUNC;
1463#define SETUP_ENV_NO_CHDIR (1 << 4) 1500#define SETUP_ENV_NO_CHDIR (1 << 4)
1464void setup_environment(const char *shell, int flags, const struct passwd *pw) FAST_FUNC; 1501void setup_environment(const char *shell, int flags, const struct passwd *pw) FAST_FUNC;
1465void nuke_str(char *str) FAST_FUNC; 1502void nuke_str(char *str) FAST_FUNC;
1503#if ENABLE_FEATURE_SECURETTY && !ENABLE_PAM
1504int is_tty_secure(const char *short_tty) FAST_FUNC;
1505#else
1506static ALWAYS_INLINE int is_tty_secure(const char *short_tty UNUSED_PARAM) { return 1; }
1507#endif
1508#define CHECKPASS_PW_HAS_EMPTY_PASSWORD 2
1466int check_password(const struct passwd *pw, const char *plaintext) FAST_FUNC; 1509int check_password(const struct passwd *pw, const char *plaintext) FAST_FUNC;
1467int ask_and_check_password_extended(const struct passwd *pw, int timeout, const char *prompt) FAST_FUNC; 1510int ask_and_check_password_extended(const struct passwd *pw, int timeout, const char *prompt) FAST_FUNC;
1468int ask_and_check_password(const struct passwd *pw) FAST_FUNC; 1511int ask_and_check_password(const struct passwd *pw) FAST_FUNC;
diff --git a/init/init.c b/init/init.c
index 833759341..4d6355167 100644
--- a/init/init.c
+++ b/init/init.c
@@ -73,6 +73,10 @@
73//config: bool "Enable init to write to syslog" 73//config: bool "Enable init to write to syslog"
74//config: default y 74//config: default y
75//config: depends on INIT || LINUXRC 75//config: depends on INIT || LINUXRC
76//config: help
77//config: If selected, some init messages are sent to syslog.
78//config: Otherwise, they are sent to VT #5 if linux virtual tty is detected
79//config: (if not, no separate logging is done).
76//config: 80//config:
77//config:config FEATURE_INIT_QUIET 81//config:config FEATURE_INIT_QUIET
78//config: bool "Be quiet on boot (no 'init started:' message)" 82//config: bool "Be quiet on boot (no 'init started:' message)"
@@ -212,7 +216,9 @@ struct init_action {
212 216
213static struct init_action *init_action_list = NULL; 217static struct init_action *init_action_list = NULL;
214 218
219#if !ENABLE_FEATURE_INIT_SYSLOG
215static const char *log_console = VC_5; 220static const char *log_console = VC_5;
221#endif
216 222
217enum { 223enum {
218 L_LOG = 0x1, 224 L_LOG = 0x1,
@@ -251,17 +257,16 @@ static void message(int where, const char *fmt, ...)
251 msg[l++] = '\n'; 257 msg[l++] = '\n';
252 msg[l] = '\0'; 258 msg[l] = '\0';
253#else 259#else
254 { 260 msg[l++] = '\n';
255 static int log_fd = -1; 261 msg[l] = '\0';
256 262 if (where & L_LOG) {
257 msg[l++] = '\n';
258 msg[l] = '\0';
259 /* Take full control of the log tty, and never close it. 263 /* Take full control of the log tty, and never close it.
260 * It's mine, all mine! Muhahahaha! */ 264 * It's mine, all mine! Muhahahaha! */
265 static int log_fd = -1;
266
261 if (log_fd < 0) { 267 if (log_fd < 0) {
262 if (!log_console) { 268 log_fd = STDERR_FILENO;
263 log_fd = STDERR_FILENO; 269 if (log_console) {
264 } else {
265 log_fd = device_open(log_console, O_WRONLY | O_NONBLOCK | O_NOCTTY); 270 log_fd = device_open(log_console, O_WRONLY | O_NONBLOCK | O_NOCTTY);
266 if (log_fd < 0) { 271 if (log_fd < 0) {
267 bb_error_msg("can't log to %s", log_console); 272 bb_error_msg("can't log to %s", log_console);
@@ -271,11 +276,9 @@ static void message(int where, const char *fmt, ...)
271 } 276 }
272 } 277 }
273 } 278 }
274 if (where & L_LOG) { 279 full_write(log_fd, msg, l);
275 full_write(log_fd, msg, l); 280 if (log_fd == STDERR_FILENO)
276 if (log_fd == STDERR_FILENO) 281 return; /* don't print dup messages */
277 return; /* don't print dup messages */
278 }
279 } 282 }
280#endif 283#endif
281 284
@@ -325,8 +328,9 @@ static void console_init(void)
325 * if TERM is set to linux (the default) */ 328 * if TERM is set to linux (the default) */
326 if (!s || strcmp(s, "linux") == 0) 329 if (!s || strcmp(s, "linux") == 0)
327 putenv((char*)"TERM=vt102"); 330 putenv((char*)"TERM=vt102");
328 if (!ENABLE_FEATURE_INIT_SYSLOG) 331# if !ENABLE_FEATURE_INIT_SYSLOG
329 log_console = NULL; 332 log_console = NULL;
333# endif
330 } else 334 } else
331#endif 335#endif
332 if (!s) 336 if (!s)
@@ -541,8 +545,8 @@ static pid_t run(const struct init_action *a)
541 } 545 }
542 546
543 /* Log the process name and args */ 547 /* Log the process name and args */
544 message(L_LOG, "starting pid %d, tty '%s': '%s'", 548 message(L_LOG, "starting pid %u, tty '%s': '%s'",
545 getpid(), a->terminal, a->command); 549 (int)getpid(), a->terminal, a->command);
546 550
547 /* Now run it. The new program will take over this PID, 551 /* Now run it. The new program will take over this PID,
548 * so nothing further in init.c should be run. */ 552 * so nothing further in init.c should be run. */
@@ -757,7 +761,7 @@ static void run_shutdown_and_kill_processes(void)
757 761
758 /* Send signals to every process _except_ pid 1 */ 762 /* Send signals to every process _except_ pid 1 */
759 kill(-1, SIGTERM); 763 kill(-1, SIGTERM);
760 message(L_CONSOLE | L_LOG, "Sent SIG%s to all processes", "TERM"); 764 message(L_CONSOLE, "Sent SIG%s to all processes", "TERM");
761 sync(); 765 sync();
762 sleep(1); 766 sleep(1);
763 767
diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src
index fc9371db1..0d7dd2a2c 100644
--- a/libbb/Kbuild.src
+++ b/libbb/Kbuild.src
@@ -77,6 +77,7 @@ lib-y += safe_gethostname.o
77lib-y += safe_poll.o 77lib-y += safe_poll.o
78lib-y += safe_strncpy.o 78lib-y += safe_strncpy.o
79lib-y += safe_write.o 79lib-y += safe_write.o
80lib-y += securetty.o
80lib-y += setup_environment.o 81lib-y += setup_environment.o
81lib-y += simplify_path.o 82lib-y += simplify_path.o
82lib-y += single_argv.o 83lib-y += single_argv.o
diff --git a/libbb/bb_cat.c b/libbb/bb_cat.c
new file mode 100644
index 000000000..0a4a350fb
--- /dev/null
+++ b/libbb/bb_cat.c
@@ -0,0 +1,33 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
4 *
5 * Licensed under GPLv2, see file LICENSE in this source tree.
6 */
7//kbuild:lib-y += bb_cat.o
8
9#include "libbb.h"
10
11int FAST_FUNC bb_cat(char **argv)
12{
13 int fd;
14 int retval = EXIT_SUCCESS;
15
16 if (!*argv)
17 argv = (char**) &bb_argv_dash;
18
19 do {
20 fd = open_or_warn_stdin(*argv);
21 if (fd >= 0) {
22 /* This is not a xfunc - never exits */
23 off_t r = bb_copyfd_eof(fd, STDOUT_FILENO);
24 if (fd != STDIN_FILENO)
25 close(fd);
26 if (r >= 0)
27 continue;
28 }
29 retval = EXIT_FAILURE;
30 } while (*++argv);
31
32 return retval;
33}
diff --git a/libbb/correct_password.c b/libbb/correct_password.c
index 513c93028..f4635a5bc 100644
--- a/libbb/correct_password.c
+++ b/libbb/correct_password.c
@@ -63,7 +63,7 @@ static const char *get_passwd(const struct passwd *pw, char buffer[SHADOW_BUFSIZ
63} 63}
64 64
65/* 65/*
66 * Return 1 if PW has an empty password. 66 * Return CHECKPASS_PW_HAS_EMPTY_PASSWORD if PW has an empty password.
67 * Return 1 if the user gives the correct password for entry PW, 67 * Return 1 if the user gives the correct password for entry PW,
68 * 0 if not. 68 * 0 if not.
69 * NULL pw means "just fake it for login with bad username" 69 * NULL pw means "just fake it for login with bad username"
@@ -77,7 +77,7 @@ int FAST_FUNC check_password(const struct passwd *pw, const char *plaintext)
77 77
78 pw_pass = get_passwd(pw, buffer); 78 pw_pass = get_passwd(pw, buffer);
79 if (!pw_pass[0]) { /* empty password field? */ 79 if (!pw_pass[0]) { /* empty password field? */
80 return 1; 80 return CHECKPASS_PW_HAS_EMPTY_PASSWORD;
81 } 81 }
82 82
83 encrypted = pw_encrypt(plaintext, /*salt:*/ pw_pass, 1); 83 encrypted = pw_encrypt(plaintext, /*salt:*/ pw_pass, 1);
@@ -88,7 +88,7 @@ int FAST_FUNC check_password(const struct passwd *pw, const char *plaintext)
88 88
89 89
90/* Ask the user for a password. 90/* Ask the user for a password.
91 * Return 1 without asking if PW has an empty password. 91 * Return CHECKPASS_PW_HAS_EMPTY_PASSWORD without asking if PW has an empty password.
92 * Return -1 on EOF, error while reading input, or timeout. 92 * Return -1 on EOF, error while reading input, or timeout.
93 * Return 1 if the user gives the correct password for entry PW, 93 * Return 1 if the user gives the correct password for entry PW,
94 * 0 if not. 94 * 0 if not.
@@ -105,7 +105,7 @@ int FAST_FUNC ask_and_check_password_extended(const struct passwd *pw,
105 105
106 pw_pass = get_passwd(pw, buffer); 106 pw_pass = get_passwd(pw, buffer);
107 if (!pw_pass[0]) /* empty password field? */ 107 if (!pw_pass[0]) /* empty password field? */
108 return 1; 108 return CHECKPASS_PW_HAS_EMPTY_PASSWORD;
109 109
110 plaintext = bb_ask(STDIN_FILENO, timeout, prompt); 110 plaintext = bb_ask(STDIN_FILENO, timeout, prompt);
111 if (!plaintext) { 111 if (!plaintext) {
diff --git a/libbb/getopt32.c b/libbb/getopt32.c
index 03fca3493..b87b83538 100644
--- a/libbb/getopt32.c
+++ b/libbb/getopt32.c
@@ -128,7 +128,7 @@ const char *opt_complementary
128 "abc" If groups of two or more chars are specified, the first char 128 "abc" If groups of two or more chars are specified, the first char
129 is the main option and the other chars are secondary options. 129 is the main option and the other chars are secondary options.
130 Their flags will be turned on if the main option is found even 130 Their flags will be turned on if the main option is found even
131 if they are not specifed on the command line. For example: 131 if they are not specified on the command line. For example:
132 132
133 opt_complementary = "abc"; 133 opt_complementary = "abc";
134 flags = getopt32(argv, "abcd") 134 flags = getopt32(argv, "abcd")
@@ -576,13 +576,7 @@ getopt32(char **argv, const char *applet_opts, ...)
576 * run_nofork_applet() does this, but we might end up here 576 * run_nofork_applet() does this, but we might end up here
577 * also via gunzip_main() -> gzip_main(). Play safe. 577 * also via gunzip_main() -> gzip_main(). Play safe.
578 */ 578 */
579#if defined(__GLIBC__) || ENABLE_PLATFORM_MINGW32 579 GETOPT_RESET();
580 optind = 0;
581#else /* BSD style */
582 optind = 1;
583 /* optreset = 1; */
584#endif
585 /* optarg = NULL; opterr = 0; optopt = 0; - do we need this?? */
586 580
587 /* Note: just "getopt() <= 0" will not work well for 581 /* Note: just "getopt() <= 0" will not work well for
588 * "fake" short options, like this one: 582 * "fake" short options, like this one:
diff --git a/libbb/isqrt.c b/libbb/isqrt.c
new file mode 100644
index 000000000..817b7d036
--- /dev/null
+++ b/libbb/isqrt.c
@@ -0,0 +1,60 @@
1/*
2 * Copyright (C) 2017 Denys Vlasenko <vda.linux@googlemail.com>
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6
7//kbuild:lib-y += isqrt.o
8
9#ifndef ISQRT_TEST
10# include "libbb.h"
11#else
12/* gcc -DISQRT_TEST -Wall -O2 isqrt.c -oisqrt && ./isqrt $((RANDOM*RANDOM)) */
13# include <stdlib.h>
14# include <stdio.h>
15# include <time.h>
16# define FAST_FUNC /* nothing */
17#endif
18
19/* Returns such x that x+1 > sqrt(N) */
20unsigned long FAST_FUNC isqrt(unsigned long long N)
21{
22 unsigned long x;
23 unsigned shift;
24#define LL_WIDTH_BITS (unsigned)(sizeof(N)*8)
25
26 shift = LL_WIDTH_BITS - 2;
27 x = 0;
28 do {
29 x = (x << 1) + 1;
30 if ((unsigned long long)x * x > (N >> shift))
31 x--; /* whoops, that +1 was too much */
32 shift -= 2;
33 } while ((int)shift >= 0);
34 return x;
35}
36
37#ifdef ISQRT_TEST
38int main(int argc, char **argv)
39{
40 unsigned long long n = argv[1] ? strtoull(argv[1], NULL, 0) : time(NULL);
41 for (;;) {
42 unsigned long h;
43 n--;
44 h = isqrt(n);
45 if (!(n & 0xffff))
46 printf("isqrt(%llx)=%lx\n", n, h);
47 if ((unsigned long long)h * h > n) {
48 printf("BAD1: isqrt(%llx)=%lx\n", n, h);
49 return 1;
50 }
51 h++;
52 if ((unsigned long long)h * h != 0 /* this can overflow to 0 - not a bug */
53 && (unsigned long long)h * h <= n)
54 {
55 printf("BAD2: isqrt(%llx)=%lx\n", n, h);
56 return 1;
57 }
58 }
59}
60#endif
diff --git a/libbb/loop.c b/libbb/loop.c
index d30b378d7..f0d4296ae 100644
--- a/libbb/loop.c
+++ b/libbb/loop.c
@@ -78,22 +78,24 @@ int FAST_FUNC del_loop(const char *device)
78 return rc; 78 return rc;
79} 79}
80 80
81/* Returns 0 if mounted RW, 1 if mounted read-only, <0 for error. 81/* Returns opened fd to the loop device, <0 on error.
82 *device is loop device to use, or if *device==NULL finds a loop device to 82 * *device is loop device to use, or if *device==NULL finds a loop device to
83 mount it on and sets *device to a strdup of that loop device name. This 83 * mount it on and sets *device to a strdup of that loop device name. This
84 search will re-use an existing loop device already bound to that 84 * search will re-use an existing loop device already bound to that
85 file/offset if it finds one. 85 * file/offset if it finds one.
86 */ 86 */
87int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offset, int ro) 87int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offset, unsigned flags)
88{ 88{
89 char dev[LOOP_NAMESIZE]; 89 char dev[LOOP_NAMESIZE];
90 char *try; 90 char *try;
91 bb_loop_info loopinfo; 91 bb_loop_info loopinfo;
92 struct stat statbuf; 92 struct stat statbuf;
93 int i, dfd, ffd, mode, rc = -1; 93 int i, dfd, ffd, mode, rc;
94
95 rc = dfd = -1;
94 96
95 /* Open the file. Barf if this doesn't work. */ 97 /* Open the file. Barf if this doesn't work. */
96 mode = ro ? O_RDONLY : O_RDWR; 98 mode = (flags & BB_LO_FLAGS_READ_ONLY) ? O_RDONLY : O_RDWR;
97 open_ffd: 99 open_ffd:
98 ffd = open(file, mode); 100 ffd = open(file, mode);
99 if (ffd < 0) { 101 if (ffd < 0) {
@@ -144,20 +146,35 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse
144 146
145 /* If device is free, claim it. */ 147 /* If device is free, claim it. */
146 if (rc && errno == ENXIO) { 148 if (rc && errno == ENXIO) {
147 memset(&loopinfo, 0, sizeof(loopinfo));
148 safe_strncpy((char *)loopinfo.lo_file_name, file, LO_NAME_SIZE);
149 loopinfo.lo_offset = offset;
150 /* Associate free loop device with file. */ 149 /* Associate free loop device with file. */
151 if (ioctl(dfd, LOOP_SET_FD, ffd) == 0) { 150 if (ioctl(dfd, LOOP_SET_FD, ffd) == 0) {
152 if (ioctl(dfd, BB_LOOP_SET_STATUS, &loopinfo) == 0) 151 memset(&loopinfo, 0, sizeof(loopinfo));
153 rc = 0; 152 safe_strncpy((char *)loopinfo.lo_file_name, file, LO_NAME_SIZE);
154 else 153 loopinfo.lo_offset = offset;
154 /*
155 * Used by mount to set LO_FLAGS_AUTOCLEAR.
156 * LO_FLAGS_READ_ONLY is not set because RO is controlled by open type of the file.
157 * Note that closing LO_FLAGS_AUTOCLEARed dfd before mount
158 * is wrong (would free the loop device!)
159 */
160 loopinfo.lo_flags = (flags & ~BB_LO_FLAGS_READ_ONLY);
161 rc = ioctl(dfd, BB_LOOP_SET_STATUS, &loopinfo);
162 if (rc != 0 && (loopinfo.lo_flags & BB_LO_FLAGS_AUTOCLEAR)) {
163 /* Old kernel, does not support LO_FLAGS_AUTOCLEAR? */
164 /* (this code path is not tested) */
165 loopinfo.lo_flags -= BB_LO_FLAGS_AUTOCLEAR;
166 rc = ioctl(dfd, BB_LOOP_SET_STATUS, &loopinfo);
167 }
168 if (rc != 0) {
155 ioctl(dfd, LOOP_CLR_FD, 0); 169 ioctl(dfd, LOOP_CLR_FD, 0);
170 }
156 } 171 }
157 } else { 172 } else {
158 rc = -1; 173 rc = -1;
159 } 174 }
160 close(dfd); 175 if (rc != 0) {
176 close(dfd);
177 }
161 try_again: 178 try_again:
162 if (*device) break; 179 if (*device) break;
163 } 180 }
@@ -165,7 +182,7 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse
165 if (rc == 0) { 182 if (rc == 0) {
166 if (!*device) 183 if (!*device)
167 *device = xstrdup(dev); 184 *device = xstrdup(dev);
168 return (mode == O_RDONLY); /* 1:ro, 0:rw */ 185 return dfd;
169 } 186 }
170 return rc; 187 return rc;
171} 188}
diff --git a/libbb/print_numbered_lines.c b/libbb/print_numbered_lines.c
new file mode 100644
index 000000000..702aed1ea
--- /dev/null
+++ b/libbb/print_numbered_lines.c
@@ -0,0 +1,29 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Copyright (C) 2017 Denys Vlasenko <vda.linux@googlemail.com>
4 *
5 * Licensed under GPLv2, see file LICENSE in this source tree.
6 */
7//kbuild:lib-y += print_numbered_lines.o
8
9#include "libbb.h"
10
11void FAST_FUNC print_numbered_lines(struct number_state *ns, const char *filename)
12{
13 FILE *fp = fopen_or_warn_stdin(filename);
14 unsigned N = ns->start;
15 char *line;
16
17 while ((line = xmalloc_fgetline(fp)) != NULL) {
18 if (ns->all
19 || (ns->nonempty && line[0])
20 ) {
21 printf("%*u%s%s\n", ns->width, N, ns->sep, line);
22 N += ns->inc;
23 } else if (ns->empty_str)
24 fputs(ns->empty_str, stdout);
25 free(line);
26 }
27
28 fclose(fp);
29}
diff --git a/libbb/recursive_action.c b/libbb/recursive_action.c
index b5cf7c0ab..8f2b8b932 100644
--- a/libbb/recursive_action.c
+++ b/libbb/recursive_action.c
@@ -30,24 +30,37 @@ static int FAST_FUNC true_action(const char *fileName UNUSED_PARAM,
30 return TRUE; 30 return TRUE;
31} 31}
32 32
33/* fileAction return value of 0 on any file in directory will make 33/* fileName is (l)stat'ed (depending on ACTION_FOLLOWLINKS[_L0]).
34 * recursive_action() return 0, but it doesn't stop directory traversal 34 *
35 * If it is a file: fileAction in run on it, its return value is returned.
36 *
37 * In case we are in a recursive invocation (see below):
38 * normally, fileAction should return 1 (TRUE) to indicate that
39 * everything is okay and processing should continue.
40 * fileAction return value of 0 (FALSE) on any file in directory will make
41 * recursive_action() also return 0, but it doesn't stop directory traversal
35 * (fileAction/dirAction will be called on each file). 42 * (fileAction/dirAction will be called on each file).
36 * 43 *
37 * If !ACTION_RECURSE, dirAction is called on the directory and its 44 * [TODO: maybe introduce -1 to mean "stop traversal NOW and return"]
45 *
46 * If it is a directory:
47 *
48 * If !ACTION_RECURSE, dirAction is called and its
38 * return value is returned from recursive_action(). No recursion. 49 * return value is returned from recursive_action(). No recursion.
39 * 50 *
40 * If ACTION_RECURSE, recursive_action() is called on each directory. 51 * If ACTION_RECURSE, directory is opened, and recursive_action() is called
52 * on each file/subdirectory.
41 * If any one of these calls returns 0, current recursive_action() returns 0. 53 * If any one of these calls returns 0, current recursive_action() returns 0.
42 * 54 *
55 * If !ACTION_DEPTHFIRST, dirAction is called before recurse.
56 * Return value of 0 (FALSE) is an error: prevents recursion,
57 * the warning is printed (unless ACTION_QUIET) and recursive_action() returns 0.
58 * Return value of 2 (SKIP) prevents recursion, instead recursive_action()
59 * returns 1 (TRUE, no error).
60 *
43 * If ACTION_DEPTHFIRST, dirAction is called after recurse. 61 * If ACTION_DEPTHFIRST, dirAction is called after recurse.
44 * If it returns 0, the warning is printed and recursive_action() returns 0. 62 * If it returns 0, the warning is printed and recursive_action() returns 0.
45 * 63 *
46 * If !ACTION_DEPTHFIRST, dirAction is called before we recurse.
47 * Return value of 0 (FALSE) or 2 (SKIP) prevents recursion
48 * into that directory, instead recursive_action() returns 0 (if FALSE)
49 * or 1 (if SKIP)
50 *
51 * ACTION_FOLLOWLINKS mainly controls handling of links to dirs. 64 * ACTION_FOLLOWLINKS mainly controls handling of links to dirs.
52 * 0: lstat(statbuf). Calls fileAction on link name even if points to dir. 65 * 0: lstat(statbuf). Calls fileAction on link name even if points to dir.
53 * 1: stat(statbuf). Calls dirAction and optionally recurse on link to dir. 66 * 1: stat(statbuf). Calls dirAction and optionally recurse on link to dir.
@@ -105,7 +118,7 @@ int FAST_FUNC recursive_action(const char *fileName,
105 118
106 if (!(flags & ACTION_DEPTHFIRST)) { 119 if (!(flags & ACTION_DEPTHFIRST)) {
107 status = dirAction(fileName, &statbuf, userData, depth); 120 status = dirAction(fileName, &statbuf, userData, depth);
108 if (!status) 121 if (status == FALSE)
109 goto done_nak_warn; 122 goto done_nak_warn;
110 if (status == SKIP) 123 if (status == SKIP)
111 return TRUE; 124 return TRUE;
@@ -121,24 +134,23 @@ int FAST_FUNC recursive_action(const char *fileName,
121 status = TRUE; 134 status = TRUE;
122 while ((next = readdir(dir)) != NULL) { 135 while ((next = readdir(dir)) != NULL) {
123 char *nextFile; 136 char *nextFile;
137 int s;
124 138
125 nextFile = concat_subpath_file(fileName, next->d_name); 139 nextFile = concat_subpath_file(fileName, next->d_name);
126 if (nextFile == NULL) 140 if (nextFile == NULL)
127 continue; 141 continue;
142
128 /* process every file (NB: ACTION_RECURSE is set in flags) */ 143 /* process every file (NB: ACTION_RECURSE is set in flags) */
129 if (!recursive_action(nextFile, flags, fileAction, dirAction, 144 s = recursive_action(nextFile, flags, fileAction, dirAction,
130 userData, depth + 1)) 145 userData, depth + 1);
146 if (s == FALSE)
131 status = FALSE; 147 status = FALSE;
132// s = recursive_action(nextFile, flags, fileAction, dirAction,
133// userData, depth + 1);
134 free(nextFile); 148 free(nextFile);
135//#define RECURSE_RESULT_ABORT 3 149//#define RECURSE_RESULT_ABORT -1
136// if (s == RECURSE_RESULT_ABORT) { 150// if (s == RECURSE_RESULT_ABORT) {
137// closedir(dir); 151// closedir(dir);
138// return s; 152// return s;
139// } 153// }
140// if (s == FALSE)
141// status = FALSE;
142 } 154 }
143 closedir(dir); 155 closedir(dir);
144 156
diff --git a/libbb/securetty.c b/libbb/securetty.c
new file mode 100644
index 000000000..21354e2fa
--- /dev/null
+++ b/libbb/securetty.c
@@ -0,0 +1,26 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * /etc/securetty checking.
4 *
5 * Licensed under GPLv2, see file LICENSE in this source tree.
6 */
7#include "libbb.h"
8
9#if ENABLE_FEATURE_SECURETTY && !ENABLE_PAM
10int FAST_FUNC is_tty_secure(const char *short_tty)
11{
12 char *buf = (char*)"/etc/securetty"; /* any non-NULL is ok */
13 parser_t *parser = config_open2("/etc/securetty", fopen_for_read);
14 while (config_read(parser, &buf, 1, 1, "# \t", PARSE_NORMAL)) {
15 if (strcmp(buf, short_tty) == 0)
16 break;
17 buf = NULL;
18 }
19 config_close(parser);
20 /* buf != NULL here if config file was not found, empty
21 * or line was found which equals short_tty.
22 * In all these cases, we report "this tty is secure".
23 */
24 return buf != NULL;
25}
26#endif
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c
index a6d260a40..9ab49d0a1 100644
--- a/libbb/vfork_daemon_rexec.c
+++ b/libbb/vfork_daemon_rexec.c
@@ -123,28 +123,8 @@ int FAST_FUNC run_nofork_applet(int applet_no, char **argv)
123 123
124 /* In case getopt() or getopt32() was already called: 124 /* In case getopt() or getopt32() was already called:
125 * reset the libc getopt() function, which keeps internal state. 125 * reset the libc getopt() function, which keeps internal state.
126 *
127 * BSD-derived getopt() functions require that optind be set to 1 in
128 * order to reset getopt() state. This used to be generally accepted
129 * way of resetting getopt(). However, glibc's getopt()
130 * has additional getopt() state beyond optind, and requires that
131 * optind be set to zero to reset its state. So the unfortunate state of
132 * affairs is that BSD-derived versions of getopt() misbehave if
133 * optind is set to 0 in order to reset getopt(), and glibc's getopt()
134 * will core dump if optind is set 1 in order to reset getopt().
135 *
136 * More modern versions of BSD require that optreset be set to 1 in
137 * order to reset getopt(). Sigh. Standards, anyone?
138 */ 126 */
139#ifdef __GLIBC__ 127 GETOPT_RESET();
140 optind = 0;
141#else /* BSD style */
142 optind = 1;
143 /* optreset = 1; */
144#endif
145 /* optarg = NULL; opterr = 1; optopt = 63; - do we need this too? */
146 /* (values above are what they initialized to in glibc and uclibc) */
147 /* option_mask32 = 0; - not needed, no applet depends on it being 0 */
148 128
149 argc = 1; 129 argc = 1;
150 while (argv[argc]) 130 while (argv[argc])
@@ -169,11 +149,7 @@ int FAST_FUNC run_nofork_applet(int applet_no, char **argv)
169 restore_nofork_data(&old); 149 restore_nofork_data(&old);
170 150
171 /* Other globals can be simply reset to defaults */ 151 /* Other globals can be simply reset to defaults */
172#ifdef __GLIBC__ 152 GETOPT_RESET();
173 optind = 0;
174#else /* BSD style */
175 optind = 1;
176#endif
177 153
178 return rc & 0xff; /* don't confuse people with "exitcodes" >255 */ 154 return rc & 0xff; /* don't confuse people with "exitcodes" >255 */
179} 155}
diff --git a/libpwdgrp/pwd_grp.c b/libpwdgrp/pwd_grp.c
index cefbc8a7e..c9bbc8bda 100644
--- a/libpwdgrp/pwd_grp.c
+++ b/libpwdgrp/pwd_grp.c
@@ -14,7 +14,7 @@
14 * exit using the atexit function to make valgrind happy. 14 * exit using the atexit function to make valgrind happy.
15 * 2) the passwd/group files: 15 * 2) the passwd/group files:
16 * a) must contain the expected number of fields (as per count of field 16 * a) must contain the expected number of fields (as per count of field
17 * delimeters ":") or we will complain with a error message. 17 * delimiters ":") or we will complain with a error message.
18 * b) leading and trailing whitespace in fields is stripped. 18 * b) leading and trailing whitespace in fields is stripped.
19 * c) some fields are not allowed to be empty (e.g. username, uid/gid), 19 * c) some fields are not allowed to be empty (e.g. username, uid/gid),
20 * and in this case NULL is returned and errno is set to EINVAL. 20 * and in this case NULL is returned and errno is set to EINVAL.
@@ -149,7 +149,7 @@ static struct statics *get_S(void)
149/* Internal functions */ 149/* Internal functions */
150 150
151/* Divide the passwd/group/shadow record in fields 151/* Divide the passwd/group/shadow record in fields
152 * by substituting the given delimeter 152 * by substituting the given delimiter
153 * e.g. ':' or ',' with '\0'. 153 * e.g. ':' or ',' with '\0'.
154 * Returns the number of fields found. 154 * Returns the number of fields found.
155 * Strips leading and trailing whitespace in fields. 155 * Strips leading and trailing whitespace in fields.
diff --git a/loginutils/add-remove-shell.c b/loginutils/add-remove-shell.c
index af7c31779..922b3333d 100644
--- a/loginutils/add-remove-shell.c
+++ b/loginutils/add-remove-shell.c
@@ -43,10 +43,7 @@
43#define REMOVE_SHELL (ENABLE_REMOVE_SHELL && (!ENABLE_ADD_SHELL || applet_name[0] == 'r')) 43#define REMOVE_SHELL (ENABLE_REMOVE_SHELL && (!ENABLE_ADD_SHELL || applet_name[0] == 'r'))
44#define ADD_SHELL (ENABLE_ADD_SHELL && (!ENABLE_REMOVE_SHELL || applet_name[0] == 'a')) 44#define ADD_SHELL (ENABLE_ADD_SHELL && (!ENABLE_REMOVE_SHELL || applet_name[0] == 'a'))
45 45
46/* NB: we use the _address_, not the value, of this string 46#define dont_add ((char*)(uintptr_t)1)
47 * as a "special value of pointer" in the code.
48 */
49static const char dont_add[] ALIGN1 = "\n";
50 47
51int add_remove_shell_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 48int add_remove_shell_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
52int add_remove_shell_main(int argc UNUSED_PARAM, char **argv) 49int add_remove_shell_main(int argc UNUSED_PARAM, char **argv)
@@ -54,6 +51,9 @@ int add_remove_shell_main(int argc UNUSED_PARAM, char **argv)
54 FILE *orig_fp; 51 FILE *orig_fp;
55 char *orig_fn; 52 char *orig_fn;
56 char *new_fn; 53 char *new_fn;
54 struct stat sb;
55
56 sb.st_mode = 0666;
57 57
58 argv++; 58 argv++;
59 59
@@ -61,6 +61,8 @@ int add_remove_shell_main(int argc UNUSED_PARAM, char **argv)
61 if (!orig_fn) 61 if (!orig_fn)
62 return EXIT_FAILURE; 62 return EXIT_FAILURE;
63 orig_fp = fopen_for_read(orig_fn); 63 orig_fp = fopen_for_read(orig_fn);
64 if (orig_fp)
65 xfstat(fileno(orig_fp), &sb, orig_fn);
64 66
65 new_fn = xasprintf("%s.tmp", orig_fn); 67 new_fn = xasprintf("%s.tmp", orig_fn);
66 /* 68 /*
@@ -71,13 +73,9 @@ int add_remove_shell_main(int argc UNUSED_PARAM, char **argv)
71 * after which it should revert to O_TRUNC. 73 * after which it should revert to O_TRUNC.
72 * For now, I settle for O_TRUNC instead. 74 * For now, I settle for O_TRUNC instead.
73 */ 75 */
74 xmove_fd(xopen(new_fn, O_WRONLY | O_CREAT | O_TRUNC), STDOUT_FILENO); 76 xmove_fd(xopen3(new_fn, O_WRONLY | O_CREAT | O_TRUNC, sb.st_mode), STDOUT_FILENO);
75 77 /* TODO?
76 /* TODO:
77 struct stat sb;
78 xfstat(fileno(orig_fp), &sb);
79 xfchown(STDOUT_FILENO, sb.st_uid, sb.st_gid); 78 xfchown(STDOUT_FILENO, sb.st_uid, sb.st_gid);
80 xfchmod(STDOUT_FILENO, sb.st_mode);
81 */ 79 */
82 80
83 if (orig_fp) { 81 if (orig_fp) {
@@ -95,7 +93,7 @@ int add_remove_shell_main(int argc UNUSED_PARAM, char **argv)
95 } 93 }
96 /* we are add-shell */ 94 /* we are add-shell */
97 /* mark this name as "do not add" */ 95 /* mark this name as "do not add" */
98 *cpp = (char*)dont_add; 96 *cpp = dont_add;
99 } 97 }
100 cpp++; 98 cpp++;
101 } 99 }
diff --git a/loginutils/cryptpw.c b/loginutils/cryptpw.c
index 696e169fc..3dc8232e0 100644
--- a/loginutils/cryptpw.c
+++ b/loginutils/cryptpw.c
@@ -64,7 +64,7 @@ OPTIONS
64 $1$. 64 $1$.
65-R, --rounds=NUMBER 65-R, --rounds=NUMBER
66 Use NUMBER rounds. This argument is ignored if the method 66 Use NUMBER rounds. This argument is ignored if the method
67 choosen does not support variable rounds. For the OpenBSD Blowfish 67 chosen does not support variable rounds. For the OpenBSD Blowfish
68 method this is the logarithm of the number of rounds. 68 method this is the logarithm of the number of rounds.
69-m, --method=TYPE 69-m, --method=TYPE
70 Compute the password using the TYPE method. If TYPE is 'help' 70 Compute the password using the TYPE method. If TYPE is 'help'
diff --git a/loginutils/login.c b/loginutils/login.c
index d1757a65d..be05def09 100644
--- a/loginutils/login.c
+++ b/loginutils/login.c
@@ -175,25 +175,6 @@ static void die_if_nologin(void)
175# define die_if_nologin() ((void)0) 175# define die_if_nologin() ((void)0)
176#endif 176#endif
177 177
178#if ENABLE_FEATURE_SECURETTY && !ENABLE_PAM
179static int check_securetty(const char *short_tty)
180{
181 char *buf = (char*)"/etc/securetty"; /* any non-NULL is ok */
182 parser_t *parser = config_open2("/etc/securetty", fopen_for_read);
183 while (config_read(parser, &buf, 1, 1, "# \t", PARSE_NORMAL)) {
184 if (strcmp(buf, short_tty) == 0)
185 break;
186 buf = NULL;
187 }
188 config_close(parser);
189 /* buf != NULL here if config file was not found, empty
190 * or line was found which equals short_tty */
191 return buf != NULL;
192}
193#else
194static ALWAYS_INLINE int check_securetty(const char *short_tty UNUSED_PARAM) { return 1; }
195#endif
196
197#if ENABLE_SELINUX 178#if ENABLE_SELINUX
198static void initselinux(char *username, char *full_tty, 179static void initselinux(char *username, char *full_tty,
199 security_context_t *user_sid) 180 security_context_t *user_sid)
@@ -505,7 +486,7 @@ int login_main(int argc UNUSED_PARAM, char **argv)
505 if (opt & LOGIN_OPT_f) 486 if (opt & LOGIN_OPT_f)
506 break; /* -f USER: success without asking passwd */ 487 break; /* -f USER: success without asking passwd */
507 488
508 if (pw->pw_uid == 0 && !check_securetty(short_tty)) 489 if (pw->pw_uid == 0 && !is_tty_secure(short_tty))
509 goto auth_failed; 490 goto auth_failed;
510 491
511 /* Don't check the password if password entry is empty (!) */ 492 /* Don't check the password if password entry is empty (!) */
diff --git a/loginutils/su.c b/loginutils/su.c
index d04b85fb1..4cce82405 100644
--- a/loginutils/su.c
+++ b/loginutils/su.c
@@ -23,6 +23,11 @@
23//config: bool "If user's shell is not in /etc/shells, disallow -s PROG" 23//config: bool "If user's shell is not in /etc/shells, disallow -s PROG"
24//config: default y 24//config: default y
25//config: depends on SU 25//config: depends on SU
26//config:
27//config:config FEATURE_SU_BLANK_PW_NEEDS_SECURE_TTY
28//config: bool "Allow blank passwords only on TTYs in /etc/securetty"
29//config: default n
30//config: depends on SU
26 31
27//applet:/* Needs to be run by root or be suid root - needs to change uid and gid: */ 32//applet:/* Needs to be run by root or be suid root - needs to change uid and gid: */
28//applet:IF_SU(APPLET(su, BB_DIR_BIN, BB_SUID_REQUIRE)) 33//applet:IF_SU(APPLET(su, BB_DIR_BIN, BB_SUID_REQUIRE))
@@ -79,6 +84,7 @@ int su_main(int argc UNUSED_PARAM, char **argv)
79 char user_buf[64]; 84 char user_buf[64];
80#endif 85#endif
81 const char *old_user; 86 const char *old_user;
87 int r;
82 88
83 /* Note: we don't use "'+': stop at first non-option" idiom here. 89 /* Note: we don't use "'+': stop at first non-option" idiom here.
84 * For su, "SCRIPT ARGS" or "-c CMD ARGS" do not stop option parsing: 90 * For su, "SCRIPT ARGS" or "-c CMD ARGS" do not stop option parsing:
@@ -99,6 +105,11 @@ int su_main(int argc UNUSED_PARAM, char **argv)
99 argv++; 105 argv++;
100 } 106 }
101 107
108 tty = xmalloc_ttyname(STDIN_FILENO);
109 if (!tty)
110 tty = "none";
111 tty = skip_dev_pfx(tty);
112
102 if (ENABLE_FEATURE_SU_SYSLOG) { 113 if (ENABLE_FEATURE_SU_SYSLOG) {
103 /* The utmp entry (via getlogin) is probably the best way to 114 /* The utmp entry (via getlogin) is probably the best way to
104 * identify the user, especially if someone su's from a su-shell. 115 * identify the user, especially if someone su's from a su-shell.
@@ -112,20 +123,26 @@ int su_main(int argc UNUSED_PARAM, char **argv)
112 pw = getpwuid(cur_uid); 123 pw = getpwuid(cur_uid);
113 old_user = pw ? xstrdup(pw->pw_name) : ""; 124 old_user = pw ? xstrdup(pw->pw_name) : "";
114 } 125 }
115 tty = xmalloc_ttyname(2);
116 if (!tty) {
117 tty = "none";
118 }
119 openlog(applet_name, 0, LOG_AUTH); 126 openlog(applet_name, 0, LOG_AUTH);
120 } 127 }
121 128
122 pw = xgetpwnam(opt_username); 129 pw = xgetpwnam(opt_username);
123 130
124 if (cur_uid == 0 || ask_and_check_password(pw) > 0) { 131 r = 1;
132 if (cur_uid != 0)
133 r = ask_and_check_password(pw);
134 if (r > 0) {
135 if (ENABLE_FEATURE_SU_BLANK_PW_NEEDS_SECURE_TTY
136 && r == CHECKPASS_PW_HAS_EMPTY_PASSWORD
137 && !is_tty_secure(tty)
138 ) {
139 goto fail;
140 }
125 if (ENABLE_FEATURE_SU_SYSLOG) 141 if (ENABLE_FEATURE_SU_SYSLOG)
126 syslog(LOG_NOTICE, "%c %s %s:%s", 142 syslog(LOG_NOTICE, "%c %s %s:%s",
127 '+', tty, old_user, opt_username); 143 '+', tty, old_user, opt_username);
128 } else { 144 } else {
145 fail:
129 if (ENABLE_FEATURE_SU_SYSLOG) 146 if (ENABLE_FEATURE_SU_SYSLOG)
130 syslog(LOG_NOTICE, "%c %s %s:%s", 147 syslog(LOG_NOTICE, "%c %s %s:%s",
131 '-', tty, old_user, opt_username); 148 '-', tty, old_user, opt_username);
diff --git a/mailutils/sendmail.c b/mailutils/sendmail.c
index 8ddb7826b..b542099fd 100644
--- a/mailutils/sendmail.c
+++ b/mailutils/sendmail.c
@@ -150,7 +150,7 @@ static char *sane_address(char *str)
150 trim(str); 150 trim(str);
151 s = str; 151 s = str;
152 while (*s) { 152 while (*s) {
153 if (!isalnum(*s) && !strchr("_-.@", *s)) { 153 if (!isalnum(*s) && !strchr("+_-.@", *s)) {
154 bb_error_msg("bad address '%s'", str); 154 bb_error_msg("bad address '%s'", str);
155 /* returning "": */ 155 /* returning "": */
156 str[0] = '\0'; 156 str[0] = '\0';
diff --git a/miscutils/inotifyd.c b/miscutils/inotifyd.c
index 601df6465..db8ddce92 100644
--- a/miscutils/inotifyd.c
+++ b/miscutils/inotifyd.c
@@ -12,7 +12,7 @@
12 * Use as follows: 12 * Use as follows:
13 * # inotifyd /user/space/agent dir/or/file/being/watched[:mask] ... 13 * # inotifyd /user/space/agent dir/or/file/being/watched[:mask] ...
14 * 14 *
15 * When a filesystem event matching the specified mask is occured on specified file (or directory) 15 * When a filesystem event matching the specified mask is occurred on specified file (or directory)
16 * a userspace agent is spawned and given the following parameters: 16 * a userspace agent is spawned and given the following parameters:
17 * $1. actual event(s) 17 * $1. actual event(s)
18 * $2. file (or directory) name 18 * $2. file (or directory) name
diff --git a/miscutils/less.c b/miscutils/less.c
index 220e2c693..16be1447e 100644
--- a/miscutils/less.c
+++ b/miscutils/less.c
@@ -271,7 +271,7 @@ struct globals {
271/* flines[] are lines read from stdin, each in malloc'ed buffer. 271/* flines[] are lines read from stdin, each in malloc'ed buffer.
272 * Line numbers are stored as uint32_t prepended to each line. 272 * Line numbers are stored as uint32_t prepended to each line.
273 * Pointer is adjusted so that flines[i] points directly past 273 * Pointer is adjusted so that flines[i] points directly past
274 * line number. Accesor: */ 274 * line number. Accessor: */
275#define MEMPTR(p) ((char*)(p) - 4) 275#define MEMPTR(p) ((char*)(p) - 4)
276#define LINENO(p) (*(uint32_t*)((p) - 4)) 276#define LINENO(p) (*(uint32_t*)((p) - 4))
277 277
diff --git a/miscutils/lsscsi.c b/miscutils/lsscsi.c
new file mode 100644
index 000000000..1521680ac
--- /dev/null
+++ b/miscutils/lsscsi.c
@@ -0,0 +1,123 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * lsscsi implementation for busybox
4 *
5 * Copyright (C) 2017 Markus Gothe <nietzsche@lysator.liu.se>
6 *
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */
9//config:config LSSCSI
10//config: bool "lsscsi"
11//config: default y
12//config: #select PLATFORM_LINUX
13//config: help
14//config: lsscsi is a utility for displaying information about SCSI buses in the
15//config: system and devices connected to them.
16//config:
17//config: This version uses sysfs (/sys/bus/scsi/devices) only.
18
19//applet:IF_LSSCSI(APPLET(lsscsi, BB_DIR_USR_BIN, BB_SUID_DROP))
20
21//kbuild:lib-$(CONFIG_LSSCSI) += lsscsi.o
22
23//usage:#define lsscsi_trivial_usage NOUSAGE_STR
24//usage:#define lsscsi_full_usage ""
25
26#include "libbb.h"
27
28static char *get_line(const char *filename, char *buf, unsigned *bufsize_p)
29{
30 unsigned bufsize = *bufsize_p;
31 ssize_t sz;
32
33 if ((int)(bufsize - 2) <= 0)
34 return buf;
35
36 sz = open_read_close(filename, buf, bufsize - 2);
37 if (sz < 0)
38 sz = 0;
39 buf[sz] = '\0';
40 trim(buf);
41
42 sz = strlen(buf) + 1;
43 bufsize -= sz;
44 buf += sz;
45 buf[0] = '\0';
46
47 *bufsize_p = bufsize;
48 return buf;
49}
50
51int lsscsi_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
52int lsscsi_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
53{
54 struct dirent *de;
55 DIR *dir;
56
57 xchdir("/sys/bus/scsi/devices");
58
59 dir = xopendir(".");
60 while ((de = readdir(dir)) != NULL) {
61 char buf[256];
62 char *ptr;
63 unsigned bufsize;
64 const char *vendor;
65 const char *type_str;
66 const char *type_name;
67 const char *model;
68 const char *rev;
69 unsigned type;
70
71 if (!isdigit(de->d_name[0]))
72 continue;
73 if (!strchr(de->d_name, ':'))
74 continue;
75 if (chdir(de->d_name) != 0)
76 continue;
77
78 bufsize = sizeof(buf);
79 vendor = buf;
80 ptr = get_line("vendor", buf, &bufsize);
81 type_str = ptr;
82 ptr = get_line("type", ptr, &bufsize);
83 model = ptr;
84 ptr = get_line("model", ptr, &bufsize);
85 rev = ptr;
86 ptr = get_line("rev", ptr, &bufsize);
87
88 printf("[%s]\t", de->d_name);
89
90#define scsi_device_types \
91 "disk\0" "tape\0" "printer\0" "process\0" \
92 "worm\0" "\0" "scanner\0" "optical\0" \
93 "mediumx\0" "comms\0" "\0" "\0" \
94 "storage\0" "enclosu\0" "sim dsk\0" "opti rd\0" \
95 "bridge\0" "osd\0" "adi\0" "\0" \
96 "\0" "\0" "\0" "\0" \
97 "\0" "\0" "\0" "\0" \
98 "\0" "\0" "wlun\0" "no dev"
99 type = bb_strtou(type_str, NULL, 10);
100 if (errno
101 || type >= 0x20
102 || (type_name = nth_string(scsi_device_types, type))[0] == '\0'
103 ) {
104 printf("(%s)\t", type_str);
105 } else {
106 printf("%s\t", type_name);
107 }
108
109 printf("%s\t""%s\t""%s\n",
110 vendor,
111 model,
112 rev
113 );
114 /* TODO: also output device column, e.g. "/dev/sdX" */
115
116 xchdir("..");
117 }
118
119 if (ENABLE_FEATURE_CLEAN_UP)
120 closedir(dir);
121
122 return EXIT_SUCCESS;
123}
diff --git a/miscutils/partprobe.c b/miscutils/partprobe.c
new file mode 100644
index 000000000..38831598d
--- /dev/null
+++ b/miscutils/partprobe.c
@@ -0,0 +1,56 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Copyright (C) 2017 Denys Vlasenko <vda.linux@googlemail.com>
4 *
5 * Licensed under GPLv2, see file LICENSE in this source tree.
6 */
7//config:config PARTPROBE
8//config: bool "partprobe"
9//config: default y
10//config: select PLATFORM_LINUX
11//config: help
12//config: Ask kernel to rescan partition table.
13
14//applet:IF_PARTPROBE(APPLET(partprobe, BB_DIR_USR_SBIN, BB_SUID_DROP))
15
16//kbuild:lib-$(CONFIG_PARTPROBE) += partprobe.o
17
18#include <linux/fs.h>
19#include "libbb.h"
20#ifndef BLKRRPART
21# define BLKRRPART _IO(0x12,95)
22#endif
23
24//usage:#define partprobe_trivial_usage
25//usage: "DEVICE..."
26//usage:#define partprobe_full_usage "\n\n"
27//usage: "Ask kernel to rescan partition table"
28//
29// partprobe (GNU parted) 3.2:
30// -d, --dry-run Don't update the kernel
31// -s, --summary Show a summary of devices and their partitions
32
33int partprobe_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
34int partprobe_main(int argc UNUSED_PARAM, char **argv)
35{
36 getopt32(argv, "");
37 argv += optind;
38
39 /* "partprobe" with no arguments just does nothing */
40
41 while (*argv) {
42 int fd = xopen(*argv, O_RDONLY);
43 /*
44 * Newer versions of parted scan partition tables themselves and
45 * use BLKPG ioctl (BLKPG_DEL_PARTITION / BLKPG_ADD_PARTITION)
46 * since this way kernel does not need to know
47 * partition table formats.
48 * We use good old BLKRRPART:
49 */
50 ioctl_or_perror_and_die(fd, BLKRRPART, NULL, "%s", *argv);
51 close(fd);
52 argv++;
53 }
54
55 return EXIT_SUCCESS;
56}
diff --git a/miscutils/time.c b/miscutils/time.c
index a73a837d8..e377bb6b7 100644
--- a/miscutils/time.c
+++ b/miscutils/time.c
@@ -21,10 +21,14 @@
21//kbuild:lib-$(CONFIG_TIME) += time.o 21//kbuild:lib-$(CONFIG_TIME) += time.o
22 22
23//usage:#define time_trivial_usage 23//usage:#define time_trivial_usage
24//usage: "[-v] PROG ARGS" 24//usage: "[-vpa] [-o FILE] PROG ARGS"
25//usage:#define time_full_usage "\n\n" 25//usage:#define time_full_usage "\n\n"
26//usage: "Run PROG, display resource usage when it exits\n" 26//usage: "Run PROG, display resource usage when it exits\n"
27//usage: "\n -v Verbose" 27//usage: "\n -v Verbose"
28//usage: "\n -p POSIX output format"
29//usage: "\n -f FMT Custom format"
30//usage: "\n -o FILE Write result to FILE"
31//usage: "\n -a Append (else overwrite)"
28 32
29#include "libbb.h" 33#include "libbb.h"
30#include <sys/resource.h> /* getrusage */ 34#include <sys/resource.h> /* getrusage */
@@ -397,7 +401,7 @@ static void run_command(char *const *cmd, resource_t *resp)
397 } 401 }
398 402
399 /* Have signals kill the child but not self (if possible). */ 403 /* Have signals kill the child but not self (if possible). */
400//TODO: just block all sigs? and reenable them in the very end in main? 404//TODO: just block all sigs? and re-enable them in the very end in main?
401 interrupt_signal = signal(SIGINT, SIG_IGN); 405 interrupt_signal = signal(SIGINT, SIG_IGN);
402 quit_signal = signal(SIGQUIT, SIG_IGN); 406 quit_signal = signal(SIGQUIT, SIG_IGN);
403 407
@@ -412,29 +416,50 @@ int time_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
412int time_main(int argc UNUSED_PARAM, char **argv) 416int time_main(int argc UNUSED_PARAM, char **argv)
413{ 417{
414 resource_t res; 418 resource_t res;
415 const char *output_format = default_format; 419 /* $TIME has lowest prio (-v,-p,-f FMT overrride it) */
420 const char *output_format = getenv("TIME") ? : default_format;
421 char *output_filename;
422 int output_fd;
416 int opt; 423 int opt;
424 int ex;
425 enum {
426 OPT_v = (1 << 0),
427 OPT_p = (1 << 1),
428 OPT_a = (1 << 2),
429 OPT_o = (1 << 3),
430 OPT_f = (1 << 4),
431 };
417 432
418 opt_complementary = "-1"; /* at least one arg */ 433 opt_complementary = "-1"; /* at least one arg */
419 /* "+": stop on first non-option */ 434 /* "+": stop on first non-option */
420 opt = getopt32(argv, "+vp"); 435 opt = getopt32(argv, "+vpao:f:", &output_filename, &output_format);
421 argv += optind; 436 argv += optind;
422 if (opt & 1) 437 if (opt & OPT_v)
423 output_format = long_format; 438 output_format = long_format;
424 if (opt & 2) 439 if (opt & OPT_p)
425 output_format = posix_format; 440 output_format = posix_format;
441 output_fd = STDERR_FILENO;
442 if (opt & OPT_o) {
443 output_fd = xopen(output_filename,
444 (opt & OPT_a) /* append? */
445 ? (O_CREAT | O_WRONLY | O_CLOEXEC | O_APPEND)
446 : (O_CREAT | O_WRONLY | O_CLOEXEC | O_TRUNC)
447 );
448 }
426 449
427 run_command(argv, &res); 450 run_command(argv, &res);
428 451
429 /* Cheat. printf's are shorter :) */ 452 /* Cheat. printf's are shorter :) */
430 xdup2(STDERR_FILENO, STDOUT_FILENO); 453 xdup2(output_fd, STDOUT_FILENO);
431 summarize(output_format, argv, &res); 454 summarize(output_format, argv, &res);
432 455
456 ex = WEXITSTATUS(res.waitstatus);
457 /* Impossible: we do not use WUNTRACED flag in wait()...
433 if (WIFSTOPPED(res.waitstatus)) 458 if (WIFSTOPPED(res.waitstatus))
434 return WSTOPSIG(res.waitstatus); 459 ex = WSTOPSIG(res.waitstatus);
460 */
435 if (WIFSIGNALED(res.waitstatus)) 461 if (WIFSIGNALED(res.waitstatus))
436 return WTERMSIG(res.waitstatus); 462 ex = WTERMSIG(res.waitstatus);
437 if (WIFEXITED(res.waitstatus)) 463
438 return WEXITSTATUS(res.waitstatus); 464 fflush_stdout_and_exit(ex);
439 fflush_stdout_and_exit(EXIT_SUCCESS);
440} 465}
diff --git a/modutils/Config.src b/modutils/Config.src
index 5f0b0cec4..9b76c83d2 100644
--- a/modutils/Config.src
+++ b/modutils/Config.src
@@ -75,7 +75,7 @@ config FEATURE_INSMOD_KSYMOOPS_SYMBOLS
75 depends on FEATURE_2_4_MODULES && (INSMOD || MODPROBE) 75 depends on FEATURE_2_4_MODULES && (INSMOD || MODPROBE)
76 help 76 help
77 By adding module symbols to the kernel symbol table, Oops messages 77 By adding module symbols to the kernel symbol table, Oops messages
78 occuring within kernel modules can be properly debugged. By enabling 78 occurring within kernel modules can be properly debugged. By enabling
79 this feature, module symbols will always be added to the kernel symbol 79 this feature, module symbols will always be added to the kernel symbol
80 table for proper debugging support. If you are not interested in 80 table for proper debugging support. If you are not interested in
81 Oops messages from kernel modules, say N. 81 Oops messages from kernel modules, say N.
diff --git a/modutils/modinfo.c b/modutils/modinfo.c
index aa641ad54..ead2cf16f 100644
--- a/modutils/modinfo.c
+++ b/modutils/modinfo.c
@@ -104,7 +104,7 @@ static void modinfo(const char *path, const char *version,
104 char *after_pattern; 104 char *after_pattern;
105 105
106 ptr = memchr(ptr, *pattern, len - (ptr - (char*)the_module)); 106 ptr = memchr(ptr, *pattern, len - (ptr - (char*)the_module));
107 if (ptr == NULL) /* no occurance left, done */ 107 if (ptr == NULL) /* no occurrence left, done */
108 break; 108 break;
109 after_pattern = is_prefixed_with(ptr, pattern); 109 after_pattern = is_prefixed_with(ptr, pattern);
110 if (after_pattern && *after_pattern == '=') { 110 if (after_pattern && *after_pattern == '=') {
diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c
index 431b8aeb2..053a7df89 100644
--- a/modutils/modprobe-small.c
+++ b/modutils/modprobe-small.c
@@ -79,6 +79,7 @@ int lsmod_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
79#define is_rmmod (ENABLE_RMMOD && (ONLY_APPLET || applet_name[0] == 'r')) 79#define is_rmmod (ENABLE_RMMOD && (ONLY_APPLET || applet_name[0] == 'r'))
80 80
81enum { 81enum {
82 DEPMOD_OPT_n = (1 << 0), /* dry-run, print to stdout */
82 OPT_q = (1 << 0), /* be quiet */ 83 OPT_q = (1 << 0), /* be quiet */
83 OPT_r = (1 << 1), /* module removal instead of loading */ 84 OPT_r = (1 << 1), /* module removal instead of loading */
84}; 85};
@@ -168,7 +169,7 @@ static char* find_keyword(char *ptr, size_t len, const char *word)
168 169
169 /* search for the first char in word */ 170 /* search for the first char in word */
170 ptr = memchr(ptr, word[0], len); 171 ptr = memchr(ptr, word[0], len);
171 if (ptr == NULL) /* no occurance left, done */ 172 if (ptr == NULL) /* no occurrence left, done */
172 break; 173 break;
173 after_word = is_prefixed_with(ptr, word); 174 after_word = is_prefixed_with(ptr, word);
174 if (after_word) 175 if (after_word)
@@ -410,7 +411,7 @@ static FAST_FUNC int fileAction(const char *pathname,
410 if (load_module(pathname, module_load_options) == 0) { 411 if (load_module(pathname, module_load_options) == 0) {
411 /* Load was successful, there is nothing else to do. 412 /* Load was successful, there is nothing else to do.
412 * This can happen ONLY for "top-level" module load, 413 * This can happen ONLY for "top-level" module load,
413 * not a dep, because deps dont do dirscan. */ 414 * not a dep, because deps don't do dirscan. */
414 exit(EXIT_SUCCESS); 415 exit(EXIT_SUCCESS);
415 } 416 }
416 } 417 }
@@ -477,7 +478,7 @@ static int start_dep_bb_writeout(void)
477 int fd; 478 int fd;
478 479
479 /* depmod -n: write result to stdout */ 480 /* depmod -n: write result to stdout */
480 if (applet_name[0] == 'd' && (option_mask32 & 1)) 481 if (is_depmod && (option_mask32 & DEPMOD_OPT_n))
481 return STDOUT_FILENO; 482 return STDOUT_FILENO;
482 483
483 fd = open(DEPFILE_BB".new", O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0644); 484 fd = open(DEPFILE_BB".new", O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0644);
@@ -764,9 +765,12 @@ static int process_module(char *name, const char *cmdline_options)
764 765
765 if (!infovec) { 766 if (!infovec) {
766 /* both dirscan and find_alias found nothing */ 767 /* both dirscan and find_alias found nothing */
767 if (!is_remove && !is_depmod) /* it wasn't rmmod or depmod */ 768 if (!is_remove && !is_depmod) { /* it wasn't rmmod or depmod */
768 bb_error_msg("module '%s' not found", name); 769 bb_error_msg("module '%s' not found", name);
769//TODO: _and_die()? or should we continue (un)loading modules listed on cmdline? 770//TODO: _and_die()? or should we continue (un)loading modules listed on cmdline?
771 /* "modprobe non-existing-module; echo $?" must print 1 */
772 exitcode = EXIT_FAILURE;
773 }
770 goto ret; 774 goto ret;
771 } 775 }
772 776
@@ -862,25 +866,28 @@ Usage: rmmod [-fhswvV] modulename ...
862 should eventually fall to zero). 866 should eventually fall to zero).
863 867
864# modprobe 868# modprobe
865Usage: modprobe [-v] [-V] [-C config-file] [-n] [-i] [-q] [-b] 869Usage: modprobe [-v] [-V] [-C config-file] [-d <dirname> ] [-n] [-i] [-q]
866 [-o <modname>] [ --dump-modversions ] <modname> [parameters...] 870 [-b] [-o <modname>] [ --dump-modversions ] <modname> [parameters...]
867modprobe -r [-n] [-i] [-v] <modulename> ... 871modprobe -r [-n] [-i] [-v] <modulename> ...
868modprobe -l -t <dirname> [ -a <modulename> ...] 872modprobe -l -t <dirname> [ -a <modulename> ...]
869 873
870# depmod --help 874# depmod --help
871depmod 3.4 -- part of module-init-tools 875depmod 3.13 -- part of module-init-tools
872depmod -[aA] [-n -e -v -q -V -r -u] 876depmod -[aA] [-n -e -v -q -V -r -u -w -m]
873 [-b basedirectory] [forced_version] 877 [-b basedirectory] [forced_version]
874depmod [-n -e -v -q -r -u] [-F kernelsyms] module1.ko module2.ko ... 878depmod [-n -e -v -q -r -u -w] [-F kernelsyms] module1.ko module2.ko ...
875If no arguments (except options) are given, "depmod -a" is assumed. 879If no arguments (except options) are given, "depmod -a" is assumed.
876depmod will output a dependency list suitable for the modprobe utility. 880depmod will output a dependency list suitable for the modprobe utility.
877Options: 881Options:
878 -a, --all Probe all modules 882 -a, --all Probe all modules
879 -A, --quick Only does the work if there's a new module 883 -A, --quick Only does the work if there's a new module
880 -n, --show Write the dependency file on stdout only
881 -e, --errsyms Report not supplied symbols 884 -e, --errsyms Report not supplied symbols
885 -m, --map Create the legacy map files
886 -n, --show Write the dependency file on stdout only
887 -P, --symbol-prefix Architecture symbol prefix
882 -V, --version Print the release version 888 -V, --version Print the release version
883 -v, --verbose Enable verbose mode 889 -v, --verbose Enable verbose mode
890 -w, --warn Warn on duplicates
884 -h, --help Print this usage message 891 -h, --help Print this usage message
885The following options are useful for people managing distributions: 892The following options are useful for people managing distributions:
886 -b basedirectory 893 -b basedirectory
@@ -889,12 +896,18 @@ The following options are useful for people managing distributions:
889 -F kernelsyms 896 -F kernelsyms
890 --filesyms kernelsyms 897 --filesyms kernelsyms
891 Use the file instead of the current kernel symbols 898 Use the file instead of the current kernel symbols
899 -E Module.symvers
900 --symvers Module.symvers
901 Use Module.symvers file to check symbol versions
892*/ 902*/
893 903
894//usage:#if ENABLE_MODPROBE_SMALL 904//usage:#if ENABLE_MODPROBE_SMALL
895 905
896//usage:#define depmod_trivial_usage NOUSAGE_STR 906//usage:#define depmod_trivial_usage "[-n]"
897//usage:#define depmod_full_usage "" 907//usage:#define depmod_full_usage "\n\n"
908//usage: "Generate modules.dep.bb"
909//usage: "\n"
910//usage: "\n -n Dry run: print file to stdout"
898 911
899//usage:#define insmod_trivial_usage 912//usage:#define insmod_trivial_usage
900//usage: "FILE" IF_FEATURE_CMDLINE_MODULE_OPTIONS(" [SYMBOL=VALUE]...") 913//usage: "FILE" IF_FEATURE_CMDLINE_MODULE_OPTIONS(" [SYMBOL=VALUE]...")
@@ -947,10 +960,12 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
947 * -e: report any symbols which a module needs 960 * -e: report any symbols which a module needs
948 * which are not supplied by other modules or the kernel 961 * which are not supplied by other modules or the kernel
949 * -F FILE: System.map (symbols for -e) 962 * -F FILE: System.map (symbols for -e)
950 * -q, -r, -u: noop? 963 * -q, -r, -u: noop
951 * Not supported: 964 * Not supported:
952 * -b BASEDIR: (TODO!) modules are in 965 * -b BASEDIR: (TODO!) modules are in
953 * $BASEDIR/lib/modules/$VERSION 966 * $BASEDIR/lib/modules/$VERSION
967 * -m: create legacy "modules.*map" files (deprecated; in
968 * kmod's depmod, prints a warning message and continues)
954 * -v: human readable deps to stdout 969 * -v: human readable deps to stdout
955 * -V: version (don't want to support it - people may depend 970 * -V: version (don't want to support it - people may depend
956 * on it as an indicator of "standard" depmod) 971 * on it as an indicator of "standard" depmod)
diff --git a/modutils/modprobe.c b/modutils/modprobe.c
index a6224fa63..51ede9204 100644
--- a/modutils/modprobe.c
+++ b/modutils/modprobe.c
@@ -171,6 +171,7 @@ static const char modprobe_longopts[] ALIGN1 =
171/* "was seen in modules.dep": */ 171/* "was seen in modules.dep": */
172#define MODULE_FLAG_FOUND_IN_MODDEP 0x0004 172#define MODULE_FLAG_FOUND_IN_MODDEP 0x0004
173#define MODULE_FLAG_BLACKLISTED 0x0008 173#define MODULE_FLAG_BLACKLISTED 0x0008
174#define MODULE_FLAG_BUILTIN 0x0010
174 175
175struct globals { 176struct globals {
176 llist_t *probes; /* MEs of module(s) requested on cmdline */ 177 llist_t *probes; /* MEs of module(s) requested on cmdline */
@@ -217,7 +218,7 @@ static void add_probe(const char *name)
217 218
218 m = get_or_add_modentry(name); 219 m = get_or_add_modentry(name);
219 if (!(option_mask32 & (OPT_REMOVE | OPT_SHOW_DEPS)) 220 if (!(option_mask32 & (OPT_REMOVE | OPT_SHOW_DEPS))
220 && (m->flags & MODULE_FLAG_LOADED) 221 && (m->flags & (MODULE_FLAG_LOADED | MODULE_FLAG_BUILTIN))
221 ) { 222 ) {
222 DBG("skipping %s, it is already loaded", name); 223 DBG("skipping %s, it is already loaded", name);
223 return; 224 return;
@@ -251,6 +252,15 @@ static int FAST_FUNC config_file_action(const char *filename,
251 if (base[0] == '.') 252 if (base[0] == '.')
252 goto error; 253 goto error;
253 254
255 /* "man modprobe.d" from kmod version 22 suggests
256 * that we shouldn't recurse into /etc/modprobe.d/dir/
257 * _subdirectories_:
258 */
259 if (depth > 1)
260 return SKIP; /* stop recursing */
261//TODO: instead, can use dirAction in recursive_action() to SKIP dirs
262//on depth == 1 level. But that's more code...
263
254 /* In dir recursion, skip files that do not end with a ".conf" 264 /* In dir recursion, skip files that do not end with a ".conf"
255 * depth==0: read_config("modules.{symbols,alias}") must work, 265 * depth==0: read_config("modules.{symbols,alias}") must work,
256 * "include FILE_NOT_ENDING_IN_CONF" must work too. 266 * "include FILE_NOT_ENDING_IN_CONF" must work too.
@@ -413,8 +423,10 @@ static int do_modprobe(struct module_entry *m)
413 423
414 if (!(m->flags & MODULE_FLAG_FOUND_IN_MODDEP)) { 424 if (!(m->flags & MODULE_FLAG_FOUND_IN_MODDEP)) {
415 if (!(option_mask32 & INSMOD_OPT_SILENT)) 425 if (!(option_mask32 & INSMOD_OPT_SILENT))
416 bb_error_msg("module %s not found in modules.dep", 426 bb_error_msg((m->flags & MODULE_FLAG_BUILTIN) ?
417 humanly_readable_name(m)); 427 "module %s is builtin" :
428 "module %s not found in modules.dep",
429 humanly_readable_name(m));
418 return -ENOENT; 430 return -ENOENT;
419 } 431 }
420 DBG("do_modprob'ing %s", m->modname); 432 DBG("do_modprob'ing %s", m->modname);
@@ -618,6 +630,11 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
618 while (config_read(parser, &s, 1, 1, "# \t", PARSE_NORMAL & ~PARSE_GREEDY)) 630 while (config_read(parser, &s, 1, 1, "# \t", PARSE_NORMAL & ~PARSE_GREEDY))
619 get_or_add_modentry(s)->flags |= MODULE_FLAG_LOADED; 631 get_or_add_modentry(s)->flags |= MODULE_FLAG_LOADED;
620 config_close(parser); 632 config_close(parser);
633
634 parser = config_open2("modules.builtin", fopen_for_read);
635 while (config_read(parser, &s, 1, 1, "# \t", PARSE_NORMAL))
636 get_or_add_modentry(s)->flags |= MODULE_FLAG_BUILTIN;
637 config_close(parser);
621 } 638 }
622 639
623 if (opt & (OPT_INSERT_ALL | OPT_REMOVE)) { 640 if (opt & (OPT_INSERT_ALL | OPT_REMOVE)) {
diff --git a/networking/dnsd.c b/networking/dnsd.c
index 7be90018d..1b85618c6 100644
--- a/networking/dnsd.c
+++ b/networking/dnsd.c
@@ -360,7 +360,7 @@ RDATA a variable length string of octets that describes the resource.
360 360
361In order to reduce the size of messages, domain names coan be compressed. 361In order to reduce the size of messages, domain names coan be compressed.
362An entire domain name or a list of labels at the end of a domain name 362An entire domain name or a list of labels at the end of a domain name
363is replaced with a pointer to a prior occurance of the same name. 363is replaced with a pointer to a prior occurrence of the same name.
364 364
365The pointer takes the form of a two octet sequence: 365The pointer takes the form of a two octet sequence:
366 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 366 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
diff --git a/networking/ifenslave.c b/networking/ifenslave.c
index 1cb765e23..070931209 100644
--- a/networking/ifenslave.c
+++ b/networking/ifenslave.c
@@ -55,7 +55,7 @@
55 * 55 *
56 * - 2003/03/18 - Tsippy Mendelson <tsippy.mendelson at intel dot com> and 56 * - 2003/03/18 - Tsippy Mendelson <tsippy.mendelson at intel dot com> and
57 * Shmulik Hen <shmulik.hen at intel dot com> 57 * Shmulik Hen <shmulik.hen at intel dot com>
58 * - Moved setting the slave's mac address and openning it, from 58 * - Moved setting the slave's mac address and opening it, from
59 * the application to the driver. This enables support of modes 59 * the application to the driver. This enables support of modes
60 * that need to use the unique mac address of each slave. 60 * that need to use the unique mac address of each slave.
61 * The driver also takes care of closing the slave and restoring its 61 * The driver also takes care of closing the slave and restoring its
diff --git a/networking/ip.c b/networking/ip.c
index 0f52b19dd..3cf52cdd7 100644
--- a/networking/ip.c
+++ b/networking/ip.c
@@ -140,47 +140,79 @@
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//--------------123456789.123456789.123456789.123456789.123456789.123456789.123456789.123....79
143//usage:#define ipaddr_trivial_usage 144//usage:#define ipaddr_trivial_usage
144//usage: "add|del IFADDR dev IFACE | show|flush [dev IFACE] [to PREFIX]" 145//usage: "add|del IFADDR dev IFACE | show|flush [dev IFACE] [to PREFIX]"
145//usage:#define ipaddr_full_usage "\n\n" 146//usage:#define ipaddr_full_usage "\n\n"
146//usage: "ipaddr add|change|replace|delete IFADDR dev IFACE\n" 147//usage: "ipaddr add|change|replace|delete dev IFACE IFADDR\n"
147//usage: "ipaddr show|flush [dev IFACE] [scope SCOPE-ID]\n" 148//usage: " IFADDR := PREFIX | ADDR peer PREFIX [broadcast ADDR|+|-]\n"
148//usage: " [to PREFIX] [label PATTERN]\n" 149//usage: " [anycast ADDR] [label STRING] [scope SCOPE]\n"
149//usage: " IFADDR := PREFIX | ADDR peer PREFIX\n" 150//usage: " PREFIX := ADDR[/MASK]\n"
150//usage: " [broadcast ADDR] [anycast ADDR]\n" 151//usage: " SCOPE := [host|link|global|NUMBER]\n"
151//usage: " [label STRING] [scope SCOPE-ID]\n" 152//usage: "ipaddr show|flush [dev IFACE] [scope SCOPE] [to PREFIX] [label PATTERN]"
152//usage: " SCOPE-ID := [host|link|global|NUMBER]"
153//usage: 153//usage:
154//--------------123456789.123456789.123456789.123456789.123456789.123456789.123456789.123....79
154//usage:#define iplink_trivial_usage 155//usage:#define iplink_trivial_usage
155//usage: "set IFACE [up|down] [arp on|off] | show [IFACE]" 156//usage: "set IFACE [up|down] [arp on|off] | show [IFACE]"
156//usage:#define iplink_full_usage "\n\n" 157//usage:#define iplink_full_usage "\n\n"
157//usage: "iplink set IFACE [up|down]\n" 158//usage: "iplink set IFACE [up|down] [arp on|off] [multicast on|off] [promisc on|off]\n"
158//usage: " [arp on|off]\n" 159//usage: " [mtu NUM] [name NAME] [qlen NUM] [address MAC]\n"
159//usage: " [dynamic on|off]\n"
160//usage: " [multicast on|off]\n"
161//usage: " [mtu MTU]\n"
162//usage: "iplink show [IFACE]" 160//usage: "iplink show [IFACE]"
163//usage: 161//usage:
162//--------------123456789.123456789.123456789.123456789.123456789.123456789.123456789.123....79
164//usage:#define iproute_trivial_usage 163//usage:#define iproute_trivial_usage
165//usage: "list|flush|add|del|change|append|replace|test ROUTE" 164//usage: "list|flush|add|del|change|append|replace|test ROUTE"
166//usage:#define iproute_full_usage "\n\n" 165//usage:#define iproute_full_usage "\n\n"
167//usage: "iproute list|flush SELECTOR\n" 166//usage: "iproute list|flush SELECTOR\n"
168//usage: "iproute get ADDRESS [from ADDRESS iif STRING]\n"
169//usage: " [oif STRING] [tos TOS]\n"
170//usage: "iproute add|del|change|append|replace|test ROUTE\n"
171//usage: " SELECTOR := [root PREFIX] [match PREFIX] [proto RTPROTO]\n" 167//usage: " SELECTOR := [root PREFIX] [match PREFIX] [proto RTPROTO]\n"
172//usage: " ROUTE := [TYPE] PREFIX [tos TOS] [proto RTPROTO] [metric METRIC]" 168//usage: " PREFIX := default|ADDR[/MASK]\n"
169//usage: "iproute get ADDR [from ADDR iif IFACE]\n"
170//usage: " [oif IFACE] [tos TOS]\n"
171//usage: "iproute add|del|change|append|replace|test ROUTE\n"
172//usage: " ROUTE := NODE_SPEC [INFO_SPEC]\n"
173//usage: " NODE_SPEC := PREFIX"IF_FEATURE_IP_RULE(" [table TABLE_ID]")" [proto RTPROTO] [scope SCOPE] [metric METRIC]\n"
174//usage: " INFO_SPEC := NH OPTIONS\n"
175//usage: " NH := [via [inet|inet6] ADDR] [dev IFACE] [src ADDR] [onlink]\n"
176//usage: " OPTIONS := [mtu [lock] NUM] [advmss [lock] NUM]"
177//upstream man ip-route:
178//======================
179//ip route { show | flush } SELECTOR
180//ip route save SELECTOR
181//ip route restore
182//ip route get ADDRESS [ from ADDRESS iif STRING ] [ oif STRING ] [ tos TOS ]
183//ip route { add | del | change | append | replace } ROUTE
184//SELECTOR := [ root PREFIX ] [ match PREFIX ] [ exact PREFIX ] [ table TABLE_ID ] [ proto RTPROTO ] [ type TYPE ] [ scope SCOPE ]
185//ROUTE := NODE_SPEC [ INFO_SPEC ]
186//NODE_SPEC := [ TYPE ] PREFIX [ tos TOS ] [ table TABLE_ID ] [ proto RTPROTO ] [ scope SCOPE ] [ metric METRIC ]
187//INFO_SPEC := NH OPTIONS FLAGS [ nexthop NH ] ...
188//NH := [ encap ENCAP ] [ via [ FAMILY ] ADDRESS ] [ dev STRING ] [ weight NUMBER ] NHFLAGS
189// ..............................................................^ I guess [src ADDRESS] should be here
190//FAMILY := [ inet | inet6 | ipx | dnet | mpls | bridge | link ]
191//OPTIONS := FLAGS [ mtu NUMBER ] [ advmss NUMBER ] [ as [ to ] ADDRESS ] rtt TIME ] [ rttvar TIME ] [ reordering NUMBER ] [ window NUMBER ] [ cwnd NUMBER ] [ ssthresh REALM ] [ realms REALM ]
192// [ rto_min TIME ] [ initcwnd NUMBER ] [ initrwnd NUMBER ] [ features FEATURES ] [ quickack BOOL ] [ congctl NAME ] [ pref PREF ] [ expires TIME ]
193//TYPE := [ unicast | local | broadcast | multicast | throw | unreachable | prohibit | blackhole | nat ]
194//TABLE_ID := [ local | main | default | all | NUMBER ]
195//SCOPE := [ host | link | global | NUMBER ]
196//NHFLAGS := [ onlink | pervasive ]
197//RTPROTO := [ kernel | boot | static | NUMBER ]
198//FEATURES := [ ecn | ]
199//PREF := [ low | medium | high ]
200//ENCAP := [ MPLS | IP ]
201//ENCAP_MPLS := mpls [ LABEL ]
202//ENCAP_IP := ip id TUNNEL_ID dst REMOTE_IP [ tos TOS ] [ ttl TTL ]
173//usage: 203//usage:
204//--------------123456789.123456789.123456789.123456789.123456789.123456789.123456789.123....79
174//usage:#define iprule_trivial_usage 205//usage:#define iprule_trivial_usage
175//usage: "[list] | add|del SELECTOR ACTION" 206//usage: "[list] | add|del SELECTOR ACTION"
176//usage:#define iprule_full_usage "\n\n" 207//usage:#define iprule_full_usage "\n\n"
177//usage: " SELECTOR := [from PREFIX] [to PREFIX] [tos TOS] [fwmark FWMARK]\n" 208//usage: " SELECTOR := [from PREFIX] [to PREFIX] [tos TOS] [fwmark FWMARK]\n"
178//usage: " [dev IFACE] [pref NUMBER]\n" 209//usage: " [dev IFACE] [pref NUMBER]\n"
179//usage: " ACTION := [table TABLE_ID] [nat ADDRESS]\n" 210//usage: " ACTION := [table TABLE_ID] [nat ADDR]\n"
180//usage: " [prohibit|reject|unreachable]\n" 211//usage: " [prohibit|reject|unreachable]\n"
181//usage: " [realms [SRCREALM/]DSTREALM]\n" 212//usage: " [realms [SRCREALM/]DSTREALM]\n"
182//usage: " TABLE_ID := [local|main|default|NUMBER]" 213//usage: " TABLE_ID := [local|main|default|NUMBER]"
183//usage: 214//usage:
215//--------------123456789.123456789.123456789.123456789.123456789.123456789.123456789.123....79
184//usage:#define iptunnel_trivial_usage 216//usage:#define iptunnel_trivial_usage
185//usage: "add|change|del|show [NAME]\n" 217//usage: "add|change|del|show [NAME]\n"
186//usage: " [mode ipip|gre|sit]\n" 218//usage: " [mode ipip|gre|sit]\n"
diff --git a/networking/isrv.c b/networking/isrv.c
index 3673db715..97f5c6d4e 100644
--- a/networking/isrv.c
+++ b/networking/isrv.c
@@ -191,7 +191,7 @@ static void handle_accept(isrv_state_t *state, int fd)
191 DPRINTF("new_peer(%d)", newfd); 191 DPRINTF("new_peer(%d)", newfd);
192 n = state->new_peer(state, newfd); 192 n = state->new_peer(state, newfd);
193 if (n) 193 if (n)
194 remove_peer(state, n); /* unsuccesful peer start */ 194 remove_peer(state, n); /* unsuccessful peer start */
195} 195}
196 196
197static void handle_fd_set(isrv_state_t *state, fd_set *fds, int (*h)(int, void **)) 197static void handle_fd_set(isrv_state_t *state, fd_set *fds, int (*h)(int, void **))
diff --git a/networking/libiproute/ipaddress.c b/networking/libiproute/ipaddress.c
index d9e099607..36d6b65c6 100644
--- a/networking/libiproute/ipaddress.c
+++ b/networking/libiproute/ipaddress.c
@@ -593,9 +593,13 @@ static int default_scope(inet_prefix *lcl)
593/* Return value becomes exitcode. It's okay to not return at all */ 593/* Return value becomes exitcode. It's okay to not return at all */
594static int ipaddr_modify(int cmd, int flags, char **argv) 594static int ipaddr_modify(int cmd, int flags, char **argv)
595{ 595{
596 /* If you add stuff here, update ipaddr_full_usage */
596 static const char option[] ALIGN1 = 597 static const char option[] ALIGN1 =
597 "peer\0""remote\0""broadcast\0""brd\0" 598 "peer\0""remote\0""broadcast\0""brd\0"
598 "anycast\0""scope\0""dev\0""label\0""local\0"; 599 "anycast\0""scope\0""dev\0""label\0""local\0";
600#define option_peer option
601#define option_broadcast (option + sizeof("peer") + sizeof("remote"))
602#define option_anycast (option_broadcast + sizeof("broadcast") + sizeof("brd"))
599 struct rtnl_handle rth; 603 struct rtnl_handle rth;
600 struct { 604 struct {
601 struct nlmsghdr n; 605 struct nlmsghdr n;
@@ -627,7 +631,7 @@ static int ipaddr_modify(int cmd, int flags, char **argv)
627 631
628 if (arg <= 1) { /* peer, remote */ 632 if (arg <= 1) { /* peer, remote */
629 if (peer_len) { 633 if (peer_len) {
630 duparg("peer", *argv); 634 duparg(option_peer, *argv);
631 } 635 }
632 get_prefix(&peer, *argv, req.ifa.ifa_family); 636 get_prefix(&peer, *argv, req.ifa.ifa_family);
633 peer_len = peer.bytelen; 637 peer_len = peer.bytelen;
@@ -639,7 +643,7 @@ static int ipaddr_modify(int cmd, int flags, char **argv)
639 } else if (arg <= 3) { /* broadcast, brd */ 643 } else if (arg <= 3) { /* broadcast, brd */
640 inet_prefix addr; 644 inet_prefix addr;
641 if (brd_len) { 645 if (brd_len) {
642 duparg("broadcast", *argv); 646 duparg(option_broadcast, *argv);
643 } 647 }
644 if (LONE_CHAR(*argv, '+')) { 648 if (LONE_CHAR(*argv, '+')) {
645 brd_len = -1; 649 brd_len = -1;
@@ -655,7 +659,7 @@ static int ipaddr_modify(int cmd, int flags, char **argv)
655 } else if (arg == 4) { /* anycast */ 659 } else if (arg == 4) { /* anycast */
656 inet_prefix addr; 660 inet_prefix addr;
657 if (any_len) { 661 if (any_len) {
658 duparg("anycast", *argv); 662 duparg(option_anycast, *argv);
659 } 663 }
660 get_addr(&addr, *argv, req.ifa.ifa_family); 664 get_addr(&addr, *argv, req.ifa.ifa_family);
661 if (req.ifa.ifa_family == AF_UNSPEC) { 665 if (req.ifa.ifa_family == AF_UNSPEC) {
diff --git a/networking/libiproute/iplink.c b/networking/libiproute/iplink.c
index ae3ef0ceb..aef5f6490 100644
--- a/networking/libiproute/iplink.c
+++ b/networking/libiproute/iplink.c
@@ -52,6 +52,9 @@ struct ifla_vlan_flags {
52# define dbg(...) ((void)0) 52# define dbg(...) ((void)0)
53#endif 53#endif
54 54
55
56#define str_on_off "on\0""off\0"
57
55/* Exits on error */ 58/* Exits on error */
56static int get_ctl_fd(void) 59static int get_ctl_fd(void)
57{ 60{
@@ -204,12 +207,14 @@ static int do_set(char **argv)
204 struct ifreq ifr0, ifr1; 207 struct ifreq ifr0, ifr1;
205 char *newname = NULL; 208 char *newname = NULL;
206 int htype, halen; 209 int htype, halen;
210 /* If you add stuff here, update iplink_full_usage */
207 static const char keywords[] ALIGN1 = 211 static const char keywords[] ALIGN1 =
208 "up\0""down\0""name\0""mtu\0""qlen\0""multicast\0" 212 "up\0""down\0""name\0""mtu\0""qlen\0""multicast\0"
209 "arp\0""address\0""dev\0"; 213 "arp\0""promisc\0""address\0"
214 "dev\0" /* must be last */;
210 enum { ARG_up = 0, ARG_down, ARG_name, ARG_mtu, ARG_qlen, ARG_multicast, 215 enum { ARG_up = 0, ARG_down, ARG_name, ARG_mtu, ARG_qlen, ARG_multicast,
211 ARG_arp, ARG_addr, ARG_dev }; 216 ARG_arp, ARG_promisc, ARG_addr,
212 static const char str_on_off[] ALIGN1 = "on\0""off\0"; 217 ARG_dev };
213 enum { PARM_on = 0, PARM_off }; 218 enum { PARM_on = 0, PARM_off };
214 smalluint key; 219 smalluint key;
215 220
@@ -232,6 +237,7 @@ static int do_set(char **argv)
232 duparg("mtu", *argv); 237 duparg("mtu", *argv);
233 mtu = get_unsigned(*argv, "mtu"); 238 mtu = get_unsigned(*argv, "mtu");
234 } else if (key == ARG_qlen) { 239 } else if (key == ARG_qlen) {
240//TODO: txqueuelen, txqlen are synonyms to qlen
235 NEXT_ARG(); 241 NEXT_ARG();
236 if (qlen != -1) 242 if (qlen != -1)
237 duparg("qlen", *argv); 243 duparg("qlen", *argv);
@@ -240,6 +246,7 @@ static int do_set(char **argv)
240 NEXT_ARG(); 246 NEXT_ARG();
241 newaddr = *argv; 247 newaddr = *argv;
242 } else if (key >= ARG_dev) { 248 } else if (key >= ARG_dev) {
249 /* ^^^^^^ ">=" here results in "dev IFACE" treated as default */
243 if (key == ARG_dev) { 250 if (key == ARG_dev) {
244 NEXT_ARG(); 251 NEXT_ARG();
245 } 252 }
@@ -247,6 +254,7 @@ static int do_set(char **argv)
247 duparg2("dev", *argv); 254 duparg2("dev", *argv);
248 dev = *argv; 255 dev = *argv;
249 } else { 256 } else {
257 /* "on|off" options */
250 int param; 258 int param;
251 NEXT_ARG(); 259 NEXT_ARG();
252 param = index_in_strings(str_on_off, *argv); 260 param = index_in_strings(str_on_off, *argv);
@@ -266,8 +274,132 @@ static int do_set(char **argv)
266 flags &= ~IFF_NOARP; 274 flags &= ~IFF_NOARP;
267 else 275 else
268 flags |= IFF_NOARP; 276 flags |= IFF_NOARP;
277 } else if (key == ARG_promisc) {
278 if (param < 0)
279 die_must_be_on_off("promisc");
280 mask |= IFF_PROMISC;
281 if (param == PARM_on)
282 flags |= IFF_PROMISC;
283 else
284 flags &= ~IFF_PROMISC;
269 } 285 }
270 } 286 }
287
288/* Other keywords recognized by iproute2-3.12.0: */
289#if 0
290 } else if (matches(*argv, "broadcast") == 0 ||
291 strcmp(*argv, "brd") == 0) {
292 NEXT_ARG();
293 len = ll_addr_a2n(abuf, sizeof(abuf), *argv);
294 if (len < 0)
295 return -1;
296 addattr_l(&req->n, sizeof(*req), IFLA_BROADCAST, abuf, len);
297 } else if (strcmp(*argv, "netns") == 0) {
298 NEXT_ARG();
299 if (netns != -1)
300 duparg("netns", *argv);
301 if ((netns = get_netns_fd(*argv)) >= 0)
302 addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_FD, &netns, 4);
303 else if (get_integer(&netns, *argv, 0) == 0)
304 addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_PID, &netns, 4);
305 else
306 invarg_1_to_2(*argv, "netns");
307 } else if (strcmp(*argv, "allmulticast") == 0) {
308 NEXT_ARG();
309 req->i.ifi_change |= IFF_ALLMULTI;
310 if (strcmp(*argv, "on") == 0) {
311 req->i.ifi_flags |= IFF_ALLMULTI;
312 } else if (strcmp(*argv, "off") == 0) {
313 req->i.ifi_flags &= ~IFF_ALLMULTI;
314 } else
315 return on_off("allmulticast", *argv);
316 } else if (strcmp(*argv, "trailers") == 0) {
317 NEXT_ARG();
318 req->i.ifi_change |= IFF_NOTRAILERS;
319 if (strcmp(*argv, "off") == 0) {
320 req->i.ifi_flags |= IFF_NOTRAILERS;
321 } else if (strcmp(*argv, "on") == 0) {
322 req->i.ifi_flags &= ~IFF_NOTRAILERS;
323 } else
324 return on_off("trailers", *argv);
325 } else if (strcmp(*argv, "vf") == 0) {
326 struct rtattr *vflist;
327 NEXT_ARG();
328 if (get_integer(&vf, *argv, 0)) {
329 invarg_1_to_2(*argv, "vf");
330 }
331 vflist = addattr_nest(&req->n, sizeof(*req),
332 IFLA_VFINFO_LIST);
333 len = iplink_parse_vf(vf, &argc, &argv, req);
334 if (len < 0)
335 return -1;
336 addattr_nest_end(&req->n, vflist);
337 } else if (matches(*argv, "master") == 0) {
338 int ifindex;
339 NEXT_ARG();
340 ifindex = ll_name_to_index(*argv);
341 if (!ifindex)
342 invarg_1_to_2(*argv, "master");
343 addattr_l(&req->n, sizeof(*req), IFLA_MASTER,
344 &ifindex, 4);
345 } else if (matches(*argv, "nomaster") == 0) {
346 int ifindex = 0;
347 addattr_l(&req->n, sizeof(*req), IFLA_MASTER,
348 &ifindex, 4);
349 } else if (matches(*argv, "dynamic") == 0) {
350 NEXT_ARG();
351 req->i.ifi_change |= IFF_DYNAMIC;
352 if (strcmp(*argv, "on") == 0) {
353 req->i.ifi_flags |= IFF_DYNAMIC;
354 } else if (strcmp(*argv, "off") == 0) {
355 req->i.ifi_flags &= ~IFF_DYNAMIC;
356 } else
357 return on_off("dynamic", *argv);
358 } else if (matches(*argv, "alias") == 0) {
359 NEXT_ARG();
360 addattr_l(&req->n, sizeof(*req), IFLA_IFALIAS,
361 *argv, strlen(*argv));
362 argc--; argv++;
363 break;
364 } else if (strcmp(*argv, "group") == 0) {
365 NEXT_ARG();
366 if (*group != -1)
367 duparg("group", *argv);
368 if (rtnl_group_a2n(group, *argv))
369 invarg_1_to_2(*argv, "group");
370 } else if (strcmp(*argv, "mode") == 0) {
371 int mode;
372 NEXT_ARG();
373 mode = get_link_mode(*argv);
374 if (mode < 0)
375 invarg_1_to_2(*argv, "mode");
376 addattr8(&req->n, sizeof(*req), IFLA_LINKMODE, mode);
377 } else if (strcmp(*argv, "state") == 0) {
378 int state;
379 NEXT_ARG();
380 state = get_operstate(*argv);
381 if (state < 0)
382 invarg_1_to_2(*argv, "state");
383 addattr8(&req->n, sizeof(*req), IFLA_OPERSTATE, state);
384 } else if (matches(*argv, "numtxqueues") == 0) {
385 NEXT_ARG();
386 if (numtxqueues != -1)
387 duparg("numtxqueues", *argv);
388 if (get_integer(&numtxqueues, *argv, 0))
389 invarg_1_to_2(*argv, "numtxqueues");
390 addattr_l(&req->n, sizeof(*req), IFLA_NUM_TX_QUEUES,
391 &numtxqueues, 4);
392 } else if (matches(*argv, "numrxqueues") == 0) {
393 NEXT_ARG();
394 if (numrxqueues != -1)
395 duparg("numrxqueues", *argv);
396 if (get_integer(&numrxqueues, *argv, 0))
397 invarg_1_to_2(*argv, "numrxqueues");
398 addattr_l(&req->n, sizeof(*req), IFLA_NUM_RX_QUEUES,
399 &numrxqueues, 4);
400 }
401#endif
402
271 argv++; 403 argv++;
272 } 404 }
273 405
@@ -322,10 +454,6 @@ static void vlan_parse_opt(char **argv, struct nlmsghdr *n, unsigned int size)
322 "802.1q\0" 454 "802.1q\0"
323 "802.1ad\0" 455 "802.1ad\0"
324 ; 456 ;
325 static const char str_on_off[] ALIGN1 =
326 "on\0"
327 "off\0"
328 ;
329 enum { 457 enum {
330 ARG_id = 0, 458 ARG_id = 0,
331 ARG_reorder_hdr, 459 ARG_reorder_hdr,
@@ -520,164 +648,6 @@ static int do_add_or_delete(char **argv, const unsigned rtm)
520 return 0; 648 return 0;
521} 649}
522 650
523/* Other keywords recognized by iproute2-3.12.0: */
524#if 0
525 } else if (matches(*argv, "broadcast") == 0 ||
526 strcmp(*argv, "brd") == 0) {
527 NEXT_ARG();
528 len = ll_addr_a2n(abuf, sizeof(abuf), *argv);
529 if (len < 0)
530 return -1;
531 addattr_l(&req->n, sizeof(*req), IFLA_BROADCAST, abuf, len);
532 } else if (matches(*argv, "txqueuelen") == 0 ||
533 strcmp(*argv, "qlen") == 0 ||
534 matches(*argv, "txqlen") == 0) {
535 NEXT_ARG();
536 if (qlen != -1)
537 duparg("txqueuelen", *argv);
538 if (get_integer(&qlen, *argv, 0))
539 invarg_1_to_2(*argv, "txqueuelen");
540 addattr_l(&req->n, sizeof(*req), IFLA_TXQLEN, &qlen, 4);
541 } else if (strcmp(*argv, "mtu") == 0) {
542 NEXT_ARG();
543 if (mtu != -1)
544 duparg("mtu", *argv);
545 if (get_integer(&mtu, *argv, 0))
546 invarg_1_to_2(*argv, "mtu");
547 addattr_l(&req->n, sizeof(*req), IFLA_MTU, &mtu, 4);
548 } else if (strcmp(*argv, "netns") == 0) {
549 NEXT_ARG();
550 if (netns != -1)
551 duparg("netns", *argv);
552 if ((netns = get_netns_fd(*argv)) >= 0)
553 addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_FD, &netns, 4);
554 else if (get_integer(&netns, *argv, 0) == 0)
555 addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_PID, &netns, 4);
556 else
557 invarg_1_to_2(*argv, "netns");
558 } else if (strcmp(*argv, "multicast") == 0) {
559 NEXT_ARG();
560 req->i.ifi_change |= IFF_MULTICAST;
561 if (strcmp(*argv, "on") == 0) {
562 req->i.ifi_flags |= IFF_MULTICAST;
563 } else if (strcmp(*argv, "off") == 0) {
564 req->i.ifi_flags &= ~IFF_MULTICAST;
565 } else
566 return on_off("multicast", *argv);
567 } else if (strcmp(*argv, "allmulticast") == 0) {
568 NEXT_ARG();
569 req->i.ifi_change |= IFF_ALLMULTI;
570 if (strcmp(*argv, "on") == 0) {
571 req->i.ifi_flags |= IFF_ALLMULTI;
572 } else if (strcmp(*argv, "off") == 0) {
573 req->i.ifi_flags &= ~IFF_ALLMULTI;
574 } else
575 return on_off("allmulticast", *argv);
576 } else if (strcmp(*argv, "promisc") == 0) {
577 NEXT_ARG();
578 req->i.ifi_change |= IFF_PROMISC;
579 if (strcmp(*argv, "on") == 0) {
580 req->i.ifi_flags |= IFF_PROMISC;
581 } else if (strcmp(*argv, "off") == 0) {
582 req->i.ifi_flags &= ~IFF_PROMISC;
583 } else
584 return on_off("promisc", *argv);
585 } else if (strcmp(*argv, "trailers") == 0) {
586 NEXT_ARG();
587 req->i.ifi_change |= IFF_NOTRAILERS;
588 if (strcmp(*argv, "off") == 0) {
589 req->i.ifi_flags |= IFF_NOTRAILERS;
590 } else if (strcmp(*argv, "on") == 0) {
591 req->i.ifi_flags &= ~IFF_NOTRAILERS;
592 } else
593 return on_off("trailers", *argv);
594 } else if (strcmp(*argv, "arp") == 0) {
595 NEXT_ARG();
596 req->i.ifi_change |= IFF_NOARP;
597 if (strcmp(*argv, "on") == 0) {
598 req->i.ifi_flags &= ~IFF_NOARP;
599 } else if (strcmp(*argv, "off") == 0) {
600 req->i.ifi_flags |= IFF_NOARP;
601 } else
602 return on_off("noarp", *argv);
603 } else if (strcmp(*argv, "vf") == 0) {
604 struct rtattr *vflist;
605 NEXT_ARG();
606 if (get_integer(&vf, *argv, 0)) {
607 invarg_1_to_2(*argv, "vf");
608 }
609 vflist = addattr_nest(&req->n, sizeof(*req),
610 IFLA_VFINFO_LIST);
611 len = iplink_parse_vf(vf, &argc, &argv, req);
612 if (len < 0)
613 return -1;
614 addattr_nest_end(&req->n, vflist);
615 } else if (matches(*argv, "master") == 0) {
616 int ifindex;
617 NEXT_ARG();
618 ifindex = ll_name_to_index(*argv);
619 if (!ifindex)
620 invarg_1_to_2(*argv, "master");
621 addattr_l(&req->n, sizeof(*req), IFLA_MASTER,
622 &ifindex, 4);
623 } else if (matches(*argv, "nomaster") == 0) {
624 int ifindex = 0;
625 addattr_l(&req->n, sizeof(*req), IFLA_MASTER,
626 &ifindex, 4);
627 } else if (matches(*argv, "dynamic") == 0) {
628 NEXT_ARG();
629 req->i.ifi_change |= IFF_DYNAMIC;
630 if (strcmp(*argv, "on") == 0) {
631 req->i.ifi_flags |= IFF_DYNAMIC;
632 } else if (strcmp(*argv, "off") == 0) {
633 req->i.ifi_flags &= ~IFF_DYNAMIC;
634 } else
635 return on_off("dynamic", *argv);
636 } else if (matches(*argv, "alias") == 0) {
637 NEXT_ARG();
638 addattr_l(&req->n, sizeof(*req), IFLA_IFALIAS,
639 *argv, strlen(*argv));
640 argc--; argv++;
641 break;
642 } else if (strcmp(*argv, "group") == 0) {
643 NEXT_ARG();
644 if (*group != -1)
645 duparg("group", *argv);
646 if (rtnl_group_a2n(group, *argv))
647 invarg_1_to_2(*argv, "group");
648 } else if (strcmp(*argv, "mode") == 0) {
649 int mode;
650 NEXT_ARG();
651 mode = get_link_mode(*argv);
652 if (mode < 0)
653 invarg_1_to_2(*argv, "mode");
654 addattr8(&req->n, sizeof(*req), IFLA_LINKMODE, mode);
655 } else if (strcmp(*argv, "state") == 0) {
656 int state;
657 NEXT_ARG();
658 state = get_operstate(*argv);
659 if (state < 0)
660 invarg_1_to_2(*argv, "state");
661 addattr8(&req->n, sizeof(*req), IFLA_OPERSTATE, state);
662 } else if (matches(*argv, "numtxqueues") == 0) {
663 NEXT_ARG();
664 if (numtxqueues != -1)
665 duparg("numtxqueues", *argv);
666 if (get_integer(&numtxqueues, *argv, 0))
667 invarg_1_to_2(*argv, "numtxqueues");
668 addattr_l(&req->n, sizeof(*req), IFLA_NUM_TX_QUEUES,
669 &numtxqueues, 4);
670 } else if (matches(*argv, "numrxqueues") == 0) {
671 NEXT_ARG();
672 if (numrxqueues != -1)
673 duparg("numrxqueues", *argv);
674 if (get_integer(&numrxqueues, *argv, 0))
675 invarg_1_to_2(*argv, "numrxqueues");
676 addattr_l(&req->n, sizeof(*req), IFLA_NUM_RX_QUEUES,
677 &numrxqueues, 4);
678 }
679#endif
680
681/* Return value becomes exitcode. It's okay to not return at all */ 651/* Return value becomes exitcode. It's okay to not return at all */
682int FAST_FUNC do_iplink(char **argv) 652int FAST_FUNC do_iplink(char **argv)
683{ 653{
diff --git a/networking/libiproute/iproute.c b/networking/libiproute/iproute.c
index 0f2b89682..cc3443a92 100644
--- a/networking/libiproute/iproute.c
+++ b/networking/libiproute/iproute.c
@@ -322,16 +322,31 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
322 return 0; 322 return 0;
323} 323}
324 324
325static int str_is_lock(const char *str)
326{
327 return strcmp(str, "lock") == 0;
328}
329
325/* Return value becomes exitcode. It's okay to not return at all */ 330/* Return value becomes exitcode. It's okay to not return at all */
326static int iproute_modify(int cmd, unsigned flags, char **argv) 331static int iproute_modify(int cmd, unsigned flags, char **argv)
327{ 332{
333 /* If you add stuff here, update iproute_full_usage */
328 static const char keywords[] ALIGN1 = 334 static const char keywords[] ALIGN1 =
329 "src\0""via\0""mtu\0""lock\0""scope\0""protocol\0"IF_FEATURE_IP_RULE("table\0") 335 "src\0""via\0"
336 "mtu\0""advmss\0"
337 "scope\0""protocol\0"IF_FEATURE_IP_RULE("table\0")
330 "dev\0""oif\0""to\0""metric\0""onlink\0"; 338 "dev\0""oif\0""to\0""metric\0""onlink\0";
339#define keyword_via (keywords + sizeof("src"))
340#define keyword_mtu (keyword_via + sizeof("via"))
341#define keyword_advmss (keyword_mtu + sizeof("mtu"))
342#define keyword_scope (keyword_advmss + sizeof("advmss"))
343#define keyword_proto (keyword_scope + sizeof("scope"))
344#define keyword_table (keyword_proto + sizeof("protocol"))
331 enum { 345 enum {
332 ARG_src, 346 ARG_src,
333 ARG_via, 347 ARG_via,
334 ARG_mtu, PARM_lock, 348 ARG_mtu,
349 ARG_advmss,
335 ARG_scope, 350 ARG_scope,
336 ARG_protocol, 351 ARG_protocol,
337IF_FEATURE_IP_RULE(ARG_table,) 352IF_FEATURE_IP_RULE(ARG_table,)
@@ -404,24 +419,33 @@ IF_FEATURE_IP_RULE(ARG_table,)
404 } else if (arg == ARG_mtu) { 419 } else if (arg == ARG_mtu) {
405 unsigned mtu; 420 unsigned mtu;
406 NEXT_ARG(); 421 NEXT_ARG();
407 if (index_in_strings(keywords, *argv) == PARM_lock) { 422 if (str_is_lock(*argv)) {
408 mxlock |= (1 << RTAX_MTU); 423 mxlock |= (1 << RTAX_MTU);
409 NEXT_ARG(); 424 NEXT_ARG();
410 } 425 }
411 mtu = get_unsigned(*argv, "mtu"); 426 mtu = get_unsigned(*argv, keyword_mtu);
412 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_MTU, mtu); 427 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_MTU, mtu);
428 } else if (arg == ARG_advmss) {
429 unsigned mss;
430 NEXT_ARG();
431 if (str_is_lock(*argv)) {
432 mxlock |= (1 << RTAX_ADVMSS);
433 NEXT_ARG();
434 }
435 mss = get_unsigned(*argv, keyword_advmss);
436 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_ADVMSS, mss);
413 } else if (arg == ARG_scope) { 437 } else if (arg == ARG_scope) {
414 uint32_t scope; 438 uint32_t scope;
415 NEXT_ARG(); 439 NEXT_ARG();
416 if (rtnl_rtscope_a2n(&scope, *argv)) 440 if (rtnl_rtscope_a2n(&scope, *argv))
417 invarg_1_to_2(*argv, "scope"); 441 invarg_1_to_2(*argv, keyword_scope);
418 req.r.rtm_scope = scope; 442 req.r.rtm_scope = scope;
419 scope_ok = 1; 443 scope_ok = 1;
420 } else if (arg == ARG_protocol) { 444 } else if (arg == ARG_protocol) {
421 uint32_t prot; 445 uint32_t prot;
422 NEXT_ARG(); 446 NEXT_ARG();
423 if (rtnl_rtprot_a2n(&prot, *argv)) 447 if (rtnl_rtprot_a2n(&prot, *argv))
424 invarg_1_to_2(*argv, "protocol"); 448 invarg_1_to_2(*argv, keyword_proto);
425 req.r.rtm_protocol = prot; 449 req.r.rtm_protocol = prot;
426 ok |= proto_ok; 450 ok |= proto_ok;
427#if ENABLE_FEATURE_IP_RULE 451#if ENABLE_FEATURE_IP_RULE
@@ -429,7 +453,7 @@ IF_FEATURE_IP_RULE(ARG_table,)
429 uint32_t tid; 453 uint32_t tid;
430 NEXT_ARG(); 454 NEXT_ARG();
431 if (rtnl_rttable_a2n(&tid, *argv)) 455 if (rtnl_rttable_a2n(&tid, *argv))
432 invarg_1_to_2(*argv, "table"); 456 invarg_1_to_2(*argv, keyword_table);
433 if (tid < 256) 457 if (tid < 256)
434 req.r.rtm_table = tid; 458 req.r.rtm_table = tid;
435 else { 459 else {
@@ -441,6 +465,7 @@ IF_FEATURE_IP_RULE(ARG_table,)
441 NEXT_ARG(); 465 NEXT_ARG();
442 d = *argv; 466 d = *argv;
443 } else if (arg == ARG_metric) { 467 } else if (arg == ARG_metric) {
468//TODO: "metric", "priority" and "preference" are synonyms
444 uint32_t metric; 469 uint32_t metric;
445 NEXT_ARG(); 470 NEXT_ARG();
446 metric = get_u32(*argv, "metric"); 471 metric = get_u32(*argv, "metric");
@@ -475,6 +500,158 @@ IF_FEATURE_IP_RULE(ARG_table,)
475 addattr_l(&req.n, sizeof(req), RTA_DST, &dst.data, dst.bytelen); 500 addattr_l(&req.n, sizeof(req), RTA_DST, &dst.data, dst.bytelen);
476 } 501 }
477 } 502 }
503/* Other keywords recognized by iproute2-3.19.0: */
504#if 0
505 } else if (strcmp(*argv, "from") == 0) {
506 inet_prefix addr;
507 NEXT_ARG();
508 get_prefix(&addr, *argv, req.r.rtm_family);
509 if (req.r.rtm_family == AF_UNSPEC)
510 req.r.rtm_family = addr.family;
511 if (addr.bytelen)
512 addattr_l(&req.n, sizeof(req), RTA_SRC, &addr.data, addr.bytelen);
513 req.r.rtm_src_len = addr.bitlen;
514 } else if (strcmp(*argv, "tos") == 0 ||
515 matches(*argv, "dsfield") == 0) {
516 __u32 tos;
517 NEXT_ARG();
518 if (rtnl_dsfield_a2n(&tos, *argv))
519 invarg("\"tos\" value is invalid\n", *argv);
520 req.r.rtm_tos = tos;
521 } else if (strcmp(*argv, "hoplimit") == 0) {
522 unsigned hoplimit;
523 NEXT_ARG();
524 if (strcmp(*argv, "lock") == 0) {
525 mxlock |= (1<<RTAX_HOPLIMIT);
526 NEXT_ARG();
527 }
528 if (get_unsigned(&hoplimit, *argv, 0))
529 invarg("\"hoplimit\" value is invalid\n", *argv);
530 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_HOPLIMIT, hoplimit);
531 } else if (matches(*argv, "reordering") == 0) {
532 unsigned reord;
533 NEXT_ARG();
534 if (strcmp(*argv, "lock") == 0) {
535 mxlock |= (1<<RTAX_REORDERING);
536 NEXT_ARG();
537 }
538 if (get_unsigned(&reord, *argv, 0))
539 invarg("\"reordering\" value is invalid\n", *argv);
540 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_REORDERING, reord);
541 } else if (strcmp(*argv, "rtt") == 0) {
542 unsigned rtt;
543 NEXT_ARG();
544 if (strcmp(*argv, "lock") == 0) {
545 mxlock |= (1<<RTAX_RTT);
546 NEXT_ARG();
547 }
548 if (get_time_rtt(&rtt, *argv, &raw))
549 invarg("\"rtt\" value is invalid\n", *argv);
550 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_RTT,
551 (raw) ? rtt : rtt * 8);
552 } else if (strcmp(*argv, "rto_min") == 0) {
553 unsigned rto_min;
554 NEXT_ARG();
555 mxlock |= (1<<RTAX_RTO_MIN);
556 if (get_time_rtt(&rto_min, *argv, &raw))
557 invarg("\"rto_min\" value is invalid\n",
558 *argv);
559 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_RTO_MIN,
560 rto_min);
561 } else if (matches(*argv, "window") == 0) {
562 unsigned win;
563 NEXT_ARG();
564 if (strcmp(*argv, "lock") == 0) {
565 mxlock |= (1<<RTAX_WINDOW);
566 NEXT_ARG();
567 }
568 if (get_unsigned(&win, *argv, 0))
569 invarg("\"window\" value is invalid\n", *argv);
570 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_WINDOW, win);
571 } else if (matches(*argv, "cwnd") == 0) {
572 unsigned win;
573 NEXT_ARG();
574 if (strcmp(*argv, "lock") == 0) {
575 mxlock |= (1<<RTAX_CWND);
576 NEXT_ARG();
577 }
578 if (get_unsigned(&win, *argv, 0))
579 invarg("\"cwnd\" value is invalid\n", *argv);
580 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_CWND, win);
581 } else if (matches(*argv, "initcwnd") == 0) {
582 unsigned win;
583 NEXT_ARG();
584 if (strcmp(*argv, "lock") == 0) {
585 mxlock |= (1<<RTAX_INITCWND);
586 NEXT_ARG();
587 }
588 if (get_unsigned(&win, *argv, 0))
589 invarg("\"initcwnd\" value is invalid\n", *argv);
590 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_INITCWND, win);
591 } else if (matches(*argv, "initrwnd") == 0) {
592 unsigned win;
593 NEXT_ARG();
594 if (strcmp(*argv, "lock") == 0) {
595 mxlock |= (1<<RTAX_INITRWND);
596 NEXT_ARG();
597 }
598 if (get_unsigned(&win, *argv, 0))
599 invarg("\"initrwnd\" value is invalid\n", *argv);
600 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_INITRWND, win);
601 } else if (matches(*argv, "features") == 0) {
602 unsigned int features = 0;
603
604 while (argc > 0) {
605 NEXT_ARG();
606
607 if (strcmp(*argv, "ecn") == 0)
608 features |= RTAX_FEATURE_ECN;
609 else
610 invarg("\"features\" value not valid\n", *argv);
611 break;
612 }
613
614 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_FEATURES, features);
615 } else if (matches(*argv, "quickack") == 0) {
616 unsigned quickack;
617 NEXT_ARG();
618 if (get_unsigned(&quickack, *argv, 0))
619 invarg("\"quickack\" value is invalid\n", *argv);
620 if (quickack != 1 && quickack != 0)
621 invarg("\"quickack\" value should be 0 or 1\n", *argv);
622 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_QUICKACK, quickack);
623 } else if (matches(*argv, "rttvar") == 0) {
624 unsigned win;
625 NEXT_ARG();
626 if (strcmp(*argv, "lock") == 0) {
627 mxlock |= (1<<RTAX_RTTVAR);
628 NEXT_ARG();
629 }
630 if (get_time_rtt(&win, *argv, &raw))
631 invarg("\"rttvar\" value is invalid\n", *argv);
632 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_RTTVAR,
633 (raw) ? win : win * 4);
634 } else if (matches(*argv, "ssthresh") == 0) {
635 unsigned win;
636 NEXT_ARG();
637 if (strcmp(*argv, "lock") == 0) {
638 mxlock |= (1<<RTAX_SSTHRESH);
639 NEXT_ARG();
640 }
641 if (get_unsigned(&win, *argv, 0))
642 invarg("\"ssthresh\" value is invalid\n", *argv);
643 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_SSTHRESH, win);
644 } else if (matches(*argv, "realms") == 0) {
645 __u32 realm;
646 NEXT_ARG();
647 if (get_rt_realms(&realm, *argv))
648 invarg("\"realm\" value is invalid\n", *argv);
649 addattr32(&req.n, sizeof(req), RTA_FLOW, realm);
650 } else if (strcmp(*argv, "nexthop") == 0) {
651 nhs_ok = 1;
652 break;
653 }
654#endif
478 argv++; 655 argv++;
479 } 656 }
480 657
@@ -912,9 +1089,15 @@ static int iproute_get(char **argv)
912int FAST_FUNC do_iproute(char **argv) 1089int FAST_FUNC do_iproute(char **argv)
913{ 1090{
914 static const char ip_route_commands[] ALIGN1 = 1091 static const char ip_route_commands[] ALIGN1 =
915 /*0-3*/ "add\0""append\0""change\0""chg\0" 1092 "a\0""add\0""append\0""change\0""chg\0"
916 /*4-7*/ "delete\0""get\0""list\0""show\0" 1093 "delete\0""get\0""list\0""show\0"
917 /*8..*/ "prepend\0""replace\0""test\0""flush\0"; 1094 "prepend\0""replace\0""test\0""flush\0"
1095 ;
1096 enum {
1097 CMD_a = 0, CMD_add, CMD_append, CMD_change, CMD_chg,
1098 CMD_delete, CMD_get, CMD_list, CMD_show,
1099 CMD_prepend, CMD_replace, CMD_test, CMD_flush,
1100 };
918 int command_num; 1101 int command_num;
919 unsigned flags = 0; 1102 unsigned flags = 0;
920 int cmd = RTM_NEWROUTE; 1103 int cmd = RTM_NEWROUTE;
@@ -929,38 +1112,39 @@ int FAST_FUNC do_iproute(char **argv)
929 command_num = index_in_substrings(ip_route_commands, *argv); 1112 command_num = index_in_substrings(ip_route_commands, *argv);
930 1113
931 switch (command_num) { 1114 switch (command_num) {
932 case 0: /* add */ 1115 case CMD_a:
1116 case CMD_add:
933 flags = NLM_F_CREATE|NLM_F_EXCL; 1117 flags = NLM_F_CREATE|NLM_F_EXCL;
934 break; 1118 break;
935 case 1: /* append */ 1119 case CMD_append:
936 flags = NLM_F_CREATE|NLM_F_APPEND; 1120 flags = NLM_F_CREATE|NLM_F_APPEND;
937 break; 1121 break;
938 case 2: /* change */ 1122 case CMD_change:
939 case 3: /* chg */ 1123 case CMD_chg:
940 flags = NLM_F_REPLACE; 1124 flags = NLM_F_REPLACE;
941 break; 1125 break;
942 case 4: /* delete */ 1126 case CMD_delete:
943 cmd = RTM_DELROUTE; 1127 cmd = RTM_DELROUTE;
944 break; 1128 break;
945 case 5: /* get */ 1129 case CMD_get:
946 return iproute_get(argv+1); 1130 return iproute_get(argv + 1);
947 case 6: /* list */ 1131 case CMD_list:
948 case 7: /* show */ 1132 case CMD_show:
949 return iproute_list_or_flush(argv+1, 0); 1133 return iproute_list_or_flush(argv + 1, 0);
950 case 8: /* prepend */ 1134 case CMD_prepend:
951 flags = NLM_F_CREATE; 1135 flags = NLM_F_CREATE;
952 break; 1136 break;
953 case 9: /* replace */ 1137 case CMD_replace:
954 flags = NLM_F_CREATE|NLM_F_REPLACE; 1138 flags = NLM_F_CREATE|NLM_F_REPLACE;
955 break; 1139 break;
956 case 10: /* test */ 1140 case CMD_test:
957 flags = NLM_F_EXCL; 1141 flags = NLM_F_EXCL;
958 break; 1142 break;
959 case 11: /* flush */ 1143 case CMD_flush:
960 return iproute_list_or_flush(argv+1, 1); 1144 return iproute_list_or_flush(argv + 1, 1);
961 default: 1145 default:
962 invarg_1_to_2(*argv, applet_name); 1146 invarg_1_to_2(*argv, applet_name);
963 } 1147 }
964 1148
965 return iproute_modify(cmd, flags, argv+1); 1149 return iproute_modify(cmd, flags, argv + 1);
966} 1150}
diff --git a/networking/libiproute/utils.c b/networking/libiproute/utils.c
index 42025bc66..fca167ac6 100644
--- a/networking/libiproute/utils.c
+++ b/networking/libiproute/utils.c
@@ -13,7 +13,7 @@
13#include "utils.h" 13#include "utils.h"
14#include "inet_common.h" 14#include "inet_common.h"
15 15
16unsigned get_hz(void) 16unsigned FAST_FUNC get_hz(void)
17{ 17{
18 static unsigned hz_internal; 18 static unsigned hz_internal;
19 FILE *fp; 19 FILE *fp;
@@ -35,7 +35,7 @@ unsigned get_hz(void)
35 return hz_internal; 35 return hz_internal;
36} 36}
37 37
38unsigned get_unsigned(char *arg, const char *errmsg) 38unsigned FAST_FUNC get_unsigned(char *arg, const char *errmsg)
39{ 39{
40 unsigned long res; 40 unsigned long res;
41 char *ptr; 41 char *ptr;
@@ -50,7 +50,7 @@ unsigned get_unsigned(char *arg, const char *errmsg)
50 invarg_1_to_2(arg, errmsg); /* does not return */ 50 invarg_1_to_2(arg, errmsg); /* does not return */
51} 51}
52 52
53uint32_t get_u32(char *arg, const char *errmsg) 53uint32_t FAST_FUNC get_u32(char *arg, const char *errmsg)
54{ 54{
55 unsigned long res; 55 unsigned long res;
56 char *ptr; 56 char *ptr;
@@ -65,7 +65,7 @@ uint32_t get_u32(char *arg, const char *errmsg)
65 invarg_1_to_2(arg, errmsg); /* does not return */ 65 invarg_1_to_2(arg, errmsg); /* does not return */
66} 66}
67 67
68uint16_t get_u16(char *arg, const char *errmsg) 68uint16_t FAST_FUNC get_u16(char *arg, const char *errmsg)
69{ 69{
70 unsigned long res; 70 unsigned long res;
71 char *ptr; 71 char *ptr;
@@ -80,7 +80,7 @@ uint16_t get_u16(char *arg, const char *errmsg)
80 invarg_1_to_2(arg, errmsg); /* does not return */ 80 invarg_1_to_2(arg, errmsg); /* does not return */
81} 81}
82 82
83int get_addr_1(inet_prefix *addr, char *name, int family) 83int FAST_FUNC get_addr_1(inet_prefix *addr, char *name, int family)
84{ 84{
85 memset(addr, 0, sizeof(*addr)); 85 memset(addr, 0, sizeof(*addr));
86 86
@@ -199,7 +199,7 @@ static void get_prefix_1(inet_prefix *dst, char *arg, int family)
199 bb_error_msg_and_die("an %s %s is expected rather than \"%s\"", "inet", "prefix", arg); 199 bb_error_msg_and_die("an %s %s is expected rather than \"%s\"", "inet", "prefix", arg);
200} 200}
201 201
202int get_addr(inet_prefix *dst, char *arg, int family) 202int FAST_FUNC get_addr(inet_prefix *dst, char *arg, int family)
203{ 203{
204 if (family == AF_PACKET) { 204 if (family == AF_PACKET) {
205 bb_error_msg_and_die("\"%s\" may be inet %s, but it is not allowed in this context", arg, "address"); 205 bb_error_msg_and_die("\"%s\" may be inet %s, but it is not allowed in this context", arg, "address");
@@ -210,7 +210,7 @@ int get_addr(inet_prefix *dst, char *arg, int family)
210 return 0; 210 return 0;
211} 211}
212 212
213void get_prefix(inet_prefix *dst, char *arg, int family) 213void FAST_FUNC get_prefix(inet_prefix *dst, char *arg, int family)
214{ 214{
215 if (family == AF_PACKET) { 215 if (family == AF_PACKET) {
216 bb_error_msg_and_die("\"%s\" may be inet %s, but it is not allowed in this context", arg, "prefix"); 216 bb_error_msg_and_die("\"%s\" may be inet %s, but it is not allowed in this context", arg, "prefix");
@@ -218,7 +218,7 @@ void get_prefix(inet_prefix *dst, char *arg, int family)
218 get_prefix_1(dst, arg, family); 218 get_prefix_1(dst, arg, family);
219} 219}
220 220
221uint32_t get_addr32(char *name) 221uint32_t FAST_FUNC get_addr32(char *name)
222{ 222{
223 inet_prefix addr; 223 inet_prefix addr;
224 224
@@ -228,27 +228,29 @@ uint32_t get_addr32(char *name)
228 return addr.data[0]; 228 return addr.data[0];
229} 229}
230 230
231void incomplete_command(void) 231char** FAST_FUNC next_arg(char **argv)
232{ 232{
233 bb_error_msg_and_die("command line is not complete, try \"help\""); 233 if (!*++argv)
234 bb_error_msg_and_die("command line is not complete, try \"help\"");
235 return argv;
234} 236}
235 237
236void invarg_1_to_2(const char *arg, const char *opt) 238void FAST_FUNC invarg_1_to_2(const char *arg, const char *opt)
237{ 239{
238 bb_error_msg_and_die(bb_msg_invalid_arg_to, arg, opt); 240 bb_error_msg_and_die(bb_msg_invalid_arg_to, arg, opt);
239} 241}
240 242
241void duparg(const char *key, const char *arg) 243void FAST_FUNC duparg(const char *key, const char *arg)
242{ 244{
243 bb_error_msg_and_die("duplicate \"%s\": \"%s\" is the second value", key, arg); 245 bb_error_msg_and_die("duplicate \"%s\": \"%s\" is the second value", key, arg);
244} 246}
245 247
246void duparg2(const char *key, const char *arg) 248void FAST_FUNC duparg2(const char *key, const char *arg)
247{ 249{
248 bb_error_msg_and_die("either \"%s\" is duplicate, or \"%s\" is garbage", key, arg); 250 bb_error_msg_and_die("either \"%s\" is duplicate, or \"%s\" is garbage", key, arg);
249} 251}
250 252
251int inet_addr_match(const inet_prefix *a, const inet_prefix *b, int bits) 253int FAST_FUNC inet_addr_match(const inet_prefix *a, const inet_prefix *b, int bits)
252{ 254{
253 const uint32_t *a1 = a->data; 255 const uint32_t *a1 = a->data;
254 const uint32_t *a2 = b->data; 256 const uint32_t *a2 = b->data;
@@ -276,7 +278,7 @@ int inet_addr_match(const inet_prefix *a, const inet_prefix *b, int bits)
276 return 0; 278 return 0;
277} 279}
278 280
279const char *rt_addr_n2a(int af, void *addr) 281const char* FAST_FUNC rt_addr_n2a(int af, void *addr)
280{ 282{
281 switch (af) { 283 switch (af) {
282 case AF_INET: 284 case AF_INET:
@@ -290,7 +292,7 @@ const char *rt_addr_n2a(int af, void *addr)
290} 292}
291 293
292#ifdef RESOLVE_HOSTNAMES 294#ifdef RESOLVE_HOSTNAMES
293const char *format_host(int af, int len, void *addr) 295const char* FAST_FUNC format_host(int af, int len, void *addr)
294{ 296{
295 if (resolve_hosts) { 297 if (resolve_hosts) {
296 struct hostent *h_ent; 298 struct hostent *h_ent;
diff --git a/networking/libiproute/utils.h b/networking/libiproute/utils.h
index 408d5f65f..55490980d 100644
--- a/networking/libiproute/utils.h
+++ b/networking/libiproute/utils.h
@@ -26,10 +26,6 @@ extern char _SL_;
26#define SPRINT_BSIZE 64 26#define SPRINT_BSIZE 64
27#define SPRINT_BUF(x) char x[SPRINT_BSIZE] 27#define SPRINT_BUF(x) char x[SPRINT_BSIZE]
28 28
29extern void incomplete_command(void) NORETURN;
30
31#define NEXT_ARG() do { if (!*++argv) incomplete_command(); } while (0)
32
33typedef struct { 29typedef struct {
34 uint8_t family; 30 uint8_t family;
35 uint8_t bytelen; 31 uint8_t bytelen;
@@ -56,36 +52,40 @@ struct ipx_addr {
56 uint8_t ipx_node[IPX_NODE_LEN]; 52 uint8_t ipx_node[IPX_NODE_LEN];
57}; 53};
58 54
59extern uint32_t get_addr32(char *name); 55char** next_arg(char **argv) FAST_FUNC;
60extern int get_addr_1(inet_prefix *dst, char *arg, int family); 56#define NEXT_ARG() do { argv = next_arg(argv); } while (0)
61/*extern void get_prefix_1(inet_prefix *dst, char *arg, int family);*/
62extern int get_addr(inet_prefix *dst, char *arg, int family);
63extern void get_prefix(inet_prefix *dst, char *arg, int family);
64 57
65extern unsigned get_unsigned(char *arg, const char *errmsg); 58uint32_t get_addr32(char *name) FAST_FUNC;
66extern uint32_t get_u32(char *arg, const char *errmsg); 59int get_addr_1(inet_prefix *dst, char *arg, int family) FAST_FUNC;
67extern uint16_t get_u16(char *arg, const char *errmsg); 60/*void get_prefix_1(inet_prefix *dst, char *arg, int family) FAST_FUNC;*/
61int get_addr(inet_prefix *dst, char *arg, int family) FAST_FUNC;
62void get_prefix(inet_prefix *dst, char *arg, int family) FAST_FUNC;
68 63
69extern const char *rt_addr_n2a(int af, void *addr); 64unsigned get_unsigned(char *arg, const char *errmsg) FAST_FUNC;
65uint32_t get_u32(char *arg, const char *errmsg) FAST_FUNC;
66uint16_t get_u16(char *arg, const char *errmsg) FAST_FUNC;
67
68const char *rt_addr_n2a(int af, void *addr) FAST_FUNC;
70#ifdef RESOLVE_HOSTNAMES 69#ifdef RESOLVE_HOSTNAMES
71extern const char *format_host(int af, int len, void *addr); 70const char *format_host(int af, int len, void *addr) FAST_FUNC;
72#else 71#else
73#define format_host(af, len, addr) \ 72#define format_host(af, len, addr) \
74 rt_addr_n2a(af, addr) 73 rt_addr_n2a(af, addr)
75#endif 74#endif
76 75
77void invarg_1_to_2(const char *, const char *) NORETURN; 76void invarg_1_to_2(const char *, const char *) FAST_FUNC NORETURN;
78void duparg(const char *, const char *) NORETURN; 77void duparg(const char *, const char *) FAST_FUNC NORETURN;
79void duparg2(const char *, const char *) NORETURN; 78void duparg2(const char *, const char *) FAST_FUNC NORETURN;
80int inet_addr_match(const inet_prefix *a, const inet_prefix *b, int bits); 79
80int inet_addr_match(const inet_prefix *a, const inet_prefix *b, int bits) FAST_FUNC;
81 81
82const char *dnet_ntop(int af, const void *addr, char *str, size_t len); 82//const char *dnet_ntop(int af, const void *addr, char *str, size_t len);
83int dnet_pton(int af, const char *src, void *addr); 83//int dnet_pton(int af, const char *src, void *addr);
84 84
85const char *ipx_ntop(int af, const void *addr, char *str, size_t len); 85//const char *ipx_ntop(int af, const void *addr, char *str, size_t len);
86int ipx_pton(int af, const char *src, void *addr); 86//int ipx_pton(int af, const char *src, void *addr);
87 87
88unsigned get_hz(void); 88unsigned get_hz(void) FAST_FUNC;
89 89
90POP_SAVED_FUNCTION_VISIBILITY 90POP_SAVED_FUNCTION_VISIBILITY
91 91
diff --git a/networking/nc.c b/networking/nc.c
index 1b70434ac..d2b1ddcce 100644
--- a/networking/nc.c
+++ b/networking/nc.c
@@ -117,7 +117,7 @@ int nc_main(int argc, char **argv)
117 IF_NOT_NC_EXTRA (const) unsigned delay = 0; 117 IF_NOT_NC_EXTRA (const) unsigned delay = 0;
118 IF_NOT_NC_EXTRA (const int execparam = 0;) 118 IF_NOT_NC_EXTRA (const int execparam = 0;)
119 IF_NC_EXTRA (char **execparam = NULL;) 119 IF_NC_EXTRA (char **execparam = NULL;)
120 fd_set readfds, testfds; 120 struct pollfd pfds[2];
121 int opt; /* must be signed (getopt returns -1) */ 121 int opt; /* must be signed (getopt returns -1) */
122 122
123 if (ENABLE_NC_SERVER || ENABLE_NC_EXTRA) { 123 if (ENABLE_NC_SERVER || ENABLE_NC_EXTRA) {
@@ -235,29 +235,28 @@ int nc_main(int argc, char **argv)
235 IF_NC_EXTRA(bb_perror_msg_and_die("can't execute '%s'", execparam[0]);) 235 IF_NC_EXTRA(bb_perror_msg_and_die("can't execute '%s'", execparam[0]);)
236 } 236 }
237 237
238 /* Select loop copying stdin to cfd, and cfd to stdout */ 238 /* loop copying stdin to cfd, and cfd to stdout */
239 239
240 FD_ZERO(&readfds); 240 pfds[0].fd = STDIN_FILENO;
241 FD_SET(cfd, &readfds); 241 pfds[0].events = POLLIN;
242 FD_SET(STDIN_FILENO, &readfds); 242 pfds[1].fd = cfd;
243 pfds[1].events = POLLIN;
243 244
244#define iobuf bb_common_bufsiz1 245#define iobuf bb_common_bufsiz1
245 setup_common_bufsiz(); 246 setup_common_bufsiz();
246 for (;;) { 247 for (;;) {
247 int fd; 248 int fdidx;
248 int ofd; 249 int ofd;
249 int nread; 250 int nread;
250 251
251 testfds = readfds; 252 if (safe_poll(pfds, 2, -1) < 0)
253 bb_perror_msg_and_die("poll");
252 254
253 if (select(cfd + 1, &testfds, NULL, NULL, NULL) < 0) 255 fdidx = 0;
254 bb_perror_msg_and_die("select");
255
256 fd = STDIN_FILENO;
257 while (1) { 256 while (1) {
258 if (FD_ISSET(fd, &testfds)) { 257 if (pfds[fdidx].revents) {
259 nread = safe_read(fd, iobuf, COMMON_BUFSIZE); 258 nread = safe_read(pfds[fdidx].fd, iobuf, COMMON_BUFSIZE);
260 if (fd == cfd) { 259 if (fdidx != 0) {
261 if (nread < 1) 260 if (nread < 1)
262 exit(EXIT_SUCCESS); 261 exit(EXIT_SUCCESS);
263 ofd = STDOUT_FILENO; 262 ofd = STDOUT_FILENO;
@@ -266,7 +265,7 @@ int nc_main(int argc, char **argv)
266 /* Close outgoing half-connection so they get EOF, 265 /* Close outgoing half-connection so they get EOF,
267 * but leave incoming alone so we can see response */ 266 * but leave incoming alone so we can see response */
268 shutdown(cfd, SHUT_WR); 267 shutdown(cfd, SHUT_WR);
269 FD_CLR(STDIN_FILENO, &readfds); 268 pfds[0].fd = -1;
270 } 269 }
271 ofd = cfd; 270 ofd = cfd;
272 } 271 }
@@ -274,9 +273,9 @@ int nc_main(int argc, char **argv)
274 if (delay > 0) 273 if (delay > 0)
275 sleep(delay); 274 sleep(delay);
276 } 275 }
277 if (fd == cfd) 276 if (fdidx == 1)
278 break; 277 break;
279 fd = cfd; 278 fdidx++;
280 } 279 }
281 } 280 }
282} 281}
diff --git a/networking/nc_bloaty.c b/networking/nc_bloaty.c
index 192e42fe5..3db784982 100644
--- a/networking/nc_bloaty.c
+++ b/networking/nc_bloaty.c
@@ -459,7 +459,7 @@ create new one, and bind() it. TODO */
459 so I don't feel bad. 459 so I don't feel bad.
460 The *real* question is why BFD sockets wasn't designed to allow listens for 460 The *real* question is why BFD sockets wasn't designed to allow listens for
461 connections *from* specific hosts/ports, instead of requiring the caller to 461 connections *from* specific hosts/ports, instead of requiring the caller to
462 accept the connection and then reject undesireable ones by closing. 462 accept the connection and then reject undesirable ones by closing.
463 In other words, we need a TCP MSG_PEEK. */ 463 In other words, we need a TCP MSG_PEEK. */
464 /* bbox: removed most of it */ 464 /* bbox: removed most of it */
465 lcladdr = xmalloc_sockaddr2dotted(&ouraddr->u.sa); 465 lcladdr = xmalloc_sockaddr2dotted(&ouraddr->u.sa);
@@ -502,7 +502,7 @@ static int udptest(void)
502 /* use the tcp-ping trick: try connecting to a normally refused port, which 502 /* use the tcp-ping trick: try connecting to a normally refused port, which
503 causes us to block for the time that SYN gets there and RST gets back. 503 causes us to block for the time that SYN gets there and RST gets back.
504 Not completely reliable, but it *does* mostly work. */ 504 Not completely reliable, but it *does* mostly work. */
505 /* Set a temporary connect timeout, so packet filtration doesnt cause 505 /* Set a temporary connect timeout, so packet filtration doesn't cause
506 us to hang forever, and hit it */ 506 us to hang forever, and hit it */
507 o_wait = 5; /* enough that we'll notice?? */ 507 o_wait = 5; /* enough that we'll notice?? */
508 rr = xsocket(ouraddr->u.sa.sa_family, SOCK_STREAM, 0); 508 rr = xsocket(ouraddr->u.sa.sa_family, SOCK_STREAM, 0);
@@ -582,11 +582,10 @@ void oprint(int direction, unsigned char *p, unsigned bc);
582#endif 582#endif
583 583
584/* readwrite: 584/* readwrite:
585 handle stdin/stdout/network I/O. Bwahaha!! -- the select loop from hell. 585 handle stdin/stdout/network I/O. Bwahaha!! -- the i/o loop from hell.
586 In this instance, return what might become our exit status. */ 586 In this instance, return what might become our exit status. */
587static int readwrite(void) 587static int readwrite(void)
588{ 588{
589 int rr;
590 char *zp = zp; /* gcc */ /* stdin buf ptr */ 589 char *zp = zp; /* gcc */ /* stdin buf ptr */
591 char *np = np; /* net-in buf ptr */ 590 char *np = np; /* net-in buf ptr */
592 unsigned rzleft; 591 unsigned rzleft;
@@ -594,45 +593,41 @@ static int readwrite(void)
594 unsigned netretry; /* net-read retry counter */ 593 unsigned netretry; /* net-read retry counter */
595 unsigned fds_open; 594 unsigned fds_open;
596 595
597 /* if you don't have all this FD_* macro hair in sys/types.h, you'll have to 596 struct pollfd pfds[2];
598 either find it or do your own bit-bashing: *ding1 |= (1 << fd), etc... */ 597 pfds[0].fd = STDIN_FILENO;
599 fd_set ding1; /* for select loop */ 598 pfds[0].events = POLLIN;
600 fd_set ding2; 599 pfds[1].fd = netfd;
601 FD_ZERO(&ding1); 600 pfds[1].events = POLLIN;
602 FD_SET(netfd, &ding1);
603 FD_SET(STDIN_FILENO, &ding1);
604 fds_open = 2;
605 601
602 fds_open = 2;
606 netretry = 2; 603 netretry = 2;
607 rzleft = rnleft = 0; 604 rzleft = rnleft = 0;
608 if (o_interval) 605 if (o_interval)
609 sleep(o_interval); /* pause *before* sending stuff, too */ 606 sleep(o_interval); /* pause *before* sending stuff, too */
610 607
611 /* and now the big ol' select shoveling loop ... */ 608 /* and now the big ol' shoveling loop ... */
612 /* nc 1.10 has "while (FD_ISSET(netfd)" here */ 609 /* nc 1.10 has "while (FD_ISSET(netfd)" here */
613 while (fds_open) { 610 while (fds_open) {
611 int rr;
612 int poll_tmout_ms;
614 unsigned wretry = 8200; /* net-write sanity counter */ 613 unsigned wretry = 8200; /* net-write sanity counter */
615 614
616 ding2 = ding1; /* FD_COPY ain't portable... */ 615 poll_tmout_ms = -1;
617 /* some systems, notably linux, crap into their select timers on return, so
618 we create a expendable copy and give *that* to select. */
619 if (o_wait) { 616 if (o_wait) {
620 struct timeval tmp_timer; 617 poll_tmout_ms = INT_MAX;
621 tmp_timer.tv_sec = o_wait; 618 if (o_wait < INT_MAX / 1000)
622 tmp_timer.tv_usec = 0; 619 poll_tmout_ms = o_wait * 1000;
623 /* highest possible fd is netfd (3) */ 620 }
624 rr = select(netfd+1, &ding2, NULL, NULL, &tmp_timer); 621 rr = poll(pfds, 2, poll_tmout_ms);
625 } else
626 rr = select(netfd+1, &ding2, NULL, NULL, NULL);
627 if (rr < 0 && errno != EINTR) { /* might have gotten ^Zed, etc */ 622 if (rr < 0 && errno != EINTR) { /* might have gotten ^Zed, etc */
628 holler_perror("select"); 623 holler_perror("poll");
629 close(netfd); 624 close(netfd);
630 return 1; 625 return 1;
631 } 626 }
632 /* if we have a timeout AND stdin is closed AND we haven't heard anything 627 /* if we have a timeout AND stdin is closed AND we haven't heard anything
633 from the net during that time, assume it's dead and close it too. */ 628 from the net during that time, assume it's dead and close it too. */
634 if (rr == 0) { 629 if (rr == 0) {
635 if (!FD_ISSET(STDIN_FILENO, &ding1)) { 630 if (!pfds[0].revents) {
636 netretry--; /* we actually try a coupla times. */ 631 netretry--; /* we actually try a coupla times. */
637 if (!netretry) { 632 if (!netretry) {
638 if (o_verbose > 1) /* normally we don't care */ 633 if (o_verbose > 1) /* normally we don't care */
@@ -641,19 +636,17 @@ static int readwrite(void)
641 return 0; /* not an error! */ 636 return 0; /* not an error! */
642 } 637 }
643 } 638 }
644 } /* select timeout */ 639 } /* timeout */
645 /* xxx: should we check the exception fds too? The read fds seem to give
646 us the right info, and none of the examples I found bothered. */
647 640
648 /* Ding!! Something arrived, go check all the incoming hoppers, net first */ 641 /* Ding!! Something arrived, go check all the incoming hoppers, net first */
649 if (FD_ISSET(netfd, &ding2)) { /* net: ding! */ 642 if (pfds[1].revents) { /* net: ding! */
650 rr = read(netfd, bigbuf_net, BIGSIZ); 643 rr = read(netfd, bigbuf_net, BIGSIZ);
651 if (rr <= 0) { 644 if (rr <= 0) {
652 if (rr < 0 && o_verbose > 1) { 645 if (rr < 0 && o_verbose > 1) {
653 /* nc 1.10 doesn't do this */ 646 /* nc 1.10 doesn't do this */
654 bb_perror_msg("net read"); 647 bb_perror_msg("net read");
655 } 648 }
656 FD_CLR(netfd, &ding1); /* net closed */ 649 pfds[1].fd = -1; /* don't poll for netfd anymore */
657 fds_open--; 650 fds_open--;
658 rzleft = 0; /* can't write anymore: broken pipe */ 651 rzleft = 0; /* can't write anymore: broken pipe */
659 } else { 652 } else {
@@ -669,12 +662,12 @@ Debug("got %d from the net, errno %d", rr, errno);
669 goto shovel; 662 goto shovel;
670 663
671 /* okay, suck more stdin */ 664 /* okay, suck more stdin */
672 if (FD_ISSET(STDIN_FILENO, &ding2)) { /* stdin: ding! */ 665 if (pfds[0].revents) { /* stdin: ding! */
673 rr = read(STDIN_FILENO, bigbuf_in, BIGSIZ); 666 rr = read(STDIN_FILENO, bigbuf_in, BIGSIZ);
674 /* Considered making reads here smaller for UDP mode, but 8192-byte 667 /* Considered making reads here smaller for UDP mode, but 8192-byte
675 mobygrams are kinda fun and exercise the reassembler. */ 668 mobygrams are kinda fun and exercise the reassembler. */
676 if (rr <= 0) { /* at end, or fukt, or ... */ 669 if (rr <= 0) { /* at end, or fukt, or ... */
677 FD_CLR(STDIN_FILENO, &ding1); /* disable stdin */ 670 pfds[0].fd = -1; /* disable stdin */
678 /*close(STDIN_FILENO); - not really necessary */ 671 /*close(STDIN_FILENO); - not really necessary */
679 /* Let peer know we have no more data */ 672 /* Let peer know we have no more data */
680 /* nc 1.10 doesn't do this: */ 673 /* nc 1.10 doesn't do this: */
@@ -718,7 +711,7 @@ Debug("wrote %d to net, errno %d", rr, errno);
718 } /* rzleft */ 711 } /* rzleft */
719 if (o_interval) { /* cycle between slow lines, or ... */ 712 if (o_interval) { /* cycle between slow lines, or ... */
720 sleep(o_interval); 713 sleep(o_interval);
721 continue; /* ...with hairy select loop... */ 714 continue; /* ...with hairy loop... */
722 } 715 }
723 if (rzleft || rnleft) { /* shovel that shit till they ain't */ 716 if (rzleft || rnleft) { /* shovel that shit till they ain't */
724 wretry--; /* none left, and get another load */ 717 wretry--; /* none left, and get another load */
diff --git a/networking/ntpd.c b/networking/ntpd.c
index 5cc71ca7a..73d27ac20 100644
--- a/networking/ntpd.c
+++ b/networking/ntpd.c
@@ -393,7 +393,7 @@ struct globals {
393 * too big and we will step. I observed it with -6. 393 * too big and we will step. I observed it with -6.
394 * 394 *
395 * OTOH, setting precision_sec far too small would result in futile 395 * OTOH, setting precision_sec far too small would result in futile
396 * attempts to syncronize to an unachievable precision. 396 * attempts to synchronize to an unachievable precision.
397 * 397 *
398 * -6 is 1/64 sec, -7 is 1/128 sec and so on. 398 * -6 is 1/64 sec, -7 is 1/128 sec and so on.
399 * -8 is 1/256 ~= 0.003906 (worked well for me --vda) 399 * -8 is 1/256 ~= 0.003906 (worked well for me --vda)
@@ -754,7 +754,7 @@ reset_peer_stats(peer_t *p, double offset)
754 bool small_ofs = fabs(offset) < STEP_THRESHOLD; 754 bool small_ofs = fabs(offset) < STEP_THRESHOLD;
755 755
756 /* Used to set p->filter_datapoint[i].d_dispersion = MAXDISP 756 /* Used to set p->filter_datapoint[i].d_dispersion = MAXDISP
757 * and clear reachable bits, but this proved to be too agressive: 757 * and clear reachable bits, but this proved to be too aggressive:
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 datapoints per peer 760 * making us needing to collect full ~8 datapoints per peer
@@ -1715,7 +1715,7 @@ update_local_clock(peer_t *p)
1715 * It looks like Linux kernel's PLL is far too gentle in changing 1715 * It looks like Linux kernel's PLL is far too gentle in changing
1716 * tmx.freq in response to clock offset. Offset keeps growing 1716 * tmx.freq in response to clock offset. Offset keeps growing
1717 * and eventually we fall back to smaller poll intervals. 1717 * and eventually we fall back to smaller poll intervals.
1718 * We can make correction more agressive (about x2) by supplying 1718 * We can make correction more aggressive (about x2) by supplying
1719 * PLL time constant which is one less than the real one. 1719 * PLL time constant which is one less than the real one.
1720 * To be on a safe side, let's do it only if offset is significantly 1720 * To be on a safe side, let's do it only if offset is significantly
1721 * larger than jitter. 1721 * larger than jitter.
diff --git a/networking/ping.c b/networking/ping.c
index ef31e000b..94fb007f5 100644
--- a/networking/ping.c
+++ b/networking/ping.c
@@ -478,7 +478,7 @@ static void sendping_tail(void (*sp)(int), int size_pkt)
478 } else { /* -c NN, and all NN are sent (and no deadline) */ 478 } else { /* -c NN, and all NN are sent (and no deadline) */
479 /* Wait for the last ping to come back. 479 /* Wait for the last ping to come back.
480 * -W timeout: wait for a response in seconds. 480 * -W timeout: wait for a response in seconds.
481 * Affects only timeout in absense of any responses, 481 * Affects only timeout in absence of any responses,
482 * otherwise ping waits for two RTTs. */ 482 * otherwise ping waits for two RTTs. */
483 unsigned expire = timeout; 483 unsigned expire = timeout;
484 484
@@ -712,7 +712,7 @@ static void ping4(len_and_sockaddr *lsa)
712 712
713 if (opt_ttl != 0) { 713 if (opt_ttl != 0) {
714 setsockopt_int(pingsock, IPPROTO_IP, IP_TTL, opt_ttl); 714 setsockopt_int(pingsock, IPPROTO_IP, IP_TTL, opt_ttl);
715 /* above doesnt affect packets sent to bcast IP, so... */ 715 /* above doesn't affect packets sent to bcast IP, so... */
716 setsockopt_int(pingsock, IPPROTO_IP, IP_MULTICAST_TTL, opt_ttl); 716 setsockopt_int(pingsock, IPPROTO_IP, IP_MULTICAST_TTL, opt_ttl);
717 } 717 }
718 718
diff --git a/networking/tcpudp.c b/networking/tcpudp.c
index 3a6c68646..3ebe7d5fc 100644
--- a/networking/tcpudp.c
+++ b/networking/tcpudp.c
@@ -683,7 +683,7 @@ prog
683-E 683-E
684 no special environment. Do not set up TCP-related environment variables. 684 no special environment. Do not set up TCP-related environment variables.
685-v 685-v
686 verbose. Print verbose messsages to standard output. 686 verbose. Print verbose messages to standard output.
687-vv 687-vv
688 more verbose. Print more verbose messages to standard output. 688 more verbose. Print more verbose messages to standard output.
689 * no difference between -v and -vv in busyboxed version 689 * no difference between -v and -vv in busyboxed version
diff --git a/networking/tls.c b/networking/tls.c
index 30afd9ea9..db518bf90 100644
--- a/networking/tls.c
+++ b/networking/tls.c
@@ -39,7 +39,7 @@
39 39
40// works against "openssl s_server -cipher NULL" 40// works against "openssl s_server -cipher NULL"
41// and against wolfssl-3.9.10-stable/examples/server/server.c: 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) 42//#define CIPHER_ID1 TLS_RSA_WITH_NULL_SHA256 // for testing (does everything except encrypting)
43 43
44// works against wolfssl-3.9.10-stable/examples/server/server.c 44// works against wolfssl-3.9.10-stable/examples/server/server.c
45// works for kernel.org 45// works for kernel.org
@@ -367,11 +367,12 @@ static unsigned hmac_sha_precomputed_v(
367 return sha_end(&pre->hashed_key_xor_opad, out); 367 return sha_end(&pre->hashed_key_xor_opad, out);
368} 368}
369 369
370static void hmac_sha256_begin(hmac_precomputed_t *pre, uint8_t *key, unsigned key_size) 370typedef void md5sha_begin_func(md5sha_ctx_t *ctx) FAST_FUNC;
371static void hmac_begin(hmac_precomputed_t *pre, uint8_t *key, unsigned key_size, md5sha_begin_func *begin)
371{ 372{
372 uint8_t key_xor_ipad[SHA_INSIZE]; 373 uint8_t key_xor_ipad[SHA_INSIZE];
373 uint8_t key_xor_opad[SHA_INSIZE]; 374 uint8_t key_xor_opad[SHA_INSIZE];
374 uint8_t tempkey[SHA256_OUTSIZE]; 375 uint8_t tempkey[SHA1_OUTSIZE < SHA256_OUTSIZE ? SHA256_OUTSIZE : SHA1_OUTSIZE];
375 unsigned i; 376 unsigned i;
376 377
377 // "The authentication key can be of any length up to INSIZE, the 378 // "The authentication key can be of any length up to INSIZE, the
@@ -380,7 +381,7 @@ static void hmac_sha256_begin(hmac_precomputed_t *pre, uint8_t *key, unsigned ke
380 // resultant OUTSIZE byte string as the actual key to HMAC." 381 // resultant OUTSIZE byte string as the actual key to HMAC."
381 if (key_size > SHA_INSIZE) { 382 if (key_size > SHA_INSIZE) {
382 md5sha_ctx_t ctx; 383 md5sha_ctx_t ctx;
383 sha256_begin(&ctx); 384 begin(&ctx);
384 md5sha_hash(&ctx, key, key_size); 385 md5sha_hash(&ctx, key, key_size);
385 key_size = sha_end(&ctx, tempkey); 386 key_size = sha_end(&ctx, tempkey);
386 } 387 }
@@ -394,41 +395,8 @@ static void hmac_sha256_begin(hmac_precomputed_t *pre, uint8_t *key, unsigned ke
394 key_xor_opad[i] = 0x5c; 395 key_xor_opad[i] = 0x5c;
395 } 396 }
396 397
397 sha256_begin(&pre->hashed_key_xor_ipad); 398 begin(&pre->hashed_key_xor_ipad);
398 sha256_begin(&pre->hashed_key_xor_opad); 399 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); 400 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); 401 md5sha_hash(&pre->hashed_key_xor_opad, key_xor_opad, SHA_INSIZE);
434} 402}
@@ -441,11 +409,11 @@ static unsigned hmac(tls_state_t *tls, uint8_t *out, uint8_t *key, unsigned key_
441 409
442 va_start(va, key_size); 410 va_start(va, key_size);
443 411
444 if (tls->MAC_size == SHA256_OUTSIZE) 412 hmac_begin(&pre, key, key_size,
445 hmac_sha256_begin(&pre, key, key_size); 413 (tls->MAC_size == SHA256_OUTSIZE)
446 else 414 ? sha256_begin
447 hmac_sha1_begin(&pre, key, key_size); 415 : sha1_begin
448 416 );
449 len = hmac_sha_precomputed_v(&pre, out, va); 417 len = hmac_sha_precomputed_v(&pre, out, va);
450 418
451 va_end(va); 419 va_end(va);
@@ -460,7 +428,7 @@ static unsigned hmac_sha256(/*tls_state_t *tls,*/ uint8_t *out, uint8_t *key, un
460 428
461 va_start(va, key_size); 429 va_start(va, key_size);
462 430
463 hmac_sha256_begin(&pre, key, key_size); 431 hmac_begin(&pre, key, key_size, sha256_begin);
464 len = hmac_sha_precomputed_v(&pre, out, va); 432 len = hmac_sha_precomputed_v(&pre, out, va);
465 433
466 va_end(va); 434 va_end(va);
@@ -507,7 +475,7 @@ static void prf_hmac_sha256(/*tls_state_t *tls,*/
507 uint8_t a[TLS_MAX_MAC_SIZE]; 475 uint8_t a[TLS_MAX_MAC_SIZE];
508 uint8_t *out_p = outbuf; 476 uint8_t *out_p = outbuf;
509 unsigned label_size = strlen(label); 477 unsigned label_size = strlen(label);
510 unsigned MAC_size = SHA256_OUTSIZE;///tls->MAC_size; 478 unsigned MAC_size = SHA256_OUTSIZE;
511 479
512 /* In P_hash() calculation, "seed" is "label + seed": */ 480 /* In P_hash() calculation, "seed" is "label + seed": */
513#define SEED label, label_size, seed, seed_size 481#define SEED label, label_size, seed, seed_size
@@ -518,7 +486,7 @@ static void prf_hmac_sha256(/*tls_state_t *tls,*/
518 hmac_sha256(/*tls,*/ a, SECRET, SEED, NULL); 486 hmac_sha256(/*tls,*/ a, SECRET, SEED, NULL);
519//TODO: convert hmac to precomputed 487//TODO: convert hmac to precomputed
520 488
521 for(;;) { 489 for (;;) {
522 /* HMAC_hash(secret, A(1) + seed) */ 490 /* HMAC_hash(secret, A(1) + seed) */
523 if (outbuf_size <= MAC_size) { 491 if (outbuf_size <= MAC_size) {
524 /* Last, possibly incomplete, block */ 492 /* Last, possibly incomplete, block */
@@ -597,8 +565,11 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type)
597 uint8_t padding_length; 565 uint8_t padding_length;
598 566
599 xhdr = (void*)(buf - RECHDR_LEN); 567 xhdr = (void*)(buf - RECHDR_LEN);
600 if (tls->cipher_id != TLS_RSA_WITH_NULL_SHA256) 568 if (CIPHER_ID1 != TLS_RSA_WITH_NULL_SHA256 /* if "no encryption" can't be selected */
569 || tls->cipher_id != TLS_RSA_WITH_NULL_SHA256 /* or if it wasn't selected */
570 ) {
601 xhdr = (void*)(buf - RECHDR_LEN - AES_BLOCKSIZE); /* place for IV */ 571 xhdr = (void*)(buf - RECHDR_LEN - AES_BLOCKSIZE); /* place for IV */
572 }
602 573
603 xhdr->type = type; 574 xhdr->type = type;
604 xhdr->proto_maj = TLS_MAJ; 575 xhdr->proto_maj = TLS_MAJ;
@@ -652,7 +623,9 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type)
652 // -------- ----------- ---------- -------------- 623 // -------- ----------- ---------- --------------
653 // SHA HMAC-SHA1 20 20 624 // SHA HMAC-SHA1 20 20
654 // SHA256 HMAC-SHA256 32 32 625 // SHA256 HMAC-SHA256 32 32
655 if (tls->cipher_id == TLS_RSA_WITH_NULL_SHA256) { 626 if (CIPHER_ID1 == TLS_RSA_WITH_NULL_SHA256
627 && tls->cipher_id == TLS_RSA_WITH_NULL_SHA256
628 ) {
656 /* No encryption, only signing */ 629 /* No encryption, only signing */
657 xhdr->len16_hi = size >> 8; 630 xhdr->len16_hi = size >> 8;
658 xhdr->len16_lo = size & 0xff; 631 xhdr->len16_lo = size & 0xff;
@@ -1698,9 +1671,11 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni)
1698 if (len != 1 || memcmp(tls->inbuf, rec_CHANGE_CIPHER_SPEC, 6) != 0) 1671 if (len != 1 || memcmp(tls->inbuf, rec_CHANGE_CIPHER_SPEC, 6) != 0)
1699 bad_record_die(tls, "switch to encrypted traffic", len); 1672 bad_record_die(tls, "switch to encrypted traffic", len);
1700 dbg("<< CHANGE_CIPHER_SPEC\n"); 1673 dbg("<< CHANGE_CIPHER_SPEC\n");
1701 if (tls->cipher_id == TLS_RSA_WITH_NULL_SHA256) 1674 if (CIPHER_ID1 == TLS_RSA_WITH_NULL_SHA256
1675 && tls->cipher_id == TLS_RSA_WITH_NULL_SHA256
1676 ) {
1702 tls->min_encrypted_len_on_read = tls->MAC_size; 1677 tls->min_encrypted_len_on_read = tls->MAC_size;
1703 else { 1678 } else {
1704 unsigned mac_blocks = (unsigned)(tls->MAC_size + AES_BLOCKSIZE-1) / AES_BLOCKSIZE; 1679 unsigned mac_blocks = (unsigned)(tls->MAC_size + AES_BLOCKSIZE-1) / AES_BLOCKSIZE;
1705 /* all incoming packets now should be encrypted and have 1680 /* all incoming packets now should be encrypted and have
1706 * at least IV + (MAC padded to blocksize): 1681 * at least IV + (MAC padded to blocksize):
@@ -1740,26 +1715,23 @@ static void tls_xwrite(tls_state_t *tls, int len)
1740 1715
1741void FAST_FUNC tls_run_copy_loop(tls_state_t *tls) 1716void FAST_FUNC tls_run_copy_loop(tls_state_t *tls)
1742{ 1717{
1743 fd_set readfds;
1744 int inbuf_size; 1718 int inbuf_size;
1745 const int INBUF_STEP = 4 * 1024; 1719 const int INBUF_STEP = 4 * 1024;
1720 struct pollfd pfds[2];
1746 1721
1747//TODO: convert to poll 1722 pfds[0].fd = STDIN_FILENO;
1748 /* Select loop copying stdin to ofd, and ifd to stdout */ 1723 pfds[0].events = POLLIN;
1749 FD_ZERO(&readfds); 1724 pfds[1].fd = tls->ifd;
1750 FD_SET(tls->ifd, &readfds); 1725 pfds[1].events = POLLIN;
1751 FD_SET(STDIN_FILENO, &readfds);
1752 1726
1753 inbuf_size = INBUF_STEP; 1727 inbuf_size = INBUF_STEP;
1754 for (;;) { 1728 for (;;) {
1755 fd_set testfds;
1756 int nread; 1729 int nread;
1757 1730
1758 testfds = readfds; 1731 if (safe_poll(pfds, 2, -1) < 0)
1759 if (select(tls->ifd + 1, &testfds, NULL, NULL, NULL) < 0) 1732 bb_perror_msg_and_die("poll");
1760 bb_perror_msg_and_die("select");
1761 1733
1762 if (FD_ISSET(STDIN_FILENO, &testfds)) { 1734 if (pfds[0].revents) {
1763 void *buf; 1735 void *buf;
1764 1736
1765 dbg("STDIN HAS DATA\n"); 1737 dbg("STDIN HAS DATA\n");
@@ -1774,7 +1746,7 @@ void FAST_FUNC tls_run_copy_loop(tls_state_t *tls)
1774 /* But TLS has no way to encode this, 1746 /* But TLS has no way to encode this,
1775 * doubt it's ok to do it "raw" 1747 * doubt it's ok to do it "raw"
1776 */ 1748 */
1777 FD_CLR(STDIN_FILENO, &readfds); 1749 pfds[0].fd = -1;
1778 tls_free_outbuf(tls); /* mem usage optimization */ 1750 tls_free_outbuf(tls); /* mem usage optimization */
1779 } else { 1751 } else {
1780 if (nread == inbuf_size) { 1752 if (nread == inbuf_size) {
@@ -1788,7 +1760,7 @@ void FAST_FUNC tls_run_copy_loop(tls_state_t *tls)
1788 tls_xwrite(tls, nread); 1760 tls_xwrite(tls, nread);
1789 } 1761 }
1790 } 1762 }
1791 if (FD_ISSET(tls->ifd, &testfds)) { 1763 if (pfds[1].revents) {
1792 dbg("NETWORK HAS DATA\n"); 1764 dbg("NETWORK HAS DATA\n");
1793 read_record: 1765 read_record:
1794 nread = tls_xread_record(tls); 1766 nread = tls_xread_record(tls);
@@ -1796,7 +1768,7 @@ void FAST_FUNC tls_run_copy_loop(tls_state_t *tls)
1796 /* TLS protocol has no real concept of one-sided shutdowns: 1768 /* TLS protocol has no real concept of one-sided shutdowns:
1797 * if we get "TLS EOF" from the peer, writes will fail too 1769 * if we get "TLS EOF" from the peer, writes will fail too
1798 */ 1770 */
1799 //FD_CLR(tls->ifd, &readfds); 1771 //pfds[1].fd = -1;
1800 //close(STDOUT_FILENO); 1772 //close(STDOUT_FILENO);
1801 //tls_free_inbuf(tls); /* mem usage optimization */ 1773 //tls_free_inbuf(tls); /* mem usage optimization */
1802 //continue; 1774 //continue;
diff --git a/networking/tls_aes.c b/networking/tls_aes.c
index ebaab15b1..6992f1c90 100644
--- a/networking/tls_aes.c
+++ b/networking/tls_aes.c
@@ -3,1774 +3,458 @@
3 * 3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree. 4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */ 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 6
52/** 7/* This AES implementation is derived from tiny-AES128-C code,
53 * @file aes.c 8 * which was put by its author into public domain:
54 * @version 33ef80f (HEAD, tag: MATRIXSSL-3-7-2-OPEN, tag: MATRIXSSL-3-7-2-COMM, origin/master, origin/HEAD, master)
55 * 9 *
56 * AES CBC block cipher implementation. 10 * tiny-AES128-C/unlicense.txt, Dec 8, 2014
57 */ 11 * """
58/* 12 * This is free and unencumbered software released into the public domain.
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 * 13 *
65 * This software is open source; you can redistribute it and/or modify 14 * Anyone is free to copy, modify, publish, use, compile, sell, or
66 * it under the terms of the GNU General Public License as published by 15 * distribute this software, either in source code form or as a compiled
67 * the Free Software Foundation; either version 2 of the License, or 16 * binary, for any purpose, commercial or non-commercial, and by any
68 * (at your option) any later version. 17 * means.
69 * 18 *
70 * This General Public License does NOT permit incorporating this software 19 * In jurisdictions that recognize copyright laws, the author or authors
71 * into proprietary programs. If you are unable to comply with the GPL, a 20 * of this software dedicate any and all copyright interest in the
72 * commercial license for this software may be purchased from INSIDE at 21 * software to the public domain. We make this dedication for the benefit
73 * http://www.insidesecure.com/eng/Company/Locations 22 * of the public at large and to the detriment of our heirs and
23 * successors. We intend this dedication to be an overt act of
24 * relinquishment in perpetuity of all present and future rights to this
25 * software under copyright law.
74 * 26 *
75 * This program is distributed in WITHOUT ANY WARRANTY; without even the 27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
76 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 28 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
77 * See the GNU General Public License for more details. 29 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
78 * 30 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
79 * You should have received a copy of the GNU General Public License 31 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
80 * along with this program; if not, write to the Free Software 32 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
81 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 33 * OTHER DEALINGS IN THE SOFTWARE.
82 * http://www.gnu.org/copyleft/gpl.html 34 * """
83 */ 35 */
84/******************************************************************************/ 36/* Note that only original tiny-AES128-C code is public domain.
85 37 * The derived code in this file has been expanded to also implement aes192
86//bbox 38 * and aes256 and use more efficient word-sized operations in many places,
87//#include "../cryptoApi.h" 39 * and put under GPLv2 license.
88 40 */
89#ifdef USE_AES 41#include "tls.h"
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 42
1050static const uint32 Tks3[] = { 43/* TODO: grep for this and move to libbb */
10510x00000000UL, 0x090d0b0eUL, 0x121a161cUL, 0x1b171d12UL, 0x24342c38UL, 0x2d392736UL, 0x362e3a24UL, 0x3f23312aUL, 44#define get_unaligned_be32(buf) ({ uint32_t v; move_from_unaligned32(v, buf); SWAP_BE32(v); })
10520x48685870UL, 0x4165537eUL, 0x5a724e6cUL, 0x537f4562UL, 0x6c5c7448UL, 0x65517f46UL, 0x7e466254UL, 0x774b695aUL, 45
10530x90d0b0e0UL, 0x99ddbbeeUL, 0x82caa6fcUL, 0x8bc7adf2UL, 0xb4e49cd8UL, 0xbde997d6UL, 0xa6fe8ac4UL, 0xaff381caUL, 46
10540xd8b8e890UL, 0xd1b5e39eUL, 0xcaa2fe8cUL, 0xc3aff582UL, 0xfc8cc4a8UL, 0xf581cfa6UL, 0xee96d2b4UL, 0xe79bd9baUL, 47// The lookup-tables are marked const so they can be placed in read-only storage instead of RAM
10550x3bbb7bdbUL, 0x32b670d5UL, 0x29a16dc7UL, 0x20ac66c9UL, 0x1f8f57e3UL, 0x16825cedUL, 0x0d9541ffUL, 0x04984af1UL, 48// The numbers below can be computed dynamically trading ROM for RAM -
10560x73d323abUL, 0x7ade28a5UL, 0x61c935b7UL, 0x68c43eb9UL, 0x57e70f93UL, 0x5eea049dUL, 0x45fd198fUL, 0x4cf01281UL, 49// This can be useful in (embedded) bootloader applications, where ROM is often limited.
10570xab6bcb3bUL, 0xa266c035UL, 0xb971dd27UL, 0xb07cd629UL, 0x8f5fe703UL, 0x8652ec0dUL, 0x9d45f11fUL, 0x9448fa11UL, 50static const uint8_t sbox[] = {
10580xe303934bUL, 0xea0e9845UL, 0xf1198557UL, 0xf8148e59UL, 0xc737bf73UL, 0xce3ab47dUL, 0xd52da96fUL, 0xdc20a261UL, 51 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
10590x766df6adUL, 0x7f60fda3UL, 0x6477e0b1UL, 0x6d7aebbfUL, 0x5259da95UL, 0x5b54d19bUL, 0x4043cc89UL, 0x494ec787UL, 52 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
10600x3e05aeddUL, 0x3708a5d3UL, 0x2c1fb8c1UL, 0x2512b3cfUL, 0x1a3182e5UL, 0x133c89ebUL, 0x082b94f9UL, 0x01269ff7UL, 53 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
10610xe6bd464dUL, 0xefb04d43UL, 0xf4a75051UL, 0xfdaa5b5fUL, 0xc2896a75UL, 0xcb84617bUL, 0xd0937c69UL, 0xd99e7767UL, 54 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
10620xaed51e3dUL, 0xa7d81533UL, 0xbccf0821UL, 0xb5c2032fUL, 0x8ae13205UL, 0x83ec390bUL, 0x98fb2419UL, 0x91f62f17UL, 55 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
10630x4dd68d76UL, 0x44db8678UL, 0x5fcc9b6aUL, 0x56c19064UL, 0x69e2a14eUL, 0x60efaa40UL, 0x7bf8b752UL, 0x72f5bc5cUL, 56 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
10640x05bed506UL, 0x0cb3de08UL, 0x17a4c31aUL, 0x1ea9c814UL, 0x218af93eUL, 0x2887f230UL, 0x3390ef22UL, 0x3a9de42cUL, 57 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
10650xdd063d96UL, 0xd40b3698UL, 0xcf1c2b8aUL, 0xc6112084UL, 0xf93211aeUL, 0xf03f1aa0UL, 0xeb2807b2UL, 0xe2250cbcUL, 58 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
10660x956e65e6UL, 0x9c636ee8UL, 0x877473faUL, 0x8e7978f4UL, 0xb15a49deUL, 0xb85742d0UL, 0xa3405fc2UL, 0xaa4d54ccUL, 59 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
10670xecdaf741UL, 0xe5d7fc4fUL, 0xfec0e15dUL, 0xf7cdea53UL, 0xc8eedb79UL, 0xc1e3d077UL, 0xdaf4cd65UL, 0xd3f9c66bUL, 60 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
10680xa4b2af31UL, 0xadbfa43fUL, 0xb6a8b92dUL, 0xbfa5b223UL, 0x80868309UL, 0x898b8807UL, 0x929c9515UL, 0x9b919e1bUL, 61 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
10690x7c0a47a1UL, 0x75074cafUL, 0x6e1051bdUL, 0x671d5ab3UL, 0x583e6b99UL, 0x51336097UL, 0x4a247d85UL, 0x4329768bUL, 62 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
10700x34621fd1UL, 0x3d6f14dfUL, 0x267809cdUL, 0x2f7502c3UL, 0x105633e9UL, 0x195b38e7UL, 0x024c25f5UL, 0x0b412efbUL, 63 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
10710xd7618c9aUL, 0xde6c8794UL, 0xc57b9a86UL, 0xcc769188UL, 0xf355a0a2UL, 0xfa58abacUL, 0xe14fb6beUL, 0xe842bdb0UL, 64 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
10720x9f09d4eaUL, 0x9604dfe4UL, 0x8d13c2f6UL, 0x841ec9f8UL, 0xbb3df8d2UL, 0xb230f3dcUL, 0xa927eeceUL, 0xa02ae5c0UL, 65 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
10730x47b13c7aUL, 0x4ebc3774UL, 0x55ab2a66UL, 0x5ca62168UL, 0x63851042UL, 0x6a881b4cUL, 0x719f065eUL, 0x78920d50UL, 66 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
10740x0fd9640aUL, 0x06d46f04UL, 0x1dc37216UL, 0x14ce7918UL, 0x2bed4832UL, 0x22e0433cUL, 0x39f75e2eUL, 0x30fa5520UL, 67 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
10750x9ab701ecUL, 0x93ba0ae2UL, 0x88ad17f0UL, 0x81a01cfeUL, 0xbe832dd4UL, 0xb78e26daUL, 0xac993bc8UL, 0xa59430c6UL, 68 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
10760xd2df599cUL, 0xdbd25292UL, 0xc0c54f80UL, 0xc9c8448eUL, 0xf6eb75a4UL, 0xffe67eaaUL, 0xe4f163b8UL, 0xedfc68b6UL, 69 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
10770x0a67b10cUL, 0x036aba02UL, 0x187da710UL, 0x1170ac1eUL, 0x2e539d34UL, 0x275e963aUL, 0x3c498b28UL, 0x35448026UL, 70 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
10780x420fe97cUL, 0x4b02e272UL, 0x5015ff60UL, 0x5918f46eUL, 0x663bc544UL, 0x6f36ce4aUL, 0x7421d358UL, 0x7d2cd856UL, 71 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
10790xa10c7a37UL, 0xa8017139UL, 0xb3166c2bUL, 0xba1b6725UL, 0x8538560fUL, 0x8c355d01UL, 0x97224013UL, 0x9e2f4b1dUL, 72 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
10800xe9642247UL, 0xe0692949UL, 0xfb7e345bUL, 0xf2733f55UL, 0xcd500e7fUL, 0xc45d0571UL, 0xdf4a1863UL, 0xd647136dUL, 73 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
10810x31dccad7UL, 0x38d1c1d9UL, 0x23c6dccbUL, 0x2acbd7c5UL, 0x15e8e6efUL, 0x1ce5ede1UL, 0x07f2f0f3UL, 0x0efffbfdUL, 74 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
10820x79b492a7UL, 0x70b999a9UL, 0x6bae84bbUL, 0x62a38fb5UL, 0x5d80be9fUL, 0x548db591UL, 0x4f9aa883UL, 0x4697a38dUL 75 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
76 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
77 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
78 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
79 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
80 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
81 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
82 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
1083}; 83};
1084 84
1085#endif /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */ 85static const uint8_t rsbox[] = {
1086 86 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
1087static const uint32 rcon[] = { 87 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
1088 0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL, 88 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
1089 0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL, 89 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
1090 0x1B000000UL, 0x36000000UL, /* for 128-bit blocks, AES never uses more than 10 rcon values */ 90 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d,
91 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
92 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2,
93 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
94 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
95 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
96 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
97 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
98 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
99 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
100 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
101 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
102 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea,
103 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
104 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85,
105 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
106 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
107 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
108 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20,
109 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
110 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31,
111 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
112 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
113 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
114 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0,
115 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
116 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26,
117 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
1091}; 118};
1092 119
1093#ifdef USE_BURN_STACK 120// SubWord() is a function that takes a four-byte input word and
1094static void _aes_ecb_decrypt(const unsigned char *ct, unsigned char *pt, 121// applies the S-box to each of the four bytes to produce an output word.
1095 psAesKey_t *skey); 122static uint32_t Subword(uint32_t x)
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{ 123{
1102 return (Te4_3[byte(temp, 2)]) ^ 124 return (sbox[(x >> 24) ] << 24)
1103 (Te4_2[byte(temp, 1)]) ^ 125 | (sbox[(x >> 16) & 255] << 16)
1104 (Te4_1[byte(temp, 0)]) ^ 126 | (sbox[(x >> 8 ) & 255] << 8 )
1105 (Te4_0[byte(temp, 3)]); 127 | (sbox[(x ) & 255] );
1106} 128}
1107 129
1108#ifndef PS_AES_IMPROVE_PERF_INCREASE_CODESIZE 130// This function produces Nb(Nr+1) round keys.
1109static uint32 setup_mix2(uint32 temp) 131// The round keys are used in each round to decrypt the states.
132static int KeyExpansion(uint32_t *RoundKey, const void *key, unsigned key_len)
1110{ 133{
1111 return Td0(255 & Te4[byte(temp, 3)]) ^ 134 // The round constant word array, Rcon[i], contains the values given by
1112 Td1(255 & Te4[byte(temp, 2)]) ^ 135 // x to th e power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8).
1113 Td2(255 & Te4[byte(temp, 1)]) ^ 136 // Note that i starts at 2, not 0.
1114 Td3(255 & Te4[byte(temp, 0)]); 137 static const uint8_t Rcon[] = {
138 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36
139 //..... 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6,...
140 // but aes256 only uses values up to 0x36
141 };
142 int rounds, words_key, words_RoundKey;
143 int i, j, k;
144
145 // key_len 16: aes128, rounds 10, words_key 4, words_RoundKey 44
146 // key_len 24: aes192, rounds 12, words_key 6, words_RoundKey 52
147 // key_len 32: aes256, rounds 14, words_key 8, words_RoundKey 60
148 words_key = key_len / 4;
149 rounds = 6 + (key_len / 4);
150 words_RoundKey = 28 + key_len;
151
152 // The first round key is the key itself.
153 for (i = 0; i < words_key; i++)
154 RoundKey[i] = get_unaligned_be32((uint32_t*)key + i);
155 // i == words_key now
156
157 // All other round keys are found from the previous round keys.
158 j = k = 0;
159 for (; i < words_RoundKey; i++) {
160 uint32_t tempa;
161
162 tempa = RoundKey[i - 1];
163 if (j == 0) {
164 // RotWord(): rotates the 4 bytes in a word to the left once.
165 tempa = (tempa << 8) | (tempa >> 24);
166 tempa = Subword(tempa);
167 tempa ^= (uint32_t)Rcon[k] << 24;
168 } else if (words_key > 6 && j == 4) {
169 tempa = Subword(tempa);
170 }
171 RoundKey[i] = RoundKey[i - words_key] ^ tempa;
172 j++;
173 if (j == words_key) {
174 j = 0;
175 k++;
176 }
177 }
178 return rounds;
1115} 179}
1116#endif /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */
1117 180
1118/* 181// This function adds the round key to state.
1119 Software implementation of AES CBC APIs 182// The round key is added to the state by an XOR function.
1120 */ 183static void AddRoundKey(unsigned astate[16], const uint32_t *RoundKeys)
1121#ifndef USE_AES_CBC_EXTERNAL
1122static //bbox
1123int32 psAesInit(psCipherContext_t *ctx, unsigned char *IV,
1124 const unsigned char *key, uint32 keylen)
1125{ 184{
1126 int32 x, err; 185 int i;
1127 186
1128//bbox 187 for (i = 0; i < 16; i += 4) {
1129// if (IV == NULL || key == NULL || ctx == NULL) { 188 uint32_t n = *RoundKeys++;
1130// psTraceCrypto("psAesInit arg fail\n"); 189 astate[i + 0] ^= (n >> 24);
1131// return PS_ARG_FAIL; 190 astate[i + 1] ^= (n >> 16) & 255;
1132// } 191 astate[i + 2] ^= (n >> 8) & 255;
1133 memset(ctx, 0x0, sizeof(psCipherContext_t)); 192 astate[i + 3] ^= n & 255;
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 } 193 }
1147 return PS_SUCCESS;
1148} 194}
1149 195
1150static //bbox 196// The SubBytes Function Substitutes the values in the
1151int32 psAesEncrypt(psCipherContext_t *ctx, const unsigned char *pt, 197// state matrix with values in an S-box.
1152 unsigned char *ct, uint32 len) 198static void SubBytes(unsigned astate[16])
1153{ 199{
1154 int32 x; 200 int i;
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 201
1166/* 202 for (i = 0; i < 16; i++)
1167 is blocklen valid? 203 astate[i] = sbox[astate[i]];
1168 */ 204}
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 205
1187/* 206// Our code actually stores "columns" (in aes encryption terminology)
1188 store IV [ciphertext] for a future block 207// of state in rows: first 4 elements are "row 0, col 0", "row 1, col 0".
1189 */ 208// "row 2, col 0", "row 3, col 0". The fifth element is "row 0, col 1",
1190 for (x = 0; x < ctx->aes.blocklen; x++) { 209// and so on.
1191 ctx->aes.IV[x] = ct[x]; 210#define ASTATE(col,row) astate[(col)*4 + (row)]
1192 }
1193 ct += ctx->aes.blocklen;
1194 pt += ctx->aes.blocklen;
1195 }
1196 211
1197 memset_s(tmp, sizeof(tmp), 0x0, sizeof(tmp)); 212// The ShiftRows() function shifts the rows in the state to the left.
1198 return len; 213// Each row is shifted with different offset.
214// Offset = Row number. So the first row is not shifted.
215static void ShiftRows(unsigned astate[16])
216{
217 unsigned v;
218
219 // Rotate first row 1 columns to left
220 v = ASTATE(0,1);
221 ASTATE(0,1) = ASTATE(1,1);
222 ASTATE(1,1) = ASTATE(2,1);
223 ASTATE(2,1) = ASTATE(3,1);
224 ASTATE(3,1) = v;
225
226 // Rotate second row 2 columns to left
227 v = ASTATE(0,2); ASTATE(0,2) = ASTATE(2,2); ASTATE(2,2) = v;
228 v = ASTATE(1,2); ASTATE(1,2) = ASTATE(3,2); ASTATE(3,2) = v;
229
230 // Rotate third row 3 columns to left
231 v = ASTATE(3,3);
232 ASTATE(3,3) = ASTATE(2,3);
233 ASTATE(2,3) = ASTATE(1,3);
234 ASTATE(1,3) = ASTATE(0,3);
235 ASTATE(0,3) = v;
1199} 236}
1200 237
1201static //bbox 238// MixColumns function mixes the columns of the state matrix
1202int32 psAesDecrypt(psCipherContext_t *ctx, const unsigned char *ct, 239static void MixColumns(unsigned astate[16])
1203 unsigned char *pt, uint32 len)
1204{ 240{
1205 int32 x; 241 int i;
1206 uint32 i; 242
1207 unsigned char tmp[MAXBLOCKSIZE], tmp2[MAXBLOCKSIZE]; 243 for (i = 0; i < 16; i += 4) {
1208 244 unsigned a, b, c, d;
1209//bbox 245 unsigned x, y, z, t;
1210// if (pt == NULL || ct == NULL || ctx == NULL || (len & 0x7) != 0) { 246
1211// psTraceCrypto("Bad parameters to psAesDecrypt\n"); 247 a = astate[i + 0];
1212// return PS_ARG_FAIL; 248 b = astate[i + 1];
1213// } 249 c = astate[i + 2];
1214 if ((len & 0x7) != 0) 250 d = astate[i + 3];
1215 bb_error_msg_and_die("AES len:%d", len); 251 x = (a << 1) ^ b ^ (b << 1) ^ c ^ d;
1216 252 y = a ^ (b << 1) ^ c ^ (c << 1) ^ d;
1217/* 253 z = a ^ b ^ (c << 1) ^ d ^ (d << 1);
1218 is blocklen valid? 254 t = a ^ (a << 1) ^ b ^ c ^ (d << 1);
1219 */ 255 astate[i + 0] = x ^ ((-(int)(x >> 8)) & 0x11b);
1220 if (ctx->aes.blocklen < 0 || (ctx->aes.blocklen > 256 astate[i + 1] = y ^ ((-(int)(y >> 8)) & 0x11b);
1221 (int32)sizeof(ctx->aes.IV))) { 257 astate[i + 2] = z ^ ((-(int)(z >> 8)) & 0x11b);
1222 psTraceCrypto("Bad blocklen in psAesDecrypt\n"); 258 astate[i + 3] = t ^ ((-(int)(t >> 8)) & 0x11b);
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 } 259 }
1252 memset_s(tmp, sizeof(tmp), 0x0, sizeof(tmp));
1253 memset_s(tmp2, sizeof(tmp2), 0x0, sizeof(tmp2));
1254
1255 return len;
1256} 260}
1257 261
1258#endif /* USE_AES_CBC_EXTERNAL */ 262// The SubBytes Function Substitutes the values in the
1259 263// state matrix with values in an S-box.
1260/******************************************************************************/ 264static void InvSubBytes(unsigned astate[16])
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{ 265{
1272 int32 i, j; 266 int i;
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 267
1291/* 268 for (i = 0; i < 16; i++)
1292 setup the forward key 269 astate[i] = rsbox[astate[i]];
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} 270}
1434 271
1435 272static void InvShiftRows(unsigned astate[16])
1436#ifdef USE_BURN_STACK
1437static //bbox
1438void psAesEncryptBlock(const unsigned char *pt, unsigned char *ct,
1439 psAesKey_t *skey)
1440{ 273{
1441 _aes_ecb_encrypt(pt, ct, skey); 274 unsigned v;
1442 psBurnStack(sizeof(uint32)*8 + sizeof(uint32*) + sizeof(int32)*2); 275
276 // Rotate first row 1 columns to right
277 v = ASTATE(3,1);
278 ASTATE(3,1) = ASTATE(2,1);
279 ASTATE(2,1) = ASTATE(1,1);
280 ASTATE(1,1) = ASTATE(0,1);
281 ASTATE(0,1) = v;
282
283 // Rotate second row 2 columns to right
284 v = ASTATE(0,2); ASTATE(0,2) = ASTATE(2,2); ASTATE(2,2) = v;
285 v = ASTATE(1,2); ASTATE(1,2) = ASTATE(3,2); ASTATE(3,2) = v;
286
287 // Rotate third row 3 columns to right
288 v = ASTATE(0,3);
289 ASTATE(0,3) = ASTATE(1,3);
290 ASTATE(1,3) = ASTATE(2,3);
291 ASTATE(2,3) = ASTATE(3,3);
292 ASTATE(3,3) = v;
1443} 293}
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 294
1460 Nr = skey->Nr; 295static ALWAYS_INLINE unsigned Multiply(unsigned x)
1461 rk = skey->eK; 296{
297 unsigned y;
1462 298
1463/* 299 y = x >> 8;
1464 map byte array block to cipher state 300 return (x ^ y ^ (y << 1) ^ (y << 3) ^ (y << 4)) & 255;
1465 and add initial round key: 301}
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 302
1472#ifndef PS_AES_IMPROVE_PERF_INCREASE_CODESIZE 303// MixColumns function mixes the columns of the state matrix.
1473 for (r = 0; ; r++) { 304// The method used to multiply may be difficult to understand for the inexperienced.
1474 rk += 4; 305// Please use the references to gain more information.
1475 t0 = 306static void InvMixColumns(unsigned astate[16])
1476 Te0(byte(s0, 3)) ^ 307{
1477 Te1(byte(s1, 2)) ^ 308 int i;
1478 Te2(byte(s2, 1)) ^ 309
1479 Te3(byte(s3, 0)) ^ 310 for (i = 0; i < 16; i += 4) {
1480 rk[0]; 311 unsigned a, b, c, d;
1481 t1 = 312 unsigned x, y, z, t;
1482 Te0(byte(s1, 3)) ^ 313
1483 Te1(byte(s2, 2)) ^ 314 a = astate[i + 0];
1484 Te2(byte(s3, 1)) ^ 315 b = astate[i + 1];
1485 Te3(byte(s0, 0)) ^ 316 c = astate[i + 2];
1486 rk[1]; 317 d = astate[i + 3];
1487 t2 = 318 x = (a << 1) ^ (a << 2) ^ (a << 3) ^ b ^ (b << 1) ^ (b << 3)
1488 Te0(byte(s2, 3)) ^ 319 /***/ ^ c ^ (c << 2) ^ (c << 3) ^ d ^ (d << 3);
1489 Te1(byte(s3, 2)) ^ 320 y = a ^ (a << 3) ^ (b << 1) ^ (b << 2) ^ (b << 3)
1490 Te2(byte(s0, 1)) ^ 321 /***/ ^ c ^ (c << 1) ^ (c << 3) ^ d ^ (d << 2) ^ (d << 3);
1491 Te3(byte(s1, 0)) ^ 322 z = a ^ (a << 2) ^ (a << 3) ^ b ^ (b << 3)
1492 rk[2]; 323 /***/ ^ (c << 1) ^ (c << 2) ^ (c << 3) ^ d ^ (d << 1) ^ (d << 3);
1493 t3 = 324 t = a ^ (a << 1) ^ (a << 3) ^ b ^ (b << 2) ^ (b << 3)
1494 Te0(byte(s3, 3)) ^ 325 /***/ ^ c ^ (c << 3) ^ (d << 1) ^ (d << 2) ^ (d << 3);
1495 Te1(byte(s0, 2)) ^ 326 astate[i + 0] = Multiply(x);
1496 Te2(byte(s1, 1)) ^ 327 astate[i + 1] = Multiply(y);
1497 Te3(byte(s2, 0)) ^ 328 astate[i + 2] = Multiply(z);
1498 rk[3]; 329 astate[i + 3] = Multiply(t);
1499 if (r == Nr-2) {
1500 break;
1501 }
1502 s0 = t0; s1 = t1; s2 = t2; s3 = t3;
1503 } 330 }
1504 rk += 4; 331}
1505#else /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */
1506 332
1507/* 333static void aes_encrypt_1(unsigned astate[16], unsigned rounds, const uint32_t *RoundKey)
1508 Nr - 1 full rounds: 334{
1509 */
1510 r = Nr >> 1;
1511 for (;;) { 335 for (;;) {
1512 336 AddRoundKey(astate, RoundKey);
1513 t0 = 337 RoundKey += 4;
1514 Te0(byte(s0, 3)) ^ 338 SubBytes(astate);
1515 Te1(byte(s1, 2)) ^ 339 ShiftRows(astate);
1516 Te2(byte(s2, 1)) ^ 340 if (--rounds == 0)
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; 341 break;
1541 } 342 MixColumns(astate);
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 } 343 }
1568#endif /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */ 344 AddRoundKey(astate, RoundKey);
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} 345}
1602 346
1603#ifdef USE_BURN_STACK 347#if 0 // UNUSED
1604static //bbox 348static void aes_encrypt_one_block(unsigned rounds, const uint32_t *RoundKey, const void *data, void *dst)
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{ 349{
1619 uint32 s0, s1, s2, s3, t0, t1, t2, t3, *rk; 350 unsigned astate[16];
1620 int32 Nr, r; 351 unsigned i;
1621 352
1622//bbox 353 const uint8_t *pt = data;
1623// if (pt == NULL || ct == NULL || skey == NULL) { 354 uint8_t *ct = dst;
1624// return;
1625// }
1626 355
1627 Nr = skey->Nr; 356 for (i = 0; i < 16; i++)
1628 rk = skey->dK; 357 astate[i] = pt[i];
358 aes_encrypt_1(astate, rounds, RoundKey);
359 for (i = 0; i < 16; i++)
360 ct[i] = astate[i];
361}
362#endif
1629 363
1630/* 364void aes_cbc_encrypt(const void *key, int klen, void *iv, const void *data, size_t len, void *dst)
1631 map byte array block to cipher state and add initial round key: 365{
1632 */ 366 uint32_t RoundKey[60];
1633 LOAD32H(s0, ct ); s0 ^= rk[0]; 367 uint8_t iv2[16];
1634 LOAD32H(s1, ct + 4); s1 ^= rk[1]; 368 unsigned rounds;
1635 LOAD32H(s2, ct + 8); s2 ^= rk[2]; 369
1636 LOAD32H(s3, ct + 12); s3 ^= rk[3]; 370 const uint8_t *pt = data;
371 uint8_t *ct = dst;
372
373 memcpy(iv2, iv, 16);
374 rounds = KeyExpansion(RoundKey, key, klen);
375 while (len > 0) {
376 {
377 /* almost aes_encrypt_one_block(rounds, RoundKey, pt, ct);
378 * but xor'ing of IV with plaintext[] is combined
379 * with plaintext[] -> astate[]
380 */
381 int i;
382 unsigned astate[16];
383 for (i = 0; i < 16; i++)
384 astate[i] = pt[i] ^ iv2[i];
385 aes_encrypt_1(astate, rounds, RoundKey);
386 for (i = 0; i < 16; i++)
387 iv2[i] = ct[i] = astate[i];
388 }
389 ct += 16;
390 pt += 16;
391 len -= 16;
392 }
393}
1637 394
1638#ifndef PS_AES_IMPROVE_PERF_INCREASE_CODESIZE 395static void aes_decrypt_1(unsigned astate[16], unsigned rounds, const uint32_t *RoundKey)
1639 for (r = 0; ; r++) { 396{
1640 rk += 4; 397 RoundKey += rounds * 4;
1641 t0 = 398 AddRoundKey(astate, RoundKey);
1642 Td0(byte(s0, 3)) ^ 399 for (;;) {
1643 Td1(byte(s3, 2)) ^ 400 InvShiftRows(astate);
1644 Td2(byte(s2, 1)) ^ 401 InvSubBytes(astate);
1645 Td3(byte(s1, 0)) ^ 402 RoundKey -= 4;
1646 rk[0]; 403 AddRoundKey(astate, RoundKey);
1647 t1 = 404 if (--rounds == 0)
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; 405 break;
1667 } 406 InvMixColumns(astate);
1668 s0 = t0; s1 = t1; s2 = t2; s3 = t3;
1669 } 407 }
1670 rk += 4; 408}
1671 409
1672#else /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */ 410#if 0 //UNUSED
411static void aes_decrypt_one_block(unsigned rounds, const uint32_t *RoundKey, const void *data, void *dst)
412{
413 unsigned astate[16];
414 unsigned i;
1673 415
1674/* 416 const uint8_t *ct = data;
1675 Nr - 1 full rounds: 417 uint8_t *pt = dst;
1676 */
1677 r = Nr >> 1;
1678 for (;;) {
1679 418
1680 t0 = 419 for (i = 0; i < 16; i++)
1681 Td0(byte(s0, 3)) ^ 420 astate[i] = ct[i];
1682 Td1(byte(s3, 2)) ^ 421 aes_decrypt_1(astate, rounds, RoundKey);
1683 Td2(byte(s2, 1)) ^ 422 for (i = 0; i < 16; i++)
1684 Td3(byte(s1, 0)) ^ 423 pt[i] = astate[i];
1685 rk[4]; 424}
1686 t1 = 425#endif
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 426
1705 rk += 8; 427void aes_cbc_decrypt(const void *key, int klen, void *iv, const void *data, size_t len, void *dst)
1706 if (--r == 0) { 428{
1707 break; 429 uint32_t RoundKey[60];
430 uint8_t iv2[16];
431 uint8_t iv3[16];
432 unsigned rounds;
433 uint8_t *ivbuf;
434 uint8_t *ivnext;
435
436 const uint8_t *ct = data;
437 uint8_t *pt = dst;
438
439 rounds = KeyExpansion(RoundKey, key, klen);
440 ivbuf = memcpy(iv2, iv, 16);
441 while (len) {
442 ivnext = (ivbuf==iv2) ? iv3 : iv2;
443 {
444 /* almost aes_decrypt_one_block(rounds, RoundKey, ct, pt)
445 * but xor'ing of ivbuf is combined with astate[] -> plaintext[]
446 */
447 int i;
448 unsigned astate[16];
449 for (i = 0; i < 16; i++)
450 ivnext[i] = astate[i] = ct[i];
451 aes_decrypt_1(astate, rounds, RoundKey);
452 for (i = 0; i < 16; i++)
453 pt[i] = astate[i] ^ ivbuf[i];
1708 } 454 }
1709 455 ivbuf = ivnext;
1710 s0 = 456 ct += 16;
1711 Td0(byte(t0, 3)) ^ 457 pt += 16;
1712 Td1(byte(t3, 2)) ^ 458 len -= 16;
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 } 459 }
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} 460}
1769
1770
1771/******************************************************************************/
1772/******************************************************************************/
1773#endif /* !USE_AES_CBC_EXTERNAL */
1774#endif /* USE_AES */
1775/******************************************************************************/
1776
diff --git a/networking/tls_pstm.c b/networking/tls_pstm.c
index acd800307..bd5bae0b7 100644
--- a/networking/tls_pstm.c
+++ b/networking/tls_pstm.c
@@ -47,7 +47,7 @@
47//#include "../cryptoApi.h" 47//#include "../cryptoApi.h"
48#ifndef DISABLE_PSTM 48#ifndef DISABLE_PSTM
49 49
50static int32 pstm_mul_2d(pstm_int *a, int16 b, pstm_int *c); 50static int32 pstm_mul_2d(pstm_int *a, int b, pstm_int *c); //bbox: was int16 b
51 51
52/******************************************************************************/ 52/******************************************************************************/
53/* 53/*
@@ -64,7 +64,7 @@ int32 pstm_init_size(psPool_t *pool, pstm_int * a, uint32 size)
64 a->dp = xzalloc(sizeof (pstm_digit) * size);//bbox 64 a->dp = xzalloc(sizeof (pstm_digit) * size);//bbox
65//bbox a->pool = pool; 65//bbox a->pool = pool;
66 a->used = 0; 66 a->used = 0;
67 a->alloc = (int16)size; 67 a->alloc = size;
68 a->sign = PSTM_ZPOS; 68 a->sign = PSTM_ZPOS;
69/* 69/*
70 zero the digits 70 zero the digits
@@ -111,9 +111,9 @@ int32 pstm_init(psPool_t *pool, pstm_int * a)
111/* 111/*
112 Grow as required 112 Grow as required
113 */ 113 */
114int32 pstm_grow(pstm_int * a, int16 size) 114int32 pstm_grow(pstm_int * a, int size)
115{ 115{
116 int16 i; 116 int i; //bbox: was int16
117 pstm_digit *tmp; 117 pstm_digit *tmp;
118 118
119/* 119/*
@@ -298,7 +298,7 @@ void pstm_zero(pstm_int * a)
298 */ 298 */
299int32 pstm_cmp_mag(pstm_int * a, pstm_int * b) 299int32 pstm_cmp_mag(pstm_int * a, pstm_int * b)
300{ 300{
301 int16 n; 301 int n; //bbox: was int16
302 pstm_digit *tmpa, *tmpb; 302 pstm_digit *tmpa, *tmpb;
303 303
304/* 304/*
@@ -406,7 +406,7 @@ int32 pstm_read_unsigned_bin(pstm_int *a, unsigned char *b, int32 c)
406 c -= excess; 406 c -= excess;
407 b += excess; 407 b += excess;
408 } 408 }
409 a->used = (int16)((c + sizeof(pstm_digit) - 1)/sizeof(pstm_digit)); 409 a->used = ((c + sizeof(pstm_digit) - 1)/sizeof(pstm_digit));
410 if (a->alloc < a->used) { 410 if (a->alloc < a->used) {
411 if (pstm_grow(a, a->used) != PSTM_OKAY) { 411 if (pstm_grow(a, a->used) != PSTM_OKAY) {
412 return PSTM_MEM; 412 return PSTM_MEM;
@@ -460,9 +460,9 @@ int32 pstm_read_unsigned_bin(pstm_int *a, unsigned char *b, int32 c)
460/******************************************************************************/ 460/******************************************************************************/
461/* 461/*
462*/ 462*/
463int16 pstm_count_bits (pstm_int * a) 463int pstm_count_bits (pstm_int * a)
464{ 464{
465 int16 r; 465 int r; //bbox: was int16
466 pstm_digit q; 466 pstm_digit q;
467 467
468 if (a->used == 0) { 468 if (a->used == 0) {
@@ -500,9 +500,9 @@ void pstm_set(pstm_int *a, pstm_digit b)
500/* 500/*
501 Right shift 501 Right shift
502*/ 502*/
503void pstm_rshd(pstm_int *a, int16 x) 503void pstm_rshd(pstm_int *a, int x)
504{ 504{
505 int16 y; 505 int y; //bbox: was int16
506 506
507 /* too many digits just zero and return */ 507 /* too many digits just zero and return */
508 if (x >= a->used) { 508 if (x >= a->used) {
@@ -529,9 +529,9 @@ void pstm_rshd(pstm_int *a, int16 x)
529/* 529/*
530 Shift left a certain amount of digits. 530 Shift left a certain amount of digits.
531 */ 531 */
532int32 pstm_lshd(pstm_int * a, int16 b) 532int32 pstm_lshd(pstm_int * a, int b)
533{ 533{
534 int16 x; 534 int x; //bbox: was int16
535 int32 res; 535 int32 res;
536 536
537/* 537/*
@@ -582,9 +582,9 @@ int32 pstm_lshd(pstm_int * a, int16 b)
582/* 582/*
583 computes a = 2**b 583 computes a = 2**b
584*/ 584*/
585int32 pstm_2expt(pstm_int *a, int16 b) 585int32 pstm_2expt(pstm_int *a, int b)
586{ 586{
587 int16 z; 587 int z; //bbox: was int16
588 588
589 /* zero a as per default */ 589 /* zero a as per default */
590 pstm_zero (a); 590 pstm_zero (a);
@@ -619,7 +619,7 @@ int32 pstm_2expt(pstm_int *a, int16 b)
619int32 pstm_mul_2(pstm_int * a, pstm_int * b) 619int32 pstm_mul_2(pstm_int * a, pstm_int * b)
620{ 620{
621 int32 res; 621 int32 res;
622 int16 x, oldused; 622 int x, oldused; //bbox: was int16
623 623
624/* 624/*
625 grow to accomodate result 625 grow to accomodate result
@@ -684,7 +684,7 @@ int32 pstm_mul_2(pstm_int * a, pstm_int * b)
684*/ 684*/
685int32 s_pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c) 685int32 s_pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c)
686{ 686{
687 int16 oldbused, oldused; 687 int oldbused, oldused; //bbox: was int16
688 int32 x; 688 int32 x;
689 pstm_word t; 689 pstm_word t;
690 690
@@ -724,7 +724,7 @@ int32 s_pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c)
724*/ 724*/
725static int32 s_pstm_add(pstm_int *a, pstm_int *b, pstm_int *c) 725static int32 s_pstm_add(pstm_int *a, pstm_int *b, pstm_int *c)
726{ 726{
727 int16 x, y, oldused; 727 int x, y, oldused; //bbox: was int16
728 register pstm_word t, adp, bdp; 728 register pstm_word t, adp, bdp;
729 729
730 y = a->used; 730 y = a->used;
@@ -781,8 +781,8 @@ static int32 s_pstm_add(pstm_int *a, pstm_int *b, pstm_int *c)
781*/ 781*/
782int32 pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c) 782int32 pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c)
783{ 783{
784 int32 res; 784 int32 res;
785 int16 sa, sb; 785 int sa, sb; //bbox: was int16
786 786
787 sa = a->sign; 787 sa = a->sign;
788 sb = b->sign; 788 sb = b->sign;
@@ -881,7 +881,7 @@ int32 pstm_montgomery_setup(pstm_int *a, pstm_digit *rho)
881int32 pstm_montgomery_calc_normalization(pstm_int *a, pstm_int *b) 881int32 pstm_montgomery_calc_normalization(pstm_int *a, pstm_int *b)
882{ 882{
883 int32 x; 883 int32 x;
884 int16 bits; 884 int bits; //bbox: was int16
885 885
886 /* how many bits of last digit does b use */ 886 /* how many bits of last digit does b use */
887 bits = pstm_count_bits (b) % DIGIT_BIT; 887 bits = pstm_count_bits (b) % DIGIT_BIT;
@@ -916,10 +916,10 @@ int32 pstm_montgomery_calc_normalization(pstm_int *a, pstm_int *b)
916/* 916/*
917 c = a * 2**d 917 c = a * 2**d
918*/ 918*/
919static int32 pstm_mul_2d(pstm_int *a, int16 b, pstm_int *c) 919static int32 pstm_mul_2d(pstm_int *a, int b, pstm_int *c)
920{ 920{
921 pstm_digit carry, carrytmp, shift; 921 pstm_digit carry, carrytmp, shift;
922 int16 x; 922 int x; //bbox: was int16
923 923
924 /* copy it */ 924 /* copy it */
925 if (pstm_copy(a, c) != PSTM_OKAY) { 925 if (pstm_copy(a, c) != PSTM_OKAY) {
@@ -961,9 +961,9 @@ static int32 pstm_mul_2d(pstm_int *a, int16 b, pstm_int *c)
961/* 961/*
962 c = a mod 2**d 962 c = a mod 2**d
963*/ 963*/
964static int32 pstm_mod_2d(pstm_int *a, int16 b, pstm_int *c) 964static int32 pstm_mod_2d(pstm_int *a, int b, pstm_int *c) //bbox: was int16 b
965{ 965{
966 int16 x; 966 int x; //bbox: was int16
967 967
968 /* zero if count less than or equal to zero */ 968 /* zero if count less than or equal to zero */
969 if (b <= 0) { 969 if (b <= 0) {
@@ -1001,7 +1001,7 @@ int32 pstm_mul_d(pstm_int *a, pstm_digit b, pstm_int *c)
1001{ 1001{
1002 pstm_word w; 1002 pstm_word w;
1003 int32 res; 1003 int32 res;
1004 int16 x, oldused; 1004 int x, oldused; //bbox: was int16
1005 1005
1006 if (c->alloc < a->used + 1) { 1006 if (c->alloc < a->used + 1) {
1007 if ((res = pstm_grow (c, a->used + 1)) != PSTM_OKAY) { 1007 if ((res = pstm_grow (c, a->used + 1)) != PSTM_OKAY) {
@@ -1032,12 +1032,12 @@ int32 pstm_mul_d(pstm_int *a, pstm_digit b, pstm_int *c)
1032/* 1032/*
1033 c = a / 2**b 1033 c = a / 2**b
1034*/ 1034*/
1035int32 pstm_div_2d(psPool_t *pool, pstm_int *a, int16 b, pstm_int *c, 1035int32 pstm_div_2d(psPool_t *pool, pstm_int *a, int b, pstm_int *c,
1036 pstm_int *d) 1036 pstm_int *d)
1037{ 1037{
1038 pstm_digit D, r, rr; 1038 pstm_digit D, r, rr;
1039 int32 res; 1039 int32 res;
1040 int16 x; 1040 int x; //bbox: was int16
1041 pstm_int t; 1041 pstm_int t;
1042 1042
1043 /* if the shift count is <= 0 then we do no work */ 1043 /* if the shift count is <= 0 then we do no work */
@@ -1120,7 +1120,7 @@ LBL_DONE:
1120*/ 1120*/
1121int32 pstm_div_2(pstm_int * a, pstm_int * b) 1121int32 pstm_div_2(pstm_int * a, pstm_int * b)
1122{ 1122{
1123 int16 x, oldused; 1123 int x, oldused; //bbox: was int16
1124 1124
1125 if (b->alloc < a->used) { 1125 if (b->alloc < a->used) {
1126 if (pstm_grow(b, a->used) != PSTM_OKAY) { 1126 if (pstm_grow(b, a->used) != PSTM_OKAY) {
@@ -1166,9 +1166,9 @@ int32 pstm_div_2(pstm_int * a, pstm_int * b)
1166/* 1166/*
1167 Creates "a" then copies b into it 1167 Creates "a" then copies b into it
1168 */ 1168 */
1169int32 pstm_init_copy(psPool_t *pool, pstm_int * a, pstm_int * b, int16 toSqr) 1169int32 pstm_init_copy(psPool_t *pool, pstm_int * a, pstm_int * b, int toSqr)
1170{ 1170{
1171 int16 x; 1171 int x; //bbox: was int16
1172 int32 res; 1172 int32 res;
1173 1173
1174 if (a == b) { 1174 if (a == b) {
@@ -1279,7 +1279,7 @@ int32 pstm_div(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c,
1279{ 1279{
1280 pstm_int q, x, y, t1, t2; 1280 pstm_int q, x, y, t1, t2;
1281 int32 res; 1281 int32 res;
1282 int16 n, t, i, norm, neg; 1282 int n, t, i, norm, neg; //bbox: was int16
1283 1283
1284 /* is divisor zero ? */ 1284 /* is divisor zero ? */
1285 if (pstm_iszero (b) == 1) { 1285 if (pstm_iszero (b) == 1) {
@@ -1531,7 +1531,7 @@ int32 pstm_mulmod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c,
1531 pstm_int *d) 1531 pstm_int *d)
1532{ 1532{
1533 int32 res; 1533 int32 res;
1534 int16 size; 1534 int size; //bbox: was int16
1535 pstm_int tmp; 1535 pstm_int tmp;
1536 1536
1537/* 1537/*
@@ -1567,7 +1567,7 @@ int32 pstm_exptmod(psPool_t *pool, pstm_int *G, pstm_int *X, pstm_int *P,
1567 pstm_digit buf, mp; 1567 pstm_digit buf, mp;
1568 pstm_digit *paD; 1568 pstm_digit *paD;
1569 int32 err, bitbuf; 1569 int32 err, bitbuf;
1570 int16 bitcpy, bitcnt, mode, digidx, x, y, winsize; 1570 int bitcpy, bitcnt, mode, digidx, x, y, winsize; //bbox: was int16
1571 uint32 paDlen; 1571 uint32 paDlen;
1572 1572
1573 /* set window size from what user set as optimization */ 1573 /* set window size from what user set as optimization */
@@ -1624,7 +1624,7 @@ int32 pstm_exptmod(psPool_t *pool, pstm_int *G, pstm_int *X, pstm_int *P,
1624 paDlen = ((M[1].used + 3) * 2) * sizeof(pstm_digit); 1624 paDlen = ((M[1].used + 3) * 2) * sizeof(pstm_digit);
1625 paD = xzalloc(paDlen);//bbox 1625 paD = xzalloc(paDlen);//bbox
1626/* 1626/*
1627 compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times 1627 compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times
1628 */ 1628 */
1629 if (pstm_init_copy(pool, &M[1 << (winsize - 1)], &M[1], 1) != PSTM_OKAY) { 1629 if (pstm_init_copy(pool, &M[1 << (winsize - 1)], &M[1], 1) != PSTM_OKAY) {
1630 err = PS_MEM_FAIL; 1630 err = PS_MEM_FAIL;
@@ -1804,7 +1804,7 @@ LBL_RES:pstm_clear(&res);
1804int32 pstm_add(pstm_int *a, pstm_int *b, pstm_int *c) 1804int32 pstm_add(pstm_int *a, pstm_int *b, pstm_int *c)
1805{ 1805{
1806 int32 res; 1806 int32 res;
1807 int16 sa, sb; 1807 int sa, sb; //bbox: was int16
1808 1808
1809 /* get sign of both inputs */ 1809 /* get sign of both inputs */
1810 sa = a->sign; 1810 sa = a->sign;
@@ -1817,7 +1817,7 @@ int32 pstm_add(pstm_int *a, pstm_int *b, pstm_int *c)
1817 if ((res = s_pstm_add (a, b, c)) != PSTM_OKAY) { 1817 if ((res = s_pstm_add (a, b, c)) != PSTM_OKAY) {
1818 return res; 1818 return res;
1819 } 1819 }
1820 } else { 1820 } else {
1821/* 1821/*
1822 one positive, the other negative 1822 one positive, the other negative
1823 subtract the one with the greater magnitude from the one of the lesser 1823 subtract the one with the greater magnitude from the one of the lesser
@@ -1842,7 +1842,7 @@ int32 pstm_add(pstm_int *a, pstm_int *b, pstm_int *c)
1842/* 1842/*
1843 reverse an array, used for radix code 1843 reverse an array, used for radix code
1844*/ 1844*/
1845static void pstm_reverse (unsigned char *s, int16 len) 1845static void pstm_reverse (unsigned char *s, int len) //bbox: was int16 len
1846{ 1846{
1847 int32 ix, iy; 1847 int32 ix, iy;
1848 unsigned char t; 1848 unsigned char t;
@@ -1865,7 +1865,7 @@ static void pstm_reverse (unsigned char *s, int16 len)
1865int32 pstm_to_unsigned_bin_nr(psPool_t *pool, pstm_int *a, unsigned char *b) 1865int32 pstm_to_unsigned_bin_nr(psPool_t *pool, pstm_int *a, unsigned char *b)
1866{ 1866{
1867 int32 res; 1867 int32 res;
1868 int16 x; 1868 int x; //bbox: was int16
1869 pstm_int t = { 0 }; 1869 pstm_int t = { 0 };
1870 1870
1871 if ((res = pstm_init_copy(pool, &t, a, 0)) != PSTM_OKAY) { 1871 if ((res = pstm_init_copy(pool, &t, a, 0)) != PSTM_OKAY) {
@@ -1890,7 +1890,7 @@ int32 pstm_to_unsigned_bin_nr(psPool_t *pool, pstm_int *a, unsigned char *b)
1890int32 pstm_to_unsigned_bin(psPool_t *pool, pstm_int *a, unsigned char *b) 1890int32 pstm_to_unsigned_bin(psPool_t *pool, pstm_int *a, unsigned char *b)
1891{ 1891{
1892 int32 res; 1892 int32 res;
1893 int16 x; 1893 int x; //bbox: was int16
1894 pstm_int t = { 0 }; 1894 pstm_int t = { 0 };
1895 1895
1896 if ((res = pstm_init_copy(pool, &t, a, 0)) != PSTM_OKAY) { 1896 if ((res = pstm_init_copy(pool, &t, a, 0)) != PSTM_OKAY) {
diff --git a/networking/tls_pstm.h b/networking/tls_pstm.h
index 3a0fd8ce6..df705adce 100644
--- a/networking/tls_pstm.h
+++ b/networking/tls_pstm.h
@@ -122,7 +122,7 @@
122#define PSTM_MAX_SIZE 4096 122#define PSTM_MAX_SIZE 4096
123 123
124typedef struct { 124typedef struct {
125 int16 used, alloc, sign; 125 int used, alloc, sign; //bbox: was int16
126 pstm_digit *dp; 126 pstm_digit *dp;
127//bbox psPool_t *pool; 127//bbox psPool_t *pool;
128} pstm_int; 128} pstm_int;
@@ -154,9 +154,9 @@ extern int32 pstm_init_size(psPool_t *pool, pstm_int * a, uint32 size);
154#define pstm_init_copy(pool, a, b, toSqr) \ 154#define pstm_init_copy(pool, a, b, toSqr) \
155 pstm_init_copy( a, b, toSqr) 155 pstm_init_copy( a, b, toSqr)
156extern int32 pstm_init_copy(psPool_t *pool, pstm_int * a, pstm_int * b, 156extern int32 pstm_init_copy(psPool_t *pool, pstm_int * a, pstm_int * b,
157 int16 toSqr); 157 int toSqr); //bbox: was int16 toSqr
158 158
159extern int16 pstm_count_bits (pstm_int * a); 159extern int pstm_count_bits (pstm_int * a); //bbox: was returning int16
160 160
161//bbox: pool unused 161//bbox: pool unused
162#define pstm_init_for_read_unsigned_bin(pool, a, len) \ 162#define pstm_init_for_read_unsigned_bin(pool, a, len) \
@@ -178,7 +178,7 @@ extern 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, 178 pstm_int *mp3, pstm_int *mp4, pstm_int *mp5, pstm_int *mp6,
179 pstm_int *mp7); 179 pstm_int *mp7);
180 180
181extern int32 pstm_grow(pstm_int * a, int16 size); 181extern int32 pstm_grow(pstm_int * a, int size); //bbox: was int16 size
182 182
183extern void pstm_clamp(pstm_int * a); 183extern void pstm_clamp(pstm_int * a);
184 184
@@ -186,9 +186,9 @@ extern int32 pstm_cmp(pstm_int * a, pstm_int * b);
186 186
187extern int32 pstm_cmp_mag(pstm_int * a, pstm_int * b); 187extern int32 pstm_cmp_mag(pstm_int * a, pstm_int * b);
188 188
189extern void pstm_rshd(pstm_int *a, int16 x); 189extern void pstm_rshd(pstm_int *a, int x); //bbox: was int16 x
190 190
191extern int32 pstm_lshd(pstm_int * a, int16 b); 191extern int32 pstm_lshd(pstm_int * a, int b); //bbox: was int16 b
192 192
193//bbox: pool unused 193//bbox: pool unused
194#define pstm_div(pool, a, b, c, d) \ 194#define pstm_div(pool, a, b, c, d) \
@@ -199,8 +199,8 @@ extern int32 pstm_div(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c,
199//bbox: pool unused 199//bbox: pool unused
200#define pstm_div_2d(pool, a, b, c, d) \ 200#define pstm_div_2d(pool, a, b, c, d) \
201 pstm_div_2d( 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, 202extern int32 pstm_div_2d(psPool_t *pool, pstm_int *a, int b, pstm_int *c,
203 pstm_int *d); 203 pstm_int *d); //bbox: was int16 b
204 204
205extern int32 pstm_div_2(pstm_int * a, pstm_int * b); 205extern int32 pstm_div_2(pstm_int * a, pstm_int * b);
206 206
@@ -232,7 +232,7 @@ extern int32 pstm_mulmod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c,
232extern int32 pstm_exptmod(psPool_t *pool, pstm_int *G, pstm_int *X, pstm_int *P, 232extern int32 pstm_exptmod(psPool_t *pool, pstm_int *G, pstm_int *X, pstm_int *P,
233 pstm_int *Y); 233 pstm_int *Y);
234 234
235extern int32 pstm_2expt(pstm_int *a, int16 b); 235extern int32 pstm_2expt(pstm_int *a, int b); //bbox: was int16 b
236 236
237extern int32 pstm_add(pstm_int *a, pstm_int *b, pstm_int *c); 237extern int32 pstm_add(pstm_int *a, pstm_int *b, pstm_int *c);
238 238
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h
index a526494d7..ee12cf91b 100644
--- a/networking/udhcp/common.h
+++ b/networking/udhcp/common.h
@@ -300,8 +300,8 @@ int udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt,
300 uint32_t dest_nip, int dest_port) FAST_FUNC; 300 uint32_t dest_nip, int dest_port) FAST_FUNC;
301 301
302void udhcp_sp_setup(void) FAST_FUNC; 302void udhcp_sp_setup(void) FAST_FUNC;
303int udhcp_sp_fd_set(fd_set *rfds, int extra_fd) FAST_FUNC; 303void udhcp_sp_fd_set(struct pollfd *pfds, int extra_fd) FAST_FUNC;
304int udhcp_sp_read(const fd_set *rfds) FAST_FUNC; 304int udhcp_sp_read(struct pollfd *pfds) FAST_FUNC;
305 305
306int udhcp_read_interface(const char *interface, int *ifindex, uint32_t *nip, uint8_t *mac) FAST_FUNC; 306int udhcp_read_interface(const char *interface, int *ifindex, uint32_t *nip, uint8_t *mac) FAST_FUNC;
307 307
diff --git a/networking/udhcp/d6_common.h b/networking/udhcp/d6_common.h
index eb211ea0f..fcec8c15a 100644
--- a/networking/udhcp/d6_common.h
+++ b/networking/udhcp/d6_common.h
@@ -81,9 +81,14 @@ struct d6_option {
81#define D6_OPT_RECONF_MSG 19 81#define D6_OPT_RECONF_MSG 19
82#define D6_OPT_RECONF_ACCEPT 20 82#define D6_OPT_RECONF_ACCEPT 20
83 83
84#define D6_OPT_DNS_SERVERS 23
85#define D6_OPT_DOMAIN_LIST 24
86
84#define D6_OPT_IA_PD 25 87#define D6_OPT_IA_PD 25
85#define D6_OPT_IAPREFIX 26 88#define D6_OPT_IAPREFIX 26
86 89
90#define D6_OPT_CLIENT_FQDN 39
91
87/*** Other shared functions ***/ 92/*** Other shared functions ***/
88 93
89struct client6_data_t { 94struct client6_data_t {
@@ -91,10 +96,14 @@ struct client6_data_t {
91 struct d6_option *ia_na; 96 struct d6_option *ia_na;
92 char **env_ptr; 97 char **env_ptr;
93 unsigned env_idx; 98 unsigned env_idx;
99 /* link-local IPv6 address */
100 struct in6_addr ll_ip6;
94}; 101};
95 102
96#define client6_data (*(struct client6_data_t*)(&bb_common_bufsiz1[COMMON_BUFSIZE - sizeof(struct client6_data_t)])) 103#define client6_data (*(struct client6_data_t*)(&bb_common_bufsiz1[COMMON_BUFSIZE - sizeof(struct client6_data_t)]))
97 104
105int FAST_FUNC d6_read_interface(const char *interface, int *ifindex, struct in6_addr *nip6, uint8_t *mac);
106
98int FAST_FUNC d6_listen_socket(int port, const char *inf); 107int FAST_FUNC d6_listen_socket(int port, const char *inf);
99 108
100int FAST_FUNC d6_recv_kernel_packet( 109int FAST_FUNC d6_recv_kernel_packet(
@@ -112,7 +121,8 @@ int FAST_FUNC d6_send_raw_packet(
112int FAST_FUNC d6_send_kernel_packet( 121int FAST_FUNC d6_send_kernel_packet(
113 struct d6_packet *d6_pkt, unsigned d6_pkt_size, 122 struct d6_packet *d6_pkt, unsigned d6_pkt_size,
114 struct in6_addr *src_ipv6, int source_port, 123 struct in6_addr *src_ipv6, int source_port,
115 struct in6_addr *dst_ipv6, int dest_port 124 struct in6_addr *dst_ipv6, int dest_port,
125 int ifindex
116); 126);
117 127
118#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 2 128#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 2
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c
index 64339c9b5..18a104c61 100644
--- a/networking/udhcp/d6_dhcpc.c
+++ b/networking/udhcp/d6_dhcpc.c
@@ -54,7 +54,9 @@ static const char udhcpc6_longopts[] ALIGN1 =
54 "request-option\0" Required_argument "O" 54 "request-option\0" Required_argument "O"
55 "no-default-options\0" No_argument "o" 55 "no-default-options\0" No_argument "o"
56 "foreground\0" No_argument "f" 56 "foreground\0" No_argument "f"
57 USE_FOR_MMU(
57 "background\0" No_argument "b" 58 "background\0" No_argument "b"
59 )
58/// IF_FEATURE_UDHCPC_ARPING("arping\0" No_argument "a") 60/// IF_FEATURE_UDHCPC_ARPING("arping\0" No_argument "a")
59 IF_FEATURE_UDHCP_PORT("client-port\0" Required_argument "P") 61 IF_FEATURE_UDHCP_PORT("client-port\0" Required_argument "P")
60 ; 62 ;
@@ -86,6 +88,19 @@ enum {
86 IF_FEATURE_UDHCP_PORT( OPT_P = 1 << OPTBIT_P,) 88 IF_FEATURE_UDHCP_PORT( OPT_P = 1 << OPTBIT_P,)
87}; 89};
88 90
91static const char opt_req[] = {
92 (D6_OPT_ORO >> 8), (D6_OPT_ORO & 0xff),
93 0, 6,
94 (D6_OPT_DNS_SERVERS >> 8), (D6_OPT_DNS_SERVERS & 0xff),
95 (D6_OPT_DOMAIN_LIST >> 8), (D6_OPT_DOMAIN_LIST & 0xff),
96 (D6_OPT_CLIENT_FQDN >> 8), (D6_OPT_CLIENT_FQDN & 0xff)
97};
98
99static const char opt_fqdn_req[] = {
100 (D6_OPT_CLIENT_FQDN >> 8), (D6_OPT_CLIENT_FQDN & 0xff),
101 0, 2,
102 0, 0
103};
89 104
90/*** Utility functions ***/ 105/*** Utility functions ***/
91 106
@@ -107,8 +122,8 @@ static void *d6_find_option(uint8_t *option, uint8_t *option_end, unsigned code)
107 /* Does its code match? */ 122 /* Does its code match? */
108 if (option[1] == code) 123 if (option[1] == code)
109 return option; /* yes! */ 124 return option; /* yes! */
110 option += option[3] + 4;
111 len_m4 -= option[3] + 4; 125 len_m4 -= option[3] + 4;
126 option += option[3] + 4;
112 } 127 }
113 return NULL; 128 return NULL;
114} 129}
@@ -139,8 +154,10 @@ static char** new_env(void)
139/* put all the parameters into the environment */ 154/* put all the parameters into the environment */
140static void option_to_env(uint8_t *option, uint8_t *option_end) 155static void option_to_env(uint8_t *option, uint8_t *option_end)
141{ 156{
157 char *dlist, *ptr;
142 /* "length minus 4" */ 158 /* "length minus 4" */
143 int len_m4 = option_end - option - 4; 159 int len_m4 = option_end - option - 4;
160 int olen, ooff;
144 while (len_m4 >= 0) { 161 while (len_m4 >= 0) {
145 uint32_t v32; 162 uint32_t v32;
146 char ipv6str[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")]; 163 char ipv6str[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")];
@@ -217,9 +234,54 @@ static void option_to_env(uint8_t *option, uint8_t *option_end)
217 234
218 sprint_nip6(ipv6str, option + 4 + 4 + 1); 235 sprint_nip6(ipv6str, option + 4 + 4 + 1);
219 *new_env() = xasprintf("ipv6prefix=%s/%u", ipv6str, (unsigned)(option[4 + 4])); 236 *new_env() = xasprintf("ipv6prefix=%s/%u", ipv6str, (unsigned)(option[4 + 4]));
237 break;
238 case D6_OPT_DNS_SERVERS:
239 olen = ((option[2] << 8) | option[3]) / 16;
240 dlist = ptr = malloc (4 + olen * 40 - 1);
241
242 memcpy (ptr, "dns=", 4);
243 ptr += 4;
244 ooff = 0;
245
246 while (olen--) {
247 sprint_nip6(ptr, option + 4 + ooff);
248 ptr += 39;
249 ooff += 16;
250 if (olen)
251 *ptr++ = ' ';
252 }
253
254 *new_env() = dlist;
255
256 break;
257 case D6_OPT_DOMAIN_LIST:
258 dlist = dname_dec(option + 4, (option[2] << 8) | option[3], "search=");
259 if (!dlist)
260 break;
261 *new_env() = dlist;
262 break;
263 case D6_OPT_CLIENT_FQDN:
264 // Work around broken ISC DHCPD6
265 if (option[4] & 0xf8) {
266 olen = ((option[2] << 8) | option[3]);
267 dlist = xmalloc(olen);
268//fixme:
269//- explain
270//- add len error check
271//- merge two allocs into one
272 memcpy(dlist, option + 4, olen);
273 *new_env() = xasprintf("fqdn=%s", dlist);
274 free(dlist);
275 break;
276 }
277 dlist = dname_dec(option + 5, ((option[2] << 8) | option[3]) - 1, "fqdn=");
278 if (!dlist)
279 break;
280 *new_env() = dlist;
281 break;
220 } 282 }
221 option += 4 + option[3];
222 len_m4 -= 4 + option[3]; 283 len_m4 -= 4 + option[3];
284 option += 4 + option[3];
223 } 285 }
224} 286}
225 287
@@ -311,7 +373,7 @@ static int d6_mcast_from_client_config_ifindex(struct d6_packet *packet, uint8_t
311 373
312 return d6_send_raw_packet( 374 return d6_send_raw_packet(
313 packet, (end - (uint8_t*) packet), 375 packet, (end - (uint8_t*) packet),
314 /*src*/ NULL, CLIENT_PORT6, 376 /*src*/ &client6_data.ll_ip6, CLIENT_PORT6,
315 /*dst*/ (struct in6_addr*)FF02__1_2, SERVER_PORT6, MAC_BCAST_ADDR, 377 /*dst*/ (struct in6_addr*)FF02__1_2, SERVER_PORT6, MAC_BCAST_ADDR,
316 client_config.ifindex 378 client_config.ifindex
317 ); 379 );
@@ -423,6 +485,10 @@ static NOINLINE int send_d6_discover(uint32_t xid, struct in6_addr *requested_ip
423 } 485 }
424 opt_ptr = d6_store_blob(opt_ptr, client6_data.ia_na, len); 486 opt_ptr = d6_store_blob(opt_ptr, client6_data.ia_na, len);
425 487
488 /* Request additional options */
489 opt_ptr = d6_store_blob(opt_ptr, &opt_req, sizeof(opt_req));
490 opt_ptr = d6_store_blob(opt_ptr, &opt_fqdn_req, sizeof(opt_fqdn_req));
491
426 /* Add options: 492 /* Add options:
427 * "param req" option according to -O, options specified with -x 493 * "param req" option according to -O, options specified with -x
428 */ 494 */
@@ -476,6 +542,10 @@ static NOINLINE int send_d6_select(uint32_t xid)
476 /* IA NA (contains requested IP) */ 542 /* IA NA (contains requested IP) */
477 opt_ptr = d6_store_blob(opt_ptr, client6_data.ia_na, client6_data.ia_na->len + 2+2); 543 opt_ptr = d6_store_blob(opt_ptr, client6_data.ia_na, client6_data.ia_na->len + 2+2);
478 544
545 /* Request additional options */
546 opt_ptr = d6_store_blob(opt_ptr, &opt_req, sizeof(opt_req));
547 opt_ptr = d6_store_blob(opt_ptr, &opt_fqdn_req, sizeof(opt_fqdn_req));
548
479 /* Add options: 549 /* Add options:
480 * "param req" option according to -O, options specified with -x 550 * "param req" option according to -O, options specified with -x
481 */ 551 */
@@ -555,7 +625,8 @@ static NOINLINE int send_d6_renew(uint32_t xid, struct in6_addr *server_ipv6, st
555 return d6_send_kernel_packet( 625 return d6_send_kernel_packet(
556 &packet, (opt_ptr - (uint8_t*) &packet), 626 &packet, (opt_ptr - (uint8_t*) &packet),
557 our_cur_ipv6, CLIENT_PORT6, 627 our_cur_ipv6, CLIENT_PORT6,
558 server_ipv6, SERVER_PORT6 628 server_ipv6, SERVER_PORT6,
629 client_config.ifindex
559 ); 630 );
560 return d6_mcast_from_client_config_ifindex(&packet, opt_ptr); 631 return d6_mcast_from_client_config_ifindex(&packet, opt_ptr);
561} 632}
@@ -577,15 +648,14 @@ static int send_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cu
577 return d6_send_kernel_packet( 648 return d6_send_kernel_packet(
578 &packet, (opt_ptr - (uint8_t*) &packet), 649 &packet, (opt_ptr - (uint8_t*) &packet),
579 our_cur_ipv6, CLIENT_PORT6, 650 our_cur_ipv6, CLIENT_PORT6,
580 server_ipv6, SERVER_PORT6 651 server_ipv6, SERVER_PORT6,
652 client_config.ifindex
581 ); 653 );
582} 654}
583 655
584/* Returns -1 on errors that are fatal for the socket, -2 for those that aren't */ 656/* Returns -1 on errors that are fatal for the socket, -2 for those that aren't */
585/* NOINLINE: limit stack usage in caller */ 657/* NOINLINE: limit stack usage in caller */
586static NOINLINE int d6_recv_raw_packet(struct in6_addr *peer_ipv6 658static NOINLINE int d6_recv_raw_packet(struct in6_addr *peer_ipv6, struct d6_packet *d6_pkt, int fd)
587 UNUSED_PARAM
588 , struct d6_packet *d6_pkt, int fd)
589{ 659{
590 int bytes; 660 int bytes;
591 struct ip6_udp_d6_packet packet; 661 struct ip6_udp_d6_packet packet;
@@ -634,6 +704,9 @@ static NOINLINE int d6_recv_raw_packet(struct in6_addr *peer_ipv6
634// return -2; 704// return -2;
635// } 705// }
636 706
707 if (peer_ipv6)
708 *peer_ipv6 = packet.ip6.ip6_src; /* struct copy */
709
637 log1("received %s", "a packet"); 710 log1("received %s", "a packet");
638 d6_dump_packet(&packet.data); 711 d6_dump_packet(&packet.data);
639 712
@@ -935,9 +1008,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
935 int timeout; /* must be signed */ 1008 int timeout; /* must be signed */
936 unsigned already_waited_sec; 1009 unsigned already_waited_sec;
937 unsigned opt; 1010 unsigned opt;
938 int max_fd;
939 int retval; 1011 int retval;
940 fd_set rfds;
941 1012
942 setup_common_bufsiz(); 1013 setup_common_bufsiz();
943 1014
@@ -1003,11 +1074,13 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1003 /* now it looks similar to udhcpd's config file line: 1074 /* now it looks similar to udhcpd's config file line:
1004 * "optname optval", using the common routine: */ 1075 * "optname optval", using the common routine: */
1005 udhcp_str2optset(optstr, &client_config.options); 1076 udhcp_str2optset(optstr, &client_config.options);
1077 if (colon)
1078 *colon = ':'; /* restore it for NOMMU reexec */
1006 } 1079 }
1007 1080
1008 if (udhcp_read_interface(client_config.interface, 1081 if (d6_read_interface(client_config.interface,
1009 &client_config.ifindex, 1082 &client_config.ifindex,
1010 NULL, 1083 &client6_data.ll_ip6,
1011 client_config.client_mac) 1084 client_config.client_mac)
1012 ) { 1085 ) {
1013 return 1; 1086 return 1;
@@ -1063,7 +1136,8 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1063 * "continue" statements in code below jump to the top of the loop. 1136 * "continue" statements in code below jump to the top of the loop.
1064 */ 1137 */
1065 for (;;) { 1138 for (;;) {
1066 struct timeval tv; 1139 int tv;
1140 struct pollfd pfds[2];
1067 struct d6_packet packet; 1141 struct d6_packet packet;
1068 uint8_t *packet_end; 1142 uint8_t *packet_end;
1069 /* silence "uninitialized!" warning */ 1143 /* silence "uninitialized!" warning */
@@ -1078,16 +1152,15 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1078 * to change_listen_mode(). Thus we open listen socket 1152 * to change_listen_mode(). Thus we open listen socket
1079 * BEFORE we send renew request (see "case BOUND:"). */ 1153 * BEFORE we send renew request (see "case BOUND:"). */
1080 1154
1081 max_fd = udhcp_sp_fd_set(&rfds, sockfd); 1155 udhcp_sp_fd_set(pfds, sockfd);
1082 1156
1083 tv.tv_sec = timeout - already_waited_sec; 1157 tv = timeout - already_waited_sec;
1084 tv.tv_usec = 0;
1085 retval = 0; 1158 retval = 0;
1086 /* If we already timed out, fall through with retval = 0, else... */ 1159 /* If we already timed out, fall through with retval = 0, else... */
1087 if ((int)tv.tv_sec > 0) { 1160 if (tv > 0) {
1088 log1("waiting on select %u seconds", (int)tv.tv_sec); 1161 log1("waiting on select %u seconds", tv);
1089 timestamp_before_wait = (unsigned)monotonic_sec(); 1162 timestamp_before_wait = (unsigned)monotonic_sec();
1090 retval = select(max_fd + 1, &rfds, NULL, NULL, &tv); 1163 retval = poll(pfds, 2, tv < INT_MAX/1000 ? tv * 1000 : INT_MAX);
1091 if (retval < 0) { 1164 if (retval < 0) {
1092 /* EINTR? A signal was caught, don't panic */ 1165 /* EINTR? A signal was caught, don't panic */
1093 if (errno == EINTR) { 1166 if (errno == EINTR) {
@@ -1108,13 +1181,14 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1108 * or if the status of the bridge changed). 1181 * or if the status of the bridge changed).
1109 * Refresh ifindex and client_mac: 1182 * Refresh ifindex and client_mac:
1110 */ 1183 */
1111 if (udhcp_read_interface(client_config.interface, 1184 if (d6_read_interface(client_config.interface,
1112 &client_config.ifindex, 1185 &client_config.ifindex,
1113 NULL, 1186 &client6_data.ll_ip6,
1114 client_config.client_mac) 1187 client_config.client_mac)
1115 ) { 1188 ) {
1116 goto ret0; /* iface is gone? */ 1189 goto ret0; /* iface is gone? */
1117 } 1190 }
1191
1118 memcpy(clientid_mac_ptr, client_config.client_mac, 6); 1192 memcpy(clientid_mac_ptr, client_config.client_mac, 6);
1119 1193
1120 /* We will restart the wait in any case */ 1194 /* We will restart the wait in any case */
@@ -1222,8 +1296,8 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1222 /* select() didn't timeout, something happened */ 1296 /* select() didn't timeout, something happened */
1223 1297
1224 /* Is it a signal? */ 1298 /* Is it a signal? */
1225 /* note: udhcp_sp_read checks FD_ISSET before reading */ 1299 /* note: udhcp_sp_read checks poll result before reading */
1226 switch (udhcp_sp_read(&rfds)) { 1300 switch (udhcp_sp_read(pfds)) {
1227 case SIGUSR1: 1301 case SIGUSR1:
1228 client_config.first_secs = 0; /* make secs field count from 0 */ 1302 client_config.first_secs = 0; /* make secs field count from 0 */
1229 already_waited_sec = 0; 1303 already_waited_sec = 0;
@@ -1258,7 +1332,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1258 } 1332 }
1259 1333
1260 /* Is it a packet? */ 1334 /* Is it a packet? */
1261 if (listen_mode == LISTEN_NONE || !FD_ISSET(sockfd, &rfds)) 1335 if (listen_mode == LISTEN_NONE || !pfds[1].revents)
1262 continue; /* no */ 1336 continue; /* no */
1263 1337
1264 { 1338 {
@@ -1307,7 +1381,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1307 struct d6_option *option, *iaaddr; 1381 struct d6_option *option, *iaaddr;
1308 type_is_ok: 1382 type_is_ok:
1309 option = d6_find_option(packet.d6_options, packet_end, D6_OPT_STATUS_CODE); 1383 option = d6_find_option(packet.d6_options, packet_end, D6_OPT_STATUS_CODE);
1310 if (option && option->data[4] != 0) { 1384 if (option && (option->data[0] | option->data[1]) != 0) {
1311 /* return to init state */ 1385 /* return to init state */
1312 bb_error_msg("received DHCP NAK (%u)", option->data[4]); 1386 bb_error_msg("received DHCP NAK (%u)", option->data[4]);
1313 d6_run_script(&packet, "nak"); 1387 d6_run_script(&packet, "nak");
@@ -1460,8 +1534,8 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1460 if (lease_seconds < 0x10) 1534 if (lease_seconds < 0x10)
1461 lease_seconds = 0x10; 1535 lease_seconds = 0x10;
1462/// TODO: check for 0 lease time? 1536/// TODO: check for 0 lease time?
1463 if (lease_seconds >= 0x10000000) 1537 if (lease_seconds > 0x7fffffff / 1000)
1464 lease_seconds = 0x0fffffff; 1538 lease_seconds = 0x7fffffff / 1000;
1465 /* enter bound state */ 1539 /* enter bound state */
1466 timeout = lease_seconds / 2; 1540 timeout = lease_seconds / 2;
1467 bb_error_msg("lease obtained, lease time %u", 1541 bb_error_msg("lease obtained, lease time %u",
diff --git a/networking/udhcp/d6_packet.c b/networking/udhcp/d6_packet.c
index e166f520d..79a0ac8a8 100644
--- a/networking/udhcp/d6_packet.c
+++ b/networking/udhcp/d6_packet.c
@@ -127,7 +127,8 @@ int FAST_FUNC d6_send_raw_packet(
127int FAST_FUNC d6_send_kernel_packet( 127int FAST_FUNC d6_send_kernel_packet(
128 struct d6_packet *d6_pkt, unsigned d6_pkt_size, 128 struct d6_packet *d6_pkt, unsigned d6_pkt_size,
129 struct in6_addr *src_ipv6, int source_port, 129 struct in6_addr *src_ipv6, int source_port,
130 struct in6_addr *dst_ipv6, int dest_port) 130 struct in6_addr *dst_ipv6, int dest_port,
131 int ifindex)
131{ 132{
132 struct sockaddr_in6 sa; 133 struct sockaddr_in6 sa;
133 int fd; 134 int fd;
@@ -154,6 +155,7 @@ int FAST_FUNC d6_send_kernel_packet(
154 sa.sin6_family = AF_INET6; 155 sa.sin6_family = AF_INET6;
155 sa.sin6_port = htons(dest_port); 156 sa.sin6_port = htons(dest_port);
156 sa.sin6_addr = *dst_ipv6; /* struct copy */ 157 sa.sin6_addr = *dst_ipv6; /* struct copy */
158 sa.sin6_scope_id = ifindex;
157 if (connect(fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) { 159 if (connect(fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
158 msg = "connect"; 160 msg = "connect";
159 goto ret_close; 161 goto ret_close;
diff --git a/networking/udhcp/d6_socket.c b/networking/udhcp/d6_socket.c
index 910f296a3..930e5e4f5 100644
--- a/networking/udhcp/d6_socket.c
+++ b/networking/udhcp/d6_socket.c
@@ -7,6 +7,67 @@
7#include "common.h" 7#include "common.h"
8#include "d6_common.h" 8#include "d6_common.h"
9#include <net/if.h> 9#include <net/if.h>
10#include <ifaddrs.h>
11#include <netpacket/packet.h>
12
13int FAST_FUNC d6_read_interface(const char *interface, int *ifindex, struct in6_addr *nip6, uint8_t *mac)
14{
15 int retval = 3;
16 struct ifaddrs *ifap, *ifa;
17
18 getifaddrs(&ifap);
19
20 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
21 struct sockaddr_in6 *sip6;
22
23 if (!ifa->ifa_addr || (strcmp(ifa->ifa_name, interface) != 0))
24 continue;
25
26 sip6 = (struct sockaddr_in6*)(ifa->ifa_addr);
27
28 if (ifa->ifa_addr->sa_family == AF_PACKET) {
29 struct sockaddr_ll *sll = (struct sockaddr_ll*)(ifa->ifa_addr);
30 memcpy(mac, sll->sll_addr, 6);
31 log1("MAC %02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
32 log1("adapter index %d", sll->sll_ifindex);
33 *ifindex = sll->sll_ifindex;
34 retval &= (0xf - (1<<0));
35 }
36#if 0
37 if (ifa->ifa_addr->sa_family == AF_INET) {
38 *nip = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr;
39 log1("IP %s", inet_ntoa(((struct sockaddr_in *)ifa->ifa_addr)->sin_addr));
40 }
41#endif
42 if (ifa->ifa_addr->sa_family == AF_INET6
43 && IN6_IS_ADDR_LINKLOCAL(&sip6->sin6_addr)
44 ) {
45 *nip6 = sip6->sin6_addr; /* struct copy */
46 log1(
47 "IPv6 %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
48 nip6->s6_addr[0], nip6->s6_addr[1],
49 nip6->s6_addr[2], nip6->s6_addr[3],
50 nip6->s6_addr[4], nip6->s6_addr[5],
51 nip6->s6_addr[6], nip6->s6_addr[7],
52 nip6->s6_addr[8], nip6->s6_addr[9],
53 nip6->s6_addr[10], nip6->s6_addr[11],
54 nip6->s6_addr[12], nip6->s6_addr[13],
55 nip6->s6_addr[14], nip6->s6_addr[15]
56 );
57 retval &= (0xf - (1<<1));
58 }
59 }
60
61 freeifaddrs(ifap);
62 if (retval == 0)
63 return retval;
64
65 if (retval & (1<<0))
66 bb_error_msg("can't get %s", "MAC");
67 if (retval & (1<<1))
68 bb_error_msg("can't get %s", "link-local IPv6 address");
69 return -1;
70}
10 71
11int FAST_FUNC d6_listen_socket(int port, const char *inf) 72int FAST_FUNC d6_listen_socket(int port, const char *inf)
12{ 73{
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index 0e236261b..6aa6731fb 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -73,7 +73,9 @@ static const char udhcpc_longopts[] ALIGN1 =
73 "request-option\0" Required_argument "O" 73 "request-option\0" Required_argument "O"
74 "no-default-options\0" No_argument "o" 74 "no-default-options\0" No_argument "o"
75 "foreground\0" No_argument "f" 75 "foreground\0" No_argument "f"
76 USE_FOR_MMU(
76 "background\0" No_argument "b" 77 "background\0" No_argument "b"
78 )
77 "broadcast\0" No_argument "B" 79 "broadcast\0" No_argument "B"
78 IF_FEATURE_UDHCPC_ARPING("arping\0" Optional_argument "a") 80 IF_FEATURE_UDHCPC_ARPING("arping\0" Optional_argument "a")
79 IF_FEATURE_UDHCP_PORT("client-port\0" Required_argument "P") 81 IF_FEATURE_UDHCP_PORT("client-port\0" Required_argument "P")
@@ -1281,9 +1283,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1281 unsigned already_waited_sec; 1283 unsigned already_waited_sec;
1282 unsigned opt; 1284 unsigned opt;
1283 IF_FEATURE_UDHCPC_ARPING(unsigned arpping_ms;) 1285 IF_FEATURE_UDHCPC_ARPING(unsigned arpping_ms;)
1284 int max_fd;
1285 int retval; 1286 int retval;
1286 fd_set rfds;
1287 1287
1288 setup_common_bufsiz(); 1288 setup_common_bufsiz();
1289 1289
@@ -1367,6 +1367,8 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1367 /* now it looks similar to udhcpd's config file line: 1367 /* now it looks similar to udhcpd's config file line:
1368 * "optname optval", using the common routine: */ 1368 * "optname optval", using the common routine: */
1369 udhcp_str2optset(optstr, &client_config.options); 1369 udhcp_str2optset(optstr, &client_config.options);
1370 if (colon)
1371 *colon = ':'; /* restore it for NOMMU reexec */
1370 } 1372 }
1371 1373
1372 if (udhcp_read_interface(client_config.interface, 1374 if (udhcp_read_interface(client_config.interface,
@@ -1432,7 +1434,8 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1432 * "continue" statements in code below jump to the top of the loop. 1434 * "continue" statements in code below jump to the top of the loop.
1433 */ 1435 */
1434 for (;;) { 1436 for (;;) {
1435 struct timeval tv; 1437 int tv;
1438 struct pollfd pfds[2];
1436 struct dhcp_packet packet; 1439 struct dhcp_packet packet;
1437 /* silence "uninitialized!" warning */ 1440 /* silence "uninitialized!" warning */
1438 unsigned timestamp_before_wait = timestamp_before_wait; 1441 unsigned timestamp_before_wait = timestamp_before_wait;
@@ -1446,23 +1449,22 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1446 * to change_listen_mode(). Thus we open listen socket 1449 * to change_listen_mode(). Thus we open listen socket
1447 * BEFORE we send renew request (see "case BOUND:"). */ 1450 * BEFORE we send renew request (see "case BOUND:"). */
1448 1451
1449 max_fd = udhcp_sp_fd_set(&rfds, sockfd); 1452 udhcp_sp_fd_set(pfds, sockfd);
1450 1453
1451 tv.tv_sec = timeout - already_waited_sec; 1454 tv = timeout - already_waited_sec;
1452 tv.tv_usec = 0;
1453 retval = 0; 1455 retval = 0;
1454 /* If we already timed out, fall through with retval = 0, else... */ 1456 /* If we already timed out, fall through with retval = 0, else... */
1455 if ((int)tv.tv_sec > 0) { 1457 if (tv > 0) {
1456 log1("waiting on select %u seconds", (int)tv.tv_sec); 1458 log1("waiting on select %u seconds", tv);
1457 timestamp_before_wait = (unsigned)monotonic_sec(); 1459 timestamp_before_wait = (unsigned)monotonic_sec();
1458 retval = select(max_fd + 1, &rfds, NULL, NULL, &tv); 1460 retval = poll(pfds, 2, tv < INT_MAX/1000 ? tv * 1000 : INT_MAX);
1459 if (retval < 0) { 1461 if (retval < 0) {
1460 /* EINTR? A signal was caught, don't panic */ 1462 /* EINTR? A signal was caught, don't panic */
1461 if (errno == EINTR) { 1463 if (errno == EINTR) {
1462 already_waited_sec += (unsigned)monotonic_sec() - timestamp_before_wait; 1464 already_waited_sec += (unsigned)monotonic_sec() - timestamp_before_wait;
1463 continue; 1465 continue;
1464 } 1466 }
1465 /* Else: an error occured, panic! */ 1467 /* Else: an error occurred, panic! */
1466 bb_perror_msg_and_die("select"); 1468 bb_perror_msg_and_die("select");
1467 } 1469 }
1468 } 1470 }
@@ -1591,8 +1593,8 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1591 /* select() didn't timeout, something happened */ 1593 /* select() didn't timeout, something happened */
1592 1594
1593 /* Is it a signal? */ 1595 /* Is it a signal? */
1594 /* note: udhcp_sp_read checks FD_ISSET before reading */ 1596 /* note: udhcp_sp_read checks poll result before reading */
1595 switch (udhcp_sp_read(&rfds)) { 1597 switch (udhcp_sp_read(pfds)) {
1596 case SIGUSR1: 1598 case SIGUSR1:
1597 client_config.first_secs = 0; /* make secs field count from 0 */ 1599 client_config.first_secs = 0; /* make secs field count from 0 */
1598 already_waited_sec = 0; 1600 already_waited_sec = 0;
@@ -1627,7 +1629,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1627 } 1629 }
1628 1630
1629 /* Is it a packet? */ 1631 /* Is it a packet? */
1630 if (listen_mode == LISTEN_NONE || !FD_ISSET(sockfd, &rfds)) 1632 if (listen_mode == LISTEN_NONE || !pfds[1].revents)
1631 continue; /* no */ 1633 continue; /* no */
1632 1634
1633 { 1635 {
@@ -1742,8 +1744,8 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1742 /* paranoia: must not be too small and not prone to overflows */ 1744 /* paranoia: must not be too small and not prone to overflows */
1743 if (lease_seconds < 0x10) 1745 if (lease_seconds < 0x10)
1744 lease_seconds = 0x10; 1746 lease_seconds = 0x10;
1745 if (lease_seconds >= 0x10000000) 1747 if (lease_seconds > 0x7fffffff / 1000)
1746 lease_seconds = 0x0fffffff; 1748 lease_seconds = 0x7fffffff / 1000;
1747 } 1749 }
1748#if ENABLE_FEATURE_UDHCPC_ARPING 1750#if ENABLE_FEATURE_UDHCPC_ARPING
1749 if (opt & OPT_a) { 1751 if (opt & OPT_a) {
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c
index e116ba3af..5eff026bc 100644
--- a/networking/udhcp/dhcpd.c
+++ b/networking/udhcp/dhcpd.c
@@ -794,7 +794,7 @@ static NOINLINE void send_inform(struct dhcp_packet *oldpacket)
794int udhcpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 794int udhcpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
795int udhcpd_main(int argc UNUSED_PARAM, char **argv) 795int udhcpd_main(int argc UNUSED_PARAM, char **argv)
796{ 796{
797 int server_socket = -1, retval, max_sock; 797 int server_socket = -1, retval;
798 uint8_t *state; 798 uint8_t *state;
799 unsigned timeout_end; 799 unsigned timeout_end;
800 unsigned num_ips; 800 unsigned num_ips;
@@ -891,10 +891,10 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv)
891 continue_with_autotime: 891 continue_with_autotime:
892 timeout_end = monotonic_sec() + server_config.auto_time; 892 timeout_end = monotonic_sec() + server_config.auto_time;
893 while (1) { /* loop until universe collapses */ 893 while (1) { /* loop until universe collapses */
894 fd_set rfds; 894 struct pollfd pfds[2];
895 struct dhcp_packet packet; 895 struct dhcp_packet packet;
896 int bytes; 896 int bytes;
897 struct timeval tv; 897 int tv;
898 uint8_t *server_id_opt; 898 uint8_t *server_id_opt;
899 uint8_t *requested_ip_opt; 899 uint8_t *requested_ip_opt;
900 uint32_t requested_nip = requested_nip; /* for compiler */ 900 uint32_t requested_nip = requested_nip; /* for compiler */
@@ -906,16 +906,11 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv)
906 server_config.interface); 906 server_config.interface);
907 } 907 }
908 908
909 max_sock = udhcp_sp_fd_set(&rfds, server_socket); 909 udhcp_sp_fd_set(pfds, server_socket);
910 if (server_config.auto_time) { 910 tv = timeout_end - monotonic_sec();
911 /* cast to signed is essential if tv_sec is wider than int */
912 tv.tv_sec = (int)(timeout_end - monotonic_sec());
913 tv.tv_usec = 0;
914 }
915 retval = 0; 911 retval = 0;
916 if (!server_config.auto_time || tv.tv_sec > 0) { 912 if (!server_config.auto_time || tv > 0) {
917 retval = select(max_sock + 1, &rfds, NULL, NULL, 913 retval = poll(pfds, 2, server_config.auto_time ? tv * 1000 : -1);
918 server_config.auto_time ? &tv : NULL);
919 } 914 }
920 if (retval == 0) { 915 if (retval == 0) {
921 write_leases(); 916 write_leases();
@@ -926,7 +921,7 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv)
926 continue; 921 continue;
927 } 922 }
928 923
929 switch (udhcp_sp_read(&rfds)) { 924 switch (udhcp_sp_read(pfds)) {
930 case SIGUSR1: 925 case SIGUSR1:
931 bb_error_msg("received %s", "SIGUSR1"); 926 bb_error_msg("received %s", "SIGUSR1");
932 write_leases(); 927 write_leases();
diff --git a/networking/udhcp/dhcprelay.c b/networking/udhcp/dhcprelay.c
index 7cb19b14e..ea84c0dd7 100644
--- a/networking/udhcp/dhcprelay.c
+++ b/networking/udhcp/dhcprelay.c
@@ -361,7 +361,7 @@ int dhcprelay_main(int argc, char **argv)
361// which the reply must be sent (i.e., the host or router interface 361// which the reply must be sent (i.e., the host or router interface
362// connected to the same network as the BOOTP client). If the content 362// connected to the same network as the BOOTP client). If the content
363// of the 'giaddr' field does not match one of the relay agent's 363// of the 'giaddr' field does not match one of the relay agent's
364// directly-connected logical interfaces, the BOOTREPLY messsage MUST be 364// directly-connected logical interfaces, the BOOTREPLY message MUST be
365// silently discarded. 365// silently discarded.
366 if (udhcp_read_interface(iface_list[i], NULL, &dhcp_msg.gateway_nip, NULL)) { 366 if (udhcp_read_interface(iface_list[i], NULL, &dhcp_msg.gateway_nip, NULL)) {
367 /* Fall back to our IP on server iface */ 367 /* Fall back to our IP on server iface */
diff --git a/networking/udhcp/signalpipe.c b/networking/udhcp/signalpipe.c
index 6355c5e90..b101b4ce4 100644
--- a/networking/udhcp/signalpipe.c
+++ b/networking/udhcp/signalpipe.c
@@ -25,9 +25,11 @@ static struct fd_pair signal_pipe;
25 25
26static void signal_handler(int sig) 26static void signal_handler(int sig)
27{ 27{
28 int sv = errno;
28 unsigned char ch = sig; /* use char, avoid dealing with partial writes */ 29 unsigned char ch = sig; /* use char, avoid dealing with partial writes */
29 if (write(signal_pipe.wr, &ch, 1) != 1) 30 if (write(signal_pipe.wr, &ch, 1) != 1)
30 bb_perror_msg("can't send signal"); 31 bb_perror_msg("can't send signal");
32 errno = sv;
31} 33}
32 34
33/* Call this before doing anything else. Sets up the socket pair 35/* Call this before doing anything else. Sets up the socket pair
@@ -46,28 +48,29 @@ void FAST_FUNC udhcp_sp_setup(void)
46 , signal_handler); 48 , signal_handler);
47} 49}
48 50
49/* Quick little function to setup the rfds. Will return the 51/* Quick little function to setup the pfds.
50 * max_fd for use with select. Limited in that you can only pass 52 * Limited in that you can only pass one extra fd.
51 * one extra fd */ 53 */
52int FAST_FUNC udhcp_sp_fd_set(fd_set *rfds, int extra_fd) 54void FAST_FUNC udhcp_sp_fd_set(struct pollfd pfds[2], int extra_fd)
53{ 55{
54 FD_ZERO(rfds); 56 pfds[0].fd = signal_pipe.rd;
55 FD_SET(signal_pipe.rd, rfds); 57 pfds[0].events = POLLIN;
58 pfds[1].fd = -1;
56 if (extra_fd >= 0) { 59 if (extra_fd >= 0) {
57 close_on_exec_on(extra_fd); 60 close_on_exec_on(extra_fd);
58 FD_SET(extra_fd, rfds); 61 pfds[1].fd = extra_fd;
62 pfds[1].events = POLLIN;
59 } 63 }
60 return signal_pipe.rd > extra_fd ? signal_pipe.rd : extra_fd;
61} 64}
62 65
63/* Read a signal from the signal pipe. Returns 0 if there is 66/* Read a signal from the signal pipe. Returns 0 if there is
64 * no signal, -1 on error (and sets errno appropriately), and 67 * no signal, -1 on error (and sets errno appropriately), and
65 * your signal on success */ 68 * your signal on success */
66int FAST_FUNC udhcp_sp_read(const fd_set *rfds) 69int FAST_FUNC udhcp_sp_read(struct pollfd pfds[2])
67{ 70{
68 unsigned char sig; 71 unsigned char sig;
69 72
70 if (!FD_ISSET(signal_pipe.rd, rfds)) 73 if (!pfds[0].revents)
71 return 0; 74 return 0;
72 75
73 if (safe_read(signal_pipe.rd, &sig, 1) != 1) 76 if (safe_read(signal_pipe.rd, &sig, 1) != 1)
diff --git a/networking/vconfig.c b/networking/vconfig.c
index f3020409a..854eca0a1 100644
--- a/networking/vconfig.c
+++ b/networking/vconfig.c
@@ -138,7 +138,7 @@ int vconfig_main(int argc, char **argv)
138 /* I suppose one could try to combine some of the function calls below, 138 /* I suppose one could try to combine some of the function calls below,
139 * since ifr.u.flag, ifr.u.VID, and ifr.u.skb_priority are all same-sized 139 * since ifr.u.flag, ifr.u.VID, and ifr.u.skb_priority are all same-sized
140 * (unsigned) int members of a unions. But because of the range checking, 140 * (unsigned) int members of a unions. But because of the range checking,
141 * doing so wouldn't save that much space and would also make maintainence 141 * doing so wouldn't save that much space and would also make maintenance
142 * more of a pain. 142 * more of a pain.
143 */ 143 */
144 if (ifr.cmd == SET_VLAN_FLAG_CMD) { 144 if (ifr.cmd == SET_VLAN_FLAG_CMD) {
diff --git a/procps/kill.c b/procps/kill.c
index 7ae5beead..975a3e8c5 100644
--- a/procps/kill.c
+++ b/procps/kill.c
@@ -201,7 +201,7 @@ int kill_main(int argc UNUSED_PARAM, char **argv)
201 pid_t sid; 201 pid_t sid;
202 procps_status_t* p = NULL; 202 procps_status_t* p = NULL;
203 /* compat: exitcode 2 is "no one was signaled" */ 203 /* compat: exitcode 2 is "no one was signaled" */
204 int ret = 2; 204 errors = 2;
205 205
206 /* Find out our session id */ 206 /* Find out our session id */
207 sid = getsid(pid); 207 sid = getsid(pid);
@@ -229,7 +229,7 @@ int kill_main(int argc UNUSED_PARAM, char **argv)
229 arg = *args++; 229 arg = *args++;
230 if (arg[0] != '-' || arg[1] != 'o') { 230 if (arg[0] != '-' || arg[1] != 'o') {
231 bb_error_msg("bad option '%s'", arg); 231 bb_error_msg("bad option '%s'", arg);
232 ret = 1; 232 errors = 1;
233 goto resume; 233 goto resume;
234 } 234 }
235 arg += 2; 235 arg += 2;
@@ -238,21 +238,21 @@ int kill_main(int argc UNUSED_PARAM, char **argv)
238 omit = bb_strtoi(arg, NULL, 10); 238 omit = bb_strtoi(arg, NULL, 10);
239 if (errno) { 239 if (errno) {
240 bb_error_msg("invalid number '%s'", arg); 240 bb_error_msg("invalid number '%s'", arg);
241 ret = 1; 241 errors = 1;
242 goto resume; 242 goto resume;
243 } 243 }
244 if (p->pid == omit) 244 if (p->pid == omit)
245 goto dont_kill; 245 goto dont_kill;
246 } 246 }
247 kill(p->pid, signo); 247 kill(p->pid, signo);
248 ret = 0; 248 errors = 0;
249 dont_kill: ; 249 dont_kill: ;
250 } 250 }
251 resume: 251 resume:
252 /* And let them continue */ 252 /* And let them continue */
253 if (signo != SIGSTOP && signo != SIGCONT) 253 if (signo != SIGSTOP && signo != SIGCONT)
254 kill(-1, SIGCONT); 254 kill(-1, SIGCONT);
255 return ret; 255 return errors;
256 } 256 }
257 257
258#if ENABLE_KILL || ENABLE_KILLALL 258#if ENABLE_KILL || ENABLE_KILLALL
diff --git a/runit/chpst.c b/runit/chpst.c
index 846c846d3..ee3a33153 100644
--- a/runit/chpst.c
+++ b/runit/chpst.c
@@ -463,6 +463,13 @@ int chpst_main(int argc UNUSED_PARAM, char **argv)
463 xchroot(root); 463 xchroot(root);
464 } 464 }
465 465
466 /* nice should be done before xsetuid */
467 if (opt & OPT_n) {
468 errno = 0;
469 if (nice(xatoi(nicestr)) == -1)
470 bb_perror_msg_and_die("nice");
471 }
472
466 if (opt & OPT_u) { 473 if (opt & OPT_u) {
467 if (setgroups(1, &ugid.gid) == -1) 474 if (setgroups(1, &ugid.gid) == -1)
468 bb_perror_msg_and_die("setgroups"); 475 bb_perror_msg_and_die("setgroups");
@@ -470,12 +477,6 @@ int chpst_main(int argc UNUSED_PARAM, char **argv)
470 xsetuid(ugid.uid); 477 xsetuid(ugid.uid);
471 } 478 }
472 479
473 if (opt & OPT_n) {
474 errno = 0;
475 if (nice(xatoi(nicestr)) == -1)
476 bb_perror_msg_and_die("nice");
477 }
478
479 if (opt & OPT_0) 480 if (opt & OPT_0)
480 close(STDIN_FILENO); 481 close(STDIN_FILENO);
481 if (opt & OPT_1) 482 if (opt & OPT_1)
diff --git a/runit/runsv.c b/runit/runsv.c
index e0e31508a..939653d12 100644
--- a/runit/runsv.c
+++ b/runit/runsv.c
@@ -134,9 +134,13 @@ static void fatal2x_cannot(const char *m1, const char *m2)
134 bb_error_msg_and_die("%s: fatal: can't %s%s", dir, m1, m2); 134 bb_error_msg_and_die("%s: fatal: can't %s%s", dir, m1, m2);
135 /* was exiting 111 */ 135 /* was exiting 111 */
136} 136}
137static void warn2_cannot(const char *m1, const char *m2)
138{
139 bb_perror_msg("%s: warning: can't %s%s", dir, m1, m2);
140}
137static void warn_cannot(const char *m) 141static void warn_cannot(const char *m)
138{ 142{
139 bb_perror_msg("%s: warning: cannot %s", dir, m); 143 warn2_cannot(m, "");
140} 144}
141 145
142static void s_child(int sig_no UNUSED_PARAM) 146static void s_child(int sig_no UNUSED_PARAM)
@@ -165,10 +169,25 @@ static void update_status(struct svdir *s)
165 ssize_t sz; 169 ssize_t sz;
166 int fd; 170 int fd;
167 svstatus_t status; 171 svstatus_t status;
172 const char *fstatus ="log/supervise/status";
173 const char *fstatusnew ="log/supervise/status.new";
174 const char *f_stat ="log/supervise/stat";
175 const char *fstatnew ="log/supervise/stat.new";
176 const char *fpid ="log/supervise/pid";
177 const char *fpidnew ="log/supervise/pid.new";
178
179 if (!s->islog) {
180 fstatus += 4;
181 fstatusnew += 4;
182 f_stat += 4;
183 fstatnew += 4;
184 fpid += 4;
185 fpidnew += 4;
186 }
168 187
169 /* pid */ 188 /* pid */
170 if (pidchanged) { 189 if (pidchanged) {
171 fd = open_trunc_or_warn("supervise/pid.new"); 190 fd = open_trunc_or_warn(fpidnew);
172 if (fd < 0) 191 if (fd < 0)
173 return; 192 return;
174 if (s->pid) { 193 if (s->pid) {
@@ -177,14 +196,13 @@ static void update_status(struct svdir *s)
177 write(fd, spid, size); 196 write(fd, spid, size);
178 } 197 }
179 close(fd); 198 close(fd);
180 if (rename_or_warn("supervise/pid.new", 199 if (rename_or_warn(fpidnew, fpid))
181 s->islog ? "log/supervise/pid" : "log/supervise/pid"+4))
182 return; 200 return;
183 pidchanged = 0; 201 pidchanged = 0;
184 } 202 }
185 203
186 /* stat */ 204 /* stat */
187 fd = open_trunc_or_warn("supervise/stat.new"); 205 fd = open_trunc_or_warn(fstatnew);
188 if (fd < -1) 206 if (fd < -1)
189 return; 207 return;
190 208
@@ -220,8 +238,7 @@ static void update_status(struct svdir *s)
220 close(fd); 238 close(fd);
221 } 239 }
222 240
223 rename_or_warn("supervise/stat.new", 241 rename_or_warn(fstatnew, f_stat);
224 s->islog ? "log/supervise/stat" : "log/supervise/stat"+4);
225 242
226 /* supervise compatibility */ 243 /* supervise compatibility */
227 memset(&status, 0, sizeof(status)); 244 memset(&status, 0, sizeof(status));
@@ -237,18 +254,17 @@ static void update_status(struct svdir *s)
237 if (s->ctrl & C_TERM) 254 if (s->ctrl & C_TERM)
238 status.got_term = 1; 255 status.got_term = 1;
239 status.run_or_finish = s->state; 256 status.run_or_finish = s->state;
240 fd = open_trunc_or_warn("supervise/status.new"); 257 fd = open_trunc_or_warn(fstatusnew);
241 if (fd < 0) 258 if (fd < 0)
242 return; 259 return;
243 sz = write(fd, &status, sizeof(status)); 260 sz = write(fd, &status, sizeof(status));
244 close(fd); 261 close(fd);
245 if (sz != sizeof(status)) { 262 if (sz != sizeof(status)) {
246 warn_cannot("write supervise/status.new"); 263 warn2_cannot("write ", fstatusnew);
247 unlink("supervise/status.new"); 264 unlink(fstatusnew);
248 return; 265 return;
249 } 266 }
250 rename_or_warn("supervise/status.new", 267 rename_or_warn(fstatusnew, fstatus);
251 s->islog ? "log/supervise/status" : "log/supervise/status"+4);
252} 268}
253 269
254static unsigned custom(struct svdir *s, char c) 270static unsigned custom(struct svdir *s, char c)
@@ -266,26 +282,26 @@ static unsigned custom(struct svdir *s, char c)
266 if (st.st_mode & S_IXUSR) { 282 if (st.st_mode & S_IXUSR) {
267 pid = vfork(); 283 pid = vfork();
268 if (pid == -1) { 284 if (pid == -1) {
269 warn_cannot("vfork for control/?"); 285 warn2_cannot("vfork for ", a);
270 return 0; 286 return 0;
271 } 287 }
272 if (pid == 0) { 288 if (pid == 0) {
273 /* child */ 289 /* child */
274 if (haslog && dup2(logpipe.wr, 1) == -1) 290 if (haslog && dup2(logpipe.wr, 1) == -1)
275 warn_cannot("setup stdout for control/?"); 291 warn2_cannot("setup stdout for ", a);
276 execl(a, a, (char *) NULL); 292 execl(a, a, (char *) NULL);
277 fatal_cannot("run control/?"); 293 fatal2_cannot("run ", a);
278 } 294 }
279 /* parent */ 295 /* parent */
280 if (safe_waitpid(pid, &w, 0) == -1) { 296 if (safe_waitpid(pid, &w, 0) == -1) {
281 warn_cannot("wait for child control/?"); 297 warn2_cannot("wait for child ", a);
282 return 0; 298 return 0;
283 } 299 }
284 return WEXITSTATUS(w) == 0; 300 return WEXITSTATUS(w) == 0;
285 } 301 }
286 } else { 302 } else {
287 if (errno != ENOENT) 303 if (errno != ENOENT)
288 warn_cannot("stat control/?"); 304 warn2_cannot("stat ", a);
289 } 305 }
290 return 0; 306 return 0;
291} 307}
@@ -387,13 +403,13 @@ static int ctrl(struct svdir *s, char c)
387 case 'd': /* down */ 403 case 'd': /* down */
388 s->sd_want = W_DOWN; 404 s->sd_want = W_DOWN;
389 update_status(s); 405 update_status(s);
390 if (s->pid && s->state != S_FINISH) 406 if (s->state == S_RUN)
391 stopservice(s); 407 stopservice(s);
392 break; 408 break;
393 case 'u': /* up */ 409 case 'u': /* up */
394 s->sd_want = W_UP; 410 s->sd_want = W_UP;
395 update_status(s); 411 update_status(s);
396 if (s->pid == 0) 412 if (s->state == S_DOWN)
397 startservice(s); 413 startservice(s);
398 break; 414 break;
399 case 'x': /* exit */ 415 case 'x': /* exit */
@@ -403,22 +419,22 @@ static int ctrl(struct svdir *s, char c)
403 update_status(s); 419 update_status(s);
404 /* FALLTHROUGH */ 420 /* FALLTHROUGH */
405 case 't': /* sig term */ 421 case 't': /* sig term */
406 if (s->pid && s->state != S_FINISH) 422 if (s->state == S_RUN)
407 stopservice(s); 423 stopservice(s);
408 break; 424 break;
409 case 'k': /* sig kill */ 425 case 'k': /* sig kill */
410 if (s->pid && !custom(s, c)) 426 if ((s->state == S_RUN) && !custom(s, c))
411 kill(s->pid, SIGKILL); 427 kill(s->pid, SIGKILL);
412 s->state = S_DOWN; 428 s->state = S_DOWN;
413 break; 429 break;
414 case 'p': /* sig pause */ 430 case 'p': /* sig pause */
415 if (s->pid && !custom(s, c)) 431 if ((s->state == S_RUN) && !custom(s, c))
416 kill(s->pid, SIGSTOP); 432 kill(s->pid, SIGSTOP);
417 s->ctrl |= C_PAUSE; 433 s->ctrl |= C_PAUSE;
418 update_status(s); 434 update_status(s);
419 break; 435 break;
420 case 'c': /* sig cont */ 436 case 'c': /* sig cont */
421 if (s->pid && !custom(s, c)) 437 if ((s->state == S_RUN) && !custom(s, c))
422 kill(s->pid, SIGCONT); 438 kill(s->pid, SIGCONT);
423 s->ctrl &= ~C_PAUSE; 439 s->ctrl &= ~C_PAUSE;
424 update_status(s); 440 update_status(s);
@@ -426,7 +442,7 @@ static int ctrl(struct svdir *s, char c)
426 case 'o': /* once */ 442 case 'o': /* once */
427 s->sd_want = W_DOWN; 443 s->sd_want = W_DOWN;
428 update_status(s); 444 update_status(s);
429 if (!s->pid) 445 if (s->state == S_DOWN)
430 startservice(s); 446 startservice(s);
431 break; 447 break;
432 case 'a': /* sig alarm */ 448 case 'a': /* sig alarm */
@@ -450,11 +466,26 @@ static int ctrl(struct svdir *s, char c)
450 } 466 }
451 return 1; 467 return 1;
452 sendsig: 468 sendsig:
453 if (s->pid && !custom(s, c)) 469 if ((s->state == S_RUN) && !custom(s, c))
454 kill(s->pid, sig); 470 kill(s->pid, sig);
455 return 1; 471 return 1;
456} 472}
457 473
474static void open_control(const char *f, struct svdir *s)
475{
476 struct stat st;
477 mkfifo(f, 0600);
478 if (stat(f, &st) == -1)
479 fatal2_cannot("stat ", f);
480 if (!S_ISFIFO(st.st_mode))
481 bb_error_msg_and_die("%s: fatal: %s exists but is not a fifo", dir, f);
482 s->fdcontrol = xopen(f, O_RDONLY|O_NDELAY);
483 close_on_exec_on(s->fdcontrol);
484 s->fdcontrolwrite = xopen(f, O_WRONLY|O_NDELAY);
485 close_on_exec_on(s->fdcontrolwrite);
486 update_status(s);
487}
488
458int runsv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 489int runsv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
459int runsv_main(int argc UNUSED_PARAM, char **argv) 490int runsv_main(int argc UNUSED_PARAM, char **argv)
460{ 491{
@@ -554,19 +585,9 @@ int runsv_main(int argc UNUSED_PARAM, char **argv)
554 close_on_exec_on(svd[1].fdlock); 585 close_on_exec_on(svd[1].fdlock);
555 } 586 }
556 587
557 mkfifo("log/supervise/control"+4, 0600); 588 open_control("log/supervise/control"+4, &svd[0]);
558 svd[0].fdcontrol = xopen("log/supervise/control"+4, O_RDONLY|O_NDELAY);
559 close_on_exec_on(svd[0].fdcontrol);
560 svd[0].fdcontrolwrite = xopen("log/supervise/control"+4, O_WRONLY|O_NDELAY);
561 close_on_exec_on(svd[0].fdcontrolwrite);
562 update_status(&svd[0]);
563 if (haslog) { 589 if (haslog) {
564 mkfifo("log/supervise/control", 0600); 590 open_control("log/supervise/control", &svd[1]);
565 svd[1].fdcontrol = xopen("log/supervise/control", O_RDONLY|O_NDELAY);
566 close_on_exec_on(svd[1].fdcontrol);
567 svd[1].fdcontrolwrite = xopen("log/supervise/control", O_WRONLY|O_NDELAY);
568 close_on_exec_on(svd[1].fdcontrolwrite);
569 update_status(&svd[1]);
570 } 591 }
571 mkfifo("log/supervise/ok"+4, 0600); 592 mkfifo("log/supervise/ok"+4, 0600);
572 fd = xopen("log/supervise/ok"+4, O_RDONLY|O_NDELAY); 593 fd = xopen("log/supervise/ok"+4, O_RDONLY|O_NDELAY);
diff --git a/runit/sv.c b/runit/sv.c
index 9e2132259..faa31d4fa 100644
--- a/runit/sv.c
+++ b/runit/sv.c
@@ -25,7 +25,7 @@ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*/ 26*/
27 27
28/* Taken from http://smarden.sunsite.dk/runit/sv.8.html: 28/* Taken from http://smarden.org/runit/sv.8.html:
29 29
30sv - control and manage services monitored by runsv 30sv - control and manage services monitored by runsv
31 31
@@ -36,17 +36,13 @@ The sv program reports the current status and controls the state of services
36monitored by the runsv(8) supervisor. 36monitored by the runsv(8) supervisor.
37 37
38services consists of one or more arguments, each argument naming a directory 38services consists of one or more arguments, each argument naming a directory
39service used by runsv(8). If service doesn't start with a dot or slash, 39service used by runsv(8). If service doesn't start with a dot or slash and
40it is searched in the default services directory /var/service/, otherwise 40doesn't end with a slash, it is searched in the default services directory
41relative to the current directory. 41/var/service/, otherwise relative to the current directory.
42 42
43command is one of up, down, status, once, pause, cont, hup, alarm, interrupt, 43command is one of up, down, status, once, pause, cont, hup, alarm, interrupt,
441, 2, term, kill, or exit, or start, stop, restart, shutdown, force-stop, 441, 2, term, kill, or exit, or start, stop, reload, restart, shutdown,
45force-reload, force-restart, force-shutdown. 45force-stop, force-reload, force-restart, force-shutdown, try-restart.
46
47The sv program can be sym-linked to /etc/init.d/ to provide an LSB init
48script interface. The service to be controlled then is specified by the
49base name of the "init script".
50 46
51status 47status
52 Report the current status of the service, and the appendant log service 48 Report the current status of the service, and the appendant log service
@@ -66,9 +62,9 @@ exit
66 If the service is running, send it the TERM signal, and the CONT signal. 62 If the service is running, send it the TERM signal, and the CONT signal.
67 Do not restart the service. If the service is down, and no log service 63 Do not restart the service. If the service is down, and no log service
68 exists, runsv(8) exits. If the service is down and a log service exists, 64 exists, runsv(8) exits. If the service is down and a log service exists,
69 send the TERM signal to the log service. If the log service is down, 65 runsv(8) closes the standard input of the log service and waits for it to
70 runsv(8) exits. This command is ignored if it is given to an appendant 66 terminate. If the log service is down, runsv(8) exits. This command is
71 log service. 67 ignored if it is given to an appendant log service.
72 68
73sv actually looks only at the first character of above commands. 69sv actually looks only at the first character of above commands.
74 70
@@ -85,6 +81,8 @@ start
85stop 81stop
86 Same as down, but wait up to 7 seconds for the service to become down. 82 Same as down, but wait up to 7 seconds for the service to become down.
87 Then report the status or timeout. 83 Then report the status or timeout.
84reload
85 Same as hup, and additionally report the status afterwards.
88restart 86restart
89 Send the commands term, cont, and up to the service, and wait up to 87 Send the commands term, cont, and up to the service, and wait up to
90 7 seconds for the service to restart. Then report the status or timeout. 88 7 seconds for the service to restart. Then report the status or timeout.
@@ -112,6 +110,9 @@ force-shutdown
112 Same as exit, but wait up to 7 seconds for the runsv(8) process to 110 Same as exit, but wait up to 7 seconds for the runsv(8) process to
113 terminate. Then report the status, and on timeout send the service 111 terminate. Then report the status, and on timeout send the service
114 the kill command. 112 the kill command.
113try-restart
114 if the service is running, send it the term and cont commands, and wait up to
115 7 seconds for the service to restart. Then report the status or timeout.
115 116
116Additional Commands 117Additional Commands
117 118
@@ -126,8 +127,8 @@ check
126Options 127Options
127 128
128-v 129-v
129 wait up to 7 seconds for the command to take effect. 130 If the command is up, down, term, once, cont, or exit, then wait up to 7
130 Then report the status or timeout. 131 seconds for the command to take effect. Then report the status or timeout.
131-w sec 132-w sec
132 Override the default timeout of 7 seconds with sec seconds. Implies -v. 133 Override the default timeout of 7 seconds with sec seconds. Implies -v.
133 134
@@ -192,6 +193,7 @@ struct globals {
192/* "Bernstein" time format: unix + 0x400000000000000aULL */ 193/* "Bernstein" time format: unix + 0x400000000000000aULL */
193 uint64_t tstart, tnow; 194 uint64_t tstart, tnow;
194 svstatus_t svstatus; 195 svstatus_t svstatus;
196 unsigned islog;
195} FIX_ALIASING; 197} FIX_ALIASING;
196#define G (*(struct globals*)bb_common_bufsiz1) 198#define G (*(struct globals*)bb_common_bufsiz1)
197#define acts (G.acts ) 199#define acts (G.acts )
@@ -200,6 +202,7 @@ struct globals {
200#define tstart (G.tstart ) 202#define tstart (G.tstart )
201#define tnow (G.tnow ) 203#define tnow (G.tnow )
202#define svstatus (G.svstatus ) 204#define svstatus (G.svstatus )
205#define islog (G.islog )
203#define INIT_G() do { setup_common_bufsiz(); } while (0) 206#define INIT_G() do { setup_common_bufsiz(); } while (0)
204 207
205 208
@@ -215,7 +218,7 @@ static void fatal_cannot(const char *m1)
215 218
216static void out(const char *p, const char *m1) 219static void out(const char *p, const char *m1)
217{ 220{
218 printf("%s%s: %s", p, *service, m1); 221 printf("%s%s%s: %s", p, *service, islog ? "/log" : "", m1);
219 if (errno) { 222 if (errno) {
220 printf(": %s", strerror(errno)); 223 printf(": %s", strerror(errno));
221 } 224 }
@@ -300,15 +303,14 @@ static unsigned svstatus_print(const char *m)
300 } 303 }
301 pid = SWAP_LE32(svstatus.pid_le32); 304 pid = SWAP_LE32(svstatus.pid_le32);
302 timestamp = SWAP_BE64(svstatus.time_be64); 305 timestamp = SWAP_BE64(svstatus.time_be64);
303 if (pid) { 306 switch (svstatus.run_or_finish) {
304 switch (svstatus.run_or_finish) { 307 case 0: printf("down: "); break;
305 case 1: printf("run: "); break; 308 case 1: printf("run: "); break;
306 case 2: printf("finish: "); break; 309 case 2: printf("finish: "); break;
307 }
308 printf("%s: (pid %d) ", m, pid);
309 } else {
310 printf("down: %s: ", m);
311 } 310 }
311 printf("%s: ", m);
312 if (svstatus.run_or_finish)
313 printf("(pid %d) ", pid);
312 diff = tnow - timestamp; 314 diff = tnow - timestamp;
313 printf("%us", (diff < 0 ? 0 : diff)); 315 printf("%us", (diff < 0 ? 0 : diff));
314 if (pid) { 316 if (pid) {
@@ -331,16 +333,21 @@ static int status(const char *unused UNUSED_PARAM)
331 return 0; 333 return 0;
332 334
333 r = svstatus_print(*service); 335 r = svstatus_print(*service);
336 islog = 1;
334 if (chdir("log") == -1) { 337 if (chdir("log") == -1) {
335 if (errno != ENOENT) { 338 if (errno != ENOENT) {
336 printf("; log: "WARN"can't change to log service directory: %s", 339 printf("; ");
337 strerror(errno)); 340 warn("can't change directory");
338 } 341 } else
339 } else if (svstatus_get()) { 342 bb_putchar('\n');
343 } else {
340 printf("; "); 344 printf("; ");
341 svstatus_print("log"); 345 if (svstatus_get()) {
346 r = svstatus_print("log");
347 bb_putchar('\n');
348 }
342 } 349 }
343 bb_putchar('\n'); /* will also flush the output */ 350 islog = 0;
344 return r; 351 return r;
345} 352}
346 353
@@ -379,35 +386,53 @@ static int check(const char *a)
379 r = svstatus_get(); 386 r = svstatus_get();
380 if (r == -1) 387 if (r == -1)
381 return -1; 388 return -1;
382 if (r == 0) { 389 while (*a) {
383 if (*a == 'x') 390 if (r == 0) {
384 return 1; 391 if (*a == 'x')
385 return -1; 392 return 1;
386 } 393 return -1;
387 pid_le32 = svstatus.pid_le32; 394 }
388 switch (*a) { 395 pid_le32 = svstatus.pid_le32;
389 case 'x': 396 switch (*a) {
390 return 0; 397 case 'x':
391 case 'u':
392 if (!pid_le32 || svstatus.run_or_finish != 1) return 0;
393 if (!checkscript()) return 0;
394 break;
395 case 'd':
396 if (pid_le32) return 0;
397 break;
398 case 'c':
399 if (pid_le32 && !checkscript()) return 0;
400 break;
401 case 't':
402 if (!pid_le32 && svstatus.want == 'd') break;
403 timestamp = SWAP_BE64(svstatus.time_be64);
404 if ((tstart > timestamp) || !pid_le32 || svstatus.got_term || !checkscript())
405 return 0;
406 break;
407 case 'o':
408 timestamp = SWAP_BE64(svstatus.time_be64);
409 if ((!pid_le32 && tstart > timestamp) || (pid_le32 && svstatus.want != 'd'))
410 return 0; 398 return 0;
399 case 'u':
400 if (!pid_le32 || svstatus.run_or_finish != 1)
401 return 0;
402 if (!checkscript())
403 return 0;
404 break;
405 case 'd':
406 if (pid_le32 || svstatus.run_or_finish != 0)
407 return 0;
408 break;
409 case 'C':
410 if (pid_le32 && !checkscript())
411 return 0;
412 break;
413 case 't':
414 case 'k':
415 if (!pid_le32 && svstatus.want == 'd')
416 break;
417 timestamp = SWAP_BE64(svstatus.time_be64);
418 if ((tstart > timestamp) || !pid_le32 || svstatus.got_term || !checkscript())
419 return 0;
420 break;
421 case 'o':
422 timestamp = SWAP_BE64(svstatus.time_be64);
423 if ((!pid_le32 && tstart > timestamp) || (pid_le32 && svstatus.want != 'd'))
424 return 0;
425 break;
426 case 'p':
427 if (pid_le32 && !svstatus.paused)
428 return 0;
429 break;
430 case 'c':
431 if (pid_le32 && svstatus.paused)
432 return 0;
433 break;
434 }
435 ++a;
411 } 436 }
412 printf(OK); 437 printf(OK);
413 svstatus_print(*service); 438 svstatus_print(*service);
@@ -419,14 +444,10 @@ static int control(const char *a)
419{ 444{
420 int fd, r, l; 445 int fd, r, l;
421 446
422/* Is it an optimization?
423 It causes problems with "sv o SRV; ...; sv d SRV"
424 ('d' is not passed to SRV because its .want == 'd'):
425 if (svstatus_get() <= 0) 447 if (svstatus_get() <= 0)
426 return -1; 448 return -1;
427 if (svstatus.want == *a) 449 if (svstatus.want == *a && (*a != 'd' || svstatus.got_term == 1))
428 return 0; 450 return 0;
429*/
430 fd = open("supervise/control", O_WRONLY|O_NDELAY); 451 fd = open("supervise/control", O_WRONLY|O_NDELAY);
431 if (fd == -1) { 452 if (fd == -1) {
432 if (errno != ENODEV) 453 if (errno != ENODEV)
@@ -516,17 +537,23 @@ static int sv(char **argv)
516 acts = "tc"; 537 acts = "tc";
517 kll = 1; 538 kll = 1;
518 break; 539 break;
540 case 't':
541 if (str_equal(action, "try-restart")) {
542 acts = "tc";
543 break;
544 }
519 case 'c': 545 case 'c':
520 if (str_equal(action, "check")) { 546 if (str_equal(action, "check")) {
521 act = NULL; 547 act = NULL;
522 acts = "c"; 548 acts = "C";
523 break; 549 break;
524 } 550 }
525 case 'u': case 'd': case 'o': case 't': case 'p': case 'h': 551 case 'u': case 'd': case 'o': case 'p': case 'h':
526 case 'a': case 'i': case 'k': case 'q': case '1': case '2': 552 case 'a': case 'i': case 'k': case 'q': case '1': case '2':
527 action[1] = '\0'; 553 action[1] = '\0';
528 acts = action; 554 acts = action;
529 if (!verbose) cbk = NULL; 555 if (!verbose)
556 cbk = NULL;
530 break; 557 break;
531 case 's': 558 case 's':
532 if (str_equal(action, "shutdown")) { 559 if (str_equal(action, "shutdown")) {
@@ -550,6 +577,10 @@ static int sv(char **argv)
550 acts = "tcu"; 577 acts = "tcu";
551 break; 578 break;
552 } 579 }
580 if (str_equal(action, "reload")) {
581 acts = "h";
582 break;
583 }
553 bb_show_usage(); 584 bb_show_usage();
554 case 'f': 585 case 'f':
555 if (str_equal(action, "force-reload")) { 586 if (str_equal(action, "force-reload")) {
@@ -578,7 +609,9 @@ static int sv(char **argv)
578 609
579 service = argv; 610 service = argv;
580 while ((x = *service) != NULL) { 611 while ((x = *service) != NULL) {
581 if (x[0] != '/' && x[0] != '.') { 612 if (x[0] != '/' && x[0] != '.'
613 && x[0] != '\0' && x[strlen(x) - 1] != '/'
614 ) {
582 if (chdir(varservice) == -1) 615 if (chdir(varservice) == -1)
583 goto chdir_failed_0; 616 goto chdir_failed_0;
584 } 617 }
@@ -688,12 +721,7 @@ int svc_main(int argc UNUSED_PARAM, char **argv)
688 /* getopt32() was already called: 721 /* getopt32() was already called:
689 * reset the libc getopt() function, which keeps internal state. 722 * reset the libc getopt() function, which keeps internal state.
690 */ 723 */
691#ifdef __GLIBC__ 724 GETOPT_RESET();
692 optind = 0;
693#else /* BSD style */
694 optind = 1;
695 /* optreset = 1; */
696#endif
697 725
698 do { 726 do {
699 if (opts & 1) { 727 if (opts & 1) {
diff --git a/runit/svlogd.c b/runit/svlogd.c
index 3ed13b67b..795bf48bb 100644
--- a/runit/svlogd.c
+++ b/runit/svlogd.c
@@ -137,9 +137,9 @@ log message, you can use a pattern like this instead
137//kbuild:lib-$(CONFIG_SVLOGD) += svlogd.o 137//kbuild:lib-$(CONFIG_SVLOGD) += svlogd.o
138 138
139//usage:#define svlogd_trivial_usage 139//usage:#define svlogd_trivial_usage
140//usage: "[-ttv] [-r C] [-R CHARS] [-l MATCHLEN] [-b BUFLEN] DIR..." 140//usage: "[-tttv] [-r C] [-R CHARS] [-l MATCHLEN] [-b BUFLEN] DIR..."
141//usage:#define svlogd_full_usage "\n\n" 141//usage:#define svlogd_full_usage "\n\n"
142//usage: "Continuously read log data from stdin and write to rotated log files in DIRs" 142//usage: "Read log data from stdin and write to rotated log files in DIRs"
143//usage: "\n" 143//usage: "\n"
144//usage: "\n""DIR/config file modifies behavior:" 144//usage: "\n""DIR/config file modifies behavior:"
145//usage: "\n""sSIZE - when to rotate logs" 145//usage: "\n""sSIZE - when to rotate logs"
@@ -339,17 +339,18 @@ static unsigned pmatch(const char *p, const char *s, unsigned len)
339/*** ex fmt_ptime.[ch] ***/ 339/*** ex fmt_ptime.[ch] ***/
340 340
341/* NUL terminated */ 341/* NUL terminated */
342static void fmt_time_human_30nul(char *s) 342static void fmt_time_human_30nul(char *s, char dt_delim)
343{ 343{
344 struct tm *ptm; 344 struct tm *ptm;
345 struct timeval tv; 345 struct timeval tv;
346 346
347 gettimeofday(&tv, NULL); 347 gettimeofday(&tv, NULL);
348 ptm = gmtime(&tv.tv_sec); 348 ptm = gmtime(&tv.tv_sec);
349 sprintf(s, "%04u-%02u-%02u_%02u:%02u:%02u.%06u000", 349 sprintf(s, "%04u-%02u-%02u%c%02u:%02u:%02u.%06u000",
350 (unsigned)(1900 + ptm->tm_year), 350 (unsigned)(1900 + ptm->tm_year),
351 (unsigned)(ptm->tm_mon + 1), 351 (unsigned)(ptm->tm_mon + 1),
352 (unsigned)(ptm->tm_mday), 352 (unsigned)(ptm->tm_mday),
353 dt_delim,
353 (unsigned)(ptm->tm_hour), 354 (unsigned)(ptm->tm_hour),
354 (unsigned)(ptm->tm_min), 355 (unsigned)(ptm->tm_min),
355 (unsigned)(ptm->tm_sec), 356 (unsigned)(ptm->tm_sec),
@@ -1160,8 +1161,8 @@ int svlogd_main(int argc, char **argv)
1160 if (timestamp) { 1161 if (timestamp) {
1161 if (timestamp == 1) 1162 if (timestamp == 1)
1162 fmt_time_bernstein_25(stamp); 1163 fmt_time_bernstein_25(stamp);
1163 else /* 2: */ 1164 else /* 2+: */
1164 fmt_time_human_30nul(stamp); 1165 fmt_time_human_30nul(stamp, timestamp == 2 ? '_' : 'T');
1165 printlen += 26; 1166 printlen += 26;
1166 printptr -= 26; 1167 printptr -= 26;
1167 memcpy(printptr, stamp, 25); 1168 memcpy(printptr, stamp, 25);
diff --git a/shell/ash.c b/shell/ash.c
index 0325a325c..bdbcd6987 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -3554,11 +3554,9 @@ unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3554{ 3554{
3555 int i; 3555 int i;
3556 3556
3557 while ((i = nextopt("a")) != '\0') { 3557 while (nextopt("a") != '\0') {
3558 if (i == 'a') { 3558 rmaliases();
3559 rmaliases(); 3559 return 0;
3560 return 0;
3561 }
3562 } 3560 }
3563 for (i = 0; *argptr; argptr++) { 3561 for (i = 0; *argptr; argptr++) {
3564 if (unalias(*argptr)) { 3562 if (unalias(*argptr)) {
@@ -4069,7 +4067,7 @@ setjobctl(int on)
4069 } 4067 }
4070 /* fd is a tty at this point */ 4068 /* fd is a tty at this point */
4071 fd = fcntl(fd, F_DUPFD, 10); 4069 fd = fcntl(fd, F_DUPFD, 10);
4072 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, dont */ 4070 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
4073 close(ofd); 4071 close(ofd);
4074 if (fd < 0) 4072 if (fd < 0)
4075 goto out; /* F_DUPFD failed */ 4073 goto out; /* F_DUPFD failed */
@@ -6692,7 +6690,7 @@ static char *evalvar(char *p, int flags, struct strlist *var_str_list);
6692 * $@ like $* since no splitting will be performed. 6690 * $@ like $* since no splitting will be performed.
6693 * 6691 *
6694 * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence 6692 * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence
6695 * over shell varables. Needed for "A=a B=$A; echo $B" case - we use it 6693 * over shell variables. Needed for "A=a B=$A; echo $B" case - we use it
6696 * for correct expansion of "B=$A" word. 6694 * for correct expansion of "B=$A" word.
6697 */ 6695 */
6698static void 6696static void
@@ -6902,8 +6900,8 @@ scanright(char *startp, char *rmesc, char *rmescend,
6902 if (try2optimize) { 6900 if (try2optimize) {
6903 /* Maybe we can optimize this: 6901 /* Maybe we can optimize this:
6904 * if pattern ends with unescaped *, we can avoid checking 6902 * if pattern ends with unescaped *, we can avoid checking
6905 * shorter strings: if "foo*" doesnt match "raw_value_of_v", 6903 * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6906 * it wont match truncated "raw_value_of_" strings too. 6904 * it won't match truncated "raw_value_of_" strings too.
6907 */ 6905 */
6908 unsigned plen = strlen(pattern); 6906 unsigned plen = strlen(pattern);
6909 /* Does it end with "*"? */ 6907 /* Does it end with "*"? */
@@ -7630,7 +7628,7 @@ expandmeta(struct strlist *str /*, int flag*/)
7630// Which means you need to unescape the string, right? Not so fast: 7628// Which means you need to unescape the string, right? Not so fast:
7631// if there _is_ a file named "file\?" (with backslash), it is returned 7629// if there _is_ a file named "file\?" (with backslash), it is returned
7632// as "file\?" too (whichever pattern you used to find it, say, "file*"). 7630// as "file\?" too (whichever pattern you used to find it, say, "file*").
7633// You DONT KNOW by looking at the result whether you need to unescape it. 7631// You DON'T KNOW by looking at the result whether you need to unescape it.
7634// 7632//
7635// Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?", 7633// Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7636// returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file. 7634// returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
@@ -8124,9 +8122,8 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **
8124 * have to change the find_command routine as well. 8122 * have to change the find_command routine as well.
8125 * argv[-1] must exist and be writable! See tryexec() for why. 8123 * argv[-1] must exist and be writable! See tryexec() for why.
8126 */ 8124 */
8127static void shellexec(char **, const char *, int) NORETURN; 8125static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
8128static void 8126static void shellexec(char *prog, char **argv, const char *path, int idx)
8129shellexec(char **argv, const char *path, int idx)
8130{ 8127{
8131 char *cmdname; 8128 char *cmdname;
8132 int e; 8129 int e;
@@ -8135,12 +8132,12 @@ shellexec(char **argv, const char *path, int idx)
8135 int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */ 8132 int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
8136 8133
8137 envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL); 8134 envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
8138 if ((strchr(argv[0], '/') || (ENABLE_PLATFORM_MINGW32 && strchr(argv[0], '\\'))) 8135 if ((strchr(prog, '/') || (ENABLE_PLATFORM_MINGW32 && strchr(prog, '\\')))
8139#if ENABLE_FEATURE_SH_STANDALONE 8136#if ENABLE_FEATURE_SH_STANDALONE
8140 || (applet_no = find_applet_by_name(argv[0])) >= 0 8137 || (applet_no = find_applet_by_name(prog)) >= 0
8141#endif 8138#endif
8142 ) { 8139 ) {
8143 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) argv[0], argv, envp); 8140 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
8144 if (applet_no >= 0) { 8141 if (applet_no >= 0) {
8145 /* We tried execing ourself, but it didn't work. 8142 /* We tried execing ourself, but it didn't work.
8146 * Maybe /proc/self/exe doesn't exist? 8143 * Maybe /proc/self/exe doesn't exist?
@@ -8157,7 +8154,7 @@ shellexec(char **argv, const char *path, int idx)
8157 } else { 8154 } else {
8158 try_PATH: 8155 try_PATH:
8159 e = ENOENT; 8156 e = ENOENT;
8160 while ((cmdname = path_advance(&path, argv[0])) != NULL) { 8157 while ((cmdname = path_advance(&path, prog)) != NULL) {
8161 if (--idx < 0 && pathopt == NULL) { 8158 if (--idx < 0 && pathopt == NULL) {
8162 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp); 8159 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
8163 if (errno != ENOENT && errno != ENOTDIR) 8160 if (errno != ENOENT && errno != ENOTDIR)
@@ -8181,8 +8178,8 @@ shellexec(char **argv, const char *path, int idx)
8181 } 8178 }
8182 exitstatus = exerrno; 8179 exitstatus = exerrno;
8183 TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n", 8180 TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
8184 argv[0], e, suppress_int)); 8181 prog, e, suppress_int));
8185 ash_msg_and_raise(EXEXIT, "%s: %s", argv[0], errmsg(e, "not found")); 8182 ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
8186 /* NOTREACHED */ 8183 /* NOTREACHED */
8187} 8184}
8188 8185
@@ -8551,7 +8548,6 @@ static int
8551describe_command(char *command, const char *path, int describe_command_verbose) 8548describe_command(char *command, const char *path, int describe_command_verbose)
8552{ 8549{
8553 struct cmdentry entry; 8550 struct cmdentry entry;
8554 struct tblentry *cmdp;
8555#if ENABLE_ASH_ALIAS 8551#if ENABLE_ASH_ALIAS
8556 const struct alias *ap; 8552 const struct alias *ap;
8557#endif 8553#endif
@@ -8581,15 +8577,8 @@ describe_command(char *command, const char *path, int describe_command_verbose)
8581 goto out; 8577 goto out;
8582 } 8578 }
8583#endif 8579#endif
8584 /* Then check if it is a tracked alias */ 8580 /* Brute force */
8585 cmdp = cmdlookup(command, 0); 8581 find_command(command, &entry, DO_ABS, path);
8586 if (cmdp != NULL) {
8587 entry.cmdtype = cmdp->cmdtype;
8588 entry.u = cmdp->param;
8589 } else {
8590 /* Finally use brute force */
8591 find_command(command, &entry, DO_ABS, path);
8592 }
8593 8582
8594 switch (entry.cmdtype) { 8583 switch (entry.cmdtype) {
8595 case CMDNORMAL: { 8584 case CMDNORMAL: {
@@ -8604,9 +8593,7 @@ describe_command(char *command, const char *path, int describe_command_verbose)
8604 } while (--j >= 0); 8593 } while (--j >= 0);
8605 } 8594 }
8606 if (describe_command_verbose) { 8595 if (describe_command_verbose) {
8607 out1fmt(" is%s %s", 8596 out1fmt(" is %s", p);
8608 (cmdp ? " a tracked alias for" : nullstr), p
8609 );
8610 } else { 8597 } else {
8611 out1str(p); 8598 out1str(p);
8612 } 8599 }
@@ -9814,7 +9801,14 @@ truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9814static int FAST_FUNC 9801static int FAST_FUNC
9815execcmd(int argc UNUSED_PARAM, char **argv) 9802execcmd(int argc UNUSED_PARAM, char **argv)
9816{ 9803{
9817 if (argv[1]) { 9804 optionarg = NULL;
9805 while (nextopt("a:") != '\0')
9806 /* nextopt() sets optionarg to "-a ARGV0" */;
9807
9808 argv = argptr;
9809 if (argv[0]) {
9810 char *prog;
9811
9818 iflag = 0; /* exit on error */ 9812 iflag = 0; /* exit on error */
9819 mflag = 0; 9813 mflag = 0;
9820 optschanged(); 9814 optschanged();
@@ -9830,7 +9824,10 @@ execcmd(int argc UNUSED_PARAM, char **argv)
9830 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */ 9824 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9831 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */ 9825 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9832 9826
9833 shellexec(argv + 1, pathval(), 0); 9827 prog = argv[0];
9828 if (optionarg)
9829 argv[0] = optionarg;
9830 shellexec(prog, argv, pathval(), 0);
9834 /* NOTREACHED */ 9831 /* NOTREACHED */
9835 } 9832 }
9836 return 0; 9833 return 0;
@@ -10255,7 +10252,7 @@ evalcommand(union node *cmd, int flags)
10255 } 10252 }
10256#endif 10253#endif
10257 listsetvar(varlist.list, VEXPORT|VSTACK); 10254 listsetvar(varlist.list, VEXPORT|VSTACK);
10258 shellexec(argv, path, cmdentry.u.index); 10255 shellexec(argv[0], argv, path, cmdentry.u.index);
10259 /* NOTREACHED */ 10256 /* NOTREACHED */
10260 } /* default */ 10257 } /* default */
10261 case CMDBUILTIN: 10258 case CMDBUILTIN:
@@ -13605,7 +13602,7 @@ exportcmd(int argc UNUSED_PARAM, char **argv)
13605 } 13602 }
13606 flag_off = ~flag_off; 13603 flag_off = ~flag_off;
13607 13604
13608 /*if (opt_p_not_specified) - bash doesnt check this. Try "export -p NAME" */ 13605 /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13609 { 13606 {
13610 aptr = argptr; 13607 aptr = argptr;
13611 name = *aptr; 13608 name = *aptr;
@@ -13785,6 +13782,7 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13785 /* "read -s" needs to save/restore termios, can't allow ^C 13782 /* "read -s" needs to save/restore termios, can't allow ^C
13786 * to jump out of it. 13783 * to jump out of it.
13787 */ 13784 */
13785 again:
13788 INT_OFF; 13786 INT_OFF;
13789 r = shell_builtin_read(setvar0, 13787 r = shell_builtin_read(setvar0,
13790 argptr, 13788 argptr,
@@ -13797,6 +13795,12 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13797 ); 13795 );
13798 INT_ON; 13796 INT_ON;
13799 13797
13798 if ((uintptr_t)r == 1 && errno == EINTR) {
13799 /* to get SIGCHLD: sleep 1 & read x; echo $x */
13800 if (pending_sig == 0)
13801 goto again;
13802 }
13803
13800 if ((uintptr_t)r > 1) 13804 if ((uintptr_t)r > 1)
13801 ash_msg_and_raise_error(r); 13805 ash_msg_and_raise_error(r);
13802 13806
@@ -14420,7 +14424,7 @@ forkshell_shellexec(struct forkshell *fs)
14420 char *path = fs->string; 14424 char *path = fs->string;
14421 14425
14422 listsetvar(varlist, VEXPORT|VSTACK); 14426 listsetvar(varlist, VEXPORT|VSTACK);
14423 shellexec(argv, path, idx); 14427 shellexec(argv[0], argv, path, idx);
14424} 14428}
14425 14429
14426static void 14430static void
diff --git a/shell/ash_test/ash-misc/unicode1.tests b/shell/ash_test/ash-misc/unicode1.tests
index 8788ba910..b8479cb41 100755
--- a/shell/ash_test/ash-misc/unicode1.tests
+++ b/shell/ash_test/ash-misc/unicode1.tests
@@ -5,7 +5,7 @@ a=`printf "\xcc\x80"`
5# Should print 1 5# Should print 1
6echo ${#a} 6echo ${#a}
7 7
8# A Japanese katakana charachter U+30a3 8# A Japanese katakana character U+30a3
9a=`printf "\xe3\x82\xa3"` 9a=`printf "\xe3\x82\xa3"`
10# Should print 1 10# Should print 1
11echo ${#a} 11echo ${#a}
diff --git a/shell/ash_test/ash-read/read_SIGCHLD.right b/shell/ash_test/ash-read/read_SIGCHLD.right
new file mode 100644
index 000000000..b3dc7ab0c
--- /dev/null
+++ b/shell/ash_test/ash-read/read_SIGCHLD.right
@@ -0,0 +1,2 @@
1x='Ok'
2exitcode:0
diff --git a/shell/ash_test/ash-read/read_SIGCHLD.tests b/shell/ash_test/ash-read/read_SIGCHLD.tests
new file mode 100755
index 000000000..c5f673aff
--- /dev/null
+++ b/shell/ash_test/ash-read/read_SIGCHLD.tests
@@ -0,0 +1,4 @@
1x=BAD
2{ sleep 0.4; echo Ok; } | { sleep 0.2 & read x; echo "x='$x'"; }
3echo "exitcode:$?"
4
diff --git a/shell/hush.c b/shell/hush.c
index 4123cc19e..125463a56 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -1908,7 +1908,7 @@ static int check_and_run_traps(void)
1908 G.count_SIGCHLD++; 1908 G.count_SIGCHLD++;
1909//bb_error_msg("[%d] check_and_run_traps: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD); 1909//bb_error_msg("[%d] check_and_run_traps: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
1910 /* Note: 1910 /* Note:
1911 * We dont do 'last_sig = sig' here -> NOT returning this sig. 1911 * We don't do 'last_sig = sig' here -> NOT returning this sig.
1912 * This simplifies wait builtin a bit. 1912 * This simplifies wait builtin a bit.
1913 */ 1913 */
1914 break; 1914 break;
@@ -1917,7 +1917,7 @@ static int check_and_run_traps(void)
1917 debug_printf_exec("%s: sig:%d default handling is to ignore\n", __func__, sig); 1917 debug_printf_exec("%s: sig:%d default handling is to ignore\n", __func__, sig);
1918 /* SIGTERM, SIGQUIT, SIGTTIN, SIGTTOU, SIGTSTP */ 1918 /* SIGTERM, SIGQUIT, SIGTTIN, SIGTTOU, SIGTSTP */
1919 /* Note: 1919 /* Note:
1920 * We dont do 'last_sig = sig' here -> NOT returning this sig. 1920 * We don't do 'last_sig = sig' here -> NOT returning this sig.
1921 * Example: wait is not interrupted by TERM 1921 * Example: wait is not interrupted by TERM
1922 * in interactive shell, because TERM is ignored. 1922 * in interactive shell, because TERM is ignored.
1923 */ 1923 */
@@ -2280,7 +2280,7 @@ static void reinit_unicode_for_hush(void)
2280 * AT\ 2280 * AT\
2281 * H\ 2281 * H\
2282 * \ 2282 * \
2283 * It excercises a lot of corner cases. 2283 * It exercises a lot of corner cases.
2284 */ 2284 */
2285static void cmdedit_update_prompt(void) 2285static void cmdedit_update_prompt(void)
2286{ 2286{
@@ -5235,7 +5235,7 @@ static void o_addblock_duplicate_backslash(o_string *o, const char *str, int len
5235 /* And now we want to add { or } and continue: 5235 /* And now we want to add { or } and continue:
5236 * o_addchr(o, c); 5236 * o_addchr(o, c);
5237 * continue; 5237 * continue;
5238 * luckily, just falling throught achieves this. 5238 * luckily, just falling through achieves this.
5239 */ 5239 */
5240 } 5240 }
5241#endif 5241#endif
@@ -5830,7 +5830,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
5830 arg++; 5830 arg++;
5831 /* Can't just stuff it into output o_string, 5831 /* Can't just stuff it into output o_string,
5832 * expanded result may need to be globbed 5832 * expanded result may need to be globbed
5833 * and $IFS-splitted */ 5833 * and $IFS-split */
5834 debug_printf_subst("SUBST '%s' first_ch %x\n", arg, first_ch); 5834 debug_printf_subst("SUBST '%s' first_ch %x\n", arg, first_ch);
5835 G.last_exitcode = process_command_subs(&subst_result, arg); 5835 G.last_exitcode = process_command_subs(&subst_result, arg);
5836 debug_printf_subst("SUBST RES:%d '%s'\n", G.last_exitcode, subst_result.data); 5836 debug_printf_subst("SUBST RES:%d '%s'\n", G.last_exitcode, subst_result.data);
@@ -7320,7 +7320,7 @@ static int process_wait_result(struct pipe *fg_pipe, pid_t childpid, int status)
7320 /* There are still running processes in the fg_pipe */ 7320 /* There are still running processes in the fg_pipe */
7321 return -1; 7321 return -1;
7322 } 7322 }
7323 /* It wasnt in fg_pipe, look for process in bg pipes */ 7323 /* It wasn't in fg_pipe, look for process in bg pipes */
7324 } 7324 }
7325 7325
7326#if ENABLE_HUSH_JOB 7326#if ENABLE_HUSH_JOB
@@ -9038,6 +9038,9 @@ static int FAST_FUNC builtin_type(char **argv)
9038 * - terminates shell (regardless of interactivity); 9038 * - terminates shell (regardless of interactivity);
9039 * if it has non-empty trap: 9039 * if it has non-empty trap:
9040 * - executes trap and returns to read; 9040 * - executes trap and returns to read;
9041 * SIGCHLD from children:
9042 * - does not interrupt read regardless of interactivity:
9043 * try: sleep 1 & read x; echo $x
9041 */ 9044 */
9042static int FAST_FUNC builtin_read(char **argv) 9045static int FAST_FUNC builtin_read(char **argv)
9043{ 9046{
@@ -9071,7 +9074,7 @@ static int FAST_FUNC builtin_read(char **argv)
9071 9074
9072 if ((uintptr_t)r == 1 && errno == EINTR) { 9075 if ((uintptr_t)r == 1 && errno == EINTR) {
9073 unsigned sig = check_and_run_traps(); 9076 unsigned sig = check_and_run_traps();
9074 if (sig && sig != SIGINT) 9077 if (sig != SIGINT)
9075 goto again; 9078 goto again;
9076 } 9079 }
9077 9080
diff --git a/shell/hush_test/hush-misc/unicode1.tests b/shell/hush_test/hush-misc/unicode1.tests
index 8788ba910..b8479cb41 100755
--- a/shell/hush_test/hush-misc/unicode1.tests
+++ b/shell/hush_test/hush-misc/unicode1.tests
@@ -5,7 +5,7 @@ a=`printf "\xcc\x80"`
5# Should print 1 5# Should print 1
6echo ${#a} 6echo ${#a}
7 7
8# A Japanese katakana charachter U+30a3 8# A Japanese katakana character U+30a3
9a=`printf "\xe3\x82\xa3"` 9a=`printf "\xe3\x82\xa3"`
10# Should print 1 10# Should print 1
11echo ${#a} 11echo ${#a}
diff --git a/shell/hush_test/hush-read/read_SIGCHLD.right b/shell/hush_test/hush-read/read_SIGCHLD.right
new file mode 100644
index 000000000..b3dc7ab0c
--- /dev/null
+++ b/shell/hush_test/hush-read/read_SIGCHLD.right
@@ -0,0 +1,2 @@
1x='Ok'
2exitcode:0
diff --git a/shell/hush_test/hush-read/read_SIGCHLD.tests b/shell/hush_test/hush-read/read_SIGCHLD.tests
new file mode 100755
index 000000000..c5f673aff
--- /dev/null
+++ b/shell/hush_test/hush-read/read_SIGCHLD.tests
@@ -0,0 +1,4 @@
1x=BAD
2{ sleep 0.4; echo Ok; } | { sleep 0.2 & read x; echo "x='$x'"; }
3echo "exitcode:$?"
4
diff --git a/shell/shell_common.c b/shell/shell_common.c
index 653154e34..55617b167 100644
--- a/shell/shell_common.c
+++ b/shell/shell_common.c
@@ -210,15 +210,17 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val),
210 c = buffer[bufpos]; 210 c = buffer[bufpos];
211 if (c == '\0' || (ENABLE_PLATFORM_MINGW32 && c == '\r')) 211 if (c == '\0' || (ENABLE_PLATFORM_MINGW32 && c == '\r'))
212 continue; 212 continue;
213 if (backslash) { 213 if (!(read_flags & BUILTIN_READ_RAW)) {
214 backslash = 0; 214 if (backslash) {
215 if (c != '\n') 215 backslash = 0;
216 goto put; 216 if (c != '\n')
217 continue; 217 goto put;
218 } 218 continue;
219 if (!(read_flags & BUILTIN_READ_RAW) && c == '\\') { 219 }
220 backslash = 1; 220 if (c == '\\') {
221 continue; 221 backslash = 1;
222 continue;
223 }
222 } 224 }
223 if (c == '\n') 225 if (c == '\n')
224 break; 226 break;
@@ -408,13 +410,7 @@ shell_builtin_ulimit(char **argv)
408 /* In case getopt was already called: 410 /* In case getopt was already called:
409 * reset the libc getopt() function, which keeps internal state. 411 * reset the libc getopt() function, which keeps internal state.
410 */ 412 */
411#ifdef __GLIBC__ 413 GETOPT_RESET();
412 optind = 0;
413#else /* BSD style */
414 optind = 1;
415 /* optreset = 1; */
416#endif
417 /* optarg = NULL; opterr = 0; optopt = 0; - do we need this?? */
418 414
419 argc = 1; 415 argc = 1;
420 while (argv[argc]) 416 while (argv[argc])
diff --git a/sysklogd/logread.c b/sysklogd/logread.c
index 1f0c6252d..71459941e 100644
--- a/sysklogd/logread.c
+++ b/sysklogd/logread.c
@@ -24,7 +24,7 @@
24//config: default y 24//config: default y
25//config: depends on LOGREAD 25//config: depends on LOGREAD
26//config: help 26//config: help
27//config: 'logread' ouput to slow serial terminals can have 27//config: 'logread' output to slow serial terminals can have
28//config: side effects on syslog because of the semaphore. 28//config: side effects on syslog because of the semaphore.
29//config: This option make logread to double buffer copy 29//config: This option make logread to double buffer copy
30//config: from circular buffer, minimizing semaphore 30//config: from circular buffer, minimizing semaphore
@@ -159,7 +159,7 @@ int logread_main(int argc UNUSED_PARAM, char **argv)
159 cur, shbuf_tail, shbuf_size); 159 cur, shbuf_tail, shbuf_size);
160 160
161 if (!(follow & 1)) { /* not -f */ 161 if (!(follow & 1)) { /* not -f */
162 /* if -F, "convert" it to -f, so that we dont 162 /* if -F, "convert" it to -f, so that we don't
163 * dump the entire buffer on each iteration 163 * dump the entire buffer on each iteration
164 */ 164 */
165 follow >>= 1; 165 follow >>= 1;
diff --git a/testsuite/factor.tests b/testsuite/factor.tests
new file mode 100755
index 000000000..2cf4a54ce
--- /dev/null
+++ b/testsuite/factor.tests
@@ -0,0 +1,48 @@
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 "test name" "command" "expected result" "file input" "stdin"
9# file input will be file called "input"
10# test can create a file "actual" instead of writing to stdout
11
12testing "factor ' 0'" \
13 "factor ' 0'" \
14 "0:\n" \
15 "" ""
16testing "factor +1" \
17 "factor +1" \
18 "1:\n" \
19 "" ""
20testing "factor ' +2'" \
21 "factor ' +2'" \
22 "2: 2\n" \
23 "" ""
24
25testing "factor 1024" \
26 "factor 1024" \
27 "1024: 2 2 2 2 2 2 2 2 2 2\n" \
28 "" ""
29
30testing "factor 2^61-1" \
31 "factor 2305843009213693951" \
32 "2305843009213693951: 2305843009213693951\n" \
33 "" ""
34testing "factor 2^62-1" \
35 "factor 4611686018427387903" \
36 "4611686018427387903: 3 715827883 2147483647\n" \
37 "" ""
38testing "factor 2^64-1" \
39 "factor 18446744073709551615" \
40 "18446744073709551615: 3 5 17 257 641 65537 6700417\n" \
41 "" ""
42# This is a 60-bit number (0x888 86ff db34 4692): first few primes multiplied together:
43testing "factor \$((2*3*5*7*11*13*17*19*23*29*31*37*41*43*47))" \
44 "factor \$((2*3*5*7*11*13*17*19*23*29*31*37*41*43*47))" \
45 "614889782588491410: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47\n" \
46 "" ""
47
48exit $FAILCOUNT
diff --git a/testsuite/paste/paste b/testsuite/paste/paste
new file mode 100644
index 000000000..349b49d49
--- /dev/null
+++ b/testsuite/paste/paste
@@ -0,0 +1,20 @@
1cat > foo <<EOF
2foo1
3foo2
4foo3
5EOF
6
7cat > bar <<EOF
8bar1
9bar2
10bar3
11EOF
12
13cat > baz <<EOF
14foo1 bar1
15foo2 bar2
16foo3 bar3
17EOF
18
19busybox paste foo bar > qux
20diff -u baz qux
diff --git a/testsuite/paste/paste-back-cuted-lines b/testsuite/paste/paste-back-cuted-lines
new file mode 100644
index 000000000..a8171bf1e
--- /dev/null
+++ b/testsuite/paste/paste-back-cuted-lines
@@ -0,0 +1,9 @@
1cat > foo <<EOF
2this is the first line
3this is the second line
4this is the third line
5EOF
6cut -b 1-13 -n foo > foo1
7cut -b 14- -n foo > foo2
8busybox paste -d '\0' foo1 foo2 > bar
9cmp foo bar
diff --git a/testsuite/paste/paste-multi-stdin b/testsuite/paste/paste-multi-stdin
new file mode 100644
index 000000000..fee543058
--- /dev/null
+++ b/testsuite/paste/paste-multi-stdin
@@ -0,0 +1,16 @@
1cat > foo <<EOF
2line1
3line2
4line3
5line4
6line5
7line6
8EOF
9
10cat > bar <<EOF
11line1 line2 line3
12line4 line5 line6
13EOF
14
15busybox paste - - - < foo > baz
16cmp bar baz
diff --git a/testsuite/paste/paste-pairs b/testsuite/paste/paste-pairs
new file mode 100644
index 000000000..90725fa87
--- /dev/null
+++ b/testsuite/paste/paste-pairs
@@ -0,0 +1,16 @@
1cat > foo <<EOF
2foo1
3bar1
4foo2
5bar2
6foo3
7EOF
8
9cat > bar <<EOF
10foo1 bar1
11foo2 bar2
12foo3
13EOF
14
15busybox paste -s -d "\t\n" foo > baz
16cmp bar baz
diff --git a/testsuite/paste/paste-separate b/testsuite/paste/paste-separate
new file mode 100644
index 000000000..40793fb31
--- /dev/null
+++ b/testsuite/paste/paste-separate
@@ -0,0 +1,19 @@
1cat > foo <<EOF
2foo1
3foo2
4foo3
5EOF
6
7cat > bar <<EOF
8bar1
9bar2
10bar3
11EOF
12
13cat > baz <<EOF
14foo1 foo2 foo3
15bar1 bar2 bar3
16EOF
17
18busybox paste -s foo bar > qux
19cmp baz qux
diff --git a/testsuite/readlink.tests b/testsuite/readlink.tests
index e9d8da0fc..27b52f6c4 100755
--- a/testsuite/readlink.tests
+++ b/testsuite/readlink.tests
@@ -29,7 +29,7 @@ pwd=`$pwd`
29testing "readlink -f on a file" "readlink -f ./$TESTFILE" "$pwd/$TESTFILE\n" "" "" 29testing "readlink -f on a file" "readlink -f ./$TESTFILE" "$pwd/$TESTFILE\n" "" ""
30testing "readlink -f on a link" "readlink -f ./$TESTLINK" "$pwd/$TESTFILE\n" "" "" 30testing "readlink -f on a link" "readlink -f ./$TESTLINK" "$pwd/$TESTFILE\n" "" ""
31testing "readlink -f on an invalid link" "readlink -f ./$FAILLINK" "" "" "" 31testing "readlink -f on an invalid link" "readlink -f ./$FAILLINK" "" "" ""
32testing "readlink -f on a wierd dir" "readlink -f $TESTDIR/../$TESTFILE" "$pwd/$TESTFILE\n" "" "" 32testing "readlink -f on a weird dir" "readlink -f $TESTDIR/../$TESTFILE" "$pwd/$TESTFILE\n" "" ""
33 33
34 34
35# clean up 35# clean up
diff --git a/coreutils/cal.c b/util-linux/cal.c
index af02608f0..8196619b0 100644
--- a/coreutils/cal.c
+++ b/util-linux/cal.c
@@ -35,7 +35,7 @@
35#include "libbb.h" 35#include "libbb.h"
36#include "unicode.h" 36#include "unicode.h"
37 37
38/* We often use "unsigned" intead of "int", it's easier to div on most CPUs */ 38/* We often use "unsigned" instead of "int", it's easier to div on most CPUs */
39 39
40#define THURSDAY 4 /* for reformation */ 40#define THURSDAY 4 /* for reformation */
41#define SATURDAY 6 /* 1 Jan 1 was a Saturday */ 41#define SATURDAY 6 /* 1 Jan 1 was a Saturday */
diff --git a/miscutils/chrt.c b/util-linux/chrt.c
index 1604a6890..1604a6890 100644
--- a/miscutils/chrt.c
+++ b/util-linux/chrt.c
diff --git a/miscutils/eject.c b/util-linux/eject.c
index 667932f6c..667932f6c 100644
--- a/miscutils/eject.c
+++ b/util-linux/eject.c
diff --git a/util-linux/fallocate.c b/util-linux/fallocate.c
new file mode 100644
index 000000000..1cd851bde
--- /dev/null
+++ b/util-linux/fallocate.c
@@ -0,0 +1,104 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Copyright (C) 2017 Denys Vlasenko <vda.linux@googlemail.com>
4 *
5 * Licensed under GPLv2, see file LICENSE in this source tree.
6 */
7
8//config:config FALLOCATE
9//config: bool "fallocate"
10//config: default y
11//config: help
12//config: Preallocate space for files.
13
14//applet:IF_FALLOCATE(APPLET(fallocate, BB_DIR_USR_BIN, BB_SUID_DROP))
15
16//kbuild:lib-$(CONFIG_FALLOCATE) += fallocate.o
17
18//usage:#define fallocate_trivial_usage
19//usage: "[-o OFS] -l LEN FILE"
20// fallocate [-c|-p|-z] [-n] [-o OFS] -l LEN FILE
21// fallocate -d [-o OFS] [-l LEN] FILE
22//usage:#define fallocate_full_usage "\n\n"
23//usage: "Preallocate space for FILE\n"
24// "\n -c Remove range"
25// "\n -p Make hole"
26// "\n -z Zero and allocate range"
27// "\n -d Convert zeros to holes"
28// "\n -n Keep size"
29//usage: "\n -o OFS Offset of range"
30//usage: "\n -l LEN Length of range"
31
32//Upstream options:
33//The options --collapse-range, --dig-holes, --punch-hole and --zero-range
34//are mutually exclusive.
35//-c, --collapse-range
36// Removes a byte range from a file, without leaving a hole. The byte range
37// to be collapsed starts at offset and continues for length bytes.
38// At the completion of the operation, the contents of the file starting
39// at the location offset+length will be appended at the location offset,
40// and the file will be length bytes smaller. The option --keep-size may
41// not be specified for the collapse-range operation.
42//-d, --dig-holes
43// Detect and dig holes. This makes the file sparse in-place, without using
44// extra disk space. The minimum size of the hole depends on filesystem I/O
45// block size (usually 4096 bytes). Also,
46//-l, --length length
47// Specifies the length of the range, in bytes.
48//-n, --keep-size
49// Do not modify the apparent length of the file. This may effectively
50// allocate blocks past EOF, which can be removed with a truncate.
51//-o, --offset offset
52// Specifies the beginning offset of the range, in bytes.
53//-p, --punch-hole
54// Deallocates space (i.e., creates a hole) in the byte range starting
55// at offset and continuing for length bytes. Within the specified range,
56// partial filesystem blocks are zeroed, and whole
57// filesystem blocks are removed from the file. After a successful call,
58// subsequent reads from this range will return zeroes. This option may not
59// be specified at the same time as the
60// --zero-range option. Also, when using this option, --keep-size is implied.
61//-z, --zero-range
62// Zeroes space in the byte range starting at offset and continuing for
63// length bytes. Within the specified range, blocks are preallocated for
64// the regions that span the holes in the file. After
65// a successful call, subsequent reads from this range will return zeroes.
66// Zeroing is done within the filesystem preferably by converting the range
67// into unwritten extents. This approach means that the specified range
68// will not be physically zeroed out on the device (except for partial
69// blocks at the either end of the range), and I/O is (otherwise) required
70// only to update metadata.
71// Option --keep-size can be specified to prevent file length modification.
72
73#include "libbb.h"
74
75int fallocate_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
76int fallocate_main(int argc UNUSED_PARAM, char **argv)
77{
78 const char *str_l;
79 const char *str_o = "0";
80 off_t ofs, len;
81 unsigned opts;
82 int fd;
83
84 /* exactly one non-option arg */
85 opt_complementary = "=1";
86 opts = getopt32(argv, "l:o:", &str_l, &str_o);
87 if (!(opts & 1))
88 bb_show_usage();
89
90 ofs = xatoull_sfx(str_o, kmg_i_suffixes);
91 len = xatoull_sfx(str_l, kmg_i_suffixes);
92
93 argv += optind;
94 fd = xopen3(*argv, O_RDWR | O_CREAT, 0666);
95
96 /* posix_fallocate has unusual method of returning error */
97 /* maybe use Linux-specific fallocate(int fd, int mode, off_t offset, off_t len) instead? */
98 if ((errno = posix_fallocate(fd, ofs, len)) != 0)
99 bb_perror_msg_and_die("fallocate '%s'", *argv);
100
101 /* util-linux also performs fsync(fd); */
102
103 return EXIT_SUCCESS;
104}
diff --git a/util-linux/fsfreeze.c b/util-linux/fsfreeze.c
new file mode 100644
index 000000000..70dec24ec
--- /dev/null
+++ b/util-linux/fsfreeze.c
@@ -0,0 +1,54 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Copyright (C) 2017 Denys Vlasenko <vda.linux@googlemail.com>
4 *
5 * Licensed under GPLv2, see file LICENSE in this source tree.
6 */
7
8//config:config FSFREEZE
9//config: bool "fsfreeze"
10//config: default y
11//config: select PLATFORM_LINUX
12//config: select LONG_OPTS
13//config: help
14//config: Halt new accesses and flush writes on a mounted filesystem.
15
16//applet:IF_FSFREEZE(APPLET(fsfreeze, BB_DIR_USR_SBIN, BB_SUID_DROP))
17
18//kbuild:lib-$(CONFIG_FSFREEZE) += fsfreeze.o
19
20//usage:#define fsfreeze_trivial_usage
21//usage: "--[un]freeze MOUNTPOINT"
22//usage:#define fsfreeze_full_usage "\n\n"
23//usage: "Flush and halt writes to MOUNTPOINT"
24
25#include "libbb.h"
26#include <linux/fs.h>
27
28#ifndef FIFREEZE
29# define FIFREEZE _IOWR('X', 119, int)
30# define FITHAW _IOWR('X', 120, int)
31#endif
32
33int fsfreeze_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
34int fsfreeze_main(int argc UNUSED_PARAM, char **argv)
35{
36 unsigned opts;
37 int fd;
38
39 applet_long_options =
40 "freeze\0" No_argument "\xff"
41 "unfreeze\0" No_argument "\xfe"
42 ;
43 /* exactly one non-option arg: the mountpoint */
44 /* one of opts is required */
45 /* opts are mutually exclusive */
46 opt_complementary = "=1:""\xff:\xfe:""\xff--\xfe:\xfe--\xff";
47 opts = getopt32(argv, "");
48
49 fd = xopen(argv[optind], O_RDONLY);
50 /* Works with NULL arg on linux-4.8.0 */
51 xioctl(fd, (opts & 1) ? FIFREEZE : FITHAW, NULL);
52
53 return EXIT_SUCCESS;
54}
diff --git a/util-linux/getopt.c b/util-linux/getopt.c
index 63294c520..79d54854b 100644
--- a/util-linux/getopt.c
+++ b/util-linux/getopt.c
@@ -246,12 +246,7 @@ static int generate_output(char **argv, int argc, const char *optstr, const stru
246 246
247 /* We used it already in main() in getopt32(), 247 /* We used it already in main() in getopt32(),
248 * we *must* reset getopt(3): */ 248 * we *must* reset getopt(3): */
249#ifdef __GLIBC__ 249 GETOPT_RESET();
250 optind = 0;
251#else /* BSD style */
252 optind = 1;
253 /* optreset = 1; */
254#endif
255 250
256 while (1) { 251 while (1) {
257#if ENABLE_FEATURE_GETOPT_LONG 252#if ENABLE_FEATURE_GETOPT_LONG
diff --git a/util-linux/hwclock.c b/util-linux/hwclock.c
index d65011a71..8cb908cb3 100644
--- a/util-linux/hwclock.c
+++ b/util-linux/hwclock.c
@@ -167,7 +167,7 @@ static void from_sys_clock(const char **pp_rtcname, int utc)
167 * On x86, even though code does set hw clock within <1ms of exact 167 * On x86, even though code does set hw clock within <1ms of exact
168 * whole seconds, apparently hw clock (at least on some machines) 168 * whole seconds, apparently hw clock (at least on some machines)
169 * doesn't reset internal fractional seconds to 0, 169 * doesn't reset internal fractional seconds to 0,
170 * making all this a pointless excercise. 170 * making all this a pointless exercise.
171 */ 171 */
172 /* If we see that we are N usec away from whole second, 172 /* If we see that we are N usec away from whole second,
173 * we'll sleep for N-ADJ usecs. ADJ corrects for the fact 173 * we'll sleep for N-ADJ usecs. ADJ corrects for the fact
diff --git a/miscutils/ionice.c b/util-linux/ionice.c
index c54b3a6e1..c54b3a6e1 100644
--- a/miscutils/ionice.c
+++ b/util-linux/ionice.c
diff --git a/miscutils/last.c b/util-linux/last.c
index b3f125c3f..b3f125c3f 100644
--- a/miscutils/last.c
+++ b/util-linux/last.c
diff --git a/miscutils/last_fancy.c b/util-linux/last_fancy.c
index e56e0ba85..e56e0ba85 100644
--- a/miscutils/last_fancy.c
+++ b/util-linux/last_fancy.c
diff --git a/util-linux/losetup.c b/util-linux/losetup.c
index 4424d9cbb..d356f49c2 100644
--- a/util-linux/losetup.c
+++ b/util-linux/losetup.c
@@ -127,12 +127,37 @@ int losetup_main(int argc UNUSED_PARAM, char **argv)
127 d = *argv++; 127 d = *argv++;
128 128
129 if (argv[0]) { 129 if (argv[0]) {
130 if (set_loop(&d, argv[0], offset, (opt & OPT_r)) < 0) 130 if (set_loop(&d, argv[0], offset, (opt & OPT_r) ? BB_LO_FLAGS_READ_ONLY : 0) < 0)
131 bb_simple_perror_msg_and_die(argv[0]); 131 bb_simple_perror_msg_and_die(argv[0]);
132 return EXIT_SUCCESS; 132 return EXIT_SUCCESS;
133 } 133 }
134 } 134 }
135 135
136 /* TODO: util-linux 2.28 shows this when run w/o params:
137 * NAME SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE DIO
138 * /dev/loop0 0 0 1 0 /PATH/TO/FILE 0
139 *
140 * implemented by reading /sys:
141 *
142 * open("/sys/block", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 3
143 * newfstatat(3, "loop0/loop/backing_file", {st_mode=S_IFREG|0444, st_size=4096, ...}, 0) = 0
144 * stat("/dev/loop0", {st_mode=S_IFBLK|0660, st_rdev=makedev(7, 0), ...}) = 0
145 * open("/sys/dev/block/7:0/loop/offset", O_RDONLY|O_CLOEXEC) = 5
146 * read(5, "0\n", 4096) = 2
147 * open("/sys/dev/block/7:0/loop/sizelimit", O_RDONLY|O_CLOEXEC) = 5
148 * read(5, "0\n", 4096) = 2
149 * open("/sys/dev/block/7:0/loop/offset", O_RDONLY|O_CLOEXEC) = 5
150 * read(5, "0\n", 4096) = 2
151 * open("/sys/dev/block/7:0/loop/autoclear", O_RDONLY|O_CLOEXEC) = 5
152 * read(5, "1\n", 4096) = 2
153 * open("/sys/dev/block/7:0/ro", O_RDONLY|O_CLOEXEC) = 5
154 * read(5, "0\n", 4096) = 2
155 * open("/sys/dev/block/7:0/loop/backing_file", O_RDONLY|O_CLOEXEC) = 5
156 * read(5, "/PATH/TO/FILE", 4096) = 37
157 * open("/sys/dev/block/7:0/loop/dio", O_RDONLY|O_CLOEXEC) = 5
158 * read(5, "0\n", 4096) = 2
159 */
160
136 bb_show_usage(); /* does not return */ 161 bb_show_usage(); /* does not return */
137 /*return EXIT_FAILURE;*/ 162 /*return EXIT_FAILURE;*/
138} 163}
diff --git a/init/mesg.c b/util-linux/mesg.c
index 45c13b8e0..45c13b8e0 100644
--- a/init/mesg.c
+++ b/util-linux/mesg.c
diff --git a/util-linux/mount.c b/util-linux/mount.c
index f0245f714..6bb18524d 100644
--- a/util-linux/mount.c
+++ b/util-linux/mount.c
@@ -1887,6 +1887,7 @@ static int nfsmount(struct mntent *mp, unsigned long vfsflags, char *filteropts)
1887// NB: mp->xxx fields may be trashed on exit 1887// NB: mp->xxx fields may be trashed on exit
1888static int singlemount(struct mntent *mp, int ignore_busy) 1888static int singlemount(struct mntent *mp, int ignore_busy)
1889{ 1889{
1890 int loopfd = -1;
1890 int rc = -1; 1891 int rc = -1;
1891 unsigned long vfsflags; 1892 unsigned long vfsflags;
1892 char *loopFile = NULL, *filteropts = NULL; 1893 char *loopFile = NULL, *filteropts = NULL;
@@ -2026,7 +2027,20 @@ static int singlemount(struct mntent *mp, int ignore_busy)
2026 if (ENABLE_FEATURE_MOUNT_LOOP && S_ISREG(st.st_mode)) { 2027 if (ENABLE_FEATURE_MOUNT_LOOP && S_ISREG(st.st_mode)) {
2027 loopFile = bb_simplify_path(mp->mnt_fsname); 2028 loopFile = bb_simplify_path(mp->mnt_fsname);
2028 mp->mnt_fsname = NULL; // will receive malloced loop dev name 2029 mp->mnt_fsname = NULL; // will receive malloced loop dev name
2029 if (set_loop(&mp->mnt_fsname, loopFile, 0, /*ro:*/ (vfsflags & MS_RDONLY)) < 0) { 2030
2031 // mount always creates AUTOCLEARed loopdevs, so that umounting
2032 // drops them without any code in the userspace.
2033 // This happens since circa linux-2.6.25:
2034 // commit 96c5865559cee0f9cbc5173f3c949f6ce3525581
2035 // Date: Wed Feb 6 01:36:27 2008 -0800
2036 // Subject: Allow auto-destruction of loop devices
2037 loopfd = set_loop(&mp->mnt_fsname,
2038 loopFile,
2039 0,
2040 ((vfsflags & MS_RDONLY) ? BB_LO_FLAGS_READ_ONLY : 0)
2041 | BB_LO_FLAGS_AUTOCLEAR
2042 );
2043 if (loopfd < 0) {
2030 if (errno == EPERM || errno == EACCES) 2044 if (errno == EPERM || errno == EACCES)
2031 bb_error_msg(bb_msg_perm_denied_are_you_root); 2045 bb_error_msg(bb_msg_perm_denied_are_you_root);
2032 else 2046 else
@@ -2074,6 +2088,8 @@ static int singlemount(struct mntent *mp, int ignore_busy)
2074 } 2088 }
2075 2089
2076 // If mount failed, clean up loop file (if any). 2090 // If mount failed, clean up loop file (if any).
2091 // (Newer kernels which support LO_FLAGS_AUTOCLEAR should not need this,
2092 // merely "close(loopfd)" should do it?)
2077 if (ENABLE_FEATURE_MOUNT_LOOP && rc && loopFile) { 2093 if (ENABLE_FEATURE_MOUNT_LOOP && rc && loopFile) {
2078 del_loop(mp->mnt_fsname); 2094 del_loop(mp->mnt_fsname);
2079 if (ENABLE_FEATURE_CLEAN_UP) { 2095 if (ENABLE_FEATURE_CLEAN_UP) {
@@ -2086,6 +2102,9 @@ static int singlemount(struct mntent *mp, int ignore_busy)
2086 if (ENABLE_FEATURE_CLEAN_UP) 2102 if (ENABLE_FEATURE_CLEAN_UP)
2087 free(filteropts); 2103 free(filteropts);
2088 2104
2105 if (loopfd >= 0)
2106 close(loopfd);
2107
2089 if (errno == EBUSY && ignore_busy) 2108 if (errno == EBUSY && ignore_busy)
2090 return 0; 2109 return 0;
2091 if (errno == ENOENT && (vfsflags & MOUNT_NOFAIL)) 2110 if (errno == ENOENT && (vfsflags & MOUNT_NOFAIL))
diff --git a/miscutils/mountpoint.c b/util-linux/mountpoint.c
index 8b9e1d779..8b9e1d779 100644
--- a/miscutils/mountpoint.c
+++ b/util-linux/mountpoint.c
diff --git a/procps/renice.c b/util-linux/renice.c
index 64213c680..4da3394a8 100644
--- a/procps/renice.c
+++ b/util-linux/renice.c
@@ -141,7 +141,7 @@ int renice_main(int argc UNUSED_PARAM, char **argv)
141 retval = EXIT_FAILURE; 141 retval = EXIT_FAILURE;
142 } 142 }
143 143
144 /* No need to check for errors outputing to stderr since, if it 144 /* No need to check for errors outputting to stderr since, if it
145 * was used, the HAD_ERROR label was reached and retval was set. */ 145 * was used, the HAD_ERROR label was reached and retval was set. */
146 146
147 return retval; 147 return retval;
diff --git a/miscutils/setsid.c b/util-linux/setsid.c
index 143a8f8fa..143a8f8fa 100644
--- a/miscutils/setsid.c
+++ b/util-linux/setsid.c
diff --git a/util-linux/switch_root.c b/util-linux/switch_root.c
index 6034485d7..f18e8a5ce 100644
--- a/util-linux/switch_root.c
+++ b/util-linux/switch_root.c
@@ -141,10 +141,12 @@ int switch_root_main(int argc UNUSED_PARAM, char **argv)
141 141
142 // If a new console specified, redirect stdin/stdout/stderr to it 142 // If a new console specified, redirect stdin/stdout/stderr to it
143 if (console) { 143 if (console) {
144 close(0); 144 int fd = open_or_warn(console, O_RDWR);
145 xopen(console, O_RDWR); 145 if (fd >= 0) {
146 xdup2(0, 1); 146 xmove_fd(fd, 0);
147 xdup2(0, 2); 147 xdup2(0, 1);
148 xdup2(0, 2);
149 }
148 } 150 }
149 151
150 // Exec real init 152 // Exec real init
@@ -181,7 +183,7 @@ So there's a step that needs to be sort of atomic but can't be as a shell
181script. (You can work around this with static linking or very carefully laid 183script. (You can work around this with static linking or very carefully laid
182out paths and sequencing, but it's brittle, ugly, and non-obvious.) 184out paths and sequencing, but it's brittle, ugly, and non-obvious.)
183 185
1842) The "find | rm" bit will acually delete everything because the mount points 1862) The "find | rm" bit will actually delete everything because the mount points
185still show up (even if their contents don't), and rm -rf will then happily zap 187still show up (even if their contents don't), and rm -rf will then happily zap
186that. So the first line is an oversimplification of what you need to do _not_ 188that. So the first line is an oversimplification of what you need to do _not_
187to descend into other filesystems and delete their contents. 189to descend into other filesystems and delete their contents.
diff --git a/miscutils/taskset.c b/util-linux/taskset.c
index 94a07383a..94a07383a 100644
--- a/miscutils/taskset.c
+++ b/util-linux/taskset.c
diff --git a/util-linux/umount.c b/util-linux/umount.c
index c958fd552..0c50dc9ee 100644
--- a/util-linux/umount.c
+++ b/util-linux/umount.c
@@ -42,7 +42,7 @@
42//usage: "\n -l Lazy umount (detach filesystem)" 42//usage: "\n -l Lazy umount (detach filesystem)"
43//usage: "\n -f Force umount (i.e., unreachable NFS server)" 43//usage: "\n -f Force umount (i.e., unreachable NFS server)"
44//usage: IF_FEATURE_MOUNT_LOOP( 44//usage: IF_FEATURE_MOUNT_LOOP(
45//usage: "\n -D Don't free loop device even if it has been used" 45//usage: "\n -d Free loop device if it has been used"
46//usage: ) 46//usage: )
47//usage: 47//usage:
48//usage:#define umount_example_usage 48//usage:#define umount_example_usage
@@ -68,22 +68,14 @@ static struct mntent *getmntent_r(FILE* stream, struct mntent* result,
68} 68}
69#endif 69#endif
70 70
71/* Ignored: -v -t -i 71/* ignored: -v -t -i */
72 * bbox always acts as if -d is present. 72#define OPTION_STRING "fldnra" "vt:i"
73 * -D can be used to suppress it (bbox extension).
74 * Rationale:
75 * (1) util-linux's umount does it if "loop=..." is seen in /etc/mtab:
76 * thus, on many systems, bare umount _does_ drop loop devices.
77 * (2) many users request this feature.
78 */
79#define OPTION_STRING "fldDnra" "vt:i"
80#define OPT_FORCE (1 << 0) // Same as MNT_FORCE 73#define OPT_FORCE (1 << 0) // Same as MNT_FORCE
81#define OPT_LAZY (1 << 1) // Same as MNT_DETACH 74#define OPT_LAZY (1 << 1) // Same as MNT_DETACH
82//#define OPT_FREE_LOOP (1 << 2) // -d is assumed always present 75#define OPT_FREELOOP (1 << 2)
83#define OPT_DONT_FREE_LOOP (1 << 3) 76#define OPT_NO_MTAB (1 << 3)
84#define OPT_NO_MTAB (1 << 4) 77#define OPT_REMOUNT (1 << 4)
85#define OPT_REMOUNT (1 << 5) 78#define OPT_ALL (ENABLE_FEATURE_UMOUNT_ALL ? (1 << 5) : 0)
86#define OPT_ALL (ENABLE_FEATURE_UMOUNT_ALL ? (1 << 6) : 0)
87 79
88int umount_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 80int umount_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
89int umount_main(int argc UNUSED_PARAM, char **argv) 81int umount_main(int argc UNUSED_PARAM, char **argv)
@@ -206,7 +198,7 @@ int umount_main(int argc UNUSED_PARAM, char **argv)
206 } else { 198 } else {
207 // De-allocate the loop device. This ioctl should be ignored on 199 // De-allocate the loop device. This ioctl should be ignored on
208 // any non-loop block devices. 200 // any non-loop block devices.
209 if (ENABLE_FEATURE_MOUNT_LOOP && !(opt & OPT_DONT_FREE_LOOP) && m) 201 if (ENABLE_FEATURE_MOUNT_LOOP && (opt & OPT_FREELOOP) && m)
210 del_loop(m->device); 202 del_loop(m->device);
211 if (ENABLE_FEATURE_MTAB_SUPPORT && !(opt & OPT_NO_MTAB) && m) 203 if (ENABLE_FEATURE_MTAB_SUPPORT && !(opt & OPT_NO_MTAB) && m)
212 erase_mtab(m->dir); 204 erase_mtab(m->dir);
diff --git a/util-linux/volume_id/udf.c b/util-linux/volume_id/udf.c
index 613c80c86..fa5dccee7 100644
--- a/util-linux/volume_id/udf.c
+++ b/util-linux/volume_id/udf.c
@@ -137,7 +137,7 @@ anchor:
137 if (type != 2) /* TAG_ID_AVDP */ 137 if (type != 2) /* TAG_ID_AVDP */
138 goto found; 138 goto found;
139 139
140 /* get desriptor list address and block count */ 140 /* get descriptor list address and block count */
141 count = le32_to_cpu(vd->type.anchor.length) / bs; 141 count = le32_to_cpu(vd->type.anchor.length) / bs;
142 loc = le32_to_cpu(vd->type.anchor.location); 142 loc = le32_to_cpu(vd->type.anchor.location);
143 dbg("0x%x descriptors starting at logical secor 0x%x", count, loc); 143 dbg("0x%x descriptors starting at logical secor 0x%x", count, loc);
diff --git a/miscutils/wall.c b/util-linux/wall.c
index 50658f457..50658f457 100644
--- a/miscutils/wall.c
+++ b/util-linux/wall.c