diff options
author | Nguyễn Thái Ngọc Duy <pclouds@gmail.com> | 2011-01-04 19:40:30 +0700 |
---|---|---|
committer | Nguyễn Thái Ngọc Duy <pclouds@gmail.com> | 2011-01-04 19:40:30 +0700 |
commit | 3b5c308768d76298bb964814ecc34de47bcac0b4 (patch) | |
tree | 795340e9d8f5e5bf9e8d895641099af343eec2a0 | |
parent | 2b9a0e715ec459198f486653023d963b79291da7 (diff) | |
parent | 5fe2f863b9cee5ab0e7ac873538bce48846dbad8 (diff) | |
download | busybox-w32-3b5c308768d76298bb964814ecc34de47bcac0b4.tar.gz busybox-w32-3b5c308768d76298bb964814ecc34de47bcac0b4.tar.bz2 busybox-w32-3b5c308768d76298bb964814ecc34de47bcac0b4.zip |
Merge commit '06f719fd79fe15ce6fd5431bc58fcb22851de24d^'
101 files changed, 2872 insertions, 2299 deletions
@@ -146,6 +146,14 @@ config FEATURE_INSTALLER | |||
146 | busybox at runtime to create hard links or symlinks for all the | 146 | busybox at runtime to create hard links or symlinks for all the |
147 | applets that are compiled into busybox. | 147 | applets that are compiled into busybox. |
148 | 148 | ||
149 | config INSTALL_NO_USR | ||
150 | bool "Don't use /usr" | ||
151 | default n | ||
152 | depends on FEATURE_INSTALLER | ||
153 | help | ||
154 | Disable use of /usr. busybox --install will install applets | ||
155 | only to /bin and /sbin, never to /usr/bin or /usr/sbin. | ||
156 | |||
149 | config LOCALE_SUPPORT | 157 | config LOCALE_SUPPORT |
150 | bool "Enable locale support (system needs locale for this to work)" | 158 | bool "Enable locale support (system needs locale for this to work)" |
151 | default n | 159 | default n |
@@ -298,15 +306,6 @@ config FEATURE_CLEAN_UP | |||
298 | Don't enable this unless you have a really good reason to clean | 306 | Don't enable this unless you have a really good reason to clean |
299 | things up manually. | 307 | things up manually. |
300 | 308 | ||
301 | config FEATURE_UTMP | ||
302 | bool "Support utmp file" | ||
303 | default y | ||
304 | help | ||
305 | The file /var/run/utmp is used to track who is currently logged in. | ||
306 | With this option on, certain applets (getty, login, telnetd etc) | ||
307 | will create and delete entries there. | ||
308 | "who" applet requires this option. | ||
309 | |||
310 | config FEATURE_WTMP | 309 | config FEATURE_WTMP |
311 | bool "Support wtmp file" | 310 | bool "Support wtmp file" |
312 | default y | 311 | default y |
@@ -318,6 +317,15 @@ config FEATURE_WTMP | |||
318 | will append new entries there. | 317 | will append new entries there. |
319 | "last" applet requires this option. | 318 | "last" applet requires this option. |
320 | 319 | ||
320 | config FEATURE_UTMP | ||
321 | bool "Support utmp file" | ||
322 | default y | ||
323 | help | ||
324 | The file /var/run/utmp is used to track who is currently logged in. | ||
325 | With this option on, certain applets (getty, login, telnetd etc) | ||
326 | will create and delete entries there. | ||
327 | "who" applet requires this option. | ||
328 | |||
321 | config FEATURE_PIDFILE | 329 | config FEATURE_PIDFILE |
322 | bool "Support writing pidfiles" | 330 | bool "Support writing pidfiles" |
323 | default y | 331 | default y |
@@ -330,14 +338,19 @@ config FEATURE_SUID | |||
330 | default y | 338 | default y |
331 | help | 339 | help |
332 | With this option you can install the busybox binary belonging | 340 | With this option you can install the busybox binary belonging |
333 | to root with the suid bit set, and it will automatically drop | 341 | to root with the suid bit set, enabling some applets to perform |
334 | priviledges for applets that don't need root access. | 342 | root-level operations even when run by ordinary users |
343 | (for example, mounting of user mounts in fstab needs this). | ||
344 | |||
345 | Busybox will automatically drop priviledges for applets | ||
346 | that don't need root access. | ||
335 | 347 | ||
336 | If you are really paranoid and don't want to do this, build two | 348 | If you are really paranoid and don't want to do this, build two |
337 | busybox binaries with different applets in them (and the appropriate | 349 | busybox binaries with different applets in them (and the appropriate |
338 | symlinks pointing to each binary), and only set the suid bit on the | 350 | symlinks pointing to each binary), and only set the suid bit on the |
339 | one that needs it. The applets currently marked to need the suid bit | 351 | one that needs it. |
340 | are: | 352 | |
353 | The applets currently marked to need the suid bit are: | ||
341 | 354 | ||
342 | crontab, dnsd, findfs, ipcrm, ipcs, login, passwd, ping, su, | 355 | crontab, dnsd, findfs, ipcrm, ipcs, login, passwd, ping, su, |
343 | traceroute, vlock. | 356 | traceroute, vlock. |
@@ -674,20 +687,13 @@ endchoice | |||
674 | 687 | ||
675 | endmenu | 688 | endmenu |
676 | 689 | ||
677 | menu 'Installation Options' | 690 | menu 'Installation Options ("make install" behavior)' |
678 | |||
679 | config INSTALL_NO_USR | ||
680 | bool "Don't use /usr" | ||
681 | default n | ||
682 | help | ||
683 | Disable use of /usr. Don't activate this option if you don't know | ||
684 | that you really want this behaviour. | ||
685 | 691 | ||
686 | choice | 692 | choice |
687 | prompt "Applets links" | 693 | prompt "What kind of applet links to install" |
688 | default INSTALL_APPLET_SYMLINKS | 694 | default INSTALL_APPLET_SYMLINKS |
689 | help | 695 | help |
690 | Choose how you install applets links. | 696 | Choose what kind of links to applets are created by "make install". |
691 | 697 | ||
692 | config INSTALL_APPLET_SYMLINKS | 698 | config INSTALL_APPLET_SYMLINKS |
693 | bool "as soft-links" | 699 | bool "as soft-links" |
@@ -711,8 +717,9 @@ config INSTALL_APPLET_DONT | |||
711 | bool "not installed" | 717 | bool "not installed" |
712 | depends on FEATURE_INSTALLER || FEATURE_SH_STANDALONE || FEATURE_PREFER_APPLETS | 718 | depends on FEATURE_INSTALLER || FEATURE_SH_STANDALONE || FEATURE_PREFER_APPLETS |
713 | help | 719 | help |
714 | Do not install applet links. Useful when using the -install feature | 720 | Do not install applet links. Useful when you plan to use |
715 | or a standalone shell for rescue purposes. | 721 | busybox --install for installing links, or plan to use |
722 | a standalone shell and thus don't need applet links. | ||
716 | 723 | ||
717 | endchoice | 724 | endchoice |
718 | 725 | ||
@@ -736,8 +743,8 @@ config INSTALL_SH_APPLET_HARDLINK | |||
736 | config INSTALL_SH_APPLET_SCRIPT_WRAPPER | 743 | config INSTALL_SH_APPLET_SCRIPT_WRAPPER |
737 | bool "as script wrapper" | 744 | bool "as script wrapper" |
738 | help | 745 | help |
739 | Install /bin/sh applet as script wrapper that call the busybox | 746 | Install /bin/sh applet as script wrapper that calls |
740 | binary. | 747 | the busybox binary. |
741 | 748 | ||
742 | endchoice | 749 | endchoice |
743 | 750 | ||
diff --git a/applets/usage_compressed b/applets/usage_compressed index e1fd0d94d..af66bc5dc 100755 --- a/applets/usage_compressed +++ b/applets/usage_compressed | |||
@@ -9,6 +9,13 @@ test -x "$loc/usage" || exit 1 | |||
9 | test "$SED" || SED=sed | 9 | test "$SED" || SED=sed |
10 | test "$DD" || DD=dd | 10 | test "$DD" || DD=dd |
11 | 11 | ||
12 | # Some people were bitten by their system lacking a (proper) od | ||
13 | od -v -t x1 </dev/null >/dev/null | ||
14 | if test $? != 0; then | ||
15 | echo 'od tool is not installed or cannot accept "-v -t x1" options' | ||
16 | exit 1 | ||
17 | fi | ||
18 | |||
12 | exec >"$target.$$" | 19 | exec >"$target.$$" |
13 | 20 | ||
14 | echo '#define UNPACKED_USAGE "" \' | 21 | echo '#define UNPACKED_USAGE "" \' |
diff --git a/archival/bbunzip.c b/archival/bbunzip.c index d96790b89..a195434e4 100644 --- a/archival/bbunzip.c +++ b/archival/bbunzip.c | |||
@@ -307,7 +307,7 @@ int gunzip_main(int argc UNUSED_PARAM, char **argv) | |||
307 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 307 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
308 | */ | 308 | */ |
309 | //usage:#define bunzip2_trivial_usage | 309 | //usage:#define bunzip2_trivial_usage |
310 | //usage: "[OPTIONS] [FILE]..." | 310 | //usage: "[-cf] [FILE]..." |
311 | //usage:#define bunzip2_full_usage "\n\n" | 311 | //usage:#define bunzip2_full_usage "\n\n" |
312 | //usage: "Decompress FILEs (or stdin)\n" | 312 | //usage: "Decompress FILEs (or stdin)\n" |
313 | //usage: "\nOptions:" | 313 | //usage: "\nOptions:" |
diff --git a/archival/cpio.c b/archival/cpio.c index 7cd8ee8a7..a2d74dc79 100644 --- a/archival/cpio.c +++ b/archival/cpio.c | |||
@@ -370,7 +370,7 @@ int cpio_main(int argc UNUSED_PARAM, char **argv) | |||
370 | if (cpio_fmt[0] != 'n') /* we _require_ "-H newc" */ | 370 | if (cpio_fmt[0] != 'n') /* we _require_ "-H newc" */ |
371 | bb_show_usage(); | 371 | bb_show_usage(); |
372 | if (opt & CPIO_OPT_FILE) { | 372 | if (opt & CPIO_OPT_FILE) { |
373 | xmove_fd(xopen3(cpio_filename, O_WRONLY | O_CREAT | O_TRUNC, 0666), STDOUT_FILENO); | 373 | xmove_fd(xopen(cpio_filename, O_WRONLY | O_CREAT | O_TRUNC), STDOUT_FILENO); |
374 | } | 374 | } |
375 | dump: | 375 | dump: |
376 | return cpio_o(); | 376 | return cpio_o(); |
diff --git a/archival/dpkg.c b/archival/dpkg.c index b36c26198..07f01501b 100644 --- a/archival/dpkg.c +++ b/archival/dpkg.c | |||
@@ -1524,8 +1524,8 @@ static char FAST_FUNC filter_rename_config(archive_handle_t *archive_handle) | |||
1524 | buf = xmalloc(4096); | 1524 | buf = xmalloc(4096); |
1525 | md5_begin(&md5); | 1525 | md5_begin(&md5); |
1526 | while ((count = safe_read(fd, buf, 4096)) > 0) | 1526 | while ((count = safe_read(fd, buf, 4096)) > 0) |
1527 | md5_hash(buf, count, &md5); | 1527 | md5_hash(&md5, buf, count); |
1528 | md5_end(buf, &md5); /* using buf as result storage */ | 1528 | md5_end(&md5, buf); /* using buf as result storage */ |
1529 | close(fd); | 1529 | close(fd); |
1530 | 1530 | ||
1531 | md5line = xmalloc(16 * 2 + 2 + strlen(name_ptr) + 1); | 1531 | md5line = xmalloc(16 * 2 + 2 + strlen(name_ptr) + 1); |
diff --git a/archival/libunarchive/data_extract_all.c b/archival/libunarchive/data_extract_all.c index cc549cd78..5fb1ab2ae 100644 --- a/archival/libunarchive/data_extract_all.c +++ b/archival/libunarchive/data_extract_all.c | |||
@@ -69,7 +69,9 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) | |||
69 | } | 69 | } |
70 | } | 70 | } |
71 | else if (existing_sb.st_mtime >= file_header->mtime) { | 71 | else if (existing_sb.st_mtime >= file_header->mtime) { |
72 | if (!(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) { | 72 | if (!(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) |
73 | && !S_ISDIR(file_header->mode) | ||
74 | ) { | ||
73 | bb_error_msg("%s not created: newer or " | 75 | bb_error_msg("%s not created: newer or " |
74 | "same age file exists", file_header->name); | 76 | "same age file exists", file_header->name); |
75 | } | 77 | } |
diff --git a/coreutils/cksum.c b/coreutils/cksum.c index 8e7800ee9..7bf383e2d 100644 --- a/coreutils/cksum.c +++ b/coreutils/cksum.c | |||
@@ -8,6 +8,8 @@ | |||
8 | */ | 8 | */ |
9 | #include "libbb.h" | 9 | #include "libbb.h" |
10 | 10 | ||
11 | /* This is a NOEXEC applet. Be very careful! */ | ||
12 | |||
11 | int cksum_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 13 | int cksum_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
12 | int cksum_main(int argc UNUSED_PARAM, char **argv) | 14 | int cksum_main(int argc UNUSED_PARAM, char **argv) |
13 | { | 15 | { |
diff --git a/coreutils/date.c b/coreutils/date.c index 881dcc429..eed4714f9 100644 --- a/coreutils/date.c +++ b/coreutils/date.c | |||
@@ -19,38 +19,7 @@ | |||
19 | /* Input parsing code is always bulky - used heavy duty libc stuff as | 19 | /* Input parsing code is always bulky - used heavy duty libc stuff as |
20 | much as possible, missed out a lot of bounds checking */ | 20 | much as possible, missed out a lot of bounds checking */ |
21 | 21 | ||
22 | /* Default input handling to save surprising some people */ | 22 | //applet:IF_DATE(APPLET(date, _BB_DIR_BIN, _BB_SUID_DROP)) |
23 | |||
24 | /* GNU coreutils 6.9 man page: | ||
25 | * date [OPTION]... [+FORMAT] | ||
26 | * date [-u|--utc|--universal] [MMDDhhmm[[CC]YY][.ss]] | ||
27 | * -d, --date=STRING | ||
28 | * display time described by STRING, not `now' | ||
29 | * -f, --file=DATEFILE | ||
30 | * like --date once for each line of DATEFILE | ||
31 | * -r, --reference=FILE | ||
32 | * display the last modification time of FILE | ||
33 | * -R, --rfc-2822 | ||
34 | * output date and time in RFC 2822 format. | ||
35 | * Example: Mon, 07 Aug 2006 12:34:56 -0600 | ||
36 | * --rfc-3339=TIMESPEC | ||
37 | * output date and time in RFC 3339 format. | ||
38 | * TIMESPEC='date', 'seconds', or 'ns' | ||
39 | * Date and time components are separated by a single space: | ||
40 | * 2006-08-07 12:34:56-06:00 | ||
41 | * -s, --set=STRING | ||
42 | * set time described by STRING | ||
43 | * -u, --utc, --universal | ||
44 | * print or set Coordinated Universal Time | ||
45 | * | ||
46 | * Busybox: | ||
47 | * long options are not supported | ||
48 | * -f is not supported | ||
49 | * -I seems to roughly match --rfc-3339, but -I has _optional_ param | ||
50 | * (thus "-I seconds" doesn't work, only "-Iseconds"), | ||
51 | * and does not support -Ins | ||
52 | * -D FMT is a bbox extension for _input_ conversion of -d DATE | ||
53 | */ | ||
54 | 23 | ||
55 | //kbuild:lib-$(CONFIG_DATE) += date.o | 24 | //kbuild:lib-$(CONFIG_DATE) += date.o |
56 | 25 | ||
@@ -69,6 +38,7 @@ | |||
69 | //config: Enable option (-I) to output an ISO-8601 compliant | 38 | //config: Enable option (-I) to output an ISO-8601 compliant |
70 | //config: date/time string. | 39 | //config: date/time string. |
71 | //config: | 40 | //config: |
41 | //config:# defaults to "no": stat's nanosecond field is a bit non-portable | ||
72 | //config:config FEATURE_DATE_NANO | 42 | //config:config FEATURE_DATE_NANO |
73 | //config: bool "Support %[num]N nanosecond format specifier" | 43 | //config: bool "Support %[num]N nanosecond format specifier" |
74 | //config: default n | 44 | //config: default n |
@@ -92,6 +62,78 @@ | |||
92 | //config: the same format. With it on, 'date DATE' additionally supports | 62 | //config: the same format. With it on, 'date DATE' additionally supports |
93 | //config: MMDDhhmm[[YY]YY][.ss] format. | 63 | //config: MMDDhhmm[[YY]YY][.ss] format. |
94 | 64 | ||
65 | /* GNU coreutils 6.9 man page: | ||
66 | * date [OPTION]... [+FORMAT] | ||
67 | * date [-u|--utc|--universal] [MMDDhhmm[[CC]YY][.ss]] | ||
68 | * -d, --date=STRING | ||
69 | * display time described by STRING, not `now' | ||
70 | * -f, --file=DATEFILE | ||
71 | * like --date once for each line of DATEFILE | ||
72 | * -r, --reference=FILE | ||
73 | * display the last modification time of FILE | ||
74 | * -R, --rfc-2822 | ||
75 | * output date and time in RFC 2822 format. | ||
76 | * Example: Mon, 07 Aug 2006 12:34:56 -0600 | ||
77 | * --rfc-3339=TIMESPEC | ||
78 | * output date and time in RFC 3339 format. | ||
79 | * TIMESPEC='date', 'seconds', or 'ns' | ||
80 | * Date and time components are separated by a single space: | ||
81 | * 2006-08-07 12:34:56-06:00 | ||
82 | * -s, --set=STRING | ||
83 | * set time described by STRING | ||
84 | * -u, --utc, --universal | ||
85 | * print or set Coordinated Universal Time | ||
86 | * | ||
87 | * Busybox: | ||
88 | * long options are not supported | ||
89 | * -f is not supported | ||
90 | * -I seems to roughly match --rfc-3339, but -I has _optional_ param | ||
91 | * (thus "-I seconds" doesn't work, only "-Iseconds"), | ||
92 | * and does not support -Ins | ||
93 | * -D FMT is a bbox extension for _input_ conversion of -d DATE | ||
94 | */ | ||
95 | |||
96 | //usage:#define date_trivial_usage | ||
97 | //usage: "[OPTIONS] [+FMT] [TIME]" | ||
98 | //usage:#define date_full_usage "\n\n" | ||
99 | //usage: "Display time (using +FMT), or set time\n" | ||
100 | //usage: "\nOptions:" | ||
101 | //usage: IF_NOT_LONG_OPTS( | ||
102 | //usage: "\n [-s] TIME Set time to TIME" | ||
103 | //usage: "\n -u Work in UTC (don't convert to local time)" | ||
104 | //usage: "\n -R Output RFC-2822 compliant date string" | ||
105 | //usage: ) IF_LONG_OPTS( | ||
106 | //usage: "\n [-s,--set] TIME Set time to TIME" | ||
107 | //usage: "\n -u,--utc Work in UTC (don't convert to local time)" | ||
108 | //usage: "\n -R,--rfc-2822 Output RFC-2822 compliant date string" | ||
109 | //usage: ) | ||
110 | //usage: IF_FEATURE_DATE_ISOFMT( | ||
111 | //usage: "\n -I[SPEC] Output ISO-8601 compliant date string" | ||
112 | //usage: "\n SPEC='date' (default) for date only," | ||
113 | //usage: "\n 'hours', 'minutes', or 'seconds' for date and" | ||
114 | //usage: "\n time to the indicated precision" | ||
115 | //usage: ) | ||
116 | //usage: IF_NOT_LONG_OPTS( | ||
117 | //usage: "\n -r FILE Display last modification time of FILE" | ||
118 | //usage: "\n -d TIME Display TIME, not 'now'" | ||
119 | //usage: ) IF_LONG_OPTS( | ||
120 | //usage: "\n -r,--reference FILE Display last modification time of FILE" | ||
121 | //usage: "\n -d,--date TIME Display TIME, not 'now'" | ||
122 | //usage: ) | ||
123 | //usage: IF_FEATURE_DATE_ISOFMT( | ||
124 | //usage: "\n -D FMT Use FMT for -d TIME conversion" | ||
125 | //usage: ) | ||
126 | //usage: "\n" | ||
127 | //usage: "\nRecognized TIME formats:" | ||
128 | //usage: "\n hh:mm[:ss]" | ||
129 | //usage: "\n [YYYY.]MM.DD-hh:mm[:ss]" | ||
130 | //usage: "\n YYYY-MM-DD hh:mm[:ss]" | ||
131 | //usage: "\n [[[[[YY]YY]MM]DD]hh]mm[.ss]" | ||
132 | //usage: | ||
133 | //usage:#define date_example_usage | ||
134 | //usage: "$ date\n" | ||
135 | //usage: "Wed Apr 12 18:52:41 MDT 2000\n" | ||
136 | |||
95 | #include "libbb.h" | 137 | #include "libbb.h" |
96 | #if ENABLE_FEATURE_DATE_NANO | 138 | #if ENABLE_FEATURE_DATE_NANO |
97 | # include <sys/syscall.h> | 139 | # include <sys/syscall.h> |
diff --git a/coreutils/dos2unix.c b/coreutils/dos2unix.c index ef1ea4328..8aa1d93b5 100644 --- a/coreutils/dos2unix.c +++ b/coreutils/dos2unix.c | |||
@@ -14,6 +14,8 @@ | |||
14 | 14 | ||
15 | #include "libbb.h" | 15 | #include "libbb.h" |
16 | 16 | ||
17 | /* This is a NOEXEC applet. Be very careful! */ | ||
18 | |||
17 | enum { | 19 | enum { |
18 | CT_UNIX2DOS = 1, | 20 | CT_UNIX2DOS = 1, |
19 | CT_DOS2UNIX | 21 | CT_DOS2UNIX |
diff --git a/coreutils/fold.c b/coreutils/fold.c index 54f1aa2ac..4a6429ad7 100644 --- a/coreutils/fold.c +++ b/coreutils/fold.c | |||
@@ -12,6 +12,8 @@ | |||
12 | #include "libbb.h" | 12 | #include "libbb.h" |
13 | #include "unicode.h" | 13 | #include "unicode.h" |
14 | 14 | ||
15 | /* This is a NOEXEC applet. Be very careful! */ | ||
16 | |||
15 | /* Must match getopt32 call */ | 17 | /* Must match getopt32 call */ |
16 | #define FLAG_COUNT_BYTES 1 | 18 | #define FLAG_COUNT_BYTES 1 |
17 | #define FLAG_BREAK_SPACES 2 | 19 | #define FLAG_BREAK_SPACES 2 |
diff --git a/coreutils/head.c b/coreutils/head.c index 0845b4375..669aae819 100644 --- a/coreutils/head.c +++ b/coreutils/head.c | |||
@@ -13,6 +13,8 @@ | |||
13 | 13 | ||
14 | #include "libbb.h" | 14 | #include "libbb.h" |
15 | 15 | ||
16 | /* This is a NOEXEC applet. Be very careful! */ | ||
17 | |||
16 | static const char head_opts[] ALIGN1 = | 18 | static const char head_opts[] ALIGN1 = |
17 | "n:" | 19 | "n:" |
18 | #if ENABLE_FEATURE_FANCY_HEAD | 20 | #if ENABLE_FEATURE_FANCY_HEAD |
diff --git a/coreutils/id.c b/coreutils/id.c index 56286f4d4..ed1dc862e 100644 --- a/coreutils/id.c +++ b/coreutils/id.c | |||
@@ -17,6 +17,8 @@ | |||
17 | 17 | ||
18 | #include "libbb.h" | 18 | #include "libbb.h" |
19 | 19 | ||
20 | /* This is a NOEXEC applet. Be very careful! */ | ||
21 | |||
20 | #if !ENABLE_USE_BB_PWD_GRP | 22 | #if !ENABLE_USE_BB_PWD_GRP |
21 | #if defined(__UCLIBC_MAJOR__) && (__UCLIBC_MAJOR__ == 0) | 23 | #if defined(__UCLIBC_MAJOR__) && (__UCLIBC_MAJOR__ == 0) |
22 | #if (__UCLIBC_MINOR__ < 9) || (__UCLIBC_MINOR__ == 9 && __UCLIBC_SUBLEVEL__ < 30) | 24 | #if (__UCLIBC_MINOR__ < 9) || (__UCLIBC_MINOR__ == 9 && __UCLIBC_SUBLEVEL__ < 30) |
diff --git a/coreutils/md5_sha1_sum.c b/coreutils/md5_sha1_sum.c index 646f8bd10..e79210c0d 100644 --- a/coreutils/md5_sha1_sum.c +++ b/coreutils/md5_sha1_sum.c | |||
@@ -8,6 +8,8 @@ | |||
8 | 8 | ||
9 | #include "libbb.h" | 9 | #include "libbb.h" |
10 | 10 | ||
11 | /* This is a NOEXEC applet. Be very careful! */ | ||
12 | |||
11 | typedef enum { | 13 | typedef enum { |
12 | /* 4th letter of applet_name is... */ | 14 | /* 4th letter of applet_name is... */ |
13 | HASH_MD5 = 's', /* "md5>s<um" */ | 15 | HASH_MD5 = 's', /* "md5>s<um" */ |
@@ -41,7 +43,7 @@ static uint8_t *hash_file(const char *filename /*, hash_algo_t hash_algo*/) | |||
41 | } context; | 43 | } context; |
42 | uint8_t *hash_value = NULL; | 44 | uint8_t *hash_value = NULL; |
43 | RESERVE_CONFIG_UBUFFER(in_buf, 4096); | 45 | RESERVE_CONFIG_UBUFFER(in_buf, 4096); |
44 | void FAST_FUNC (*update)(const void*, size_t, void*); | 46 | void FAST_FUNC (*update)(void*, const void*, size_t); |
45 | void FAST_FUNC (*final)(void*, void*); | 47 | void FAST_FUNC (*final)(void*, void*); |
46 | hash_algo_t hash_algo = applet_name[3]; | 48 | hash_algo_t hash_algo = applet_name[3]; |
47 | 49 | ||
@@ -76,11 +78,11 @@ static uint8_t *hash_file(const char *filename /*, hash_algo_t hash_algo*/) | |||
76 | } | 78 | } |
77 | 79 | ||
78 | while (0 < (count = safe_read(src_fd, in_buf, 4096))) { | 80 | while (0 < (count = safe_read(src_fd, in_buf, 4096))) { |
79 | update(in_buf, count, &context); | 81 | update(&context, in_buf, count); |
80 | } | 82 | } |
81 | 83 | ||
82 | if (count == 0) { | 84 | if (count == 0) { |
83 | final(in_buf, &context); | 85 | final(&context, in_buf); |
84 | hash_value = hash_bin_to_hex(in_buf, hash_len); | 86 | hash_value = hash_bin_to_hex(in_buf, hash_len); |
85 | } | 87 | } |
86 | 88 | ||
diff --git a/coreutils/mkfifo.c b/coreutils/mkfifo.c index 41aedd099..4388ccaa3 100644 --- a/coreutils/mkfifo.c +++ b/coreutils/mkfifo.c | |||
@@ -13,6 +13,8 @@ | |||
13 | #include "libbb.h" | 13 | #include "libbb.h" |
14 | #include "libcoreutils/coreutils.h" | 14 | #include "libcoreutils/coreutils.h" |
15 | 15 | ||
16 | /* This is a NOEXEC applet. Be very careful! */ | ||
17 | |||
16 | int mkfifo_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 18 | int mkfifo_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
17 | int mkfifo_main(int argc UNUSED_PARAM, char **argv) | 19 | int mkfifo_main(int argc UNUSED_PARAM, char **argv) |
18 | { | 20 | { |
diff --git a/coreutils/mknod.c b/coreutils/mknod.c index 0e5542dde..14d91b5df 100644 --- a/coreutils/mknod.c +++ b/coreutils/mknod.c | |||
@@ -14,6 +14,8 @@ | |||
14 | #include "libbb.h" | 14 | #include "libbb.h" |
15 | #include "libcoreutils/coreutils.h" | 15 | #include "libcoreutils/coreutils.h" |
16 | 16 | ||
17 | /* This is a NOEXEC applet. Be very careful! */ | ||
18 | |||
17 | static const char modes_chars[] ALIGN1 = { 'p', 'c', 'u', 'b', 0, 1, 1, 2 }; | 19 | static const char modes_chars[] ALIGN1 = { 'p', 'c', 'u', 'b', 0, 1, 1, 2 }; |
18 | static const mode_t modes_cubp[] = { S_IFIFO, S_IFCHR, S_IFBLK }; | 20 | static const mode_t modes_cubp[] = { S_IFIFO, S_IFCHR, S_IFBLK }; |
19 | 21 | ||
diff --git a/coreutils/printenv.c b/coreutils/printenv.c index d38f8fb5f..33be5c096 100644 --- a/coreutils/printenv.c +++ b/coreutils/printenv.c | |||
@@ -10,6 +10,8 @@ | |||
10 | 10 | ||
11 | #include "libbb.h" | 11 | #include "libbb.h" |
12 | 12 | ||
13 | /* This is a NOFORK applet. Be very careful! */ | ||
14 | |||
13 | int printenv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 15 | int printenv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
14 | int printenv_main(int argc UNUSED_PARAM, char **argv) | 16 | int printenv_main(int argc UNUSED_PARAM, char **argv) |
15 | { | 17 | { |
diff --git a/coreutils/seq.c b/coreutils/seq.c index 8be25360f..22bf3ec9d 100644 --- a/coreutils/seq.c +++ b/coreutils/seq.c | |||
@@ -86,7 +86,8 @@ int seq_main(int argc, char **argv) | |||
86 | v = first; | 86 | v = first; |
87 | n = 0; | 87 | n = 0; |
88 | while (increment >= 0 ? v <= last : v >= last) { | 88 | while (increment >= 0 ? v <= last : v >= last) { |
89 | printf("%s%0*.*f", sep, width, frac_part, v); | 89 | if (printf("%s%0*.*f", sep, width, frac_part, v) < 0) |
90 | break; /* I/O error, bail out (yes, this really happens) */ | ||
90 | sep = opt_s; | 91 | sep = opt_s; |
91 | /* v += increment; - would accumulate floating point errors */ | 92 | /* v += increment; - would accumulate floating point errors */ |
92 | n++; | 93 | n++; |
diff --git a/coreutils/sleep.c b/coreutils/sleep.c index b983df47e..433f9d6ee 100644 --- a/coreutils/sleep.c +++ b/coreutils/sleep.c | |||
@@ -20,7 +20,7 @@ | |||
20 | 20 | ||
21 | #include "libbb.h" | 21 | #include "libbb.h" |
22 | 22 | ||
23 | /* This is a NOFORK applet. Be very careful! */ | 23 | /* Do not make this applet NOFORK. It breaks ^C-ing of pauses in shells */ |
24 | 24 | ||
25 | 25 | ||
26 | #if ENABLE_FEATURE_FANCY_SLEEP || ENABLE_FEATURE_FLOAT_SLEEP | 26 | #if ENABLE_FEATURE_FANCY_SLEEP || ENABLE_FEATURE_FLOAT_SLEEP |
@@ -49,6 +49,10 @@ int sleep_main(int argc UNUSED_PARAM, char **argv) | |||
49 | 49 | ||
50 | #if ENABLE_FEATURE_FLOAT_SLEEP | 50 | #if ENABLE_FEATURE_FLOAT_SLEEP |
51 | 51 | ||
52 | # if ENABLE_LOCALE_SUPPORT | ||
53 | /* undo busybox.c setlocale */ | ||
54 | setlocale(LC_NUMERIC, "C"); | ||
55 | # endif | ||
52 | duration = 0; | 56 | duration = 0; |
53 | do { | 57 | do { |
54 | char *arg = *argv; | 58 | char *arg = *argv; |
@@ -62,14 +66,15 @@ int sleep_main(int argc UNUSED_PARAM, char **argv) | |||
62 | d = strtod(arg, &pp); | 66 | d = strtod(arg, &pp); |
63 | if (errno || *pp) | 67 | if (errno || *pp) |
64 | bb_show_usage(); | 68 | bb_show_usage(); |
65 | arg[len] = sv; | 69 | arg += len; |
66 | len--; | 70 | *arg-- = sv; |
67 | sv = arg[len]; | 71 | sv = *arg; |
68 | arg[len] = '1'; | 72 | *arg = '1'; |
69 | duration += d * xatoul_sfx(&arg[len], sfx); | 73 | duration += d * xatoul_sfx(arg, sfx); |
70 | arg[len] = sv; | 74 | *arg = sv; |
71 | } else | 75 | } else { |
72 | duration += xatoul_sfx(arg, sfx); | 76 | duration += xatoul_sfx(arg, sfx); |
77 | } | ||
73 | } while (*++argv); | 78 | } while (*++argv); |
74 | 79 | ||
75 | ts.tv_sec = MAXINT(typeof(ts.tv_sec)); | 80 | ts.tv_sec = MAXINT(typeof(ts.tv_sec)); |
diff --git a/coreutils/sort.c b/coreutils/sort.c index 4407b7105..eccc2d437 100644 --- a/coreutils/sort.c +++ b/coreutils/sort.c | |||
@@ -412,7 +412,7 @@ int sort_main(int argc UNUSED_PARAM, char **argv) | |||
412 | #if ENABLE_FEATURE_SORT_BIG | 412 | #if ENABLE_FEATURE_SORT_BIG |
413 | /* Open output file _after_ we read all input ones */ | 413 | /* Open output file _after_ we read all input ones */ |
414 | if (option_mask32 & FLAG_o) | 414 | if (option_mask32 & FLAG_o) |
415 | xmove_fd(xopen3(str_o, O_WRONLY, 0666), STDOUT_FILENO); | 415 | xmove_fd(xopen(str_o, O_WRONLY|O_CREAT|O_TRUNC), STDOUT_FILENO); |
416 | #endif | 416 | #endif |
417 | flag = (option_mask32 & FLAG_z) ? '\0' : '\n'; | 417 | flag = (option_mask32 & FLAG_z) ? '\0' : '\n'; |
418 | for (i = 0; i < linecount; i++) | 418 | for (i = 0; i < linecount; i++) |
diff --git a/coreutils/tee.c b/coreutils/tee.c index 2e1e367f2..e66e885ec 100644 --- a/coreutils/tee.c +++ b/coreutils/tee.c | |||
@@ -42,7 +42,7 @@ int tee_main(int argc, char **argv) | |||
42 | * that doesn't consume all its input. Good idea... */ | 42 | * that doesn't consume all its input. Good idea... */ |
43 | signal(SIGPIPE, SIG_IGN); | 43 | signal(SIGPIPE, SIG_IGN); |
44 | 44 | ||
45 | /* Allocate an array of FILE *'s, with one extra for a sentinal. */ | 45 | /* Allocate an array of FILE *'s, with one extra for a sentinel. */ |
46 | fp = files = xzalloc(sizeof(FILE *) * (argc + 2)); | 46 | fp = files = xzalloc(sizeof(FILE *) * (argc + 2)); |
47 | np = names = argv - 1; | 47 | np = names = argv - 1; |
48 | 48 | ||
diff --git a/coreutils/uniq.c b/coreutils/uniq.c index f0364b9a1..358de7894 100644 --- a/coreutils/uniq.c +++ b/coreutils/uniq.c | |||
@@ -52,8 +52,8 @@ int uniq_main(int argc UNUSED_PARAM, char **argv) | |||
52 | if (output[0] != '-' || output[1]) { | 52 | if (output[0] != '-' || output[1]) { |
53 | // Won't work with "uniq - FILE" and closed stdin: | 53 | // Won't work with "uniq - FILE" and closed stdin: |
54 | //close(STDOUT_FILENO); | 54 | //close(STDOUT_FILENO); |
55 | //xopen3(output, O_WRONLY | O_CREAT | O_TRUNC, 0666); | 55 | //xopen(output, O_WRONLY | O_CREAT | O_TRUNC); |
56 | xmove_fd(xopen3(output, O_WRONLY | O_CREAT | O_TRUNC, 0666), STDOUT_FILENO); | 56 | xmove_fd(xopen(output, O_WRONLY | O_CREAT | O_TRUNC), STDOUT_FILENO); |
57 | } | 57 | } |
58 | } | 58 | } |
59 | } | 59 | } |
diff --git a/coreutils/uudecode.c b/coreutils/uudecode.c index 0da9b0988..0c4311f24 100644 --- a/coreutils/uudecode.c +++ b/coreutils/uudecode.c | |||
@@ -13,7 +13,7 @@ | |||
13 | #include "libbb.h" | 13 | #include "libbb.h" |
14 | 14 | ||
15 | #if ENABLE_UUDECODE | 15 | #if ENABLE_UUDECODE |
16 | static void read_stduu(FILE *src_stream, FILE *dst_stream) | 16 | static void FAST_FUNC read_stduu(FILE *src_stream, FILE *dst_stream, int flags UNUSED_PARAM) |
17 | { | 17 | { |
18 | char *line; | 18 | char *line; |
19 | 19 | ||
@@ -75,71 +75,6 @@ static void read_stduu(FILE *src_stream, FILE *dst_stream) | |||
75 | } | 75 | } |
76 | #endif | 76 | #endif |
77 | 77 | ||
78 | static void read_base64(FILE *src_stream, FILE *dst_stream) | ||
79 | { | ||
80 | int term_count = 0; | ||
81 | |||
82 | while (1) { | ||
83 | unsigned char translated[4]; | ||
84 | int count = 0; | ||
85 | |||
86 | /* Process one group of 4 chars */ | ||
87 | while (count < 4) { | ||
88 | char *table_ptr; | ||
89 | int ch; | ||
90 | |||
91 | /* Get next _valid_ character. | ||
92 | * bb_uuenc_tbl_base64[] contains this string: | ||
93 | * 0 1 2 3 4 5 6 | ||
94 | * 012345678901234567890123456789012345678901234567890123456789012345 | ||
95 | * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n" | ||
96 | */ | ||
97 | do { | ||
98 | ch = fgetc(src_stream); | ||
99 | if (ch == EOF) { | ||
100 | if (ENABLE_BASE64 | ||
101 | && (!ENABLE_UUDECODE || applet_name[0] == 'b') | ||
102 | && count == 0 | ||
103 | ) { | ||
104 | return; | ||
105 | } | ||
106 | bb_error_msg_and_die("short file"); | ||
107 | } | ||
108 | table_ptr = strchr(bb_uuenc_tbl_base64, ch); | ||
109 | } while (!table_ptr); | ||
110 | |||
111 | /* Convert encoded character to decimal */ | ||
112 | ch = table_ptr - bb_uuenc_tbl_base64; | ||
113 | |||
114 | if (ch == 65 /* '\n' */) { | ||
115 | /* Terminating "====" line? */ | ||
116 | if (term_count == 4) | ||
117 | return; /* yes */ | ||
118 | term_count = 0; | ||
119 | continue; | ||
120 | } | ||
121 | /* ch is 64 is char was '=', otherwise 0..63 */ | ||
122 | translated[count] = ch & 63; /* 64 -> 0 */ | ||
123 | if (ch == 64) { | ||
124 | term_count++; | ||
125 | break; | ||
126 | } | ||
127 | count++; | ||
128 | } | ||
129 | |||
130 | /* Merge 6 bit chars to 8 bit. | ||
131 | * count can be < 4 when we decode the tail: | ||
132 | * "eQ==" -> "y", not "y NUL NUL" | ||
133 | */ | ||
134 | if (count > 1) | ||
135 | fputc(translated[0] << 2 | translated[1] >> 4, dst_stream); | ||
136 | if (count > 2) | ||
137 | fputc(translated[1] << 4 | translated[2] >> 2, dst_stream); | ||
138 | if (count > 3) | ||
139 | fputc(translated[2] << 6 | translated[3], dst_stream); | ||
140 | } /* while (1) */ | ||
141 | } | ||
142 | |||
143 | #if ENABLE_UUDECODE | 78 | #if ENABLE_UUDECODE |
144 | int uudecode_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 79 | int uudecode_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
145 | int uudecode_main(int argc UNUSED_PARAM, char **argv) | 80 | int uudecode_main(int argc UNUSED_PARAM, char **argv) |
@@ -158,7 +93,7 @@ int uudecode_main(int argc UNUSED_PARAM, char **argv) | |||
158 | 93 | ||
159 | /* Search for the start of the encoding */ | 94 | /* Search for the start of the encoding */ |
160 | while ((line = xmalloc_fgetline(src_stream)) != NULL) { | 95 | while ((line = xmalloc_fgetline(src_stream)) != NULL) { |
161 | void (*decode_fn_ptr)(FILE *src, FILE *dst); | 96 | void FAST_FUNC (*decode_fn_ptr)(FILE *src, FILE *dst, int flags); |
162 | char *line_ptr; | 97 | char *line_ptr; |
163 | FILE *dst_stream; | 98 | FILE *dst_stream; |
164 | int mode; | 99 | int mode; |
@@ -189,7 +124,7 @@ int uudecode_main(int argc UNUSED_PARAM, char **argv) | |||
189 | fchmod(fileno(dst_stream), mode & (S_IRWXU | S_IRWXG | S_IRWXO)); | 124 | fchmod(fileno(dst_stream), mode & (S_IRWXU | S_IRWXG | S_IRWXO)); |
190 | } | 125 | } |
191 | free(line); | 126 | free(line); |
192 | decode_fn_ptr(src_stream, dst_stream); | 127 | decode_fn_ptr(src_stream, dst_stream, /*flags:*/ BASE64_FLAG_UU_STOP + BASE64_FLAG_NO_STOP_CHAR); |
193 | /* fclose_if_not_stdin(src_stream); - redundant */ | 128 | /* fclose_if_not_stdin(src_stream); - redundant */ |
194 | return EXIT_SUCCESS; | 129 | return EXIT_SUCCESS; |
195 | } | 130 | } |
@@ -231,7 +166,7 @@ int base64_main(int argc UNUSED_PARAM, char **argv) | |||
231 | *--argv = (char*)"-"; | 166 | *--argv = (char*)"-"; |
232 | src_stream = xfopen_stdin(argv[0]); | 167 | src_stream = xfopen_stdin(argv[0]); |
233 | if (opts) { | 168 | if (opts) { |
234 | read_base64(src_stream, stdout); | 169 | read_base64(src_stream, stdout, /*flags:*/ (char)EOF); |
235 | } else { | 170 | } else { |
236 | enum { | 171 | enum { |
237 | SRC_BUF_SIZE = 76/4*3, /* This *MUST* be a multiple of 3 */ | 172 | SRC_BUF_SIZE = 76/4*3, /* This *MUST* be a multiple of 3 */ |
diff --git a/coreutils/wc.c b/coreutils/wc.c index 4f14374c3..ecadae59b 100644 --- a/coreutils/wc.c +++ b/coreutils/wc.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | /* BB_AUDIT SUSv3 _NOT_ compliant -- option -m is not currently supported. */ | 10 | /* BB_AUDIT SUSv3 compliant. */ |
11 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/wc.html */ | 11 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/wc.html */ |
12 | 12 | ||
13 | /* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) | 13 | /* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) |
@@ -19,10 +19,6 @@ | |||
19 | * 3) no checking of ferror on EOF returns | 19 | * 3) no checking of ferror on EOF returns |
20 | * 4) isprint() wasn't considered when word counting. | 20 | * 4) isprint() wasn't considered when word counting. |
21 | * | 21 | * |
22 | * TODO: | ||
23 | * | ||
24 | * When locale support is enabled, count multibyte chars in the '-m' case. | ||
25 | * | ||
26 | * NOTES: | 22 | * NOTES: |
27 | * | 23 | * |
28 | * The previous busybox wc attempted an optimization using stat for the | 24 | * The previous busybox wc attempted an optimization using stat for the |
@@ -40,8 +36,8 @@ | |||
40 | * | 36 | * |
41 | * for which 'wc -c' should output '0'. | 37 | * for which 'wc -c' should output '0'. |
42 | */ | 38 | */ |
43 | |||
44 | #include "libbb.h" | 39 | #include "libbb.h" |
40 | #include "unicode.h" | ||
45 | 41 | ||
46 | #if !ENABLE_LOCALE_SUPPORT | 42 | #if !ENABLE_LOCALE_SUPPORT |
47 | # undef isprint | 43 | # undef isprint |
@@ -58,11 +54,39 @@ | |||
58 | # define COUNT_FMT "u" | 54 | # define COUNT_FMT "u" |
59 | #endif | 55 | #endif |
60 | 56 | ||
57 | /* We support -m even when UNICODE_SUPPORT is off, | ||
58 | * we just don't advertise it in help text, | ||
59 | * since it is the same as -c in this case. | ||
60 | */ | ||
61 | |||
62 | //usage:#define wc_trivial_usage | ||
63 | //usage: "[-c"IF_UNICODE_SUPPORT("m")"lwL] [FILE]..." | ||
64 | //usage: | ||
65 | //usage:#define wc_full_usage "\n\n" | ||
66 | //usage: "Count lines, words, and bytes for each FILE (or stdin)\n" | ||
67 | //usage: "\nOptions:" | ||
68 | //usage: "\n -c Count bytes" | ||
69 | //usage: IF_UNICODE_SUPPORT( | ||
70 | //usage: "\n -m Count characters" | ||
71 | //usage: ) | ||
72 | //usage: "\n -l Count newlines" | ||
73 | //usage: "\n -w Count words" | ||
74 | //usage: "\n -L Print longest line length" | ||
75 | //usage: | ||
76 | //usage:#define wc_example_usage | ||
77 | //usage: "$ wc /etc/passwd\n" | ||
78 | //usage: " 31 46 1365 /etc/passwd\n" | ||
79 | |||
80 | /* Order is important if we want to be compatible with | ||
81 | * column order in "wc -cmlwL" output: | ||
82 | */ | ||
61 | enum { | 83 | enum { |
62 | WC_LINES = 0, | 84 | WC_LINES = 0, |
63 | WC_WORDS = 1, | 85 | WC_WORDS = 1, |
64 | WC_CHARS = 2, | 86 | WC_UNICHARS = 2, |
65 | WC_LENGTH = 3 | 87 | WC_CHARS = 3, |
88 | WC_LENGTH = 4, | ||
89 | NUM_WCS = 5, | ||
66 | }; | 90 | }; |
67 | 91 | ||
68 | int wc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 92 | int wc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
@@ -72,13 +96,15 @@ int wc_main(int argc UNUSED_PARAM, char **argv) | |||
72 | const char *start_fmt = " %9"COUNT_FMT + 1; | 96 | const char *start_fmt = " %9"COUNT_FMT + 1; |
73 | const char *fname_fmt = " %s\n"; | 97 | const char *fname_fmt = " %s\n"; |
74 | COUNT_T *pcounts; | 98 | COUNT_T *pcounts; |
75 | COUNT_T counts[4]; | 99 | COUNT_T counts[NUM_WCS]; |
76 | COUNT_T totals[4]; | 100 | COUNT_T totals[NUM_WCS]; |
77 | int num_files; | 101 | int num_files; |
78 | smallint status = EXIT_SUCCESS; | 102 | smallint status = EXIT_SUCCESS; |
79 | unsigned print_type; | 103 | unsigned print_type; |
80 | 104 | ||
81 | print_type = getopt32(argv, "lwcL"); | 105 | init_unicode(); |
106 | |||
107 | print_type = getopt32(argv, "lwcmL"); | ||
82 | 108 | ||
83 | if (print_type == 0) { | 109 | if (print_type == 0) { |
84 | print_type = (1 << WC_LINES) | (1 << WC_WORDS) | (1 << WC_CHARS); | 110 | print_type = (1 << WC_LINES) | (1 << WC_WORDS) | (1 << WC_CHARS); |
@@ -99,7 +125,7 @@ int wc_main(int argc UNUSED_PARAM, char **argv) | |||
99 | pcounts = counts; | 125 | pcounts = counts; |
100 | 126 | ||
101 | num_files = 0; | 127 | num_files = 0; |
102 | while ((arg = *argv++) != 0) { | 128 | while ((arg = *argv++) != NULL) { |
103 | FILE *fp; | 129 | FILE *fp; |
104 | const char *s; | 130 | const char *s; |
105 | unsigned u; | 131 | unsigned u; |
@@ -117,21 +143,28 @@ int wc_main(int argc UNUSED_PARAM, char **argv) | |||
117 | linepos = 0; | 143 | linepos = 0; |
118 | in_word = 0; | 144 | in_word = 0; |
119 | 145 | ||
120 | do { | 146 | while (1) { |
121 | int c; | 147 | int c; |
122 | /* Our -w doesn't match GNU wc exactly... oh well */ | 148 | /* Our -w doesn't match GNU wc exactly... oh well */ |
123 | 149 | ||
124 | ++counts[WC_CHARS]; | ||
125 | c = getc(fp); | 150 | c = getc(fp); |
126 | if (c == EOF) { | 151 | if (c == EOF) { |
127 | if (ferror(fp)) { | 152 | if (ferror(fp)) { |
128 | bb_simple_perror_msg(arg); | 153 | bb_simple_perror_msg(arg); |
129 | status = EXIT_FAILURE; | 154 | status = EXIT_FAILURE; |
130 | } | 155 | } |
131 | --counts[WC_CHARS]; | ||
132 | goto DO_EOF; /* Treat an EOF as '\r'. */ | 156 | goto DO_EOF; /* Treat an EOF as '\r'. */ |
133 | } | 157 | } |
134 | if (isprint_asciionly(c)) { | 158 | |
159 | /* Cater for -c and -m */ | ||
160 | ++counts[WC_CHARS]; | ||
161 | if (unicode_status != UNICODE_ON /* every byte is a new char */ | ||
162 | || (c & 0xc0) != 0x80 /* it isn't a 2nd+ byte of a Unicode char */ | ||
163 | ) { | ||
164 | ++counts[WC_UNICHARS]; | ||
165 | } | ||
166 | |||
167 | if (isprint_asciionly(c)) { /* FIXME: not unicode-aware */ | ||
135 | ++linepos; | 168 | ++linepos; |
136 | if (!isspace(c)) { | 169 | if (!isspace(c)) { |
137 | in_word = 1; | 170 | in_word = 1; |
@@ -167,18 +200,18 @@ int wc_main(int argc UNUSED_PARAM, char **argv) | |||
167 | if (c == EOF) { | 200 | if (c == EOF) { |
168 | break; | 201 | break; |
169 | } | 202 | } |
170 | } while (1); | 203 | } |
204 | |||
205 | fclose_if_not_stdin(fp); | ||
171 | 206 | ||
172 | if (totals[WC_LENGTH] < counts[WC_LENGTH]) { | 207 | if (totals[WC_LENGTH] < counts[WC_LENGTH]) { |
173 | totals[WC_LENGTH] = counts[WC_LENGTH]; | 208 | totals[WC_LENGTH] = counts[WC_LENGTH]; |
174 | } | 209 | } |
175 | totals[WC_LENGTH] -= counts[WC_LENGTH]; | 210 | totals[WC_LENGTH] -= counts[WC_LENGTH]; |
176 | 211 | ||
177 | fclose_if_not_stdin(fp); | ||
178 | |||
179 | OUTPUT: | 212 | OUTPUT: |
180 | /* coreutils wc tries hard to print pretty columns | 213 | /* coreutils wc tries hard to print pretty columns |
181 | * (saves results for all files, find max col len etc...) | 214 | * (saves results for all files, finds max col len etc...) |
182 | * we won't try that hard, it will bloat us too much */ | 215 | * we won't try that hard, it will bloat us too much */ |
183 | s = start_fmt; | 216 | s = start_fmt; |
184 | u = 0; | 217 | u = 0; |
@@ -188,7 +221,7 @@ int wc_main(int argc UNUSED_PARAM, char **argv) | |||
188 | s = " %9"COUNT_FMT; /* Ok... restore the leading space. */ | 221 | s = " %9"COUNT_FMT; /* Ok... restore the leading space. */ |
189 | } | 222 | } |
190 | totals[u] += pcounts[u]; | 223 | totals[u] += pcounts[u]; |
191 | } while (++u < 4); | 224 | } while (++u < NUM_WCS); |
192 | printf(fname_fmt, arg); | 225 | printf(fname_fmt, arg); |
193 | } | 226 | } |
194 | 227 | ||
diff --git a/docs/busybox_footer.pod b/docs/busybox_footer.pod index 47eabaeeb..c346c736b 100644 --- a/docs/busybox_footer.pod +++ b/docs/busybox_footer.pod | |||
@@ -252,4 +252,34 @@ Tito Ragusa <farmatito@tiscali.it> | |||
252 | 252 | ||
253 | devfsd and size optimizations in strings, openvt and deallocvt. | 253 | devfsd and size optimizations in strings, openvt and deallocvt. |
254 | 254 | ||
255 | =for html <br> | ||
256 | |||
257 | Paul Fox <pgf@foxharp.boston.ma.us> | ||
258 | |||
259 | vi editing mode for ash, various other patches/fixes | ||
260 | |||
261 | =for html <br> | ||
262 | |||
263 | Roberto A. Foglietta <me@roberto.foglietta.name> | ||
264 | |||
265 | port: dnsd | ||
266 | |||
267 | =for html <br> | ||
268 | |||
269 | Bernhard Reutner-Fischer <rep.dot.nop@gmail.com> | ||
270 | |||
271 | misc | ||
272 | |||
273 | =for html <br> | ||
274 | |||
275 | Mike Frysinger <vapier@gentoo.org> | ||
276 | |||
277 | initial e2fsprogs, printenv, setarch, sum, misc | ||
278 | |||
279 | =for html <br> | ||
280 | |||
281 | Jie Zhang <jie.zhang@analog.com> | ||
282 | |||
283 | fixed two bugs in msh and hush (exitcode of killed processes) | ||
284 | |||
255 | =cut | 285 | =cut |
diff --git a/docs/contributing.txt b/docs/contributing.txt index 39aaef1b5..e3289fd49 100644 --- a/docs/contributing.txt +++ b/docs/contributing.txt | |||
@@ -229,8 +229,11 @@ Here are some guidelines on how to submit a patch to Busybox. | |||
229 | Making A Patch | 229 | Making A Patch |
230 | ~~~~~~~~~~~~~~ | 230 | ~~~~~~~~~~~~~~ |
231 | 231 | ||
232 | If you've got anonymous CVS access set up, making a patch is simple. Just make | 232 | If you've got anonymous Git access set up, making a patch is simple. Just make |
233 | sure you're in the busybox/ directory and type 'cvs diff -bwu > mychanges.patch'. | 233 | sure you're in the busybox/ directory and type: |
234 | |||
235 | git diff -b -w > mychanges.patch | ||
236 | |||
234 | You can send the resulting .patch file to the mailing list with a description | 237 | You can send the resulting .patch file to the mailing list with a description |
235 | of what it does. (But not before you test it! See the next section for some | 238 | of what it does. (But not before you test it! See the next section for some |
236 | guidelines.) It is preferred that patches be sent as attachments, but it is | 239 | guidelines.) It is preferred that patches be sent as attachments, but it is |
@@ -238,8 +241,12 @@ not required. | |||
238 | 241 | ||
239 | Also, feel free to help test other people's patches and reply to them with | 242 | Also, feel free to help test other people's patches and reply to them with |
240 | comments. You can apply a patch by saving it into your busybox/ directory and | 243 | comments. You can apply a patch by saving it into your busybox/ directory and |
241 | typing 'patch < mychanges.patch'. Then you can recompile, see if it runs, test | 244 | typing: |
242 | if it works as advertised, and post your findings to the mailing list. | 245 | |
246 | patch -p1 < mychanges.patch | ||
247 | |||
248 | Then you can recompile, see if it runs, test if it works as advertised, and | ||
249 | post your findings to the mailing list. | ||
243 | 250 | ||
244 | NOTE: Please do not include extraneous or irrelevant changes in your patches. | 251 | NOTE: Please do not include extraneous or irrelevant changes in your patches. |
245 | Please do not try to "bundle" two patches together into one. Make single, | 252 | Please do not try to "bundle" two patches together into one. Make single, |
@@ -252,7 +259,7 @@ Testing Guidelines | |||
252 | ~~~~~~~~~~~~~~~~~~ | 259 | ~~~~~~~~~~~~~~~~~~ |
253 | 260 | ||
254 | It's considered good form to test your new feature before you submit a patch | 261 | It's considered good form to test your new feature before you submit a patch |
255 | to the mailing list, and especially before you commit a change to CVS. Here | 262 | to the mailing list, and especially before you push a change to Git. Here |
256 | are some guidelines on how to test your changes. | 263 | are some guidelines on how to test your changes. |
257 | 264 | ||
258 | - Always test Busybox applets against GNU counterparts and make sure the | 265 | - Always test Busybox applets against GNU counterparts and make sure the |
@@ -348,7 +355,7 @@ responses from queries to applet maintainer or positive responses from folks | |||
348 | on the mailing list. | 355 | on the mailing list. |
349 | 356 | ||
350 | We've made strident efforts to put a useful "collaboration" infrastructure in | 357 | We've made strident efforts to put a useful "collaboration" infrastructure in |
351 | place in the form of mailing lists, the bug tracking system, and CVS. Please | 358 | place in the form of mailing lists, the bug tracking system, and Git. Please |
352 | use these resources. | 359 | use these resources. |
353 | 360 | ||
354 | 361 | ||
@@ -373,39 +380,43 @@ opposite effect. | |||
373 | 380 | ||
374 | 381 | ||
375 | 382 | ||
376 | Committing Changes to CVS | 383 | Pushing Changes to Git |
377 | ------------------------- | 384 | ---------------------- |
378 | 385 | ||
379 | If you submit several patches that demonstrate that you are a skilled and wise | 386 | If you submit several patches that demonstrate that you are a skilled and wise |
380 | coder, you may be invited to become a committer, thus enabling you to commit | 387 | coder, you may be invited to become a committer, thus enabling you to push |
381 | changes directly to CVS. This is nice because you don't have to wait for | 388 | changes directly to Git. This is nice because you don't have to wait for |
382 | someone else to commit your change for you, you can just do it yourself. | 389 | someone else to push your change for you, you can just do it yourself. |
383 | 390 | ||
384 | But note that this is a privilege that comes with some responsibilities. You | 391 | But note that this is a privilege that comes with some responsibilities. You |
385 | should test your changes before you commit them. You should also talk to an | 392 | should test your changes before you push them. You should also talk to an |
386 | applet maintainer before you make any kind of sweeping changes to somebody | 393 | applet maintainer before you make any kind of sweeping changes to somebody |
387 | else's code. Big changes should still go to the mailing list first. Remember, | 394 | else's code. Big changes should still go to the mailing list first. Remember, |
388 | being wise, polite, and discreet is more important than being clever. | 395 | being wise, polite, and discreet is more important than being clever. |
389 | 396 | ||
397 | For more information on Git push access, see: | ||
390 | 398 | ||
391 | When To Commit | 399 | http://busybox.net/developer.html |
392 | ~~~~~~~~~~~~~~ | ||
393 | 400 | ||
394 | Generally, you should feel free to commit a change if: | 401 | |
402 | When To Push | ||
403 | ~~~~~~~~~~~~ | ||
404 | |||
405 | Generally, you should feel free to push a change if: | ||
395 | 406 | ||
396 | - Your changes are small and don't touch many files | 407 | - Your changes are small and don't touch many files |
397 | - You are fixing a bug | 408 | - You are fixing a bug |
398 | - Somebody has told you that it's okay | 409 | - Somebody has told you that it's okay |
399 | - It's obviously the Right Thing | 410 | - It's obviously the Right Thing |
400 | 411 | ||
401 | The more of the above are true, the better it is to just commit a change | 412 | The more of the above are true, the better it is to just push a change |
402 | directly to CVS. | 413 | directly to Git. |
403 | 414 | ||
404 | 415 | ||
405 | When Not To Commit | 416 | When Not To Push |
406 | ~~~~~~~~~~~~~~~~~~ | 417 | ~~~~~~~~~~~~~~~~ |
407 | 418 | ||
408 | Even if you have commit rights, you should probably still post a patch to the | 419 | Even if you have push access, you should probably still post a patch to the |
409 | mailing list if: | 420 | mailing list if: |
410 | 421 | ||
411 | - Your changes are broad and touch many different files | 422 | - Your changes are broad and touch many different files |
@@ -414,7 +425,7 @@ mailing list if: | |||
414 | - You are not the maintainer and your changes make the maintainer cringe | 425 | - You are not the maintainer and your changes make the maintainer cringe |
415 | 426 | ||
416 | The more of the above are true, the better it is to post a patch to the | 427 | The more of the above are true, the better it is to post a patch to the |
417 | mailing list instead of committing. | 428 | mailing list instead of pushing. |
418 | 429 | ||
419 | 430 | ||
420 | 431 | ||
diff --git a/e2fsprogs/tune2fs.c b/e2fsprogs/tune2fs.c index 311349fec..75e4f6bcf 100644 --- a/e2fsprogs/tune2fs.c +++ b/e2fsprogs/tune2fs.c | |||
@@ -27,24 +27,40 @@ do { \ | |||
27 | #define FETCH_LE32(field) \ | 27 | #define FETCH_LE32(field) \ |
28 | (sizeof(field) == 4 ? SWAP_LE32(field) : BUG_wrong_field_size()) | 28 | (sizeof(field) == 4 ? SWAP_LE32(field) : BUG_wrong_field_size()) |
29 | 29 | ||
30 | //usage:#define tune2fs_trivial_usage | ||
31 | //usage: "[-c MOUNT_CNT] " | ||
32 | ////usage: "[-e errors-behavior] [-g group] " | ||
33 | //usage: "[-i DAYS] " | ||
34 | ////usage: "[-j] [-J journal-options] [-l] [-s sparse-flag] " | ||
35 | ////usage: "[-m reserved-blocks-percent] [-o [^]mount-options[,...]] " | ||
36 | ////usage: "[-r reserved-blocks-count] [-u user] [-C mount-count] " | ||
37 | //usage: "[-L LABEL] " | ||
38 | ////usage: "[-M last-mounted-dir] [-O [^]feature[,...]] " | ||
39 | ////usage: "[-T last-check-time] [-U UUID] " | ||
40 | //usage: "BLOCKDEV" | ||
41 | //usage: | ||
42 | //usage:#define tune2fs_full_usage "\n\n" | ||
43 | //usage: "Adjust filesystem options on ext[23] filesystems" | ||
44 | |||
30 | enum { | 45 | enum { |
31 | OPT_L = 1 << 0, // label | 46 | OPT_L = 1 << 0, // label |
47 | OPT_c = 1 << 1, // max mount count | ||
48 | OPT_i = 1 << 2, // check interval | ||
32 | }; | 49 | }; |
33 | 50 | ||
34 | int tune2fs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 51 | int tune2fs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
35 | int tune2fs_main(int argc UNUSED_PARAM, char **argv) | 52 | int tune2fs_main(int argc UNUSED_PARAM, char **argv) |
36 | { | 53 | { |
37 | unsigned opts; | 54 | unsigned opts; |
38 | const char *label; | 55 | const char *label, *str_c, *str_i; |
39 | struct ext2_super_block *sb; | 56 | struct ext2_super_block *sb; |
40 | int fd; | 57 | int fd; |
41 | 58 | ||
42 | opt_complementary = "=1"; | 59 | opt_complementary = "=1"; |
43 | opts = getopt32(argv, "L:", &label); | 60 | opts = getopt32(argv, "L:c:i:", &label, &str_c, &str_i); |
44 | argv += optind; // argv[0] -- device | ||
45 | |||
46 | if (!opts) | 61 | if (!opts) |
47 | bb_show_usage(); | 62 | bb_show_usage(); |
63 | argv += optind; // argv[0] -- device | ||
48 | 64 | ||
49 | // read superblock | 65 | // read superblock |
50 | fd = xopen(argv[0], O_RDWR); | 66 | fd = xopen(argv[0], O_RDWR); |
@@ -54,9 +70,23 @@ int tune2fs_main(int argc UNUSED_PARAM, char **argv) | |||
54 | 70 | ||
55 | // mangle superblock | 71 | // mangle superblock |
56 | //STORE_LE(sb->s_wtime, time(NULL)); - why bother? | 72 | //STORE_LE(sb->s_wtime, time(NULL)); - why bother? |
73 | |||
57 | // set the label | 74 | // set the label |
58 | if (1 /*opts & OPT_L*/) | 75 | if (opts & OPT_L) |
59 | safe_strncpy((char *)sb->s_volume_name, label, sizeof(sb->s_volume_name)); | 76 | safe_strncpy((char *)sb->s_volume_name, label, sizeof(sb->s_volume_name)); |
77 | |||
78 | if (opts & OPT_c) { | ||
79 | int n = xatoi_range(str_c, -1, 0xfffe); | ||
80 | if (n == 0) | ||
81 | n = -1; | ||
82 | STORE_LE(sb->s_max_mnt_count, (unsigned)n); | ||
83 | } | ||
84 | |||
85 | if (opts & OPT_i) { | ||
86 | unsigned n = xatou_range(str_i, 0, (unsigned)0xffffffff / (24*60*60)) * 24*60*60; | ||
87 | STORE_LE(sb->s_checkinterval, n); | ||
88 | } | ||
89 | |||
60 | // write superblock | 90 | // write superblock |
61 | xlseek(fd, 1024, SEEK_SET); | 91 | xlseek(fd, 1024, SEEK_SET); |
62 | xwrite(fd, sb, 1024); | 92 | xwrite(fd, sb, 1024); |
diff --git a/editors/awk.c b/editors/awk.c index f47d1ab02..2245cad03 100644 --- a/editors/awk.c +++ b/editors/awk.c | |||
@@ -17,10 +17,14 @@ | |||
17 | /* If you comment out one of these below, it will be #defined later | 17 | /* If you comment out one of these below, it will be #defined later |
18 | * to perform debug printfs to stderr: */ | 18 | * to perform debug printfs to stderr: */ |
19 | #define debug_printf_walker(...) do {} while (0) | 19 | #define debug_printf_walker(...) do {} while (0) |
20 | #define debug_printf_eval(...) do {} while (0) | ||
20 | 21 | ||
21 | #ifndef debug_printf_walker | 22 | #ifndef debug_printf_walker |
22 | # define debug_printf_walker(...) (fprintf(stderr, __VA_ARGS__)) | 23 | # define debug_printf_walker(...) (fprintf(stderr, __VA_ARGS__)) |
23 | #endif | 24 | #endif |
25 | #ifndef debug_printf_eval | ||
26 | # define debug_printf_eval(...) (fprintf(stderr, __VA_ARGS__)) | ||
27 | #endif | ||
24 | 28 | ||
25 | 29 | ||
26 | 30 | ||
@@ -700,14 +704,27 @@ static ALWAYS_INLINE int isalnum_(int c) | |||
700 | 704 | ||
701 | static double my_strtod(char **pp) | 705 | static double my_strtod(char **pp) |
702 | { | 706 | { |
707 | char *cp = *pp; | ||
703 | #if ENABLE_DESKTOP | 708 | #if ENABLE_DESKTOP |
704 | if ((*pp)[0] == '0' | 709 | if (cp[0] == '0') { |
705 | && ((((*pp)[1] | 0x20) == 'x') || isdigit((*pp)[1])) | 710 | /* Might be hex or octal integer: 0x123abc or 07777 */ |
706 | ) { | 711 | char c = (cp[1] | 0x20); |
707 | return strtoull(*pp, pp, 0); | 712 | if (c == 'x' || isdigit(cp[1])) { |
713 | unsigned long long ull = strtoull(cp, pp, 0); | ||
714 | if (c == 'x') | ||
715 | return ull; | ||
716 | c = **pp; | ||
717 | if (!isdigit(c) && c != '.') | ||
718 | return ull; | ||
719 | /* else: it may be a floating number. Examples: | ||
720 | * 009.123 (*pp points to '9') | ||
721 | * 000.123 (*pp points to '.') | ||
722 | * fall through to strtod. | ||
723 | */ | ||
724 | } | ||
708 | } | 725 | } |
709 | #endif | 726 | #endif |
710 | return strtod(*pp, pp); | 727 | return strtod(cp, pp); |
711 | } | 728 | } |
712 | 729 | ||
713 | /* -------- working with variables (set/get/copy/etc) -------- */ | 730 | /* -------- working with variables (set/get/copy/etc) -------- */ |
@@ -817,17 +834,21 @@ static double getvar_i(var *v) | |||
817 | v->number = 0; | 834 | v->number = 0; |
818 | s = v->string; | 835 | s = v->string; |
819 | if (s && *s) { | 836 | if (s && *s) { |
837 | debug_printf_eval("getvar_i: '%s'->", s); | ||
820 | v->number = my_strtod(&s); | 838 | v->number = my_strtod(&s); |
839 | debug_printf_eval("%f (s:'%s')\n", v->number, s); | ||
821 | if (v->type & VF_USER) { | 840 | if (v->type & VF_USER) { |
822 | s = skip_spaces(s); | 841 | s = skip_spaces(s); |
823 | if (*s != '\0') | 842 | if (*s != '\0') |
824 | v->type &= ~VF_USER; | 843 | v->type &= ~VF_USER; |
825 | } | 844 | } |
826 | } else { | 845 | } else { |
846 | debug_printf_eval("getvar_i: '%s'->zero\n", s); | ||
827 | v->type &= ~VF_USER; | 847 | v->type &= ~VF_USER; |
828 | } | 848 | } |
829 | v->type |= VF_CACHED; | 849 | v->type |= VF_CACHED; |
830 | } | 850 | } |
851 | debug_printf_eval("getvar_i: %f\n", v->number); | ||
831 | return v->number; | 852 | return v->number; |
832 | } | 853 | } |
833 | 854 | ||
@@ -849,6 +870,7 @@ static var *copyvar(var *dest, const var *src) | |||
849 | if (dest != src) { | 870 | if (dest != src) { |
850 | clrvar(dest); | 871 | clrvar(dest); |
851 | dest->type |= (src->type & ~(VF_DONTTOUCH | VF_FSTR)); | 872 | dest->type |= (src->type & ~(VF_DONTTOUCH | VF_FSTR)); |
873 | debug_printf_eval("copyvar: number:%f string:'%s'\n", src->number, src->string); | ||
852 | dest->number = src->number; | 874 | dest->number = src->number; |
853 | if (src->string) | 875 | if (src->string) |
854 | dest->string = xstrdup(src->string); | 876 | dest->string = xstrdup(src->string); |
@@ -965,7 +987,6 @@ static uint32_t next_token(uint32_t expected) | |||
965 | const char *tl; | 987 | const char *tl; |
966 | uint32_t tc; | 988 | uint32_t tc; |
967 | const uint32_t *ti; | 989 | const uint32_t *ti; |
968 | int l; | ||
969 | 990 | ||
970 | if (t_rollback) { | 991 | if (t_rollback) { |
971 | t_rollback = FALSE; | 992 | t_rollback = FALSE; |
@@ -1031,7 +1052,7 @@ static uint32_t next_token(uint32_t expected) | |||
1031 | char *pp = p; | 1052 | char *pp = p; |
1032 | t_double = my_strtod(&pp); | 1053 | t_double = my_strtod(&pp); |
1033 | p = pp; | 1054 | p = pp; |
1034 | if (*pp == '.') | 1055 | if (*p == '.') |
1035 | syntax_error(EMSG_UNEXP_TOKEN); | 1056 | syntax_error(EMSG_UNEXP_TOKEN); |
1036 | tc = TC_NUMBER; | 1057 | tc = TC_NUMBER; |
1037 | 1058 | ||
@@ -1041,52 +1062,51 @@ static uint32_t next_token(uint32_t expected) | |||
1041 | tc = 0x00000001; | 1062 | tc = 0x00000001; |
1042 | ti = tokeninfo; | 1063 | ti = tokeninfo; |
1043 | while (*tl) { | 1064 | while (*tl) { |
1044 | l = *tl++; | 1065 | int l = (unsigned char) *tl++; |
1045 | if (l == NTCC) { | 1066 | if (l == (unsigned char) NTCC) { |
1046 | tc <<= 1; | 1067 | tc <<= 1; |
1047 | continue; | 1068 | continue; |
1048 | } | 1069 | } |
1049 | /* if token class is expected, token | 1070 | /* if token class is expected, |
1050 | * matches and it's not a longer word, | 1071 | * token matches, |
1051 | * then this is what we are looking for | 1072 | * and it's not a longer word, |
1052 | */ | 1073 | */ |
1053 | if ((tc & (expected | TC_WORD | TC_NEWLINE)) | 1074 | if ((tc & (expected | TC_WORD | TC_NEWLINE)) |
1054 | && *tl == *p && strncmp(p, tl, l) == 0 | 1075 | && strncmp(p, tl, l) == 0 |
1055 | && !((tc & TC_WORD) && isalnum_(p[l])) | 1076 | && !((tc & TC_WORD) && isalnum_(p[l])) |
1056 | ) { | 1077 | ) { |
1078 | /* then this is what we are looking for */ | ||
1057 | t_info = *ti; | 1079 | t_info = *ti; |
1058 | p += l; | 1080 | p += l; |
1059 | break; | 1081 | goto token_found; |
1060 | } | 1082 | } |
1061 | ti++; | 1083 | ti++; |
1062 | tl += l; | 1084 | tl += l; |
1063 | } | 1085 | } |
1064 | 1086 | /* not a known token */ | |
1065 | if (!*tl) { | 1087 | |
1066 | /* it's a name (var/array/function), | 1088 | /* is it a name? (var/array/function) */ |
1067 | * otherwise it's something wrong | 1089 | if (!isalnum_(*p)) |
1068 | */ | 1090 | syntax_error(EMSG_UNEXP_TOKEN); /* no */ |
1069 | if (!isalnum_(*p)) | 1091 | /* yes */ |
1070 | syntax_error(EMSG_UNEXP_TOKEN); | 1092 | t_string = --p; |
1071 | 1093 | while (isalnum_(*++p)) { | |
1072 | t_string = --p; | 1094 | p[-1] = *p; |
1073 | while (isalnum_(*++p)) { | 1095 | } |
1074 | p[-1] = *p; | 1096 | p[-1] = '\0'; |
1075 | } | 1097 | tc = TC_VARIABLE; |
1076 | p[-1] = '\0'; | 1098 | /* also consume whitespace between functionname and bracket */ |
1077 | tc = TC_VARIABLE; | 1099 | if (!(expected & TC_VARIABLE) || (expected & TC_ARRAY)) |
1078 | /* also consume whitespace between functionname and bracket */ | 1100 | p = skip_spaces(p); |
1079 | if (!(expected & TC_VARIABLE) || (expected & TC_ARRAY)) | 1101 | if (*p == '(') { |
1080 | p = skip_spaces(p); | 1102 | tc = TC_FUNCTION; |
1081 | if (*p == '(') { | 1103 | } else { |
1082 | tc = TC_FUNCTION; | 1104 | if (*p == '[') { |
1083 | } else { | 1105 | p++; |
1084 | if (*p == '[') { | 1106 | tc = TC_ARRAY; |
1085 | p++; | ||
1086 | tc = TC_ARRAY; | ||
1087 | } | ||
1088 | } | 1107 | } |
1089 | } | 1108 | } |
1109 | token_found: ; | ||
1090 | } | 1110 | } |
1091 | g_pos = p; | 1111 | g_pos = p; |
1092 | 1112 | ||
@@ -1164,6 +1184,7 @@ static node *parse_expr(uint32_t iexp) | |||
1164 | xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP | iexp; | 1184 | xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP | iexp; |
1165 | 1185 | ||
1166 | while (!((tc = next_token(xtc)) & iexp)) { | 1186 | while (!((tc = next_token(xtc)) & iexp)) { |
1187 | |||
1167 | if (glptr && (t_info == (OC_COMPARE | VV | P(39) | 2))) { | 1188 | if (glptr && (t_info == (OC_COMPARE | VV | P(39) | 2))) { |
1168 | /* input redirection (<) attached to glptr node */ | 1189 | /* input redirection (<) attached to glptr node */ |
1169 | cn = glptr->l.n = new_node(OC_CONCAT | SS | P(37)); | 1190 | cn = glptr->l.n = new_node(OC_CONCAT | SS | P(37)); |
@@ -1500,10 +1521,10 @@ static node *mk_splitter(const char *s, tsplitter *spl) | |||
1500 | regfree(re); | 1521 | regfree(re); |
1501 | regfree(ire); // TODO: nuke ire, use re+1? | 1522 | regfree(ire); // TODO: nuke ire, use re+1? |
1502 | } | 1523 | } |
1503 | if (strlen(s) > 1) { | 1524 | if (s[0] && s[1]) { /* strlen(s) > 1 */ |
1504 | mk_re_node(s, n, re); | 1525 | mk_re_node(s, n, re); |
1505 | } else { | 1526 | } else { |
1506 | n->info = (uint32_t) *s; | 1527 | n->info = (uint32_t) s[0]; |
1507 | } | 1528 | } |
1508 | 1529 | ||
1509 | return n; | 1530 | return n; |
@@ -1560,24 +1581,22 @@ static void fsrealloc(int size) | |||
1560 | if (size >= maxfields) { | 1581 | if (size >= maxfields) { |
1561 | i = maxfields; | 1582 | i = maxfields; |
1562 | maxfields = size + 16; | 1583 | maxfields = size + 16; |
1563 | Fields = xrealloc(Fields, maxfields * sizeof(var)); | 1584 | Fields = xrealloc(Fields, maxfields * sizeof(Fields[0])); |
1564 | for (; i < maxfields; i++) { | 1585 | for (; i < maxfields; i++) { |
1565 | Fields[i].type = VF_SPECIAL; | 1586 | Fields[i].type = VF_SPECIAL; |
1566 | Fields[i].string = NULL; | 1587 | Fields[i].string = NULL; |
1567 | } | 1588 | } |
1568 | } | 1589 | } |
1569 | 1590 | /* if size < nfields, clear extra field variables */ | |
1570 | if (size < nfields) { | 1591 | for (i = size; i < nfields; i++) { |
1571 | for (i = size; i < nfields; i++) { | 1592 | clrvar(Fields + i); |
1572 | clrvar(Fields + i); | ||
1573 | } | ||
1574 | } | 1593 | } |
1575 | nfields = size; | 1594 | nfields = size; |
1576 | } | 1595 | } |
1577 | 1596 | ||
1578 | static int awk_split(const char *s, node *spl, char **slist) | 1597 | static int awk_split(const char *s, node *spl, char **slist) |
1579 | { | 1598 | { |
1580 | int l, n = 0; | 1599 | int l, n; |
1581 | char c[4]; | 1600 | char c[4]; |
1582 | char *s1; | 1601 | char *s1; |
1583 | regmatch_t pmatch[2]; // TODO: why [2]? [1] is enough... | 1602 | regmatch_t pmatch[2]; // TODO: why [2]? [1] is enough... |
@@ -1591,6 +1610,7 @@ static int awk_split(const char *s, node *spl, char **slist) | |||
1591 | if (*getvar_s(intvar[RS]) == '\0') | 1610 | if (*getvar_s(intvar[RS]) == '\0') |
1592 | c[2] = '\n'; | 1611 | c[2] = '\n'; |
1593 | 1612 | ||
1613 | n = 0; | ||
1594 | if ((spl->info & OPCLSMASK) == OC_REGEXP) { /* regex split */ | 1614 | if ((spl->info & OPCLSMASK) == OC_REGEXP) { /* regex split */ |
1595 | if (!*s) | 1615 | if (!*s) |
1596 | return n; /* "": zero fields */ | 1616 | return n; /* "": zero fields */ |
@@ -1636,7 +1656,7 @@ static int awk_split(const char *s, node *spl, char **slist) | |||
1636 | } | 1656 | } |
1637 | if (*s1) | 1657 | if (*s1) |
1638 | n++; | 1658 | n++; |
1639 | while ((s1 = strpbrk(s1, c))) { | 1659 | while ((s1 = strpbrk(s1, c)) != NULL) { |
1640 | *s1++ = '\0'; | 1660 | *s1++ = '\0'; |
1641 | n++; | 1661 | n++; |
1642 | } | 1662 | } |
@@ -2347,18 +2367,25 @@ static var *evaluate(node *op, var *res) | |||
2347 | opn = (opinfo & OPNMASK); | 2367 | opn = (opinfo & OPNMASK); |
2348 | g_lineno = op->lineno; | 2368 | g_lineno = op->lineno; |
2349 | op1 = op->l.n; | 2369 | op1 = op->l.n; |
2370 | debug_printf_eval("opinfo:%08x opn:%08x XC:%x\n", opinfo, opn, XC(opinfo & OPCLSMASK)); | ||
2350 | 2371 | ||
2351 | /* execute inevitable things */ | 2372 | /* execute inevitable things */ |
2352 | if (opinfo & OF_RES1) | 2373 | if (opinfo & OF_RES1) |
2353 | L.v = evaluate(op1, v1); | 2374 | L.v = evaluate(op1, v1); |
2354 | if (opinfo & OF_RES2) | 2375 | if (opinfo & OF_RES2) |
2355 | R.v = evaluate(op->r.n, v1+1); | 2376 | R.v = evaluate(op->r.n, v1+1); |
2356 | if (opinfo & OF_STR1) | 2377 | if (opinfo & OF_STR1) { |
2357 | L.s = getvar_s(L.v); | 2378 | L.s = getvar_s(L.v); |
2358 | if (opinfo & OF_STR2) | 2379 | debug_printf_eval("L.s:'%s'\n", L.s); |
2380 | } | ||
2381 | if (opinfo & OF_STR2) { | ||
2359 | R.s = getvar_s(R.v); | 2382 | R.s = getvar_s(R.v); |
2360 | if (opinfo & OF_NUM1) | 2383 | debug_printf_eval("R.s:'%s'\n", R.s); |
2384 | } | ||
2385 | if (opinfo & OF_NUM1) { | ||
2361 | L_d = getvar_i(L.v); | 2386 | L_d = getvar_i(L.v); |
2387 | debug_printf_eval("L_d:%f\n", L_d); | ||
2388 | } | ||
2362 | 2389 | ||
2363 | switch (XC(opinfo & OPCLSMASK)) { | 2390 | switch (XC(opinfo & OPCLSMASK)) { |
2364 | 2391 | ||
@@ -2526,6 +2553,7 @@ static var *evaluate(node *op, var *res) | |||
2526 | break; | 2553 | break; |
2527 | 2554 | ||
2528 | case XC( OC_MOVE ): | 2555 | case XC( OC_MOVE ): |
2556 | debug_printf_eval("MOVE\n"); | ||
2529 | /* if source is a temporary string, jusk relink it to dest */ | 2557 | /* if source is a temporary string, jusk relink it to dest */ |
2530 | //Disabled: if R.v is numeric but happens to have cached R.v->string, | 2558 | //Disabled: if R.v is numeric but happens to have cached R.v->string, |
2531 | //then L.v ends up being a string, which is wrong | 2559 | //then L.v ends up being a string, which is wrong |
@@ -2777,6 +2805,7 @@ static var *evaluate(node *op, var *res) | |||
2777 | case XC( OC_BINARY ): | 2805 | case XC( OC_BINARY ): |
2778 | case XC( OC_REPLACE ): { | 2806 | case XC( OC_REPLACE ): { |
2779 | double R_d = getvar_i(R.v); | 2807 | double R_d = getvar_i(R.v); |
2808 | debug_printf_eval("BINARY/REPLACE: R_d:%f opn:%c\n", R_d, opn); | ||
2780 | switch (opn) { | 2809 | switch (opn) { |
2781 | case '+': | 2810 | case '+': |
2782 | L_d += R_d; | 2811 | L_d += R_d; |
@@ -2805,6 +2834,7 @@ static var *evaluate(node *op, var *res) | |||
2805 | L_d -= (int)(L_d / R_d) * R_d; | 2834 | L_d -= (int)(L_d / R_d) * R_d; |
2806 | break; | 2835 | break; |
2807 | } | 2836 | } |
2837 | debug_printf_eval("BINARY/REPLACE result:%f\n", L_d); | ||
2808 | res = setvar_i(((opinfo & OPCLSMASK) == OC_BINARY) ? res : L.v, L_d); | 2838 | res = setvar_i(((opinfo & OPCLSMASK) == OC_BINARY) ? res : L.v, L_d); |
2809 | break; | 2839 | break; |
2810 | } | 2840 | } |
diff --git a/editors/patch.c b/editors/patch.c index c40f54155..66a9474fe 100644 --- a/editors/patch.c +++ b/editors/patch.c | |||
@@ -344,14 +344,12 @@ static int apply_one_hunk(void) | |||
344 | while (plist && *plist->data == "+-"[reverse]) { | 344 | while (plist && *plist->data == "+-"[reverse]) { |
345 | if (data && !strcmp(data, plist->data+1)) { | 345 | if (data && !strcmp(data, plist->data+1)) { |
346 | if (!backwarn) { | 346 | if (!backwarn) { |
347 | backwarn++; | 347 | backwarn = TT.linenum; |
348 | if (option_mask32 & FLAG_IGNORE) { | 348 | if (option_mask32 & FLAG_IGNORE) { |
349 | dummy_revert = 1; | 349 | dummy_revert = 1; |
350 | reverse ^= 1; | 350 | reverse ^= 1; |
351 | continue; | 351 | continue; |
352 | } | 352 | } |
353 | fdprintf(2,"Possibly reversed hunk %d at %ld\n", | ||
354 | TT.hunknum, TT.linenum); | ||
355 | } | 353 | } |
356 | } | 354 | } |
357 | plist = plist->next; | 355 | plist = plist->next; |
@@ -364,6 +362,10 @@ static int apply_one_hunk(void) | |||
364 | // Does this hunk need to match EOF? | 362 | // Does this hunk need to match EOF? |
365 | if (!plist && matcheof) break; | 363 | if (!plist && matcheof) break; |
366 | 364 | ||
365 | if (backwarn) | ||
366 | fdprintf(2,"Possibly reversed hunk %d at %ld\n", | ||
367 | TT.hunknum, TT.linenum); | ||
368 | |||
367 | // File ended before we found a place for this hunk. | 369 | // File ended before we found a place for this hunk. |
368 | fail_hunk(); | 370 | fail_hunk(); |
369 | goto done; | 371 | goto done; |
@@ -552,7 +554,7 @@ int patch_main(int argc UNUSED_PARAM, char **argv) | |||
552 | int oldsum, newsum, del = 0; | 554 | int oldsum, newsum, del = 0; |
553 | char *name; | 555 | char *name; |
554 | 556 | ||
555 | oldsum = TT.oldline + TT.oldlen; | 557 | oldsum = TT.oldline + TT.oldlen; |
556 | newsum = TT.newline + TT.newlen; | 558 | newsum = TT.newline + TT.newlen; |
557 | 559 | ||
558 | name = reverse ? oldname : newname; | 560 | name = reverse ? oldname : newname; |
@@ -589,10 +591,10 @@ int patch_main(int argc UNUSED_PARAM, char **argv) | |||
589 | xmkpath(name, -1); | 591 | xmkpath(name, -1); |
590 | *s = '/'; | 592 | *s = '/'; |
591 | } | 593 | } |
592 | TT.filein = xopen3(name, O_CREAT|O_EXCL|O_RDWR, 0666); | 594 | TT.filein = xopen(name, O_CREAT|O_EXCL|O_RDWR); |
593 | } else { | 595 | } else { |
594 | printf("patching file %s\n", name); | 596 | printf("patching file %s\n", name); |
595 | TT.filein = xopen(name, O_RDWR); | 597 | TT.filein = xopen(name, O_RDONLY); |
596 | } | 598 | } |
597 | TT.fileout = copy_tempfile(TT.filein, name, &TT.tempname); | 599 | TT.fileout = copy_tempfile(TT.filein, name, &TT.tempname); |
598 | TT.linenum = 0; | 600 | TT.linenum = 0; |
diff --git a/editors/patch_toybox.c b/editors/patch_toybox.c index 7f3234e66..a60bf070f 100644 --- a/editors/patch_toybox.c +++ b/editors/patch_toybox.c | |||
@@ -522,7 +522,7 @@ int patch_main(int argc UNUSED_PARAM, char **argv) | |||
522 | int oldsum, newsum, del = 0; | 522 | int oldsum, newsum, del = 0; |
523 | char *s, *name; | 523 | char *s, *name; |
524 | 524 | ||
525 | oldsum = TT.oldline + TT.oldlen; | 525 | oldsum = TT.oldline + TT.oldlen; |
526 | newsum = TT.newline + TT.newlen; | 526 | newsum = TT.newline + TT.newlen; |
527 | 527 | ||
528 | name = reverse ? oldname : newname; | 528 | name = reverse ? oldname : newname; |
@@ -559,7 +559,7 @@ int patch_main(int argc UNUSED_PARAM, char **argv) | |||
559 | xmkpath(name, -1); | 559 | xmkpath(name, -1); |
560 | *s = '/'; | 560 | *s = '/'; |
561 | } | 561 | } |
562 | TT.filein = xopen3(name, O_CREAT|O_EXCL|O_RDWR, 0666); | 562 | TT.filein = xopen(name, O_CREAT|O_EXCL|O_RDWR); |
563 | } else { | 563 | } else { |
564 | printf("patching file %s\n", name); | 564 | printf("patching file %s\n", name); |
565 | TT.filein = xopen(name, O_RDWR); | 565 | TT.filein = xopen(name, O_RDWR); |
diff --git a/findutils/.gitignore b/findutils/.gitignore deleted file mode 100644 index 7a30caf5c..000000000 --- a/findutils/.gitignore +++ /dev/null | |||
@@ -1,3 +0,0 @@ | |||
1 | # Config.in and Kbuild are auto-generated | ||
2 | Config.in | ||
3 | Kbuild | ||
diff --git a/findutils/grep.c b/findutils/grep.c index bf42753c5..f166aa48a 100644 --- a/findutils/grep.c +++ b/findutils/grep.c | |||
@@ -629,30 +629,33 @@ int grep_main(int argc UNUSED_PARAM, char **argv) | |||
629 | 629 | ||
630 | /* do normal option parsing */ | 630 | /* do normal option parsing */ |
631 | #if ENABLE_FEATURE_GREP_CONTEXT | 631 | #if ENABLE_FEATURE_GREP_CONTEXT |
632 | int Copt; | 632 | int Copt, opts; |
633 | 633 | ||
634 | /* -H unsets -h; -C unsets -A,-B; -e,-f are lists; | 634 | /* -H unsets -h; -C unsets -A,-B; -e,-f are lists; |
635 | * -m,-A,-B,-C have numeric param */ | 635 | * -m,-A,-B,-C have numeric param */ |
636 | opt_complementary = "H-h:C-AB:e::f::m+:A+:B+:C+"; | 636 | opt_complementary = "H-h:C-AB:e::f::m+:A+:B+:C+"; |
637 | getopt32(argv, | 637 | opts = getopt32(argv, |
638 | OPTSTR_GREP, | 638 | OPTSTR_GREP, |
639 | &pattern_head, &fopt, &max_matches, | 639 | &pattern_head, &fopt, &max_matches, |
640 | &lines_after, &lines_before, &Copt); | 640 | &lines_after, &lines_before, &Copt); |
641 | 641 | ||
642 | if (option_mask32 & OPT_C) { | 642 | if (opts & OPT_C) { |
643 | /* -C unsets prev -A and -B, but following -A or -B | 643 | /* -C unsets prev -A and -B, but following -A or -B |
644 | may override it */ | 644 | may override it */ |
645 | if (!(option_mask32 & OPT_A)) /* not overridden */ | 645 | if (!(opts & OPT_A)) /* not overridden */ |
646 | lines_after = Copt; | 646 | lines_after = Copt; |
647 | if (!(option_mask32 & OPT_B)) /* not overridden */ | 647 | if (!(opts & OPT_B)) /* not overridden */ |
648 | lines_before = Copt; | 648 | lines_before = Copt; |
649 | } | 649 | } |
650 | /* sanity checks */ | 650 | /* sanity checks */ |
651 | if (option_mask32 & (OPT_c|OPT_q|OPT_l|OPT_L)) { | 651 | if (opts & (OPT_c|OPT_q|OPT_l|OPT_L)) { |
652 | option_mask32 &= ~OPT_n; | 652 | option_mask32 &= ~OPT_n; |
653 | lines_before = 0; | 653 | lines_before = 0; |
654 | lines_after = 0; | 654 | lines_after = 0; |
655 | } else if (lines_before > 0) { | 655 | } else if (lines_before > 0) { |
656 | if (lines_before > INT_MAX / sizeof(long long)) | ||
657 | lines_before = INT_MAX / sizeof(long long); | ||
658 | /* overflow in (lines_before * sizeof(x)) is prevented (above) */ | ||
656 | before_buf = xzalloc(lines_before * sizeof(before_buf[0])); | 659 | before_buf = xzalloc(lines_before * sizeof(before_buf[0])); |
657 | IF_EXTRA_COMPAT(before_buf_size = xzalloc(lines_before * sizeof(before_buf_size[0]));) | 660 | IF_EXTRA_COMPAT(before_buf_size = xzalloc(lines_before * sizeof(before_buf_size[0]));) |
658 | } | 661 | } |
diff --git a/include/applets.src.h b/include/applets.src.h index 0e4f966de..879dbf760 100644 --- a/include/applets.src.h +++ b/include/applets.src.h | |||
@@ -56,11 +56,6 @@ s - suid type: | |||
56 | # define APPLET_NOFORK(name,main,l,s,name2) { #name, #main, l, s, 1, 1 }, | 56 | # define APPLET_NOFORK(name,main,l,s,name2) { #name, #main, l, s, 1, 1 }, |
57 | #endif | 57 | #endif |
58 | 58 | ||
59 | #if ENABLE_INSTALL_NO_USR | ||
60 | # define _BB_DIR_USR_BIN _BB_DIR_BIN | ||
61 | # define _BB_DIR_USR_SBIN _BB_DIR_SBIN | ||
62 | #endif | ||
63 | |||
64 | 59 | ||
65 | INSERT | 60 | INSERT |
66 | IF_TEST(APPLET_NOFORK([, test, _BB_DIR_USR_BIN, _BB_SUID_DROP, test)) | 61 | IF_TEST(APPLET_NOFORK([, test, _BB_DIR_USR_BIN, _BB_SUID_DROP, test)) |
@@ -77,7 +72,6 @@ IF_BASENAME(APPLET_NOFORK(basename, basename, _BB_DIR_USR_BIN, _BB_SUID_DROP, ba | |||
77 | IF_BBCONFIG(APPLET(bbconfig, _BB_DIR_BIN, _BB_SUID_DROP)) | 72 | IF_BBCONFIG(APPLET(bbconfig, _BB_DIR_BIN, _BB_SUID_DROP)) |
78 | IF_BEEP(APPLET(beep, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 73 | IF_BEEP(APPLET(beep, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
79 | IF_BLKID(APPLET(blkid, _BB_DIR_SBIN, _BB_SUID_DROP)) | 74 | IF_BLKID(APPLET(blkid, _BB_DIR_SBIN, _BB_SUID_DROP)) |
80 | IF_BOOTCHARTD(APPLET(bootchartd, _BB_DIR_SBIN, _BB_SUID_DROP)) | ||
81 | IF_BRCTL(APPLET(brctl, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) | 75 | IF_BRCTL(APPLET(brctl, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) |
82 | IF_BZIP2(APPLET(bzip2, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 76 | IF_BZIP2(APPLET(bzip2, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
83 | IF_CAL(APPLET(cal, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 77 | IF_CAL(APPLET(cal, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
@@ -94,7 +88,7 @@ IF_CHPST(APPLET(chpst, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | |||
94 | IF_CHROOT(APPLET(chroot, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) | 88 | IF_CHROOT(APPLET(chroot, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) |
95 | IF_CHRT(APPLET(chrt, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 89 | IF_CHRT(APPLET(chrt, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
96 | IF_CHVT(APPLET(chvt, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 90 | IF_CHVT(APPLET(chvt, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
97 | IF_CKSUM(APPLET(cksum, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 91 | IF_CKSUM(APPLET_NOEXEC(cksum, cksum, _BB_DIR_USR_BIN, _BB_SUID_DROP, cksum)) |
98 | IF_CLEAR(APPLET(clear, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 92 | IF_CLEAR(APPLET(clear, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
99 | IF_CMP(APPLET(cmp, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 93 | IF_CMP(APPLET(cmp, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
100 | IF_COMM(APPLET(comm, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 94 | IF_COMM(APPLET(comm, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
@@ -104,14 +98,11 @@ IF_CROND(APPLET(crond, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) | |||
104 | IF_CRONTAB(APPLET(crontab, _BB_DIR_USR_BIN, _BB_SUID_REQUIRE)) | 98 | IF_CRONTAB(APPLET(crontab, _BB_DIR_USR_BIN, _BB_SUID_REQUIRE)) |
105 | IF_CRYPTPW(APPLET(cryptpw, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 99 | IF_CRYPTPW(APPLET(cryptpw, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
106 | IF_CUT(APPLET_NOEXEC(cut, cut, _BB_DIR_USR_BIN, _BB_SUID_DROP, cut)) | 100 | IF_CUT(APPLET_NOEXEC(cut, cut, _BB_DIR_USR_BIN, _BB_SUID_DROP, cut)) |
107 | IF_DATE(APPLET(date, _BB_DIR_BIN, _BB_SUID_DROP)) | ||
108 | IF_DC(APPLET(dc, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 101 | IF_DC(APPLET(dc, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
109 | IF_DD(APPLET_NOEXEC(dd, dd, _BB_DIR_BIN, _BB_SUID_DROP, dd)) | 102 | IF_DD(APPLET_NOEXEC(dd, dd, _BB_DIR_BIN, _BB_SUID_DROP, dd)) |
110 | IF_DEALLOCVT(APPLET(deallocvt, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 103 | IF_DEALLOCVT(APPLET(deallocvt, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
111 | IF_DELGROUP(APPLET_ODDNAME(delgroup, deluser, _BB_DIR_BIN, _BB_SUID_DROP, delgroup)) | 104 | IF_DELGROUP(APPLET_ODDNAME(delgroup, deluser, _BB_DIR_BIN, _BB_SUID_DROP, delgroup)) |
112 | IF_DELUSER(APPLET(deluser, _BB_DIR_BIN, _BB_SUID_DROP)) | 105 | IF_DELUSER(APPLET(deluser, _BB_DIR_BIN, _BB_SUID_DROP)) |
113 | IF_DEPMOD(APPLET(depmod, _BB_DIR_SBIN, _BB_SUID_DROP)) | ||
114 | IF_MODPROBE_SMALL(APPLET_ODDNAME(depmod, modprobe, _BB_DIR_SBIN, _BB_SUID_DROP, modprobe)) | ||
115 | IF_DEVFSD(APPLET(devfsd, _BB_DIR_SBIN, _BB_SUID_DROP)) | 106 | IF_DEVFSD(APPLET(devfsd, _BB_DIR_SBIN, _BB_SUID_DROP)) |
116 | IF_DEVMEM(APPLET(devmem, _BB_DIR_SBIN, _BB_SUID_DROP)) | 107 | IF_DEVMEM(APPLET(devmem, _BB_DIR_SBIN, _BB_SUID_DROP)) |
117 | IF_DF(APPLET(df, _BB_DIR_BIN, _BB_SUID_DROP)) | 108 | IF_DF(APPLET(df, _BB_DIR_BIN, _BB_SUID_DROP)) |
@@ -121,7 +112,7 @@ IF_DIRNAME(APPLET_NOFORK(dirname, dirname, _BB_DIR_USR_BIN, _BB_SUID_DROP, dirna | |||
121 | IF_DMESG(APPLET(dmesg, _BB_DIR_BIN, _BB_SUID_DROP)) | 112 | IF_DMESG(APPLET(dmesg, _BB_DIR_BIN, _BB_SUID_DROP)) |
122 | IF_DNSD(APPLET(dnsd, _BB_DIR_USR_SBIN, _BB_SUID_REQUIRE)) | 113 | IF_DNSD(APPLET(dnsd, _BB_DIR_USR_SBIN, _BB_SUID_REQUIRE)) |
123 | IF_HOSTNAME(APPLET_ODDNAME(dnsdomainname, hostname, _BB_DIR_BIN, _BB_SUID_DROP, dnsdomainname)) | 114 | IF_HOSTNAME(APPLET_ODDNAME(dnsdomainname, hostname, _BB_DIR_BIN, _BB_SUID_DROP, dnsdomainname)) |
124 | IF_DOS2UNIX(APPLET(dos2unix, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 115 | IF_DOS2UNIX(APPLET_NOEXEC(dos2unix, dos2unix, _BB_DIR_USR_BIN, _BB_SUID_DROP, dos2unix)) |
125 | IF_DPKG(APPLET(dpkg, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 116 | IF_DPKG(APPLET(dpkg, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
126 | IF_DPKG_DEB(APPLET_ODDNAME(dpkg-deb, dpkg_deb, _BB_DIR_USR_BIN, _BB_SUID_DROP, dpkg_deb)) | 117 | IF_DPKG_DEB(APPLET_ODDNAME(dpkg-deb, dpkg_deb, _BB_DIR_USR_BIN, _BB_SUID_DROP, dpkg_deb)) |
127 | IF_DU(APPLET(du, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 118 | IF_DU(APPLET(du, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
@@ -152,7 +143,7 @@ IF_FLASH_LOCK(APPLET_ODDNAME(flash_lock, flash_lock_unlock, _BB_DIR_USR_SBIN, _B | |||
152 | IF_FLASH_UNLOCK(APPLET_ODDNAME(flash_unlock, flash_lock_unlock, _BB_DIR_USR_SBIN, _BB_SUID_DROP, flash_unlock)) | 143 | IF_FLASH_UNLOCK(APPLET_ODDNAME(flash_unlock, flash_lock_unlock, _BB_DIR_USR_SBIN, _BB_SUID_DROP, flash_unlock)) |
153 | IF_FLASHCP(APPLET(flashcp, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) | 144 | IF_FLASHCP(APPLET(flashcp, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) |
154 | IF_FLOCK(APPLET(flock, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 145 | IF_FLOCK(APPLET(flock, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
155 | IF_FOLD(APPLET(fold, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 146 | IF_FOLD(APPLET_NOEXEC(fold, fold, _BB_DIR_USR_BIN, _BB_SUID_DROP, fold)) |
156 | IF_FREE(APPLET(free, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 147 | IF_FREE(APPLET(free, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
157 | IF_FREERAMDISK(APPLET(freeramdisk, _BB_DIR_SBIN, _BB_SUID_DROP)) | 148 | IF_FREERAMDISK(APPLET(freeramdisk, _BB_DIR_SBIN, _BB_SUID_DROP)) |
158 | IF_FSCK(APPLET(fsck, _BB_DIR_SBIN, _BB_SUID_DROP)) | 149 | IF_FSCK(APPLET(fsck, _BB_DIR_SBIN, _BB_SUID_DROP)) |
@@ -170,26 +161,22 @@ IF_GETSEBOOL(APPLET(getsebool, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) | |||
170 | IF_GETTY(APPLET(getty, _BB_DIR_SBIN, _BB_SUID_DROP)) | 161 | IF_GETTY(APPLET(getty, _BB_DIR_SBIN, _BB_SUID_DROP)) |
171 | IF_GUNZIP(APPLET(gunzip, _BB_DIR_BIN, _BB_SUID_DROP)) | 162 | IF_GUNZIP(APPLET(gunzip, _BB_DIR_BIN, _BB_SUID_DROP)) |
172 | IF_GZIP(APPLET(gzip, _BB_DIR_BIN, _BB_SUID_DROP)) | 163 | IF_GZIP(APPLET(gzip, _BB_DIR_BIN, _BB_SUID_DROP)) |
173 | IF_HALT(APPLET(halt, _BB_DIR_SBIN, _BB_SUID_DROP)) | ||
174 | IF_HD(APPLET_NOEXEC(hd, hexdump, _BB_DIR_USR_BIN, _BB_SUID_DROP, hd)) | 164 | IF_HD(APPLET_NOEXEC(hd, hexdump, _BB_DIR_USR_BIN, _BB_SUID_DROP, hd)) |
175 | IF_HDPARM(APPLET(hdparm, _BB_DIR_SBIN, _BB_SUID_DROP)) | 165 | IF_HDPARM(APPLET(hdparm, _BB_DIR_SBIN, _BB_SUID_DROP)) |
176 | IF_HEAD(APPLET(head, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 166 | IF_HEAD(APPLET_NOEXEC(head, head, _BB_DIR_USR_BIN, _BB_SUID_DROP, head)) |
177 | IF_HEXDUMP(APPLET_NOEXEC(hexdump, hexdump, _BB_DIR_USR_BIN, _BB_SUID_DROP, hexdump)) | 167 | IF_HEXDUMP(APPLET_NOEXEC(hexdump, hexdump, _BB_DIR_USR_BIN, _BB_SUID_DROP, hexdump)) |
178 | IF_HOSTID(APPLET_NOFORK(hostid, hostid, _BB_DIR_USR_BIN, _BB_SUID_DROP, hostid)) | 168 | IF_HOSTID(APPLET_NOFORK(hostid, hostid, _BB_DIR_USR_BIN, _BB_SUID_DROP, hostid)) |
179 | IF_HOSTNAME(APPLET(hostname, _BB_DIR_BIN, _BB_SUID_DROP)) | 169 | IF_HOSTNAME(APPLET(hostname, _BB_DIR_BIN, _BB_SUID_DROP)) |
180 | IF_HTTPD(APPLET(httpd, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) | 170 | IF_HTTPD(APPLET(httpd, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) |
181 | IF_HWCLOCK(APPLET(hwclock, _BB_DIR_SBIN, _BB_SUID_DROP)) | 171 | IF_HWCLOCK(APPLET(hwclock, _BB_DIR_SBIN, _BB_SUID_DROP)) |
182 | IF_ID(APPLET(id, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 172 | IF_ID(APPLET_NOEXEC(id, id, _BB_DIR_USR_BIN, _BB_SUID_DROP, id)) |
183 | IF_IFCONFIG(APPLET(ifconfig, _BB_DIR_SBIN, _BB_SUID_DROP)) | 173 | IF_IFCONFIG(APPLET(ifconfig, _BB_DIR_SBIN, _BB_SUID_DROP)) |
184 | IF_IFUPDOWN(APPLET_ODDNAME(ifdown, ifupdown, _BB_DIR_SBIN, _BB_SUID_DROP, ifdown)) | 174 | IF_IFUPDOWN(APPLET_ODDNAME(ifdown, ifupdown, _BB_DIR_SBIN, _BB_SUID_DROP, ifdown)) |
185 | IF_IFENSLAVE(APPLET(ifenslave, _BB_DIR_SBIN, _BB_SUID_DROP)) | 175 | IF_IFENSLAVE(APPLET(ifenslave, _BB_DIR_SBIN, _BB_SUID_DROP)) |
186 | IF_IFPLUGD(APPLET(ifplugd, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 176 | IF_IFPLUGD(APPLET(ifplugd, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
187 | IF_IFUPDOWN(APPLET_ODDNAME(ifup, ifupdown, _BB_DIR_SBIN, _BB_SUID_DROP, ifup)) | 177 | IF_IFUPDOWN(APPLET_ODDNAME(ifup, ifupdown, _BB_DIR_SBIN, _BB_SUID_DROP, ifup)) |
188 | IF_INETD(APPLET(inetd, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) | 178 | IF_INETD(APPLET(inetd, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) |
189 | IF_INIT(APPLET(init, _BB_DIR_SBIN, _BB_SUID_DROP)) | ||
190 | IF_INOTIFYD(APPLET(inotifyd, _BB_DIR_SBIN, _BB_SUID_DROP)) | 179 | IF_INOTIFYD(APPLET(inotifyd, _BB_DIR_SBIN, _BB_SUID_DROP)) |
191 | IF_INSMOD(APPLET(insmod, _BB_DIR_SBIN, _BB_SUID_DROP)) | ||
192 | IF_MODPROBE_SMALL(APPLET_ODDNAME(insmod, modprobe, _BB_DIR_SBIN, _BB_SUID_DROP, modprobe)) | ||
193 | IF_INSTALL(APPLET(install, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 180 | IF_INSTALL(APPLET(install, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
194 | IF_IONICE(APPLET(ionice, _BB_DIR_BIN, _BB_SUID_DROP)) | 181 | IF_IONICE(APPLET(ionice, _BB_DIR_BIN, _BB_SUID_DROP)) |
195 | #if ENABLE_FEATURE_IP_ADDRESS \ | 182 | #if ENABLE_FEATURE_IP_ADDRESS \ |
@@ -217,7 +204,6 @@ IF_LENGTH(APPLET_NOFORK(length, length, _BB_DIR_USR_BIN, _BB_SUID_DROP, length)) | |||
217 | IF_LESS(APPLET(less, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 204 | IF_LESS(APPLET(less, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
218 | IF_SETARCH(APPLET_ODDNAME(linux32, setarch, _BB_DIR_BIN, _BB_SUID_DROP, linux32)) | 205 | IF_SETARCH(APPLET_ODDNAME(linux32, setarch, _BB_DIR_BIN, _BB_SUID_DROP, linux32)) |
219 | IF_SETARCH(APPLET_ODDNAME(linux64, setarch, _BB_DIR_BIN, _BB_SUID_DROP, linux64)) | 206 | IF_SETARCH(APPLET_ODDNAME(linux64, setarch, _BB_DIR_BIN, _BB_SUID_DROP, linux64)) |
220 | IF_FEATURE_INITRD(APPLET_ODDNAME(linuxrc, init, _BB_DIR_ROOT, _BB_SUID_DROP, linuxrc)) | ||
221 | IF_LN(APPLET_NOEXEC(ln, ln, _BB_DIR_BIN, _BB_SUID_DROP, ln)) | 207 | IF_LN(APPLET_NOEXEC(ln, ln, _BB_DIR_BIN, _BB_SUID_DROP, ln)) |
222 | IF_LOAD_POLICY(APPLET(load_policy, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) | 208 | IF_LOAD_POLICY(APPLET(load_policy, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) |
223 | IF_LOADFONT(APPLET(loadfont, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) | 209 | IF_LOADFONT(APPLET(loadfont, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) |
@@ -232,8 +218,6 @@ IF_LPQ(APPLET_ODDNAME(lpq, lpqr, _BB_DIR_USR_BIN, _BB_SUID_DROP, lpq)) | |||
232 | IF_LPR(APPLET_ODDNAME(lpr, lpqr, _BB_DIR_USR_BIN, _BB_SUID_DROP, lpr)) | 218 | IF_LPR(APPLET_ODDNAME(lpr, lpqr, _BB_DIR_USR_BIN, _BB_SUID_DROP, lpr)) |
233 | IF_LS(APPLET_NOEXEC(ls, ls, _BB_DIR_BIN, _BB_SUID_DROP, ls)) | 219 | IF_LS(APPLET_NOEXEC(ls, ls, _BB_DIR_BIN, _BB_SUID_DROP, ls)) |
234 | IF_LSATTR(APPLET(lsattr, _BB_DIR_BIN, _BB_SUID_DROP)) | 220 | IF_LSATTR(APPLET(lsattr, _BB_DIR_BIN, _BB_SUID_DROP)) |
235 | IF_LSMOD(APPLET(lsmod, _BB_DIR_SBIN, _BB_SUID_DROP)) | ||
236 | IF_MODPROBE_SMALL(APPLET_ODDNAME(lsmod, modprobe, _BB_DIR_SBIN, _BB_SUID_DROP, modprobe)) | ||
237 | IF_LSPCI(APPLET(lspci, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 221 | IF_LSPCI(APPLET(lspci, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
238 | IF_LSUSB(APPLET(lsusb, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 222 | IF_LSUSB(APPLET(lsusb, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
239 | IF_UNLZMA(APPLET_ODDNAME(lzcat, unlzma, _BB_DIR_USR_BIN, _BB_SUID_DROP, lzcat)) | 223 | IF_UNLZMA(APPLET_ODDNAME(lzcat, unlzma, _BB_DIR_USR_BIN, _BB_SUID_DROP, lzcat)) |
@@ -244,25 +228,22 @@ IF_MAKEDEVS(APPLET(makedevs, _BB_DIR_SBIN, _BB_SUID_DROP)) | |||
244 | IF_MAKEMIME(APPLET(makemime, _BB_DIR_BIN, _BB_SUID_DROP)) | 228 | IF_MAKEMIME(APPLET(makemime, _BB_DIR_BIN, _BB_SUID_DROP)) |
245 | IF_MAN(APPLET(man, _BB_DIR_SBIN, _BB_SUID_DROP)) | 229 | IF_MAN(APPLET(man, _BB_DIR_SBIN, _BB_SUID_DROP)) |
246 | IF_MATCHPATHCON(APPLET(matchpathcon, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) | 230 | IF_MATCHPATHCON(APPLET(matchpathcon, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) |
247 | IF_MD5SUM(APPLET_ODDNAME(md5sum, md5_sha1_sum, _BB_DIR_USR_BIN, _BB_SUID_DROP, md5sum)) | 231 | IF_MD5SUM(APPLET_NOEXEC(md5sum, md5_sha1_sum, _BB_DIR_USR_BIN, _BB_SUID_DROP, md5sum)) |
248 | IF_MDEV(APPLET(mdev, _BB_DIR_SBIN, _BB_SUID_DROP)) | 232 | IF_MDEV(APPLET(mdev, _BB_DIR_SBIN, _BB_SUID_DROP)) |
249 | IF_MESG(APPLET(mesg, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | ||
250 | IF_MICROCOM(APPLET(microcom, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 233 | IF_MICROCOM(APPLET(microcom, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
251 | IF_MKDIR(APPLET_NOFORK(mkdir, mkdir, _BB_DIR_BIN, _BB_SUID_DROP, mkdir)) | 234 | IF_MKDIR(APPLET_NOFORK(mkdir, mkdir, _BB_DIR_BIN, _BB_SUID_DROP, mkdir)) |
252 | IF_MKFS_VFAT(APPLET_ODDNAME(mkdosfs, mkfs_vfat, _BB_DIR_SBIN, _BB_SUID_DROP, mkfs_vfat)) | 235 | IF_MKFS_VFAT(APPLET_ODDNAME(mkdosfs, mkfs_vfat, _BB_DIR_SBIN, _BB_SUID_DROP, mkfs_vfat)) |
253 | IF_MKFS_EXT2(APPLET_ODDNAME(mke2fs, mkfs_ext2, _BB_DIR_SBIN, _BB_SUID_DROP, mkfs_ext2)) | 236 | IF_MKFS_EXT2(APPLET_ODDNAME(mke2fs, mkfs_ext2, _BB_DIR_SBIN, _BB_SUID_DROP, mkfs_ext2)) |
254 | IF_MKFIFO(APPLET(mkfifo, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 237 | IF_MKFIFO(APPLET_NOEXEC(mkfifo, mkfifo, _BB_DIR_USR_BIN, _BB_SUID_DROP, mkfifo)) |
255 | IF_MKFS_EXT2(APPLET_ODDNAME(mkfs.ext2, mkfs_ext2, _BB_DIR_SBIN, _BB_SUID_DROP, mkfs_ext2)) | 238 | IF_MKFS_EXT2(APPLET_ODDNAME(mkfs.ext2, mkfs_ext2, _BB_DIR_SBIN, _BB_SUID_DROP, mkfs_ext2)) |
256 | //IF_MKE2FS(APPLET_ODDNAME(mkfs.ext3, mke2fs, _BB_DIR_SBIN, _BB_SUID_DROP, mkfs_ext3)) | 239 | //IF_MKE2FS(APPLET_ODDNAME(mkfs.ext3, mke2fs, _BB_DIR_SBIN, _BB_SUID_DROP, mkfs_ext3)) |
257 | IF_MKFS_MINIX(APPLET_ODDNAME(mkfs.minix, mkfs_minix, _BB_DIR_SBIN, _BB_SUID_DROP, mkfs_minix)) | 240 | IF_MKFS_MINIX(APPLET_ODDNAME(mkfs.minix, mkfs_minix, _BB_DIR_SBIN, _BB_SUID_DROP, mkfs_minix)) |
258 | IF_MKFS_REISER(APPLET_ODDNAME(mkfs.reiser, mkfs_reiser, _BB_DIR_SBIN, _BB_SUID_DROP, mkfs_reiser)) | 241 | IF_MKFS_REISER(APPLET_ODDNAME(mkfs.reiser, mkfs_reiser, _BB_DIR_SBIN, _BB_SUID_DROP, mkfs_reiser)) |
259 | IF_MKFS_VFAT(APPLET_ODDNAME(mkfs.vfat, mkfs_vfat, _BB_DIR_SBIN, _BB_SUID_DROP, mkfs_vfat)) | 242 | IF_MKFS_VFAT(APPLET_ODDNAME(mkfs.vfat, mkfs_vfat, _BB_DIR_SBIN, _BB_SUID_DROP, mkfs_vfat)) |
260 | IF_MKNOD(APPLET(mknod, _BB_DIR_BIN, _BB_SUID_DROP)) | 243 | IF_MKNOD(APPLET_NOEXEC(mknod, mknod, _BB_DIR_BIN, _BB_SUID_DROP, mknod)) |
261 | IF_CRYPTPW(APPLET_ODDNAME(mkpasswd, cryptpw, _BB_DIR_USR_BIN, _BB_SUID_DROP, mkpasswd)) | 244 | IF_CRYPTPW(APPLET_ODDNAME(mkpasswd, cryptpw, _BB_DIR_USR_BIN, _BB_SUID_DROP, mkpasswd)) |
262 | IF_MKSWAP(APPLET(mkswap, _BB_DIR_SBIN, _BB_SUID_DROP)) | 245 | IF_MKSWAP(APPLET(mkswap, _BB_DIR_SBIN, _BB_SUID_DROP)) |
263 | IF_MKTEMP(APPLET(mktemp, _BB_DIR_BIN, _BB_SUID_DROP)) | 246 | IF_MKTEMP(APPLET(mktemp, _BB_DIR_BIN, _BB_SUID_DROP)) |
264 | IF_MODPROBE(APPLET(modprobe, _BB_DIR_SBIN, _BB_SUID_DROP)) | ||
265 | IF_MODPROBE_SMALL(APPLET(modprobe, _BB_DIR_SBIN, _BB_SUID_DROP)) | ||
266 | IF_MORE(APPLET(more, _BB_DIR_BIN, _BB_SUID_DROP)) | 247 | IF_MORE(APPLET(more, _BB_DIR_BIN, _BB_SUID_DROP)) |
267 | IF_MOUNT(APPLET(mount, _BB_DIR_BIN, IF_DESKTOP(_BB_SUID_MAYBE) IF_NOT_DESKTOP(_BB_SUID_DROP))) | 248 | IF_MOUNT(APPLET(mount, _BB_DIR_BIN, IF_DESKTOP(_BB_SUID_MAYBE) IF_NOT_DESKTOP(_BB_SUID_DROP))) |
268 | IF_MOUNTPOINT(APPLET(mountpoint, _BB_DIR_BIN, _BB_SUID_DROP)) | 249 | IF_MOUNTPOINT(APPLET(mountpoint, _BB_DIR_BIN, _BB_SUID_DROP)) |
@@ -289,8 +270,7 @@ IF_PIPE_PROGRESS(APPLET(pipe_progress, _BB_DIR_BIN, _BB_SUID_DROP)) | |||
289 | IF_PIVOT_ROOT(APPLET(pivot_root, _BB_DIR_SBIN, _BB_SUID_DROP)) | 270 | IF_PIVOT_ROOT(APPLET(pivot_root, _BB_DIR_SBIN, _BB_SUID_DROP)) |
290 | IF_PKILL(APPLET_ODDNAME(pkill, pgrep, _BB_DIR_USR_BIN, _BB_SUID_DROP, pkill)) | 271 | IF_PKILL(APPLET_ODDNAME(pkill, pgrep, _BB_DIR_USR_BIN, _BB_SUID_DROP, pkill)) |
291 | IF_POPMAILDIR(APPLET(popmaildir, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) | 272 | IF_POPMAILDIR(APPLET(popmaildir, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) |
292 | IF_HALT(APPLET_ODDNAME(poweroff, halt, _BB_DIR_SBIN, _BB_SUID_DROP, poweroff)) | 273 | IF_PRINTENV(APPLET_NOFORK(printenv, printenv, _BB_DIR_BIN, _BB_SUID_DROP, printenv)) |
293 | IF_PRINTENV(APPLET(printenv, _BB_DIR_BIN, _BB_SUID_DROP)) | ||
294 | IF_PRINTF(APPLET_NOFORK(printf, printf, _BB_DIR_USR_BIN, _BB_SUID_DROP, printf)) | 274 | IF_PRINTF(APPLET_NOFORK(printf, printf, _BB_DIR_USR_BIN, _BB_SUID_DROP, printf)) |
295 | IF_PS(APPLET(ps, _BB_DIR_BIN, _BB_SUID_DROP)) | 275 | IF_PS(APPLET(ps, _BB_DIR_BIN, _BB_SUID_DROP)) |
296 | IF_PSCAN(APPLET(pscan, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 276 | IF_PSCAN(APPLET(pscan, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
@@ -302,7 +282,6 @@ IF_READAHEAD(APPLET(readahead, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | |||
302 | IF_READLINK(APPLET(readlink, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 282 | IF_READLINK(APPLET(readlink, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
303 | IF_READPROFILE(APPLET(readprofile, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) | 283 | IF_READPROFILE(APPLET(readprofile, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) |
304 | IF_REALPATH(APPLET(realpath, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 284 | IF_REALPATH(APPLET(realpath, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
305 | IF_HALT(APPLET_ODDNAME(reboot, halt, _BB_DIR_SBIN, _BB_SUID_DROP, reboot)) | ||
306 | IF_REFORMIME(APPLET(reformime, _BB_DIR_BIN, _BB_SUID_DROP)) | 285 | IF_REFORMIME(APPLET(reformime, _BB_DIR_BIN, _BB_SUID_DROP)) |
307 | IF_RENICE(APPLET(renice, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 286 | IF_RENICE(APPLET(renice, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
308 | IF_RESET(APPLET(reset, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 287 | IF_RESET(APPLET(reset, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
@@ -311,8 +290,6 @@ IF_RESTORECON(APPLET_ODDNAME(restorecon, setfiles, _BB_DIR_SBIN, _BB_SUID_DROP, | |||
311 | IF_RFKILL(APPLET(rfkill, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) | 290 | IF_RFKILL(APPLET(rfkill, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) |
312 | IF_RM(APPLET_NOFORK(rm, rm, _BB_DIR_BIN, _BB_SUID_DROP, rm)) | 291 | IF_RM(APPLET_NOFORK(rm, rm, _BB_DIR_BIN, _BB_SUID_DROP, rm)) |
313 | IF_RMDIR(APPLET_NOFORK(rmdir, rmdir, _BB_DIR_BIN, _BB_SUID_DROP, rmdir)) | 292 | IF_RMDIR(APPLET_NOFORK(rmdir, rmdir, _BB_DIR_BIN, _BB_SUID_DROP, rmdir)) |
314 | IF_RMMOD(APPLET(rmmod, _BB_DIR_SBIN, _BB_SUID_DROP)) | ||
315 | IF_MODPROBE_SMALL(APPLET_ODDNAME(rmmod, modprobe, _BB_DIR_SBIN, _BB_SUID_DROP, modprobe)) | ||
316 | IF_ROUTE(APPLET(route, _BB_DIR_SBIN, _BB_SUID_DROP)) | 293 | IF_ROUTE(APPLET(route, _BB_DIR_SBIN, _BB_SUID_DROP)) |
317 | IF_RPM(APPLET(rpm, _BB_DIR_BIN, _BB_SUID_DROP)) | 294 | IF_RPM(APPLET(rpm, _BB_DIR_BIN, _BB_SUID_DROP)) |
318 | IF_RPM2CPIO(APPLET(rpm2cpio, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 295 | IF_RPM2CPIO(APPLET(rpm2cpio, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
@@ -340,12 +317,13 @@ IF_SETLOGCONS(APPLET(setlogcons, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) | |||
340 | IF_SETSEBOOL(APPLET(setsebool, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) | 317 | IF_SETSEBOOL(APPLET(setsebool, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) |
341 | IF_SETSID(APPLET(setsid, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 318 | IF_SETSID(APPLET(setsid, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
342 | IF_SETUIDGID(APPLET_ODDNAME(setuidgid, chpst, _BB_DIR_USR_BIN, _BB_SUID_DROP, setuidgid)) | 319 | IF_SETUIDGID(APPLET_ODDNAME(setuidgid, chpst, _BB_DIR_USR_BIN, _BB_SUID_DROP, setuidgid)) |
343 | IF_SHA1SUM(APPLET_ODDNAME(sha1sum, md5_sha1_sum, _BB_DIR_USR_BIN, _BB_SUID_DROP, sha1sum)) | 320 | IF_SHA1SUM(APPLET_NOEXEC(sha1sum, md5_sha1_sum, _BB_DIR_USR_BIN, _BB_SUID_DROP, sha1sum)) |
344 | IF_SHA256SUM(APPLET_ODDNAME(sha256sum, md5_sha1_sum, _BB_DIR_USR_BIN, _BB_SUID_DROP, sha256sum)) | 321 | IF_SHA256SUM(APPLET_NOEXEC(sha256sum, md5_sha1_sum, _BB_DIR_USR_BIN, _BB_SUID_DROP, sha256sum)) |
345 | IF_SHA512SUM(APPLET_ODDNAME(sha512sum, md5_sha1_sum, _BB_DIR_USR_BIN, _BB_SUID_DROP, sha512sum)) | 322 | IF_SHA512SUM(APPLET_NOEXEC(sha512sum, md5_sha1_sum, _BB_DIR_USR_BIN, _BB_SUID_DROP, sha512sum)) |
346 | IF_SHOWKEY(APPLET(showkey, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 323 | IF_SHOWKEY(APPLET(showkey, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
347 | IF_SLATTACH(APPLET(slattach, _BB_DIR_SBIN, _BB_SUID_DROP)) | 324 | IF_SLATTACH(APPLET(slattach, _BB_DIR_SBIN, _BB_SUID_DROP)) |
348 | IF_SLEEP(APPLET_NOFORK(sleep, sleep, _BB_DIR_BIN, _BB_SUID_DROP, sleep)) | 325 | /* Do not make this applet NOFORK. It breaks ^C-ing of pauses in shells */ |
326 | IF_SLEEP(APPLET(sleep, _BB_DIR_BIN, _BB_SUID_DROP)) | ||
349 | IF_SOFTLIMIT(APPLET_ODDNAME(softlimit, chpst, _BB_DIR_USR_BIN, _BB_SUID_DROP, softlimit)) | 327 | IF_SOFTLIMIT(APPLET_ODDNAME(softlimit, chpst, _BB_DIR_USR_BIN, _BB_SUID_DROP, softlimit)) |
350 | IF_SORT(APPLET_NOEXEC(sort, sort, _BB_DIR_USR_BIN, _BB_SUID_DROP, sort)) | 328 | IF_SORT(APPLET_NOEXEC(sort, sort, _BB_DIR_USR_BIN, _BB_SUID_DROP, sort)) |
351 | IF_SPLIT(APPLET(split, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 329 | IF_SPLIT(APPLET(split, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
@@ -358,7 +336,7 @@ IF_SULOGIN(APPLET(sulogin, _BB_DIR_SBIN, _BB_SUID_DROP)) | |||
358 | IF_SUM(APPLET(sum, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 336 | IF_SUM(APPLET(sum, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
359 | IF_SV(APPLET(sv, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 337 | IF_SV(APPLET(sv, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
360 | IF_SVLOGD(APPLET(svlogd, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) | 338 | IF_SVLOGD(APPLET(svlogd, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) |
361 | IF_SWAPONOFF(APPLET_ODDNAME(swapoff, swap_on_off, _BB_DIR_SBIN, _BB_SUID_DROP,swapoff)) | 339 | IF_SWAPONOFF(APPLET_ODDNAME(swapoff, swap_on_off, _BB_DIR_SBIN, _BB_SUID_DROP, swapoff)) |
362 | IF_SWAPONOFF(APPLET_ODDNAME(swapon, swap_on_off, _BB_DIR_SBIN, _BB_SUID_DROP, swapon)) | 340 | IF_SWAPONOFF(APPLET_ODDNAME(swapon, swap_on_off, _BB_DIR_SBIN, _BB_SUID_DROP, swapon)) |
363 | IF_SWITCH_ROOT(APPLET(switch_root, _BB_DIR_SBIN, _BB_SUID_DROP)) | 341 | IF_SWITCH_ROOT(APPLET(switch_root, _BB_DIR_SBIN, _BB_SUID_DROP)) |
364 | IF_SYNC(APPLET_NOFORK(sync, sync, _BB_DIR_BIN, _BB_SUID_DROP, sync)) | 342 | IF_SYNC(APPLET_NOFORK(sync, sync, _BB_DIR_BIN, _BB_SUID_DROP, sync)) |
@@ -398,7 +376,7 @@ IF_UNAME(APPLET(uname, _BB_DIR_BIN, _BB_SUID_DROP)) | |||
398 | IF_UNCOMPRESS(APPLET(uncompress, _BB_DIR_BIN, _BB_SUID_DROP)) | 376 | IF_UNCOMPRESS(APPLET(uncompress, _BB_DIR_BIN, _BB_SUID_DROP)) |
399 | IF_UNEXPAND(APPLET_ODDNAME(unexpand, expand, _BB_DIR_USR_BIN, _BB_SUID_DROP, unexpand)) | 377 | IF_UNEXPAND(APPLET_ODDNAME(unexpand, expand, _BB_DIR_USR_BIN, _BB_SUID_DROP, unexpand)) |
400 | IF_UNIQ(APPLET(uniq, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 378 | IF_UNIQ(APPLET(uniq, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
401 | IF_UNIX2DOS(APPLET_ODDNAME(unix2dos, dos2unix, _BB_DIR_USR_BIN, _BB_SUID_DROP, unix2dos)) | 379 | IF_UNIX2DOS(APPLET_NOEXEC(unix2dos, dos2unix, _BB_DIR_USR_BIN, _BB_SUID_DROP, unix2dos)) |
402 | IF_UNXZ(APPLET(unxz, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 380 | IF_UNXZ(APPLET(unxz, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
403 | IF_UNLZMA(APPLET(unlzma, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 381 | IF_UNLZMA(APPLET(unlzma, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
404 | IF_LZOP(APPLET_ODDNAME(unlzop, lzop, _BB_DIR_USR_BIN, _BB_SUID_DROP, unlzop)) | 382 | IF_LZOP(APPLET_ODDNAME(unlzop, lzop, _BB_DIR_USR_BIN, _BB_SUID_DROP, unlzop)) |
diff --git a/include/busybox.h b/include/busybox.h index 76415dd72..757317fc7 100644 --- a/include/busybox.h +++ b/include/busybox.h | |||
@@ -16,8 +16,13 @@ typedef enum bb_install_loc_t { | |||
16 | _BB_DIR_ROOT = 0, | 16 | _BB_DIR_ROOT = 0, |
17 | _BB_DIR_BIN, | 17 | _BB_DIR_BIN, |
18 | _BB_DIR_SBIN, | 18 | _BB_DIR_SBIN, |
19 | #if ENABLE_INSTALL_NO_USR | ||
20 | _BB_DIR_USR_BIN = _BB_DIR_BIN, | ||
21 | _BB_DIR_USR_SBIN = _BB_DIR_SBIN, | ||
22 | #else | ||
19 | _BB_DIR_USR_BIN, | 23 | _BB_DIR_USR_BIN, |
20 | _BB_DIR_USR_SBIN | 24 | _BB_DIR_USR_SBIN, |
25 | #endif | ||
21 | } bb_install_loc_t; | 26 | } bb_install_loc_t; |
22 | 27 | ||
23 | typedef enum bb_suid_t { | 28 | typedef enum bb_suid_t { |
diff --git a/include/libbb.h b/include/libbb.h index 221837b64..9ece2f9ec 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -1522,37 +1522,42 @@ unsigned get_cpu_count(void) FAST_FUNC; | |||
1522 | extern const char bb_uuenc_tbl_base64[]; | 1522 | extern const char bb_uuenc_tbl_base64[]; |
1523 | extern const char bb_uuenc_tbl_std[]; | 1523 | extern const char bb_uuenc_tbl_std[]; |
1524 | void bb_uuencode(char *store, const void *s, int length, const char *tbl) FAST_FUNC; | 1524 | void bb_uuencode(char *store, const void *s, int length, const char *tbl) FAST_FUNC; |
1525 | enum { | ||
1526 | BASE64_FLAG_UU_STOP = 0x100, | ||
1527 | /* Sign-extends to a value which never matches fgetc result: */ | ||
1528 | BASE64_FLAG_NO_STOP_CHAR = 0x80, | ||
1529 | }; | ||
1530 | void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags); | ||
1525 | 1531 | ||
1526 | typedef struct sha1_ctx_t { | 1532 | typedef struct sha1_ctx_t { |
1527 | uint32_t hash[8]; /* 5, +3 elements for sha256 */ | 1533 | uint32_t hash[8]; /* 5, +3 elements for sha256 */ |
1528 | uint64_t total64; | 1534 | uint64_t total64; /* must be directly after hash[] */ |
1529 | uint8_t wbuffer[64]; /* NB: always correctly aligned for uint64_t */ | 1535 | uint8_t wbuffer[64]; /* NB: always correctly aligned for uint64_t */ |
1530 | void (*process_block)(struct sha1_ctx_t*) FAST_FUNC; | 1536 | void (*process_block)(struct sha1_ctx_t*) FAST_FUNC; |
1531 | } sha1_ctx_t; | 1537 | } sha1_ctx_t; |
1532 | void sha1_begin(sha1_ctx_t *ctx) FAST_FUNC; | 1538 | void sha1_begin(sha1_ctx_t *ctx) FAST_FUNC; |
1533 | void sha1_hash(const void *data, size_t length, sha1_ctx_t *ctx) FAST_FUNC; | 1539 | void sha1_hash(sha1_ctx_t *ctx, const void *data, size_t length) FAST_FUNC; |
1534 | void sha1_end(void *resbuf, sha1_ctx_t *ctx) FAST_FUNC; | 1540 | void sha1_end(sha1_ctx_t *ctx, void *resbuf) FAST_FUNC; |
1535 | typedef struct sha1_ctx_t sha256_ctx_t; | 1541 | typedef struct sha1_ctx_t sha256_ctx_t; |
1536 | void sha256_begin(sha256_ctx_t *ctx) FAST_FUNC; | 1542 | void sha256_begin(sha256_ctx_t *ctx) FAST_FUNC; |
1537 | #define sha256_hash sha1_hash | 1543 | #define sha256_hash sha1_hash |
1538 | #define sha256_end sha1_end | 1544 | #define sha256_end sha1_end |
1539 | typedef struct sha512_ctx_t { | 1545 | typedef struct sha512_ctx_t { |
1540 | uint64_t hash[8]; | 1546 | uint64_t hash[8]; |
1541 | uint64_t total64[2]; | 1547 | uint64_t total64[2]; /* must be directly after hash[] */ |
1542 | uint8_t wbuffer[128]; /* NB: always correctly aligned for uint64_t */ | 1548 | uint8_t wbuffer[128]; /* NB: always correctly aligned for uint64_t */ |
1543 | } sha512_ctx_t; | 1549 | } sha512_ctx_t; |
1544 | void sha512_begin(sha512_ctx_t *ctx) FAST_FUNC; | 1550 | void sha512_begin(sha512_ctx_t *ctx) FAST_FUNC; |
1545 | void sha512_hash(const void *buffer, size_t len, sha512_ctx_t *ctx) FAST_FUNC; | 1551 | void sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len) FAST_FUNC; |
1546 | void sha512_end(void *resbuf, sha512_ctx_t *ctx) FAST_FUNC; | 1552 | void sha512_end(sha512_ctx_t *ctx, void *resbuf) FAST_FUNC; |
1547 | #if 1 | 1553 | #if 1 |
1548 | typedef struct md5_ctx_t { | 1554 | typedef struct md5_ctx_t { |
1549 | uint32_t A; | 1555 | uint32_t A; |
1550 | uint32_t B; | 1556 | uint32_t B; |
1551 | uint32_t C; | 1557 | uint32_t C; |
1552 | uint32_t D; | 1558 | uint32_t D; |
1553 | uint64_t total; | 1559 | uint64_t total64; |
1554 | uint32_t buflen; | 1560 | char wbuffer[64]; |
1555 | char buffer[128]; | ||
1556 | } md5_ctx_t; | 1561 | } md5_ctx_t; |
1557 | #else | 1562 | #else |
1558 | /* libbb/md5prime.c uses a bit different one: */ | 1563 | /* libbb/md5prime.c uses a bit different one: */ |
@@ -1563,8 +1568,8 @@ typedef struct md5_ctx_t { | |||
1563 | } md5_ctx_t; | 1568 | } md5_ctx_t; |
1564 | #endif | 1569 | #endif |
1565 | void md5_begin(md5_ctx_t *ctx) FAST_FUNC; | 1570 | void md5_begin(md5_ctx_t *ctx) FAST_FUNC; |
1566 | void md5_hash(const void *data, size_t length, md5_ctx_t *ctx) FAST_FUNC; | 1571 | void md5_hash(md5_ctx_t *ctx, const void *data, size_t length) FAST_FUNC; |
1567 | void md5_end(void *resbuf, md5_ctx_t *ctx) FAST_FUNC; | 1572 | void md5_end(md5_ctx_t *ctx, void *resbuf) FAST_FUNC; |
1568 | 1573 | ||
1569 | 1574 | ||
1570 | uint32_t *crc32_filltable(uint32_t *tbl256, int endian) FAST_FUNC; | 1575 | uint32_t *crc32_filltable(uint32_t *tbl256, int endian) FAST_FUNC; |
diff --git a/include/platform.h b/include/platform.h index 2b3ad42bd..ed8c137e1 100644 --- a/include/platform.h +++ b/include/platform.h | |||
@@ -215,6 +215,8 @@ | |||
215 | # define SWAP_LE16(x) bswap_16(x) | 215 | # define SWAP_LE16(x) bswap_16(x) |
216 | # define SWAP_LE32(x) bswap_32(x) | 216 | # define SWAP_LE32(x) bswap_32(x) |
217 | # define SWAP_LE64(x) bswap_64(x) | 217 | # define SWAP_LE64(x) bswap_64(x) |
218 | # define IF_BIG_ENDIAN(...) __VA_ARGS__ | ||
219 | # define IF_LITTLE_ENDIAN(...) | ||
218 | #else | 220 | #else |
219 | # define SWAP_BE16(x) bswap_16(x) | 221 | # define SWAP_BE16(x) bswap_16(x) |
220 | # define SWAP_BE32(x) bswap_32(x) | 222 | # define SWAP_BE32(x) bswap_32(x) |
@@ -222,6 +224,8 @@ | |||
222 | # define SWAP_LE16(x) (x) | 224 | # define SWAP_LE16(x) (x) |
223 | # define SWAP_LE32(x) (x) | 225 | # define SWAP_LE32(x) (x) |
224 | # define SWAP_LE64(x) (x) | 226 | # define SWAP_LE64(x) (x) |
227 | # define IF_BIG_ENDIAN(...) | ||
228 | # define IF_LITTLE_ENDIAN(...) __VA_ARGS__ | ||
225 | #endif | 229 | #endif |
226 | 230 | ||
227 | /* ---- Unaligned access ------------------------------------ */ | 231 | /* ---- Unaligned access ------------------------------------ */ |
diff --git a/include/usage.src.h b/include/usage.src.h index 2866bdbba..5d7767bb4 100644 --- a/include/usage.src.h +++ b/include/usage.src.h | |||
@@ -18,21 +18,27 @@ | |||
18 | INSERT | 18 | INSERT |
19 | 19 | ||
20 | #define acpid_trivial_usage \ | 20 | #define acpid_trivial_usage \ |
21 | "[-d] [-c CONFDIR] [-l LOGFILE] [-e PROC_EVENT_FILE] [EVDEV_EVENT_FILE]..." | 21 | "[-d] [-c CONFDIR] [-l LOGFILE] [-a ACTIONFILE] [-M MAPFILE] [-e PROC_EVENT_FILE] [-p PIDFILE]" |
22 | #define acpid_full_usage "\n\n" \ | 22 | #define acpid_full_usage "\n\n" \ |
23 | "Listen to ACPI events and spawn specific helpers on event arrival\n" \ | 23 | "Listen to ACPI events and spawn specific helpers on event arrival\n" \ |
24 | "\nOptions:" \ | 24 | "\nOptions:" \ |
25 | "\n -d Don't daemonize, log to stderr" \ | ||
26 | "\n -c DIR Config directory [/etc/acpi]" \ | 25 | "\n -c DIR Config directory [/etc/acpi]" \ |
26 | "\n -d Don't daemonize, (implies -f)" \ | ||
27 | "\n -e FILE /proc event file [/proc/acpi/event]" \ | 27 | "\n -e FILE /proc event file [/proc/acpi/event]" \ |
28 | "\n -l FILE Log file [/var/log/acpid]" \ | 28 | "\n -f Run in foreground" \ |
29 | "\n -l FILE Log file [/var/log/acpid.log]" \ | ||
30 | "\n -p FILE Pid file [/var/run/acpid.pid]" \ | ||
31 | "\n -a FILE Action file [/etc/acpid.conf]" \ | ||
32 | "\n -M FILE Map file [/etc/acpi.map]" \ | ||
29 | IF_FEATURE_ACPID_COMPAT( \ | 33 | IF_FEATURE_ACPID_COMPAT( \ |
30 | "\n\nAccept and ignore compatibility options -g -m -s -S -v" \ | 34 | "\n\nAccept and ignore compatibility options -g -m -s -S -v" \ |
31 | ) | 35 | ) |
32 | 36 | ||
33 | #define acpid_example_usage \ | 37 | #define acpid_example_usage \ |
38 | "Without -e option, acpid uses all /dev/input/event* files\n" \ | ||
39 | "# acpid\n" \ | ||
34 | "# acpid -l /var/log/my-acpi-log\n" \ | 40 | "# acpid -l /var/log/my-acpi-log\n" \ |
35 | "# acpid -d /dev/input/event*\n" | 41 | "# acpid -e /proc/acpi/event\n" |
36 | 42 | ||
37 | #define addgroup_trivial_usage \ | 43 | #define addgroup_trivial_usage \ |
38 | "[-g GID] " IF_FEATURE_ADDUSER_TO_GROUP("[USER] ") "GROUP" | 44 | "[-g GID] " IF_FEATURE_ADDUSER_TO_GROUP("[USER] ") "GROUP" |
@@ -95,7 +101,7 @@ INSERT | |||
95 | "\n -n Don't resolve names" \ | 101 | "\n -n Don't resolve names" \ |
96 | "\n -i IF Network interface" \ | 102 | "\n -i IF Network interface" \ |
97 | "\n -D Read <hwaddr> from given device" \ | 103 | "\n -D Read <hwaddr> from given device" \ |
98 | "\n -A, -p AF Protocol family" \ | 104 | "\n -A,-p AF Protocol family" \ |
99 | "\n -H HWTYPE Hardware address type" \ | 105 | "\n -H HWTYPE Hardware address type" \ |
100 | 106 | ||
101 | #define arping_trivial_usage \ | 107 | #define arping_trivial_usage \ |
@@ -214,7 +220,7 @@ INSERT | |||
214 | "\n -F Don't store or verify checksum" \ | 220 | "\n -F Don't store or verify checksum" \ |
215 | 221 | ||
216 | #define unlzma_trivial_usage \ | 222 | #define unlzma_trivial_usage \ |
217 | "[OPTIONS] [FILE]..." | 223 | "[-cf] [FILE]..." |
218 | #define unlzma_full_usage "\n\n" \ | 224 | #define unlzma_full_usage "\n\n" \ |
219 | "Decompress FILE (or stdin)\n" \ | 225 | "Decompress FILE (or stdin)\n" \ |
220 | "\nOptions:" \ | 226 | "\nOptions:" \ |
@@ -222,7 +228,7 @@ INSERT | |||
222 | "\n -f Force" \ | 228 | "\n -f Force" \ |
223 | 229 | ||
224 | #define lzma_trivial_usage \ | 230 | #define lzma_trivial_usage \ |
225 | "-d [OPTIONS] [FILE]..." | 231 | "-d [-cf] [FILE]..." |
226 | #define lzma_full_usage "\n\n" \ | 232 | #define lzma_full_usage "\n\n" \ |
227 | "Decompress FILE (or stdin)\n" \ | 233 | "Decompress FILE (or stdin)\n" \ |
228 | "\nOptions:" \ | 234 | "\nOptions:" \ |
@@ -236,7 +242,7 @@ INSERT | |||
236 | "Decompress to stdout" | 242 | "Decompress to stdout" |
237 | 243 | ||
238 | #define unxz_trivial_usage \ | 244 | #define unxz_trivial_usage \ |
239 | "[OPTIONS] [FILE]..." | 245 | "[-cf] [FILE]..." |
240 | #define unxz_full_usage "\n\n" \ | 246 | #define unxz_full_usage "\n\n" \ |
241 | "Decompress FILE (or stdin)\n" \ | 247 | "Decompress FILE (or stdin)\n" \ |
242 | "\nOptions:" \ | 248 | "\nOptions:" \ |
@@ -244,7 +250,7 @@ INSERT | |||
244 | "\n -f Force" \ | 250 | "\n -f Force" \ |
245 | 251 | ||
246 | #define xz_trivial_usage \ | 252 | #define xz_trivial_usage \ |
247 | "-d [OPTIONS] [FILE]..." | 253 | "-d [-cf] [FILE]..." |
248 | #define xz_full_usage "\n\n" \ | 254 | #define xz_full_usage "\n\n" \ |
249 | "Decompress FILE (or stdin)\n" \ | 255 | "Decompress FILE (or stdin)\n" \ |
250 | "\nOptions:" \ | 256 | "\nOptions:" \ |
@@ -528,7 +534,7 @@ INSERT | |||
528 | "Print the config file used by busybox build" | 534 | "Print the config file used by busybox build" |
529 | 535 | ||
530 | #define chrt_trivial_usage \ | 536 | #define chrt_trivial_usage \ |
531 | "[OPTIONS] [PRIO] [PID | PROG ARGS]" | 537 | "[-prfom] [PRIO] [PID | PROG ARGS]" |
532 | #define chrt_full_usage "\n\n" \ | 538 | #define chrt_full_usage "\n\n" \ |
533 | "Change scheduling priority and class for a process\n" \ | 539 | "Change scheduling priority and class for a process\n" \ |
534 | "\nOptions:" \ | 540 | "\nOptions:" \ |
@@ -696,46 +702,6 @@ INSERT | |||
696 | "$ echo \"Hello world\" | cut -f 2 -d ' '\n" \ | 702 | "$ echo \"Hello world\" | cut -f 2 -d ' '\n" \ |
697 | "world\n" | 703 | "world\n" |
698 | 704 | ||
699 | #define date_trivial_usage \ | ||
700 | "[OPTIONS] [+FMT] [TIME]" | ||
701 | #define date_full_usage "\n\n" \ | ||
702 | "Display time (using +FMT), or set time\n" \ | ||
703 | "\nOptions:" \ | ||
704 | IF_NOT_LONG_OPTS( \ | ||
705 | "\n [-s] TIME Set time to TIME" \ | ||
706 | "\n -u Work in UTC (don't convert to local time)" \ | ||
707 | "\n -R Output RFC-2822 compliant date string" \ | ||
708 | ) IF_LONG_OPTS( \ | ||
709 | "\n [-s,--set] TIME Set time to TIME" \ | ||
710 | "\n -u,--utc Work in UTC (don't convert to local time)" \ | ||
711 | "\n -R,--rfc-2822 Output RFC-2822 compliant date string" \ | ||
712 | ) \ | ||
713 | IF_FEATURE_DATE_ISOFMT( \ | ||
714 | "\n -I[SPEC] Output ISO-8601 compliant date string" \ | ||
715 | "\n SPEC='date' (default) for date only," \ | ||
716 | "\n 'hours', 'minutes', or 'seconds' for date and" \ | ||
717 | "\n time to the indicated precision" \ | ||
718 | ) IF_NOT_LONG_OPTS( \ | ||
719 | "\n -r FILE Display last modification time of FILE" \ | ||
720 | "\n -d TIME Display TIME, not 'now'" \ | ||
721 | ) IF_LONG_OPTS( \ | ||
722 | "\n -r,--reference FILE Display last modification time of FILE" \ | ||
723 | "\n -d,--date TIME Display TIME, not 'now'" \ | ||
724 | ) \ | ||
725 | IF_FEATURE_DATE_ISOFMT( \ | ||
726 | "\n -D FMT Use FMT for -d TIME conversion" \ | ||
727 | ) \ | ||
728 | "\n" \ | ||
729 | "\nRecognized TIME formats:" \ | ||
730 | "\n hh:mm[:ss]" \ | ||
731 | "\n [YYYY.]MM.DD-hh:mm[:ss]" \ | ||
732 | "\n YYYY-MM-DD hh:mm[:ss]" \ | ||
733 | "\n [[[[[YY]YY]MM]DD]hh]mm[.ss]" \ | ||
734 | |||
735 | #define date_example_usage \ | ||
736 | "$ date\n" \ | ||
737 | "Wed Apr 12 18:52:41 MDT 2000\n" | ||
738 | |||
739 | #define dd_trivial_usage \ | 705 | #define dd_trivial_usage \ |
740 | "[if=FILE] [of=FILE] " IF_FEATURE_DD_IBS_OBS("[ibs=N] [obs=N] ") "[bs=N] [count=N] [skip=N]\n" \ | 706 | "[if=FILE] [of=FILE] " IF_FEATURE_DD_IBS_OBS("[ibs=N] [obs=N] ") "[bs=N] [count=N] [skip=N]\n" \ |
741 | " [seek=N]" IF_FEATURE_DD_IBS_OBS(" [conv=notrunc|noerror|sync|fsync]") | 707 | " [seek=N]" IF_FEATURE_DD_IBS_OBS(" [conv=notrunc|noerror|sync|fsync]") |
@@ -785,9 +751,6 @@ INSERT | |||
785 | #define deluser_full_usage "\n\n" \ | 751 | #define deluser_full_usage "\n\n" \ |
786 | "Delete USER from the system" | 752 | "Delete USER from the system" |
787 | 753 | ||
788 | #define depmod_trivial_usage NOUSAGE_STR | ||
789 | #define depmod_full_usage "" | ||
790 | |||
791 | #define devmem_trivial_usage \ | 754 | #define devmem_trivial_usage \ |
792 | "ADDRESS [WIDTH [VALUE]]" | 755 | "ADDRESS [WIDTH [VALUE]]" |
793 | 756 | ||
@@ -910,7 +873,7 @@ INSERT | |||
910 | "\n nameserver NORNAL_DNS_SERVER" \ | 873 | "\n nameserver NORNAL_DNS_SERVER" \ |
911 | 874 | ||
912 | #define dos2unix_trivial_usage \ | 875 | #define dos2unix_trivial_usage \ |
913 | "[OPTIONS] [FILE]" | 876 | "[-ud] [FILE]" |
914 | #define dos2unix_full_usage "\n\n" \ | 877 | #define dos2unix_full_usage "\n\n" \ |
915 | "Convert FILE in-place from DOS to Unix format.\n" \ | 878 | "Convert FILE in-place from DOS to Unix format.\n" \ |
916 | "When no file is given, use stdin/stdout.\n" \ | 879 | "When no file is given, use stdin/stdout.\n" \ |
@@ -919,7 +882,7 @@ INSERT | |||
919 | "\n -d unix2dos" \ | 882 | "\n -d unix2dos" \ |
920 | 883 | ||
921 | #define unix2dos_trivial_usage \ | 884 | #define unix2dos_trivial_usage \ |
922 | "[OPTIONS] [FILE]" | 885 | "[-ud] [FILE]" |
923 | #define unix2dos_full_usage "\n\n" \ | 886 | #define unix2dos_full_usage "\n\n" \ |
924 | "Convert FILE in-place from Unix to DOS format.\n" \ | 887 | "Convert FILE in-place from Unix to DOS format.\n" \ |
925 | "When no file is given, use stdin/stdout.\n" \ | 888 | "When no file is given, use stdin/stdout.\n" \ |
@@ -1295,7 +1258,7 @@ INSERT | |||
1295 | "\n -w Use WIDTH columns instead of 80" \ | 1258 | "\n -w Use WIDTH columns instead of 80" \ |
1296 | 1259 | ||
1297 | #define free_trivial_usage \ | 1260 | #define free_trivial_usage \ |
1298 | "" | 1261 | "" IF_DESKTOP("[-b/k/m/g]") |
1299 | #define free_full_usage "\n\n" \ | 1262 | #define free_full_usage "\n\n" \ |
1300 | "Display the amount of free and used system memory" | 1263 | "Display the amount of free and used system memory" |
1301 | #define free_example_usage \ | 1264 | #define free_example_usage \ |
@@ -1400,8 +1363,7 @@ INSERT | |||
1400 | "Find processes which use FILEs or PORTs\n" \ | 1363 | "Find processes which use FILEs or PORTs\n" \ |
1401 | "\nOptions:" \ | 1364 | "\nOptions:" \ |
1402 | "\n -m Find processes which use same fs as FILEs" \ | 1365 | "\n -m Find processes which use same fs as FILEs" \ |
1403 | "\n -4 Search only IPv4 space" \ | 1366 | "\n -4,-6 Search only IPv4/IPv6 space" \ |
1404 | "\n -6 Search only IPv6 space" \ | ||
1405 | "\n -s Don't display PIDs" \ | 1367 | "\n -s Don't display PIDs" \ |
1406 | "\n -k Kill found processes" \ | 1368 | "\n -k Kill found processes" \ |
1407 | "\n -SIGNAL Signal to send (default: KILL)" \ | 1369 | "\n -SIGNAL Signal to send (default: KILL)" \ |
@@ -1479,7 +1441,7 @@ INSERT | |||
1479 | "\n -H HOST Log HOST into the utmp file as the hostname" \ | 1441 | "\n -H HOST Log HOST into the utmp file as the hostname" \ |
1480 | 1442 | ||
1481 | #define gunzip_trivial_usage \ | 1443 | #define gunzip_trivial_usage \ |
1482 | "[OPTIONS] [FILE]..." | 1444 | "[-cft] [FILE]..." |
1483 | #define gunzip_full_usage "\n\n" \ | 1445 | #define gunzip_full_usage "\n\n" \ |
1484 | "Decompress FILEs (or stdin)\n" \ | 1446 | "Decompress FILEs (or stdin)\n" \ |
1485 | "\nOptions:" \ | 1447 | "\nOptions:" \ |
@@ -1495,7 +1457,7 @@ INSERT | |||
1495 | "-rw-rw-r-- 1 andersen andersen 1761280 Apr 14 17:47 /tmp/BusyBox-0.43.tar\n" | 1457 | "-rw-rw-r-- 1 andersen andersen 1761280 Apr 14 17:47 /tmp/BusyBox-0.43.tar\n" |
1496 | 1458 | ||
1497 | #define gzip_trivial_usage \ | 1459 | #define gzip_trivial_usage \ |
1498 | "[OPTIONS] [FILE]..." | 1460 | "[-cfd] [FILE]..." |
1499 | #define gzip_full_usage "\n\n" \ | 1461 | #define gzip_full_usage "\n\n" \ |
1500 | "Compress FILEs (or stdin)\n" \ | 1462 | "Compress FILEs (or stdin)\n" \ |
1501 | "\nOptions:" \ | 1463 | "\nOptions:" \ |
@@ -1510,18 +1472,6 @@ INSERT | |||
1510 | "$ ls -la /tmp/busybox*\n" \ | 1472 | "$ ls -la /tmp/busybox*\n" \ |
1511 | "-rw-rw-r-- 1 andersen andersen 554058 Apr 14 17:49 /tmp/busybox.tar.gz\n" | 1473 | "-rw-rw-r-- 1 andersen andersen 554058 Apr 14 17:49 /tmp/busybox.tar.gz\n" |
1512 | 1474 | ||
1513 | #define halt_trivial_usage \ | ||
1514 | "[-d DELAY] [-n] [-f]" IF_FEATURE_WTMP(" [-w]") | ||
1515 | #define halt_full_usage "\n\n" \ | ||
1516 | "Halt the system\n" \ | ||
1517 | "\nOptions:" \ | ||
1518 | "\n -d Delay interval for halting" \ | ||
1519 | "\n -n No call to sync()" \ | ||
1520 | "\n -f Force halt (don't go through init)" \ | ||
1521 | IF_FEATURE_WTMP( \ | ||
1522 | "\n -w Only write a wtmp record" \ | ||
1523 | ) | ||
1524 | |||
1525 | #define hdparm_trivial_usage \ | 1475 | #define hdparm_trivial_usage \ |
1526 | "[OPTIONS] [DEVICE]" | 1476 | "[OPTIONS] [DEVICE]" |
1527 | #define hdparm_full_usage "\n\n" \ | 1477 | #define hdparm_full_usage "\n\n" \ |
@@ -1679,7 +1629,7 @@ INSERT | |||
1679 | "\n -i Inetd mode" \ | 1629 | "\n -i Inetd mode" \ |
1680 | "\n -f Don't daemonize" \ | 1630 | "\n -f Don't daemonize" \ |
1681 | "\n -v[v] Verbose" \ | 1631 | "\n -v[v] Verbose" \ |
1682 | "\n -p [IP:]PORT Bind to ip:port (default *:80)" \ | 1632 | "\n -p [IP:]PORT Bind to IP:PORT (default *:80)" \ |
1683 | IF_FEATURE_HTTPD_SETUID( \ | 1633 | IF_FEATURE_HTTPD_SETUID( \ |
1684 | "\n -u USER[:GRP] Set uid/gid after binding to port") \ | 1634 | "\n -u USER[:GRP] Set uid/gid after binding to port") \ |
1685 | IF_FEATURE_HTTPD_BASIC_AUTH( \ | 1635 | IF_FEATURE_HTTPD_BASIC_AUTH( \ |
@@ -1716,13 +1666,13 @@ INSERT | |||
1716 | "Print information about USER or the current user\n" \ | 1666 | "Print information about USER or the current user\n" \ |
1717 | "\nOptions:" \ | 1667 | "\nOptions:" \ |
1718 | IF_SELINUX( \ | 1668 | IF_SELINUX( \ |
1719 | "\n -Z Print the security context" \ | 1669 | "\n -Z Security context" \ |
1720 | ) \ | 1670 | ) \ |
1721 | "\n -u Print user ID" \ | 1671 | "\n -u User ID" \ |
1722 | "\n -g Print group ID" \ | 1672 | "\n -g Group ID" \ |
1723 | "\n -G Print supplementary group IDs" \ | 1673 | "\n -G Supplementary group IDs" \ |
1724 | "\n -n Print name instead of a number" \ | 1674 | "\n -n Print names instead of numbers" \ |
1725 | "\n -r Print real user ID instead of effective ID" \ | 1675 | "\n -r Print real ID instead of effective ID" \ |
1726 | 1676 | ||
1727 | #define id_example_usage \ | 1677 | #define id_example_usage \ |
1728 | "$ id\n" \ | 1678 | "$ id\n" \ |
@@ -1754,10 +1704,10 @@ INSERT | |||
1754 | #define ifenslave_full_usage "\n\n" \ | 1704 | #define ifenslave_full_usage "\n\n" \ |
1755 | "Configure network interfaces for parallel routing\n" \ | 1705 | "Configure network interfaces for parallel routing\n" \ |
1756 | "\nOptions:" \ | 1706 | "\nOptions:" \ |
1757 | "\n -c, --change-active Change active slave" \ | 1707 | "\n -c,--change-active Change active slave" \ |
1758 | "\n -d, --detach Remove slave interface from bonding device" \ | 1708 | "\n -d,--detach Remove slave interface from bonding device" \ |
1759 | "\n -f, --force Force, even if interface is not Ethernet" \ | 1709 | "\n -f,--force Force, even if interface is not Ethernet" \ |
1760 | /* "\n -r, --receive-slave Create a receive-only slave" */ | 1710 | /* "\n -r,--receive-slave Create a receive-only slave" */ |
1761 | 1711 | ||
1762 | #define ifenslave_example_usage \ | 1712 | #define ifenslave_example_usage \ |
1763 | "To create a bond device, simply follow these three steps:\n" \ | 1713 | "To create a bond device, simply follow these three steps:\n" \ |
@@ -1802,7 +1752,7 @@ INSERT | |||
1802 | "\n -k Kill running daemon" \ | 1752 | "\n -k Kill running daemon" \ |
1803 | 1753 | ||
1804 | #define ifup_trivial_usage \ | 1754 | #define ifup_trivial_usage \ |
1805 | "[-ain"IF_FEATURE_IFUPDOWN_MAPPING("m")"vf] IFACE..." | 1755 | "[-an"IF_FEATURE_IFUPDOWN_MAPPING("m")"vf] [-i FILE] IFACE..." |
1806 | #define ifup_full_usage "\n\n" \ | 1756 | #define ifup_full_usage "\n\n" \ |
1807 | "Options:" \ | 1757 | "Options:" \ |
1808 | "\n -a De/configure all interfaces automatically" \ | 1758 | "\n -a De/configure all interfaces automatically" \ |
@@ -1816,7 +1766,7 @@ INSERT | |||
1816 | "\n -f Force de/configuration" \ | 1766 | "\n -f Force de/configuration" \ |
1817 | 1767 | ||
1818 | #define ifdown_trivial_usage \ | 1768 | #define ifdown_trivial_usage \ |
1819 | "[-ain"IF_FEATURE_IFUPDOWN_MAPPING("m")"vf] ifaces..." | 1769 | "[-an"IF_FEATURE_IFUPDOWN_MAPPING("m")"vf] [-i FILE] IFACE..." |
1820 | #define ifdown_full_usage "\n\n" \ | 1770 | #define ifdown_full_usage "\n\n" \ |
1821 | "Options:" \ | 1771 | "Options:" \ |
1822 | "\n -a De/configure all interfaces automatically" \ | 1772 | "\n -a De/configure all interfaces automatically" \ |
@@ -1840,138 +1790,6 @@ INSERT | |||
1840 | "\n -R N Pause services after N connects/min" \ | 1790 | "\n -R N Pause services after N connects/min" \ |
1841 | "\n (default: 0 - disabled)" \ | 1791 | "\n (default: 0 - disabled)" \ |
1842 | 1792 | ||
1843 | #define init_trivial_usage \ | ||
1844 | "" | ||
1845 | #define init_full_usage "\n\n" \ | ||
1846 | "Init is the parent of all processes" | ||
1847 | |||
1848 | #define init_notes_usage \ | ||
1849 | "This version of init is designed to be run only by the kernel.\n" \ | ||
1850 | "\n" \ | ||
1851 | "BusyBox init doesn't support multiple runlevels. The runlevels field of\n" \ | ||
1852 | "the /etc/inittab file is completely ignored by BusyBox init. If you want\n" \ | ||
1853 | "runlevels, use sysvinit.\n" \ | ||
1854 | "\n" \ | ||
1855 | "BusyBox init works just fine without an inittab. If no inittab is found,\n" \ | ||
1856 | "it has the following default behavior:\n" \ | ||
1857 | "\n" \ | ||
1858 | " ::sysinit:/etc/init.d/rcS\n" \ | ||
1859 | " ::askfirst:/bin/sh\n" \ | ||
1860 | " ::ctrlaltdel:/sbin/reboot\n" \ | ||
1861 | " ::shutdown:/sbin/swapoff -a\n" \ | ||
1862 | " ::shutdown:/bin/umount -a -r\n" \ | ||
1863 | " ::restart:/sbin/init\n" \ | ||
1864 | "\n" \ | ||
1865 | "if it detects that /dev/console is _not_ a serial console, it will also run:\n" \ | ||
1866 | "\n" \ | ||
1867 | " tty2::askfirst:/bin/sh\n" \ | ||
1868 | " tty3::askfirst:/bin/sh\n" \ | ||
1869 | " tty4::askfirst:/bin/sh\n" \ | ||
1870 | "\n" \ | ||
1871 | "If you choose to use an /etc/inittab file, the inittab entry format is as follows:\n" \ | ||
1872 | "\n" \ | ||
1873 | " <id>:<runlevels>:<action>:<process>\n" \ | ||
1874 | "\n" \ | ||
1875 | " <id>:\n" \ | ||
1876 | "\n" \ | ||
1877 | " WARNING: This field has a non-traditional meaning for BusyBox init!\n" \ | ||
1878 | " The id field is used by BusyBox init to specify the controlling tty for\n" \ | ||
1879 | " the specified process to run on. The contents of this field are\n" \ | ||
1880 | " appended to \"/dev/\" and used as-is. There is no need for this field to\n" \ | ||
1881 | " be unique, although if it isn't you may have strange results. If this\n" \ | ||
1882 | " field is left blank, the controlling tty is set to the console. Also\n" \ | ||
1883 | " note that if BusyBox detects that a serial console is in use, then only\n" \ | ||
1884 | " entries whose controlling tty is either the serial console or /dev/null\n" \ | ||
1885 | " will be run. BusyBox init does nothing with utmp. We don't need no\n" \ | ||
1886 | " stinkin' utmp.\n" \ | ||
1887 | "\n" \ | ||
1888 | " <runlevels>:\n" \ | ||
1889 | "\n" \ | ||
1890 | " The runlevels field is completely ignored.\n" \ | ||
1891 | "\n" \ | ||
1892 | " <action>:\n" \ | ||
1893 | "\n" \ | ||
1894 | " Valid actions include: sysinit, respawn, askfirst, wait,\n" \ | ||
1895 | " once, restart, ctrlaltdel, and shutdown.\n" \ | ||
1896 | "\n" \ | ||
1897 | " The available actions can be classified into two groups: actions\n" \ | ||
1898 | " that are run only once, and actions that are re-run when the specified\n" \ | ||
1899 | " process exits.\n" \ | ||
1900 | "\n" \ | ||
1901 | " Run only-once actions:\n" \ | ||
1902 | "\n" \ | ||
1903 | " 'sysinit' is the first item run on boot. init waits until all\n" \ | ||
1904 | " sysinit actions are completed before continuing. Following the\n" \ | ||
1905 | " completion of all sysinit actions, all 'wait' actions are run.\n" \ | ||
1906 | " 'wait' actions, like 'sysinit' actions, cause init to wait until\n" \ | ||
1907 | " the specified task completes. 'once' actions are asynchronous,\n" \ | ||
1908 | " therefore, init does not wait for them to complete. 'restart' is\n" \ | ||
1909 | " the action taken to restart the init process. By default this should\n" \ | ||
1910 | " simply run /sbin/init, but can be a script which runs pivot_root or it\n" \ | ||
1911 | " can do all sorts of other interesting things. The 'ctrlaltdel' init\n" \ | ||
1912 | " actions are run when the system detects that someone on the system\n" \ | ||
1913 | " console has pressed the CTRL-ALT-DEL key combination. Typically one\n" \ | ||
1914 | " wants to run 'reboot' at this point to cause the system to reboot.\n" \ | ||
1915 | " Finally the 'shutdown' action specifies the actions to taken when\n" \ | ||
1916 | " init is told to reboot. Unmounting filesystems and disabling swap\n" \ | ||
1917 | " is a very good here.\n" \ | ||
1918 | "\n" \ | ||
1919 | " Run repeatedly actions:\n" \ | ||
1920 | "\n" \ | ||
1921 | " 'respawn' actions are run after the 'once' actions. When a process\n" \ | ||
1922 | " started with a 'respawn' action exits, init automatically restarts\n" \ | ||
1923 | " it. Unlike sysvinit, BusyBox init does not stop processes from\n" \ | ||
1924 | " respawning out of control. The 'askfirst' actions acts just like\n" \ | ||
1925 | " respawn, except that before running the specified process it\n" \ | ||
1926 | " displays the line \"Please press Enter to activate this console.\"\n" \ | ||
1927 | " and then waits for the user to press enter before starting the\n" \ | ||
1928 | " specified process.\n" \ | ||
1929 | "\n" \ | ||
1930 | " Unrecognized actions (like initdefault) will cause init to emit an\n" \ | ||
1931 | " error message, and then go along with its business. All actions are\n" \ | ||
1932 | " run in the order they appear in /etc/inittab.\n" \ | ||
1933 | "\n" \ | ||
1934 | " <process>:\n" \ | ||
1935 | "\n" \ | ||
1936 | " Specifies the process to be executed and its command line.\n" \ | ||
1937 | "\n" \ | ||
1938 | "Example /etc/inittab file:\n" \ | ||
1939 | "\n" \ | ||
1940 | " # This is run first except when booting in single-user mode\n" \ | ||
1941 | " #\n" \ | ||
1942 | " ::sysinit:/etc/init.d/rcS\n" \ | ||
1943 | " \n" \ | ||
1944 | " # /bin/sh invocations on selected ttys\n" \ | ||
1945 | " #\n" \ | ||
1946 | " # Start an \"askfirst\" shell on the console (whatever that may be)\n" \ | ||
1947 | " ::askfirst:-/bin/sh\n" \ | ||
1948 | " # Start an \"askfirst\" shell on /dev/tty2-4\n" \ | ||
1949 | " tty2::askfirst:-/bin/sh\n" \ | ||
1950 | " tty3::askfirst:-/bin/sh\n" \ | ||
1951 | " tty4::askfirst:-/bin/sh\n" \ | ||
1952 | " \n" \ | ||
1953 | " # /sbin/getty invocations for selected ttys\n" \ | ||
1954 | " #\n" \ | ||
1955 | " tty4::respawn:/sbin/getty 38400 tty4\n" \ | ||
1956 | " tty5::respawn:/sbin/getty 38400 tty5\n" \ | ||
1957 | " \n" \ | ||
1958 | " \n" \ | ||
1959 | " # Example of how to put a getty on a serial line (for a terminal)\n" \ | ||
1960 | " #\n" \ | ||
1961 | " #::respawn:/sbin/getty -L ttyS0 9600 vt100\n" \ | ||
1962 | " #::respawn:/sbin/getty -L ttyS1 9600 vt100\n" \ | ||
1963 | " #\n" \ | ||
1964 | " # Example how to put a getty on a modem line\n" \ | ||
1965 | " #::respawn:/sbin/getty 57600 ttyS2\n" \ | ||
1966 | " \n" \ | ||
1967 | " # Stuff to do when restarting the init process\n" \ | ||
1968 | " ::restart:/sbin/init\n" \ | ||
1969 | " \n" \ | ||
1970 | " # Stuff to do before rebooting\n" \ | ||
1971 | " ::ctrlaltdel:/sbin/reboot\n" \ | ||
1972 | " ::shutdown:/bin/umount -a -r\n" \ | ||
1973 | " ::shutdown:/sbin/swapoff -a\n" | ||
1974 | |||
1975 | #define inotifyd_trivial_usage \ | 1793 | #define inotifyd_trivial_usage \ |
1976 | "PROG FILE1[:MASK]..." | 1794 | "PROG FILE1[:MASK]..." |
1977 | #define inotifyd_full_usage "\n\n" \ | 1795 | #define inotifyd_full_usage "\n\n" \ |
@@ -2303,7 +2121,7 @@ INSERT | |||
2303 | "root\n" | 2121 | "root\n" |
2304 | 2122 | ||
2305 | #define logread_trivial_usage \ | 2123 | #define logread_trivial_usage \ |
2306 | "[OPTIONS]" | 2124 | "[-f]" |
2307 | #define logread_full_usage "\n\n" \ | 2125 | #define logread_full_usage "\n\n" \ |
2308 | "Show messages in syslogd's circular buffer\n" \ | 2126 | "Show messages in syslogd's circular buffer\n" \ |
2309 | "\nOptions:" \ | 2127 | "\nOptions:" \ |
@@ -2430,11 +2248,6 @@ INSERT | |||
2430 | "\n -l List long flag names" \ | 2248 | "\n -l List long flag names" \ |
2431 | "\n -v List the file's version/generation number" \ | 2249 | "\n -v List the file's version/generation number" \ |
2432 | 2250 | ||
2433 | #define lsmod_trivial_usage \ | ||
2434 | "" | ||
2435 | #define lsmod_full_usage "\n\n" \ | ||
2436 | "List the currently loaded kernel modules" | ||
2437 | |||
2438 | #define lspci_trivial_usage \ | 2251 | #define lspci_trivial_usage \ |
2439 | "[-mk]" | 2252 | "[-mk]" |
2440 | #define lspci_full_usage "\n\n" \ | 2253 | #define lspci_full_usage "\n\n" \ |
@@ -2520,7 +2333,7 @@ INSERT | |||
2520 | "\nOther options are silently ignored" \ | 2333 | "\nOther options are silently ignored" \ |
2521 | 2334 | ||
2522 | #define man_trivial_usage \ | 2335 | #define man_trivial_usage \ |
2523 | "[OPTIONS] [MANPAGE]..." | 2336 | "[-aw] [MANPAGE]..." |
2524 | #define man_full_usage "\n\n" \ | 2337 | #define man_full_usage "\n\n" \ |
2525 | "Format and display manual page\n" \ | 2338 | "Format and display manual page\n" \ |
2526 | "\nOptions:" \ | 2339 | "\nOptions:" \ |
@@ -2537,8 +2350,8 @@ INSERT | |||
2537 | "\n -V Verify file context on disk matches defaults" \ | 2350 | "\n -V Verify file context on disk matches defaults" \ |
2538 | 2351 | ||
2539 | #define md5sum_trivial_usage \ | 2352 | #define md5sum_trivial_usage \ |
2540 | "[OPTIONS] [FILE]..." \ | 2353 | "[FILE]..." \ |
2541 | IF_FEATURE_MD5_SHA1_SUM_CHECK("\n or: md5sum [OPTIONS] -c [FILE]") | 2354 | IF_FEATURE_MD5_SHA1_SUM_CHECK("\n or: md5sum -c [-sw] [FILE]") |
2542 | #define md5sum_full_usage "\n\n" \ | 2355 | #define md5sum_full_usage "\n\n" \ |
2543 | "Print" IF_FEATURE_MD5_SHA1_SUM_CHECK(" or check") " MD5 checksums" \ | 2356 | "Print" IF_FEATURE_MD5_SHA1_SUM_CHECK(" or check") " MD5 checksums" \ |
2544 | IF_FEATURE_MD5_SHA1_SUM_CHECK( "\n" \ | 2357 | IF_FEATURE_MD5_SHA1_SUM_CHECK( "\n" \ |
@@ -2559,8 +2372,8 @@ INSERT | |||
2559 | "^D\n" | 2372 | "^D\n" |
2560 | 2373 | ||
2561 | #define sha1sum_trivial_usage \ | 2374 | #define sha1sum_trivial_usage \ |
2562 | "[OPTIONS] [FILE]..." \ | 2375 | "[FILE]..." \ |
2563 | IF_FEATURE_MD5_SHA1_SUM_CHECK("\n or: sha1sum [OPTIONS] -c [FILE]") | 2376 | IF_FEATURE_MD5_SHA1_SUM_CHECK("\n or: sha1sum -c [-sw] [FILE]") |
2564 | #define sha1sum_full_usage "\n\n" \ | 2377 | #define sha1sum_full_usage "\n\n" \ |
2565 | "Print" IF_FEATURE_MD5_SHA1_SUM_CHECK(" or check") " SHA1 checksums" \ | 2378 | "Print" IF_FEATURE_MD5_SHA1_SUM_CHECK(" or check") " SHA1 checksums" \ |
2566 | IF_FEATURE_MD5_SHA1_SUM_CHECK( "\n" \ | 2379 | IF_FEATURE_MD5_SHA1_SUM_CHECK( "\n" \ |
@@ -2571,8 +2384,8 @@ INSERT | |||
2571 | ) | 2384 | ) |
2572 | 2385 | ||
2573 | #define sha256sum_trivial_usage \ | 2386 | #define sha256sum_trivial_usage \ |
2574 | "[OPTIONS] [FILE]..." \ | 2387 | "[FILE]..." \ |
2575 | IF_FEATURE_MD5_SHA1_SUM_CHECK("\n or: sha256sum [OPTIONS] -c [FILE]") | 2388 | IF_FEATURE_MD5_SHA1_SUM_CHECK("\n or: sha256sum -c [-sw] [FILE]") |
2576 | #define sha256sum_full_usage "\n\n" \ | 2389 | #define sha256sum_full_usage "\n\n" \ |
2577 | "Print" IF_FEATURE_MD5_SHA1_SUM_CHECK(" or check") " SHA256 checksums" \ | 2390 | "Print" IF_FEATURE_MD5_SHA1_SUM_CHECK(" or check") " SHA256 checksums" \ |
2578 | IF_FEATURE_MD5_SHA1_SUM_CHECK( "\n" \ | 2391 | IF_FEATURE_MD5_SHA1_SUM_CHECK( "\n" \ |
@@ -2583,8 +2396,8 @@ INSERT | |||
2583 | ) | 2396 | ) |
2584 | 2397 | ||
2585 | #define sha512sum_trivial_usage \ | 2398 | #define sha512sum_trivial_usage \ |
2586 | "[OPTIONS] [FILE]..." \ | 2399 | "[FILE]..." \ |
2587 | IF_FEATURE_MD5_SHA1_SUM_CHECK("\n or: sha512sum [OPTIONS] -c [FILE]") | 2400 | IF_FEATURE_MD5_SHA1_SUM_CHECK("\n or: sha512sum -c [-sw] [FILE]") |
2588 | #define sha512sum_full_usage "\n\n" \ | 2401 | #define sha512sum_full_usage "\n\n" \ |
2589 | "Print" IF_FEATURE_MD5_SHA1_SUM_CHECK(" or check") " SHA512 checksums" \ | 2402 | "Print" IF_FEATURE_MD5_SHA1_SUM_CHECK(" or check") " SHA512 checksums" \ |
2590 | IF_FEATURE_MD5_SHA1_SUM_CHECK( "\n" \ | 2403 | IF_FEATURE_MD5_SHA1_SUM_CHECK( "\n" \ |
@@ -2628,13 +2441,6 @@ INSERT | |||
2628 | "the last line match .* to override this.)\n\n" \ | 2441 | "the last line match .* to override this.)\n\n" \ |
2629 | ) | 2442 | ) |
2630 | 2443 | ||
2631 | #define mesg_trivial_usage \ | ||
2632 | "[y|n]" | ||
2633 | #define mesg_full_usage "\n\n" \ | ||
2634 | "Control write access to your terminal\n" \ | ||
2635 | " y Allow write access to your terminal\n" \ | ||
2636 | " n Disallow write access to your terminal" | ||
2637 | |||
2638 | #define microcom_trivial_usage \ | 2444 | #define microcom_trivial_usage \ |
2639 | "[-d DELAY] [-t TIMEOUT] [-s SPEED] [-X] TTY" | 2445 | "[-d DELAY] [-t TIMEOUT] [-s SPEED] [-X] TTY" |
2640 | #define microcom_full_usage "\n\n" \ | 2446 | #define microcom_full_usage "\n\n" \ |
@@ -2651,7 +2457,7 @@ INSERT | |||
2651 | #define mkdir_full_usage "\n\n" \ | 2457 | #define mkdir_full_usage "\n\n" \ |
2652 | "Create DIRECTORY\n" \ | 2458 | "Create DIRECTORY\n" \ |
2653 | "\nOptions:" \ | 2459 | "\nOptions:" \ |
2654 | "\n -m Mode" \ | 2460 | "\n -m MODE Mode" \ |
2655 | "\n -p No error if exists; make parent directories as needed" \ | 2461 | "\n -p No error if exists; make parent directories as needed" \ |
2656 | IF_SELINUX( \ | 2462 | IF_SELINUX( \ |
2657 | "\n -Z Set security context" \ | 2463 | "\n -Z Set security context" \ |
@@ -2666,9 +2472,9 @@ INSERT | |||
2666 | "$ mkdir -p /tmp/foo/bar/baz\n" | 2472 | "$ mkdir -p /tmp/foo/bar/baz\n" |
2667 | 2473 | ||
2668 | #define mkfifo_trivial_usage \ | 2474 | #define mkfifo_trivial_usage \ |
2669 | "[OPTIONS] name" | 2475 | "[-m MODE] " IF_SELINUX("[-Z] ") "NAME" |
2670 | #define mkfifo_full_usage "\n\n" \ | 2476 | #define mkfifo_full_usage "\n\n" \ |
2671 | "Create named pipe (identical to 'mknod name p')\n" \ | 2477 | "Create named pipe\n" \ |
2672 | "\nOptions:" \ | 2478 | "\nOptions:" \ |
2673 | "\n -m MODE Mode (default a=rw)" \ | 2479 | "\n -m MODE Mode (default a=rw)" \ |
2674 | IF_SELINUX( \ | 2480 | IF_SELINUX( \ |
@@ -2750,25 +2556,25 @@ INSERT | |||
2750 | "\n -n LBL Volume label" \ | 2556 | "\n -n LBL Volume label" \ |
2751 | 2557 | ||
2752 | #define mknod_trivial_usage \ | 2558 | #define mknod_trivial_usage \ |
2753 | "[OPTIONS] NAME TYPE MAJOR MINOR" | 2559 | "[-m MODE] " IF_SELINUX("[-Z] ") "NAME TYPE MAJOR MINOR" |
2754 | #define mknod_full_usage "\n\n" \ | 2560 | #define mknod_full_usage "\n\n" \ |
2755 | "Create a special file (block, character, or pipe)\n" \ | 2561 | "Create a special file (block, character, or pipe)\n" \ |
2756 | "\nOptions:" \ | 2562 | "\nOptions:" \ |
2757 | "\n -m Create the special file using the specified mode (default a=rw)" \ | 2563 | "\n -m MODE Creation mode (default a=rw)" \ |
2758 | "\nTYPEs include:" \ | ||
2759 | "\n b: Make a block device" \ | ||
2760 | "\n c or u: Make a character device" \ | ||
2761 | "\n p: Make a named pipe (MAJOR and MINOR are ignored)" \ | ||
2762 | IF_SELINUX( \ | 2564 | IF_SELINUX( \ |
2763 | "\n -Z Set security context" \ | 2565 | "\n -Z Set security context" \ |
2764 | ) | 2566 | ) \ |
2567 | "\nTYPE:" \ | ||
2568 | "\n b Block device" \ | ||
2569 | "\n c or u Character device" \ | ||
2570 | "\n p Named pipe (MAJOR and MINOR are ignored)" \ | ||
2765 | 2571 | ||
2766 | #define mknod_example_usage \ | 2572 | #define mknod_example_usage \ |
2767 | "$ mknod /dev/fd0 b 2 0\n" \ | 2573 | "$ mknod /dev/fd0 b 2 0\n" \ |
2768 | "$ mknod -m 644 /tmp/pipe p\n" | 2574 | "$ mknod -m 644 /tmp/pipe p\n" |
2769 | 2575 | ||
2770 | #define mkswap_trivial_usage \ | 2576 | #define mkswap_trivial_usage \ |
2771 | "[OPTIONS] BLOCKDEV [KBYTES]" | 2577 | "[-L LBL] BLOCKDEV [KBYTES]" |
2772 | #define mkswap_full_usage "\n\n" \ | 2578 | #define mkswap_full_usage "\n\n" \ |
2773 | "Prepare BLOCKDEV to be used as swap partition\n" \ | 2579 | "Prepare BLOCKDEV to be used as swap partition\n" \ |
2774 | "\nOptions:" \ | 2580 | "\nOptions:" \ |
@@ -2890,8 +2696,8 @@ INSERT | |||
2890 | "setpart tell unload unlock weof wset" \ | 2696 | "setpart tell unload unlock weof wset" \ |
2891 | 2697 | ||
2892 | #define mv_trivial_usage \ | 2698 | #define mv_trivial_usage \ |
2893 | "[OPTIONS] SOURCE DEST\n" \ | 2699 | "[-fi] SOURCE DEST\n" \ |
2894 | "or: mv [OPTIONS] SOURCE... DIRECTORY" | 2700 | "or: mv [-fi] SOURCE... DIRECTORY" |
2895 | #define mv_full_usage "\n\n" \ | 2701 | #define mv_full_usage "\n\n" \ |
2896 | "Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY\n" \ | 2702 | "Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY\n" \ |
2897 | "\nOptions:" \ | 2703 | "\nOptions:" \ |
@@ -3026,7 +2832,7 @@ INSERT | |||
3026 | "Change USER's password. If no USER is specified,\n" \ | 2832 | "Change USER's password. If no USER is specified,\n" \ |
3027 | "changes the password for the current user.\n" \ | 2833 | "changes the password for the current user.\n" \ |
3028 | "\nOptions:" \ | 2834 | "\nOptions:" \ |
3029 | "\n -a Algorithm to use for password (des, md5)" /* ", sha1)" */ \ | 2835 | "\n -a ALG Algorithm to use for password (des, md5)" /* ", sha1)" */ \ |
3030 | "\n -d Delete password for the account" \ | 2836 | "\n -d Delete password for the account" \ |
3031 | "\n -l Lock (disable) account" \ | 2837 | "\n -l Lock (disable) account" \ |
3032 | "\n -u Unlock (re-enable) account" \ | 2838 | "\n -u Unlock (re-enable) account" \ |
@@ -3093,10 +2899,12 @@ INSERT | |||
3093 | "List PIDs of all processes with names that match NAMEs" \ | 2899 | "List PIDs of all processes with names that match NAMEs" \ |
3094 | USAGE_PIDOF \ | 2900 | USAGE_PIDOF \ |
3095 | IF_FEATURE_PIDOF_SINGLE( \ | 2901 | IF_FEATURE_PIDOF_SINGLE( \ |
3096 | "\n -s Show only one PID") \ | 2902 | "\n -s Show only one PID" \ |
2903 | ) \ | ||
3097 | IF_FEATURE_PIDOF_OMIT( \ | 2904 | IF_FEATURE_PIDOF_OMIT( \ |
3098 | "\n -o PID Omit given pid" \ | 2905 | "\n -o PID Omit given pid" \ |
3099 | "\n Use %PPID to omit pid of pidof's parent") \ | 2906 | "\n Use %PPID to omit pid of pidof's parent" \ |
2907 | ) \ | ||
3100 | 2908 | ||
3101 | #define pidof_example_usage \ | 2909 | #define pidof_example_usage \ |
3102 | "$ pidof init\n" \ | 2910 | "$ pidof init\n" \ |
@@ -3121,7 +2929,7 @@ INSERT | |||
3121 | #define ping_full_usage "\n\n" \ | 2929 | #define ping_full_usage "\n\n" \ |
3122 | "Send ICMP ECHO_REQUEST packets to network hosts\n" \ | 2930 | "Send ICMP ECHO_REQUEST packets to network hosts\n" \ |
3123 | "\nOptions:" \ | 2931 | "\nOptions:" \ |
3124 | "\n -4, -6 Force IP or IPv6 name resolution" \ | 2932 | "\n -4,-6 Force IP or IPv6 name resolution" \ |
3125 | "\n -c CNT Send only CNT pings" \ | 2933 | "\n -c CNT Send only CNT pings" \ |
3126 | "\n -s SIZE Send SIZE data bytes in packets (default:56)" \ | 2934 | "\n -s SIZE Send SIZE data bytes in packets (default:56)" \ |
3127 | "\n -I IFACE/IP Use interface or IP address as source" \ | 2935 | "\n -I IFACE/IP Use interface or IP address as source" \ |
@@ -3216,15 +3024,6 @@ INSERT | |||
3216 | "$ popmaildir -k ~/Maildir -- nc pop.drvv.ru 110 [<password_file]\n" \ | 3024 | "$ popmaildir -k ~/Maildir -- nc pop.drvv.ru 110 [<password_file]\n" \ |
3217 | "$ popmaildir ~/Maildir -- openssl s_client -quiet -connect pop.gmail.com:995 [<password_file]\n" | 3025 | "$ popmaildir ~/Maildir -- openssl s_client -quiet -connect pop.gmail.com:995 [<password_file]\n" |
3218 | 3026 | ||
3219 | #define poweroff_trivial_usage \ | ||
3220 | "[-d DELAY] [-n] [-f]" | ||
3221 | #define poweroff_full_usage "\n\n" \ | ||
3222 | "Halt and shut off power\n" \ | ||
3223 | "\nOptions:" \ | ||
3224 | "\n -d Delay interval for halting" \ | ||
3225 | "\n -n Do not sync" \ | ||
3226 | "\n -f Force power off (don't go through init)" \ | ||
3227 | |||
3228 | #define printenv_trivial_usage \ | 3027 | #define printenv_trivial_usage \ |
3229 | "[VARIABLE]..." | 3028 | "[VARIABLE]..." |
3230 | #define printenv_full_usage "\n\n" \ | 3029 | #define printenv_full_usage "\n\n" \ |
@@ -3367,15 +3166,6 @@ INSERT | |||
3367 | #define realpath_full_usage "\n\n" \ | 3166 | #define realpath_full_usage "\n\n" \ |
3368 | "Return the absolute pathnames of given FILE" | 3167 | "Return the absolute pathnames of given FILE" |
3369 | 3168 | ||
3370 | #define reboot_trivial_usage \ | ||
3371 | "[-d DELAY] [-n] [-f]" | ||
3372 | #define reboot_full_usage "\n\n" \ | ||
3373 | "Reboot the system\n" \ | ||
3374 | "\nOptions:" \ | ||
3375 | "\n -d Delay interval for rebooting" \ | ||
3376 | "\n -n No call to sync()" \ | ||
3377 | "\n -f Force reboot (don't go through init)" \ | ||
3378 | |||
3379 | #define reformime_trivial_usage \ | 3169 | #define reformime_trivial_usage \ |
3380 | "[OPTIONS] [FILE]..." | 3170 | "[OPTIONS] [FILE]..." |
3381 | #define reformime_full_usage "\n\n" \ | 3171 | #define reformime_full_usage "\n\n" \ |
@@ -3431,7 +3221,7 @@ INSERT | |||
3431 | "\n wimax, wwan, gps, fm" \ | 3221 | "\n wimax, wwan, gps, fm" \ |
3432 | 3222 | ||
3433 | #define rm_trivial_usage \ | 3223 | #define rm_trivial_usage \ |
3434 | "[OPTIONS] FILE..." | 3224 | "[-irf] FILE..." |
3435 | #define rm_full_usage "\n\n" \ | 3225 | #define rm_full_usage "\n\n" \ |
3436 | "Remove (unlink) FILEs\n" \ | 3226 | "Remove (unlink) FILEs\n" \ |
3437 | "\nOptions:" \ | 3227 | "\nOptions:" \ |
@@ -3458,18 +3248,6 @@ INSERT | |||
3458 | #define rmdir_example_usage \ | 3248 | #define rmdir_example_usage \ |
3459 | "# rmdir /tmp/foo\n" | 3249 | "# rmdir /tmp/foo\n" |
3460 | 3250 | ||
3461 | #define rmmod_trivial_usage \ | ||
3462 | "[OPTIONS] [MODULE]..." | ||
3463 | #define rmmod_full_usage "\n\n" \ | ||
3464 | "Unload the specified kernel modules from the kernel\n" \ | ||
3465 | "\nOptions:" \ | ||
3466 | "\n -w Wait until the module is no longer used" \ | ||
3467 | "\n -f Force unloading" \ | ||
3468 | "\n -a Remove all unused modules (recursively)" \ | ||
3469 | |||
3470 | #define rmmod_example_usage \ | ||
3471 | "$ rmmod tulip\n" | ||
3472 | |||
3473 | #define route_trivial_usage \ | 3251 | #define route_trivial_usage \ |
3474 | "[{add|del|delete}]" | 3252 | "[{add|del|delete}]" |
3475 | #define route_full_usage "\n\n" \ | 3253 | #define route_full_usage "\n\n" \ |
@@ -3849,9 +3627,9 @@ INSERT | |||
3849 | "[OPTIONS] [INPUT [PREFIX]]" | 3627 | "[OPTIONS] [INPUT [PREFIX]]" |
3850 | #define split_full_usage "\n\n" \ | 3628 | #define split_full_usage "\n\n" \ |
3851 | "Options:" \ | 3629 | "Options:" \ |
3852 | "\n -b n[k|m] Split by bytes" \ | 3630 | "\n -b N[k|m] Split by N (kilo|mega)bytes" \ |
3853 | "\n -l n Split by lines" \ | 3631 | "\n -l N Split by N lines" \ |
3854 | "\n -a n Use n letters as suffix" \ | 3632 | "\n -a N Use N letters as suffix" \ |
3855 | 3633 | ||
3856 | #define split_example_usage \ | 3634 | #define split_example_usage \ |
3857 | "$ split TODO foo\n" \ | 3635 | "$ split TODO foo\n" \ |
@@ -4080,7 +3858,7 @@ INSERT | |||
4080 | "Write all buffered blocks to disk" | 3858 | "Write all buffered blocks to disk" |
4081 | 3859 | ||
4082 | #define fsync_trivial_usage \ | 3860 | #define fsync_trivial_usage \ |
4083 | "[OPTIONS] FILE..." | 3861 | "[-d] FILE..." |
4084 | #define fsync_full_usage "\n\n" \ | 3862 | #define fsync_full_usage "\n\n" \ |
4085 | "Write files' buffered blocks to disk\n" \ | 3863 | "Write files' buffered blocks to disk\n" \ |
4086 | "\nOptions:" \ | 3864 | "\nOptions:" \ |
@@ -4156,7 +3934,7 @@ INSERT | |||
4156 | "pid 1's current affinity mask: 3\n" | 3934 | "pid 1's current affinity mask: 3\n" |
4157 | 3935 | ||
4158 | #define tee_trivial_usage \ | 3936 | #define tee_trivial_usage \ |
4159 | "[OPTIONS] [FILE]..." | 3937 | "[-ai] [FILE]..." |
4160 | #define tee_full_usage "\n\n" \ | 3938 | #define tee_full_usage "\n\n" \ |
4161 | "Copy stdin to each FILE, and also to stdout\n" \ | 3939 | "Copy stdin to each FILE, and also to stdout\n" \ |
4162 | "\nOptions:" \ | 3940 | "\nOptions:" \ |
@@ -4261,7 +4039,7 @@ INSERT | |||
4261 | "\n -u USER[:GRP] Change to user/group after bind" \ | 4039 | "\n -u USER[:GRP] Change to user/group after bind" \ |
4262 | "\n -c N Handle up to N connections simultaneously" \ | 4040 | "\n -c N Handle up to N connections simultaneously" \ |
4263 | "\n -b N Allow a backlog of approximately N TCP SYNs" \ | 4041 | "\n -b N Allow a backlog of approximately N TCP SYNs" \ |
4264 | "\n -C N[:MSG] Allow only up to N connections from the same IP" \ | 4042 | "\n -C N[:MSG] Allow only up to N connections from the same IP." \ |
4265 | "\n New connections from this IP address are closed" \ | 4043 | "\n New connections from this IP address are closed" \ |
4266 | "\n immediately. MSG is written to the peer before close" \ | 4044 | "\n immediately. MSG is written to the peer before close" \ |
4267 | "\n -h Look up peer's hostname" \ | 4045 | "\n -h Look up peer's hostname" \ |
@@ -4317,7 +4095,7 @@ INSERT | |||
4317 | "\n -u Access files as USER" \ | 4095 | "\n -u Access files as USER" \ |
4318 | 4096 | ||
4319 | #define time_trivial_usage \ | 4097 | #define time_trivial_usage \ |
4320 | "[OPTIONS] PROG ARGS" | 4098 | "[-v] PROG ARGS" |
4321 | #define time_full_usage "\n\n" \ | 4099 | #define time_full_usage "\n\n" \ |
4322 | "Run PROG, display resource usage when it exits\n" \ | 4100 | "Run PROG, display resource usage when it exits\n" \ |
4323 | "\nOptions:" \ | 4101 | "\nOptions:" \ |
@@ -4338,12 +4116,13 @@ INSERT | |||
4338 | //TODO: add options and keyboard commands | 4116 | //TODO: add options and keyboard commands |
4339 | 4117 | ||
4340 | #define touch_trivial_usage \ | 4118 | #define touch_trivial_usage \ |
4341 | "[-c] [-d DATE] FILE [FILE]..." | 4119 | "[-c] [-d DATE] [-r FILE] FILE [FILE]..." |
4342 | #define touch_full_usage "\n\n" \ | 4120 | #define touch_full_usage "\n\n" \ |
4343 | "Update the last-modified date on the given FILE[s]\n" \ | 4121 | "Update the last-modified date on the given FILE[s]\n" \ |
4344 | "\nOptions:" \ | 4122 | "\nOptions:" \ |
4345 | "\n -c Don't create files" \ | 4123 | "\n -c Don't create files" \ |
4346 | "\n -d DT Date/time to use" \ | 4124 | "\n -d DT Date/time to use" \ |
4125 | "\n -r FILE Use FILE's date/time" \ | ||
4347 | 4126 | ||
4348 | #define touch_example_usage \ | 4127 | #define touch_example_usage \ |
4349 | "$ ls -l /tmp/foo\n" \ | 4128 | "$ ls -l /tmp/foo\n" \ |
@@ -4373,7 +4152,7 @@ INSERT | |||
4373 | "Trace the route to HOST\n" \ | 4152 | "Trace the route to HOST\n" \ |
4374 | "\nOptions:" \ | 4153 | "\nOptions:" \ |
4375 | IF_TRACEROUTE6( \ | 4154 | IF_TRACEROUTE6( \ |
4376 | "\n -4, -6 Force IP or IPv6 name resolution" \ | 4155 | "\n -4,-6 Force IP or IPv6 name resolution" \ |
4377 | ) \ | 4156 | ) \ |
4378 | "\n -F Set the don't fragment bit" \ | 4157 | "\n -F Set the don't fragment bit" \ |
4379 | "\n -I Use ICMP ECHO instead of UDP datagrams" \ | 4158 | "\n -I Use ICMP ECHO instead of UDP datagrams" \ |
@@ -4453,18 +4232,6 @@ INSERT | |||
4453 | "# tunctl\n" \ | 4232 | "# tunctl\n" \ |
4454 | "# tunctl -d tun0\n" | 4233 | "# tunctl -d tun0\n" |
4455 | 4234 | ||
4456 | #define tune2fs_trivial_usage \ | ||
4457 | /* "[-c max-mounts-count] [-e errors-behavior] [-g group] " */ \ | ||
4458 | /* "[-i interval[d|m|w]] [-j] [-J journal-options] [-l] [-s sparse-flag] " */ \ | ||
4459 | /* "[-m reserved-blocks-percent] [-o [^]mount-options[,...]] " */ \ | ||
4460 | /* "[-r reserved-blocks-count] [-u user] [-C mount-count] " */ \ | ||
4461 | "[-L LABEL] " \ | ||
4462 | /* "[-M last-mounted-dir] [-O [^]feature[,...]] " */ \ | ||
4463 | /* "[-T last-check-time] [-U UUID] " */ \ | ||
4464 | "BLOCKDEV" | ||
4465 | #define tune2fs_full_usage "\n\n" \ | ||
4466 | "Adjust filesystem options on ext[23] filesystems" | ||
4467 | |||
4468 | #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1 | 4235 | #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1 |
4469 | # define IF_UDHCP_VERBOSE(...) __VA_ARGS__ | 4236 | # define IF_UDHCP_VERBOSE(...) __VA_ARGS__ |
4470 | #else | 4237 | #else |
@@ -4708,13 +4475,15 @@ INSERT | |||
4708 | "Edit FILE\n" \ | 4475 | "Edit FILE\n" \ |
4709 | "\nOptions:" \ | 4476 | "\nOptions:" \ |
4710 | IF_FEATURE_VI_COLON( \ | 4477 | IF_FEATURE_VI_COLON( \ |
4711 | "\n -c Initial command to run ($EXINIT also available)") \ | 4478 | "\n -c Initial command to run ($EXINIT also available)" \ |
4479 | ) \ | ||
4712 | IF_FEATURE_VI_READONLY( \ | 4480 | IF_FEATURE_VI_READONLY( \ |
4713 | "\n -R Read-only") \ | 4481 | "\n -R Read-only" \ |
4482 | ) \ | ||
4714 | "\n -H Short help regarding available features" \ | 4483 | "\n -H Short help regarding available features" \ |
4715 | 4484 | ||
4716 | #define vlock_trivial_usage \ | 4485 | #define vlock_trivial_usage \ |
4717 | "[OPTIONS]" | 4486 | "[-a]" |
4718 | #define vlock_full_usage "\n\n" \ | 4487 | #define vlock_full_usage "\n\n" \ |
4719 | "Lock a virtual terminal. A password is required to unlock.\n" \ | 4488 | "Lock a virtual terminal. A password is required to unlock.\n" \ |
4720 | "\nOptions:" \ | 4489 | "\nOptions:" \ |
@@ -4758,21 +4527,6 @@ INSERT | |||
4758 | "\n" \ | 4527 | "\n" \ |
4759 | "\nUse 500ms to specify period in milliseconds" \ | 4528 | "\nUse 500ms to specify period in milliseconds" \ |
4760 | 4529 | ||
4761 | #define wc_trivial_usage \ | ||
4762 | "[OPTIONS] [FILE]..." | ||
4763 | #define wc_full_usage "\n\n" \ | ||
4764 | "Print line, word, and byte counts for each FILE (or stdin),\n" \ | ||
4765 | "and a total line if more than one FILE is specified\n" \ | ||
4766 | "\nOptions:" \ | ||
4767 | "\n -c Print the byte counts" \ | ||
4768 | "\n -l Print the newline counts" \ | ||
4769 | "\n -L Print the length of the longest line" \ | ||
4770 | "\n -w Print the word counts" \ | ||
4771 | |||
4772 | #define wc_example_usage \ | ||
4773 | "$ wc /etc/passwd\n" \ | ||
4774 | " 31 46 1365 /etc/passwd\n" | ||
4775 | |||
4776 | #define wget_trivial_usage \ | 4530 | #define wget_trivial_usage \ |
4777 | IF_FEATURE_WGET_LONG_OPTIONS( \ | 4531 | IF_FEATURE_WGET_LONG_OPTIONS( \ |
4778 | "[-c|--continue] [-s|--spider] [-q|--quiet] [-O|--output-document FILE]\n" \ | 4532 | "[-c|--continue] [-s|--spider] [-q|--quiet] [-O|--output-document FILE]\n" \ |
diff --git a/init/Config.src b/init/Config.src index 2cac3573e..5767c93f0 100644 --- a/init/Config.src +++ b/init/Config.src | |||
@@ -7,131 +7,4 @@ menu "Init Utilities" | |||
7 | 7 | ||
8 | INSERT | 8 | INSERT |
9 | 9 | ||
10 | config INIT | ||
11 | bool "init" | ||
12 | default y | ||
13 | select FEATURE_SYSLOG | ||
14 | help | ||
15 | init is the first program run when the system boots. | ||
16 | |||
17 | config FEATURE_USE_INITTAB | ||
18 | bool "Support reading an inittab file" | ||
19 | default y | ||
20 | depends on INIT | ||
21 | help | ||
22 | Allow init to read an inittab file when the system boot. | ||
23 | |||
24 | config FEATURE_KILL_REMOVED | ||
25 | bool "Support killing processes that have been removed from inittab" | ||
26 | default n | ||
27 | depends on FEATURE_USE_INITTAB | ||
28 | help | ||
29 | When respawn entries are removed from inittab and a SIGHUP is | ||
30 | sent to init, this option will make init kill the processes | ||
31 | that have been removed. | ||
32 | |||
33 | config FEATURE_KILL_DELAY | ||
34 | int "How long to wait between TERM and KILL (0 - send TERM only)" if FEATURE_KILL_REMOVED | ||
35 | range 0 1024 | ||
36 | default 0 | ||
37 | depends on FEATURE_KILL_REMOVED | ||
38 | help | ||
39 | With nonzero setting, init sends TERM, forks, child waits N | ||
40 | seconds, sends KILL and exits. Setting it too high is unwise | ||
41 | (child will hang around for too long and could actually kill | ||
42 | the wrong process!) | ||
43 | |||
44 | config FEATURE_INIT_SCTTY | ||
45 | bool "Run commands with leading dash with controlling tty" | ||
46 | default y | ||
47 | depends on INIT | ||
48 | help | ||
49 | If this option is enabled, init will try to give a controlling | ||
50 | tty to any command which has leading hyphen (often it's "-/bin/sh"). | ||
51 | More precisely, init will do "ioctl(STDIN_FILENO, TIOCSCTTY, 0)". | ||
52 | If device attached to STDIN_FILENO can be a ctty but is not yet | ||
53 | a ctty for other session, it will become this process' ctty. | ||
54 | This is not the traditional init behavour, but is often what you want | ||
55 | in an embedded system where the console is only accessed during | ||
56 | development or for maintenance. | ||
57 | NB: using cttyhack applet may work better. | ||
58 | |||
59 | config FEATURE_INIT_SYSLOG | ||
60 | bool "Enable init to write to syslog" | ||
61 | default y | ||
62 | depends on INIT | ||
63 | |||
64 | config FEATURE_EXTRA_QUIET | ||
65 | bool "Be _extra_ quiet on boot" | ||
66 | default y | ||
67 | depends on INIT | ||
68 | help | ||
69 | Prevent init from logging some messages to the console during boot. | ||
70 | |||
71 | config FEATURE_INIT_COREDUMPS | ||
72 | bool "Support dumping core for child processes (debugging only)" | ||
73 | default y | ||
74 | depends on INIT | ||
75 | help | ||
76 | If this option is enabled and the file /.init_enable_core | ||
77 | exists, then init will call setrlimit() to allow unlimited | ||
78 | core file sizes. If this option is disabled, processes | ||
79 | will not generate any core files. | ||
80 | |||
81 | config FEATURE_INITRD | ||
82 | bool "Support running init from within an initrd (not initramfs)" | ||
83 | default y | ||
84 | depends on INIT | ||
85 | help | ||
86 | Legacy support for running init under the old-style initrd. Allows | ||
87 | the name linuxrc to act as init, and it doesn't assume init is PID 1. | ||
88 | |||
89 | This does not apply to initramfs, which runs /init as PID 1 and | ||
90 | requires no special support. | ||
91 | |||
92 | config INIT_TERMINAL_TYPE | ||
93 | string "Initial terminal type" | ||
94 | default "linux" | ||
95 | depends on INIT | ||
96 | help | ||
97 | This is the initial value set by init for the TERM environment | ||
98 | variable. This variable is used by programs which make use of | ||
99 | extended terminal capabilities. | ||
100 | |||
101 | Note that on Linux, init attempts to detect serial terminal and | ||
102 | sets TERM to "vt102" if one is found. | ||
103 | |||
104 | config HALT | ||
105 | bool "poweroff, halt, and reboot" | ||
106 | default y | ||
107 | help | ||
108 | Stop all processes and either halt, reboot, or power off the system. | ||
109 | |||
110 | config FEATURE_CALL_TELINIT | ||
111 | bool "Call telinit on shutdown and reboot" | ||
112 | default y | ||
113 | depends on HALT && !INIT | ||
114 | help | ||
115 | Call an external program (normally telinit) to facilitate | ||
116 | a switch to a proper runlevel. | ||
117 | |||
118 | This option is only available if you selected halt and friends, | ||
119 | but did not select init. | ||
120 | |||
121 | config TELINIT_PATH | ||
122 | string "Path to telinit executable" | ||
123 | default "/sbin/telinit" | ||
124 | depends on FEATURE_CALL_TELINIT | ||
125 | help | ||
126 | When busybox halt and friends have to call external telinit | ||
127 | to facilitate proper shutdown, this path is to be used when | ||
128 | locating telinit executable. | ||
129 | |||
130 | config MESG | ||
131 | bool "mesg" | ||
132 | default y | ||
133 | help | ||
134 | Mesg controls access to your terminal by others. It is typically | ||
135 | used to allow or disallow other users to write to your terminal | ||
136 | |||
137 | endmenu | 10 | endmenu |
diff --git a/init/Kbuild.src b/init/Kbuild.src index 32dd5a045..6b4fb7470 100644 --- a/init/Kbuild.src +++ b/init/Kbuild.src | |||
@@ -7,7 +7,3 @@ | |||
7 | lib-y:= | 7 | lib-y:= |
8 | 8 | ||
9 | INSERT | 9 | INSERT |
10 | lib-$(CONFIG_HALT) += halt.o | ||
11 | lib-$(CONFIG_INIT) += init.o | ||
12 | lib-$(CONFIG_MESG) += mesg.o | ||
13 | lib-$(CONFIG_BOOTCHARTD) += bootchartd.o | ||
diff --git a/init/bootchartd.c b/init/bootchartd.c index f14d5c0fd..5a1b3e8e8 100644 --- a/init/bootchartd.c +++ b/init/bootchartd.c | |||
@@ -3,6 +3,10 @@ | |||
3 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 3 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
4 | */ | 4 | */ |
5 | 5 | ||
6 | //applet:IF_BOOTCHARTD(APPLET(bootchartd, _BB_DIR_SBIN, _BB_SUID_DROP)) | ||
7 | |||
8 | //kbuild:lib-$(CONFIG_BOOTCHARTD) += bootchartd.o | ||
9 | |||
6 | //config:config BOOTCHARTD | 10 | //config:config BOOTCHARTD |
7 | //config: bool "bootchartd" | 11 | //config: bool "bootchartd" |
8 | //config: default y | 12 | //config: default y |
diff --git a/init/halt.c b/init/halt.c index 903953e80..47f1ef7b2 100644 --- a/init/halt.c +++ b/init/halt.c | |||
@@ -7,6 +7,68 @@ | |||
7 | * Licensed under GPLv2, see file LICENSE in this source tree. | 7 | * Licensed under GPLv2, see file LICENSE in this source tree. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | //applet:IF_HALT(APPLET(halt, _BB_DIR_SBIN, _BB_SUID_DROP)) | ||
11 | //applet:IF_HALT(APPLET_ODDNAME(poweroff, halt, _BB_DIR_SBIN, _BB_SUID_DROP, poweroff)) | ||
12 | //applet:IF_HALT(APPLET_ODDNAME(reboot, halt, _BB_DIR_SBIN, _BB_SUID_DROP, reboot)) | ||
13 | |||
14 | //kbuild:lib-$(CONFIG_HALT) += halt.o | ||
15 | |||
16 | //config:config HALT | ||
17 | //config: bool "poweroff, halt, and reboot" | ||
18 | //config: default y | ||
19 | //config: help | ||
20 | //config: Stop all processes and either halt, reboot, or power off the system. | ||
21 | //config: | ||
22 | //config:config FEATURE_CALL_TELINIT | ||
23 | //config: bool "Call telinit on shutdown and reboot" | ||
24 | //config: default y | ||
25 | //config: depends on HALT && !INIT | ||
26 | //config: help | ||
27 | //config: Call an external program (normally telinit) to facilitate | ||
28 | //config: a switch to a proper runlevel. | ||
29 | //config: | ||
30 | //config: This option is only available if you selected halt and friends, | ||
31 | //config: but did not select init. | ||
32 | //config: | ||
33 | //config:config TELINIT_PATH | ||
34 | //config: string "Path to telinit executable" | ||
35 | //config: default "/sbin/telinit" | ||
36 | //config: depends on FEATURE_CALL_TELINIT | ||
37 | //config: help | ||
38 | //config: When busybox halt and friends have to call external telinit | ||
39 | //config: to facilitate proper shutdown, this path is to be used when | ||
40 | //config: locating telinit executable. | ||
41 | |||
42 | //usage:#define halt_trivial_usage | ||
43 | //usage: "[-d DELAY] [-n] [-f]" IF_FEATURE_WTMP(" [-w]") | ||
44 | //usage:#define halt_full_usage "\n\n" | ||
45 | //usage: "Halt the system\n" | ||
46 | //usage: "\nOptions:" | ||
47 | //usage: "\n -d SEC Delay interval" | ||
48 | //usage: "\n -n Do not sync" | ||
49 | //usage: "\n -f Force (don't go through init)" | ||
50 | //usage: IF_FEATURE_WTMP( | ||
51 | //usage: "\n -w Only write a wtmp record" | ||
52 | //usage: ) | ||
53 | //usage: | ||
54 | //usage:#define poweroff_trivial_usage | ||
55 | //usage: "[-d DELAY] [-n] [-f]" | ||
56 | //usage:#define poweroff_full_usage "\n\n" | ||
57 | //usage: "Halt and shut off power\n" | ||
58 | //usage: "\nOptions:" | ||
59 | //usage: "\n -d SEC Delay interval" | ||
60 | //usage: "\n -n Do not sync" | ||
61 | //usage: "\n -f Force (don't go through init)" | ||
62 | //usage: | ||
63 | //usage:#define reboot_trivial_usage | ||
64 | //usage: "[-d DELAY] [-n] [-f]" | ||
65 | //usage:#define reboot_full_usage "\n\n" | ||
66 | //usage: "Reboot the system\n" | ||
67 | //usage: "\nOptions:" | ||
68 | //usage: "\n -d SEC Delay interval" | ||
69 | //usage: "\n -n Do not sync" | ||
70 | //usage: "\n -f Force (don't go through init)" | ||
71 | |||
10 | #include "libbb.h" | 72 | #include "libbb.h" |
11 | #include "reboot.h" | 73 | #include "reboot.h" |
12 | 74 | ||
diff --git a/init/init.c b/init/init.c index 5c0d11402..340731b8b 100644 --- a/init/init.c +++ b/init/init.c | |||
@@ -9,6 +9,237 @@ | |||
9 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 9 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | //applet:IF_INIT(APPLET(init, _BB_DIR_SBIN, _BB_SUID_DROP)) | ||
13 | //applet:IF_FEATURE_INITRD(APPLET_ODDNAME(linuxrc, init, _BB_DIR_ROOT, _BB_SUID_DROP, linuxrc)) | ||
14 | |||
15 | //kbuild:lib-$(CONFIG_INIT) += init.o | ||
16 | |||
17 | //config:config INIT | ||
18 | //config: bool "init" | ||
19 | //config: default y | ||
20 | //config: select FEATURE_SYSLOG | ||
21 | //config: help | ||
22 | //config: init is the first program run when the system boots. | ||
23 | //config: | ||
24 | //config:config FEATURE_USE_INITTAB | ||
25 | //config: bool "Support reading an inittab file" | ||
26 | //config: default y | ||
27 | //config: depends on INIT | ||
28 | //config: help | ||
29 | //config: Allow init to read an inittab file when the system boot. | ||
30 | //config: | ||
31 | //config:config FEATURE_KILL_REMOVED | ||
32 | //config: bool "Support killing processes that have been removed from inittab" | ||
33 | //config: default n | ||
34 | //config: depends on FEATURE_USE_INITTAB | ||
35 | //config: help | ||
36 | //config: When respawn entries are removed from inittab and a SIGHUP is | ||
37 | //config: sent to init, this option will make init kill the processes | ||
38 | //config: that have been removed. | ||
39 | //config: | ||
40 | //config:config FEATURE_KILL_DELAY | ||
41 | //config: int "How long to wait between TERM and KILL (0 - send TERM only)" if FEATURE_KILL_REMOVED | ||
42 | //config: range 0 1024 | ||
43 | //config: default 0 | ||
44 | //config: depends on FEATURE_KILL_REMOVED | ||
45 | //config: help | ||
46 | //config: With nonzero setting, init sends TERM, forks, child waits N | ||
47 | //config: seconds, sends KILL and exits. Setting it too high is unwise | ||
48 | //config: (child will hang around for too long and could actually kill | ||
49 | //config: the wrong process!) | ||
50 | //config: | ||
51 | //config:config FEATURE_INIT_SCTTY | ||
52 | //config: bool "Run commands with leading dash with controlling tty" | ||
53 | //config: default y | ||
54 | //config: depends on INIT | ||
55 | //config: help | ||
56 | //config: If this option is enabled, init will try to give a controlling | ||
57 | //config: tty to any command which has leading hyphen (often it's "-/bin/sh"). | ||
58 | //config: More precisely, init will do "ioctl(STDIN_FILENO, TIOCSCTTY, 0)". | ||
59 | //config: If device attached to STDIN_FILENO can be a ctty but is not yet | ||
60 | //config: a ctty for other session, it will become this process' ctty. | ||
61 | //config: This is not the traditional init behavour, but is often what you want | ||
62 | //config: in an embedded system where the console is only accessed during | ||
63 | //config: development or for maintenance. | ||
64 | //config: NB: using cttyhack applet may work better. | ||
65 | //config: | ||
66 | //config:config FEATURE_INIT_SYSLOG | ||
67 | //config: bool "Enable init to write to syslog" | ||
68 | //config: default y | ||
69 | //config: depends on INIT | ||
70 | //config: | ||
71 | //config:config FEATURE_EXTRA_QUIET | ||
72 | //config: bool "Be _extra_ quiet on boot" | ||
73 | //config: default y | ||
74 | //config: depends on INIT | ||
75 | //config: help | ||
76 | //config: Prevent init from logging some messages to the console during boot. | ||
77 | //config: | ||
78 | //config:config FEATURE_INIT_COREDUMPS | ||
79 | //config: bool "Support dumping core for child processes (debugging only)" | ||
80 | //config: default y | ||
81 | //config: depends on INIT | ||
82 | //config: help | ||
83 | //config: If this option is enabled and the file /.init_enable_core | ||
84 | //config: exists, then init will call setrlimit() to allow unlimited | ||
85 | //config: core file sizes. If this option is disabled, processes | ||
86 | //config: will not generate any core files. | ||
87 | //config: | ||
88 | //config:config FEATURE_INITRD | ||
89 | //config: bool "Support running init from within an initrd (not initramfs)" | ||
90 | //config: default y | ||
91 | //config: depends on INIT | ||
92 | //config: help | ||
93 | //config: Legacy support for running init under the old-style initrd. Allows | ||
94 | //config: the name linuxrc to act as init, and it doesn't assume init is PID 1. | ||
95 | //config: | ||
96 | //config: This does not apply to initramfs, which runs /init as PID 1 and | ||
97 | //config: requires no special support. | ||
98 | //config: | ||
99 | //config:config INIT_TERMINAL_TYPE | ||
100 | //config: string "Initial terminal type" | ||
101 | //config: default "linux" | ||
102 | //config: depends on INIT | ||
103 | //config: help | ||
104 | //config: This is the initial value set by init for the TERM environment | ||
105 | //config: variable. This variable is used by programs which make use of | ||
106 | //config: extended terminal capabilities. | ||
107 | //config: | ||
108 | //config: Note that on Linux, init attempts to detect serial terminal and | ||
109 | //config: sets TERM to "vt102" if one is found. | ||
110 | |||
111 | //usage:#define init_trivial_usage | ||
112 | //usage: "" | ||
113 | //usage:#define init_full_usage "\n\n" | ||
114 | //usage: "Init is the parent of all processes" | ||
115 | //usage: | ||
116 | //usage:#define init_notes_usage | ||
117 | //usage: "This version of init is designed to be run only by the kernel.\n" | ||
118 | //usage: "\n" | ||
119 | //usage: "BusyBox init doesn't support multiple runlevels. The runlevels field of\n" | ||
120 | //usage: "the /etc/inittab file is completely ignored by BusyBox init. If you want\n" | ||
121 | //usage: "runlevels, use sysvinit.\n" | ||
122 | //usage: "\n" | ||
123 | //usage: "BusyBox init works just fine without an inittab. If no inittab is found,\n" | ||
124 | //usage: "it has the following default behavior:\n" | ||
125 | //usage: "\n" | ||
126 | //usage: " ::sysinit:/etc/init.d/rcS\n" | ||
127 | //usage: " ::askfirst:/bin/sh\n" | ||
128 | //usage: " ::ctrlaltdel:/sbin/reboot\n" | ||
129 | //usage: " ::shutdown:/sbin/swapoff -a\n" | ||
130 | //usage: " ::shutdown:/bin/umount -a -r\n" | ||
131 | //usage: " ::restart:/sbin/init\n" | ||
132 | //usage: "\n" | ||
133 | //usage: "if it detects that /dev/console is _not_ a serial console, it will also run:\n" | ||
134 | //usage: "\n" | ||
135 | //usage: " tty2::askfirst:/bin/sh\n" | ||
136 | //usage: " tty3::askfirst:/bin/sh\n" | ||
137 | //usage: " tty4::askfirst:/bin/sh\n" | ||
138 | //usage: "\n" | ||
139 | //usage: "If you choose to use an /etc/inittab file, the inittab entry format is as follows:\n" | ||
140 | //usage: "\n" | ||
141 | //usage: " <id>:<runlevels>:<action>:<process>\n" | ||
142 | //usage: "\n" | ||
143 | //usage: " <id>:\n" | ||
144 | //usage: "\n" | ||
145 | //usage: " WARNING: This field has a non-traditional meaning for BusyBox init!\n" | ||
146 | //usage: " The id field is used by BusyBox init to specify the controlling tty for\n" | ||
147 | //usage: " the specified process to run on. The contents of this field are\n" | ||
148 | //usage: " appended to \"/dev/\" and used as-is. There is no need for this field to\n" | ||
149 | //usage: " be unique, although if it isn't you may have strange results. If this\n" | ||
150 | //usage: " field is left blank, the controlling tty is set to the console. Also\n" | ||
151 | //usage: " note that if BusyBox detects that a serial console is in use, then only\n" | ||
152 | //usage: " entries whose controlling tty is either the serial console or /dev/null\n" | ||
153 | //usage: " will be run. BusyBox init does nothing with utmp. We don't need no\n" | ||
154 | //usage: " stinkin' utmp.\n" | ||
155 | //usage: "\n" | ||
156 | //usage: " <runlevels>:\n" | ||
157 | //usage: "\n" | ||
158 | //usage: " The runlevels field is completely ignored.\n" | ||
159 | //usage: "\n" | ||
160 | //usage: " <action>:\n" | ||
161 | //usage: "\n" | ||
162 | //usage: " Valid actions include: sysinit, respawn, askfirst, wait,\n" | ||
163 | //usage: " once, restart, ctrlaltdel, and shutdown.\n" | ||
164 | //usage: "\n" | ||
165 | //usage: " The available actions can be classified into two groups: actions\n" | ||
166 | //usage: " that are run only once, and actions that are re-run when the specified\n" | ||
167 | //usage: " process exits.\n" | ||
168 | //usage: "\n" | ||
169 | //usage: " Run only-once actions:\n" | ||
170 | //usage: "\n" | ||
171 | //usage: " 'sysinit' is the first item run on boot. init waits until all\n" | ||
172 | //usage: " sysinit actions are completed before continuing. Following the\n" | ||
173 | //usage: " completion of all sysinit actions, all 'wait' actions are run.\n" | ||
174 | //usage: " 'wait' actions, like 'sysinit' actions, cause init to wait until\n" | ||
175 | //usage: " the specified task completes. 'once' actions are asynchronous,\n" | ||
176 | //usage: " therefore, init does not wait for them to complete. 'restart' is\n" | ||
177 | //usage: " the action taken to restart the init process. By default this should\n" | ||
178 | //usage: " simply run /sbin/init, but can be a script which runs pivot_root or it\n" | ||
179 | //usage: " can do all sorts of other interesting things. The 'ctrlaltdel' init\n" | ||
180 | //usage: " actions are run when the system detects that someone on the system\n" | ||
181 | //usage: " console has pressed the CTRL-ALT-DEL key combination. Typically one\n" | ||
182 | //usage: " wants to run 'reboot' at this point to cause the system to reboot.\n" | ||
183 | //usage: " Finally the 'shutdown' action specifies the actions to taken when\n" | ||
184 | //usage: " init is told to reboot. Unmounting filesystems and disabling swap\n" | ||
185 | //usage: " is a very good here.\n" | ||
186 | //usage: "\n" | ||
187 | //usage: " Run repeatedly actions:\n" | ||
188 | //usage: "\n" | ||
189 | //usage: " 'respawn' actions are run after the 'once' actions. When a process\n" | ||
190 | //usage: " started with a 'respawn' action exits, init automatically restarts\n" | ||
191 | //usage: " it. Unlike sysvinit, BusyBox init does not stop processes from\n" | ||
192 | //usage: " respawning out of control. The 'askfirst' actions acts just like\n" | ||
193 | //usage: " respawn, except that before running the specified process it\n" | ||
194 | //usage: " displays the line \"Please press Enter to activate this console.\"\n" | ||
195 | //usage: " and then waits for the user to press enter before starting the\n" | ||
196 | //usage: " specified process.\n" | ||
197 | //usage: "\n" | ||
198 | //usage: " Unrecognized actions (like initdefault) will cause init to emit an\n" | ||
199 | //usage: " error message, and then go along with its business. All actions are\n" | ||
200 | //usage: " run in the order they appear in /etc/inittab.\n" | ||
201 | //usage: "\n" | ||
202 | //usage: " <process>:\n" | ||
203 | //usage: "\n" | ||
204 | //usage: " Specifies the process to be executed and its command line.\n" | ||
205 | //usage: "\n" | ||
206 | //usage: "Example /etc/inittab file:\n" | ||
207 | //usage: "\n" | ||
208 | //usage: " # This is run first except when booting in single-user mode\n" | ||
209 | //usage: " #\n" | ||
210 | //usage: " ::sysinit:/etc/init.d/rcS\n" | ||
211 | //usage: " \n" | ||
212 | //usage: " # /bin/sh invocations on selected ttys\n" | ||
213 | //usage: " #\n" | ||
214 | //usage: " # Start an \"askfirst\" shell on the console (whatever that may be)\n" | ||
215 | //usage: " ::askfirst:-/bin/sh\n" | ||
216 | //usage: " # Start an \"askfirst\" shell on /dev/tty2-4\n" | ||
217 | //usage: " tty2::askfirst:-/bin/sh\n" | ||
218 | //usage: " tty3::askfirst:-/bin/sh\n" | ||
219 | //usage: " tty4::askfirst:-/bin/sh\n" | ||
220 | //usage: " \n" | ||
221 | //usage: " # /sbin/getty invocations for selected ttys\n" | ||
222 | //usage: " #\n" | ||
223 | //usage: " tty4::respawn:/sbin/getty 38400 tty4\n" | ||
224 | //usage: " tty5::respawn:/sbin/getty 38400 tty5\n" | ||
225 | //usage: " \n" | ||
226 | //usage: " \n" | ||
227 | //usage: " # Example of how to put a getty on a serial line (for a terminal)\n" | ||
228 | //usage: " #\n" | ||
229 | //usage: " #::respawn:/sbin/getty -L ttyS0 9600 vt100\n" | ||
230 | //usage: " #::respawn:/sbin/getty -L ttyS1 9600 vt100\n" | ||
231 | //usage: " #\n" | ||
232 | //usage: " # Example how to put a getty on a modem line\n" | ||
233 | //usage: " #::respawn:/sbin/getty 57600 ttyS2\n" | ||
234 | //usage: " \n" | ||
235 | //usage: " # Stuff to do when restarting the init process\n" | ||
236 | //usage: " ::restart:/sbin/init\n" | ||
237 | //usage: " \n" | ||
238 | //usage: " # Stuff to do before rebooting\n" | ||
239 | //usage: " ::ctrlaltdel:/sbin/reboot\n" | ||
240 | //usage: " ::shutdown:/bin/umount -a -r\n" | ||
241 | //usage: " ::shutdown:/sbin/swapoff -a\n" | ||
242 | |||
12 | #include "libbb.h" | 243 | #include "libbb.h" |
13 | #include <syslog.h> | 244 | #include <syslog.h> |
14 | #include <paths.h> | 245 | #include <paths.h> |
diff --git a/init/mesg.c b/init/mesg.c index ef5f0eb66..b560df205 100644 --- a/init/mesg.c +++ b/init/mesg.c | |||
@@ -7,6 +7,24 @@ | |||
7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | //applet:IF_MESG(APPLET(mesg, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | ||
11 | |||
12 | //kbuild:lib-$(CONFIG_MESG) += mesg.o | ||
13 | |||
14 | //config:config MESG | ||
15 | //config: bool "mesg" | ||
16 | //config: default y | ||
17 | //config: help | ||
18 | //config: Mesg controls access to your terminal by others. It is typically | ||
19 | //config: used to allow or disallow other users to write to your terminal | ||
20 | |||
21 | //usage:#define mesg_trivial_usage | ||
22 | //usage: "[y|n]" | ||
23 | //usage:#define mesg_full_usage "\n\n" | ||
24 | //usage: "Control write access to your terminal\n" | ||
25 | //usage: " y Allow write access to your terminal\n" | ||
26 | //usage: " n Disallow write access to your terminal" | ||
27 | |||
10 | #include "libbb.h" | 28 | #include "libbb.h" |
11 | 29 | ||
12 | #ifdef USE_TTY_GROUP | 30 | #ifdef USE_TTY_GROUP |
diff --git a/libbb/appletlib.c b/libbb/appletlib.c index ab1d48c31..3b691f945 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c | |||
@@ -592,9 +592,11 @@ static const char usr_sbin[] ALIGN1 = "/usr/sbin/"; | |||
592 | static const char *const install_dir[] = { | 592 | static const char *const install_dir[] = { |
593 | &usr_bin [8], /* "/" */ | 593 | &usr_bin [8], /* "/" */ |
594 | &usr_bin [4], /* "/bin/" */ | 594 | &usr_bin [4], /* "/bin/" */ |
595 | &usr_sbin[4], /* "/sbin/" */ | 595 | &usr_sbin[4] /* "/sbin/" */ |
596 | usr_bin, | 596 | # if !ENABLE_INSTALL_NO_USR |
597 | usr_sbin | 597 | ,usr_bin |
598 | ,usr_sbin | ||
599 | # endif | ||
598 | }; | 600 | }; |
599 | 601 | ||
600 | 602 | ||
diff --git a/libbb/md5.c b/libbb/md5.c index d8655ba91..051c8ede4 100644 --- a/libbb/md5.c +++ b/libbb/md5.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | 1 | /* vi: set sw=4 ts=4: */ |
2 | /* | 2 | /* |
3 | * md5.c - Compute MD5 checksum of strings according to the | 3 | * Compute MD5 checksum of strings according to the |
4 | * definition of MD5 in RFC 1321 from April 1992. | 4 | * definition of MD5 in RFC 1321 from April 1992. |
5 | * | 5 | * |
6 | * Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. | 6 | * Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. |
7 | * | 7 | * |
@@ -33,8 +33,7 @@ void FAST_FUNC md5_begin(md5_ctx_t *ctx) | |||
33 | ctx->B = 0xefcdab89; | 33 | ctx->B = 0xefcdab89; |
34 | ctx->C = 0x98badcfe; | 34 | ctx->C = 0x98badcfe; |
35 | ctx->D = 0x10325476; | 35 | ctx->D = 0x10325476; |
36 | ctx->total = 0; | 36 | ctx->total64 = 0; |
37 | ctx->buflen = 0; | ||
38 | } | 37 | } |
39 | 38 | ||
40 | /* These are the four functions used in the four steps of the MD5 algorithm | 39 | /* These are the four functions used in the four steps of the MD5 algorithm |
@@ -49,13 +48,14 @@ void FAST_FUNC md5_begin(md5_ctx_t *ctx) | |||
49 | 48 | ||
50 | #define rotl32(w, s) (((w) << (s)) | ((w) >> (32 - (s)))) | 49 | #define rotl32(w, s) (((w) << (s)) | ((w) >> (32 - (s)))) |
51 | 50 | ||
52 | /* Hash a single block, 64 bytes long and 4-byte aligned. */ | 51 | /* Hash a single block, 64 bytes long and 4-byte aligned */ |
53 | static void md5_hash_block(const void *buffer, md5_ctx_t *ctx) | 52 | static void md5_process_block64(md5_ctx_t *ctx) |
54 | { | 53 | { |
55 | uint32_t correct_words[16]; | ||
56 | const uint32_t *words = buffer; | ||
57 | |||
58 | #if MD5_SIZE_VS_SPEED > 0 | 54 | #if MD5_SIZE_VS_SPEED > 0 |
55 | /* Before we start, one word to the strange constants. | ||
56 | They are defined in RFC 1321 as | ||
57 | T[i] = (int)(4294967296.0 * fabs(sin(i))), i=1..64 | ||
58 | */ | ||
59 | static const uint32_t C_array[] = { | 59 | static const uint32_t C_array[] = { |
60 | /* round 1 */ | 60 | /* round 1 */ |
61 | 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, | 61 | 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, |
@@ -64,7 +64,7 @@ static void md5_hash_block(const void *buffer, md5_ctx_t *ctx) | |||
64 | 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, | 64 | 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, |
65 | /* round 2 */ | 65 | /* round 2 */ |
66 | 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, | 66 | 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, |
67 | 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8, | 67 | 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, |
68 | 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, | 68 | 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, |
69 | 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, | 69 | 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, |
70 | /* round 3 */ | 70 | /* round 3 */ |
@@ -86,40 +86,33 @@ static void md5_hash_block(const void *buffer, md5_ctx_t *ctx) | |||
86 | 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, /* 3 */ | 86 | 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, /* 3 */ |
87 | 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 /* 4 */ | 87 | 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 /* 4 */ |
88 | }; | 88 | }; |
89 | # if MD5_SIZE_VS_SPEED > 1 | ||
90 | static const char S_array[] ALIGN1 = { | ||
91 | 7, 12, 17, 22, | ||
92 | 5, 9, 14, 20, | ||
93 | 4, 11, 16, 23, | ||
94 | 6, 10, 15, 21 | ||
95 | }; | ||
96 | # endif /* MD5_SIZE_VS_SPEED > 1 */ | ||
97 | #endif | 89 | #endif |
90 | uint32_t *words = (void*) ctx->wbuffer; | ||
98 | uint32_t A = ctx->A; | 91 | uint32_t A = ctx->A; |
99 | uint32_t B = ctx->B; | 92 | uint32_t B = ctx->B; |
100 | uint32_t C = ctx->C; | 93 | uint32_t C = ctx->C; |
101 | uint32_t D = ctx->D; | 94 | uint32_t D = ctx->D; |
102 | 95 | ||
103 | /* Process all bytes in the buffer with 64 bytes in each round of | 96 | #if MD5_SIZE_VS_SPEED >= 2 /* 2 or 3 */ |
104 | the loop. */ | ||
105 | uint32_t *cwp = correct_words; | ||
106 | uint32_t A_save = A; | ||
107 | uint32_t B_save = B; | ||
108 | uint32_t C_save = C; | ||
109 | uint32_t D_save = D; | ||
110 | 97 | ||
111 | #if MD5_SIZE_VS_SPEED > 1 | 98 | static const char S_array[] ALIGN1 = { |
99 | 7, 12, 17, 22, | ||
100 | 5, 9, 14, 20, | ||
101 | 4, 11, 16, 23, | ||
102 | 6, 10, 15, 21 | ||
103 | }; | ||
112 | const uint32_t *pc; | 104 | const uint32_t *pc; |
113 | const char *pp; | 105 | const char *pp; |
114 | const char *ps; | 106 | const char *ps; |
115 | int i; | 107 | int i; |
116 | uint32_t temp; | 108 | uint32_t temp; |
117 | 109 | ||
110 | # if BB_BIG_ENDIAN | ||
118 | for (i = 0; i < 16; i++) | 111 | for (i = 0; i < 16; i++) |
119 | cwp[i] = SWAP_LE32(words[i]); | 112 | words[i] = SWAP_LE32(words[i]); |
120 | words += 16; | 113 | # endif |
121 | 114 | ||
122 | # if MD5_SIZE_VS_SPEED > 2 | 115 | # if MD5_SIZE_VS_SPEED == 3 |
123 | pc = C_array; | 116 | pc = C_array; |
124 | pp = P_array; | 117 | pp = P_array; |
125 | ps = S_array - 4; | 118 | ps = S_array - 4; |
@@ -141,7 +134,7 @@ static void md5_hash_block(const void *buffer, md5_ctx_t *ctx) | |||
141 | case 3: | 134 | case 3: |
142 | temp += FI(B, C, D); | 135 | temp += FI(B, C, D); |
143 | } | 136 | } |
144 | temp += cwp[(int) (*pp++)] + *pc++; | 137 | temp += words[(int) (*pp++)] + *pc++; |
145 | temp = rotl32(temp, ps[i & 3]); | 138 | temp = rotl32(temp, ps[i & 3]); |
146 | temp += B; | 139 | temp += B; |
147 | A = D; | 140 | A = D; |
@@ -149,13 +142,13 @@ static void md5_hash_block(const void *buffer, md5_ctx_t *ctx) | |||
149 | C = B; | 142 | C = B; |
150 | B = temp; | 143 | B = temp; |
151 | } | 144 | } |
152 | # else | 145 | # else /* MD5_SIZE_VS_SPEED == 2 */ |
153 | pc = C_array; | 146 | pc = C_array; |
154 | pp = P_array; | 147 | pp = P_array; |
155 | ps = S_array; | 148 | ps = S_array; |
156 | 149 | ||
157 | for (i = 0; i < 16; i++) { | 150 | for (i = 0; i < 16; i++) { |
158 | temp = A + FF(B, C, D) + cwp[(int) (*pp++)] + *pc++; | 151 | temp = A + FF(B, C, D) + words[(int) (*pp++)] + *pc++; |
159 | temp = rotl32(temp, ps[i & 3]); | 152 | temp = rotl32(temp, ps[i & 3]); |
160 | temp += B; | 153 | temp += B; |
161 | A = D; | 154 | A = D; |
@@ -165,7 +158,7 @@ static void md5_hash_block(const void *buffer, md5_ctx_t *ctx) | |||
165 | } | 158 | } |
166 | ps += 4; | 159 | ps += 4; |
167 | for (i = 0; i < 16; i++) { | 160 | for (i = 0; i < 16; i++) { |
168 | temp = A + FG(B, C, D) + cwp[(int) (*pp++)] + *pc++; | 161 | temp = A + FG(B, C, D) + words[(int) (*pp++)] + *pc++; |
169 | temp = rotl32(temp, ps[i & 3]); | 162 | temp = rotl32(temp, ps[i & 3]); |
170 | temp += B; | 163 | temp += B; |
171 | A = D; | 164 | A = D; |
@@ -175,7 +168,7 @@ static void md5_hash_block(const void *buffer, md5_ctx_t *ctx) | |||
175 | } | 168 | } |
176 | ps += 4; | 169 | ps += 4; |
177 | for (i = 0; i < 16; i++) { | 170 | for (i = 0; i < 16; i++) { |
178 | temp = A + FH(B, C, D) + cwp[(int) (*pp++)] + *pc++; | 171 | temp = A + FH(B, C, D) + words[(int) (*pp++)] + *pc++; |
179 | temp = rotl32(temp, ps[i & 3]); | 172 | temp = rotl32(temp, ps[i & 3]); |
180 | temp += B; | 173 | temp += B; |
181 | A = D; | 174 | A = D; |
@@ -185,7 +178,7 @@ static void md5_hash_block(const void *buffer, md5_ctx_t *ctx) | |||
185 | } | 178 | } |
186 | ps += 4; | 179 | ps += 4; |
187 | for (i = 0; i < 16; i++) { | 180 | for (i = 0; i < 16; i++) { |
188 | temp = A + FI(B, C, D) + cwp[(int) (*pp++)] + *pc++; | 181 | temp = A + FI(B, C, D) + words[(int) (*pp++)] + *pc++; |
189 | temp = rotl32(temp, ps[i & 3]); | 182 | temp = rotl32(temp, ps[i & 3]); |
190 | temp += B; | 183 | temp += B; |
191 | A = D; | 184 | A = D; |
@@ -193,35 +186,41 @@ static void md5_hash_block(const void *buffer, md5_ctx_t *ctx) | |||
193 | C = B; | 186 | C = B; |
194 | B = temp; | 187 | B = temp; |
195 | } | 188 | } |
189 | # endif | ||
190 | /* Add checksum to the starting values */ | ||
191 | ctx->A += A; | ||
192 | ctx->B += B; | ||
193 | ctx->C += C; | ||
194 | ctx->D += D; | ||
195 | |||
196 | #else /* MD5_SIZE_VS_SPEED == 0 or 1 */ | ||
197 | |||
198 | uint32_t A_save = A; | ||
199 | uint32_t B_save = B; | ||
200 | uint32_t C_save = C; | ||
201 | uint32_t D_save = D; | ||
202 | # if MD5_SIZE_VS_SPEED == 1 | ||
203 | const uint32_t *pc; | ||
204 | const char *pp; | ||
205 | int i; | ||
206 | # endif | ||
196 | 207 | ||
197 | # endif /* MD5_SIZE_VS_SPEED > 2 */ | ||
198 | #else | ||
199 | /* First round: using the given function, the context and a constant | 208 | /* First round: using the given function, the context and a constant |
200 | the next context is computed. Because the algorithms processing | 209 | the next context is computed. Because the algorithm's processing |
201 | unit is a 32-bit word and it is determined to work on words in | 210 | unit is a 32-bit word and it is determined to work on words in |
202 | little endian byte order we perhaps have to change the byte order | 211 | little endian byte order we perhaps have to change the byte order |
203 | before the computation. To reduce the work for the next steps | 212 | before the computation. To reduce the work for the next steps |
204 | we store the swapped words in the array CORRECT_WORDS. */ | 213 | we save swapped words in WORDS array. */ |
214 | # undef OP | ||
205 | # define OP(a, b, c, d, s, T) \ | 215 | # define OP(a, b, c, d, s, T) \ |
206 | do { \ | 216 | do { \ |
207 | a += FF(b, c, d) + (*cwp++ = SWAP_LE32(*words)) + T; \ | 217 | a += FF(b, c, d) + (*words IF_BIG_ENDIAN(= SWAP_LE32(*words))) + T; \ |
208 | ++words; \ | 218 | words++; \ |
209 | a = rotl32(a, s); \ | 219 | a = rotl32(a, s); \ |
210 | a += b; \ | 220 | a += b; \ |
211 | } while (0) | 221 | } while (0) |
212 | 222 | ||
213 | /* Before we start, one word to the strange constants. | 223 | /* Round 1 */ |
214 | They are defined in RFC 1321 as | ||
215 | T[i] = (int)(4294967296.0 * fabs(sin(i))), i=1..64 | ||
216 | */ | ||
217 | |||
218 | # if MD5_SIZE_VS_SPEED == 1 | ||
219 | const uint32_t *pc; | ||
220 | const char *pp; | ||
221 | int i; | ||
222 | # endif /* MD5_SIZE_VS_SPEED */ | ||
223 | |||
224 | /* Round 1. */ | ||
225 | # if MD5_SIZE_VS_SPEED == 1 | 224 | # if MD5_SIZE_VS_SPEED == 1 |
226 | pc = C_array; | 225 | pc = C_array; |
227 | for (i = 0; i < 4; i++) { | 226 | for (i = 0; i < 4; i++) { |
@@ -247,20 +246,21 @@ static void md5_hash_block(const void *buffer, md5_ctx_t *ctx) | |||
247 | OP(D, A, B, C, 12, 0xfd987193); | 246 | OP(D, A, B, C, 12, 0xfd987193); |
248 | OP(C, D, A, B, 17, 0xa679438e); | 247 | OP(C, D, A, B, 17, 0xa679438e); |
249 | OP(B, C, D, A, 22, 0x49b40821); | 248 | OP(B, C, D, A, 22, 0x49b40821); |
250 | # endif /* MD5_SIZE_VS_SPEED == 1 */ | 249 | # endif |
250 | words -= 16; | ||
251 | 251 | ||
252 | /* For the second to fourth round we have the possibly swapped words | 252 | /* For the second to fourth round we have the possibly swapped words |
253 | in CORRECT_WORDS. Redefine the macro to take an additional first | 253 | in WORDS. Redefine the macro to take an additional first |
254 | argument specifying the function to use. */ | 254 | argument specifying the function to use. */ |
255 | # undef OP | 255 | # undef OP |
256 | # define OP(f, a, b, c, d, k, s, T) \ | 256 | # define OP(f, a, b, c, d, k, s, T) \ |
257 | do { \ | 257 | do { \ |
258 | a += f(b, c, d) + correct_words[k] + T; \ | 258 | a += f(b, c, d) + words[k] + T; \ |
259 | a = rotl32(a, s); \ | 259 | a = rotl32(a, s); \ |
260 | a += b; \ | 260 | a += b; \ |
261 | } while (0) | 261 | } while (0) |
262 | 262 | ||
263 | /* Round 2. */ | 263 | /* Round 2 */ |
264 | # if MD5_SIZE_VS_SPEED == 1 | 264 | # if MD5_SIZE_VS_SPEED == 1 |
265 | pp = P_array; | 265 | pp = P_array; |
266 | for (i = 0; i < 4; i++) { | 266 | for (i = 0; i < 4; i++) { |
@@ -286,9 +286,9 @@ static void md5_hash_block(const void *buffer, md5_ctx_t *ctx) | |||
286 | OP(FG, D, A, B, C, 2, 9, 0xfcefa3f8); | 286 | OP(FG, D, A, B, C, 2, 9, 0xfcefa3f8); |
287 | OP(FG, C, D, A, B, 7, 14, 0x676f02d9); | 287 | OP(FG, C, D, A, B, 7, 14, 0x676f02d9); |
288 | OP(FG, B, C, D, A, 12, 20, 0x8d2a4c8a); | 288 | OP(FG, B, C, D, A, 12, 20, 0x8d2a4c8a); |
289 | # endif /* MD5_SIZE_VS_SPEED == 1 */ | 289 | # endif |
290 | 290 | ||
291 | /* Round 3. */ | 291 | /* Round 3 */ |
292 | # if MD5_SIZE_VS_SPEED == 1 | 292 | # if MD5_SIZE_VS_SPEED == 1 |
293 | for (i = 0; i < 4; i++) { | 293 | for (i = 0; i < 4; i++) { |
294 | OP(FH, A, B, C, D, (int) (*pp++), 4, *pc++); | 294 | OP(FH, A, B, C, D, (int) (*pp++), 4, *pc++); |
@@ -313,9 +313,9 @@ static void md5_hash_block(const void *buffer, md5_ctx_t *ctx) | |||
313 | OP(FH, D, A, B, C, 12, 11, 0xe6db99e5); | 313 | OP(FH, D, A, B, C, 12, 11, 0xe6db99e5); |
314 | OP(FH, C, D, A, B, 15, 16, 0x1fa27cf8); | 314 | OP(FH, C, D, A, B, 15, 16, 0x1fa27cf8); |
315 | OP(FH, B, C, D, A, 2, 23, 0xc4ac5665); | 315 | OP(FH, B, C, D, A, 2, 23, 0xc4ac5665); |
316 | # endif /* MD5_SIZE_VS_SPEED == 1 */ | 316 | # endif |
317 | 317 | ||
318 | /* Round 4. */ | 318 | /* Round 4 */ |
319 | # if MD5_SIZE_VS_SPEED == 1 | 319 | # if MD5_SIZE_VS_SPEED == 1 |
320 | for (i = 0; i < 4; i++) { | 320 | for (i = 0; i < 4; i++) { |
321 | OP(FI, A, B, C, D, (int) (*pp++), 6, *pc++); | 321 | OP(FI, A, B, C, D, (int) (*pp++), 6, *pc++); |
@@ -340,52 +340,62 @@ static void md5_hash_block(const void *buffer, md5_ctx_t *ctx) | |||
340 | OP(FI, D, A, B, C, 11, 10, 0xbd3af235); | 340 | OP(FI, D, A, B, C, 11, 10, 0xbd3af235); |
341 | OP(FI, C, D, A, B, 2, 15, 0x2ad7d2bb); | 341 | OP(FI, C, D, A, B, 2, 15, 0x2ad7d2bb); |
342 | OP(FI, B, C, D, A, 9, 21, 0xeb86d391); | 342 | OP(FI, B, C, D, A, 9, 21, 0xeb86d391); |
343 | # endif /* MD5_SIZE_VS_SPEED == 1 */ | 343 | # endif |
344 | #endif /* MD5_SIZE_VS_SPEED > 1 */ | 344 | /* Add checksum to the starting values */ |
345 | 345 | ctx->A = A_save + A; | |
346 | /* Add the starting values of the context. */ | 346 | ctx->B = B_save + B; |
347 | A += A_save; | 347 | ctx->C = C_save + C; |
348 | B += B_save; | 348 | ctx->D = D_save + D; |
349 | C += C_save; | 349 | #endif |
350 | D += D_save; | ||
351 | |||
352 | /* Put checksum in context given as argument. */ | ||
353 | ctx->A = A; | ||
354 | ctx->B = B; | ||
355 | ctx->C = C; | ||
356 | ctx->D = D; | ||
357 | } | 350 | } |
358 | 351 | ||
359 | /* Feed data through a temporary buffer to call md5_hash_aligned_block() | 352 | /* Feed data through a temporary buffer to call md5_hash_aligned_block() |
360 | * with chunks of data that are 4-byte aligned and a multiple of 64 bytes. | 353 | * with chunks of data that are 4-byte aligned and a multiple of 64 bytes. |
361 | * This function's internal buffer remembers previous data until it has 64 | 354 | * This function's internal buffer remembers previous data until it has 64 |
362 | * bytes worth to pass on. Call md5_end() to flush this buffer. */ | 355 | * bytes worth to pass on. Call md5_end() to flush this buffer. */ |
363 | void FAST_FUNC md5_hash(const void *buffer, size_t len, md5_ctx_t *ctx) | 356 | void FAST_FUNC md5_hash(md5_ctx_t *ctx, const void *buffer, size_t len) |
364 | { | 357 | { |
365 | char *buf = (char *)buffer; | 358 | unsigned bufpos = ctx->total64 & 63; |
359 | unsigned remaining; | ||
366 | 360 | ||
367 | /* RFC 1321 specifies the possible length of the file up to 2^64 bits, | 361 | /* RFC 1321 specifies the possible length of the file up to 2^64 bits. |
368 | * Here we only track the number of bytes. */ | 362 | * Here we only track the number of bytes. */ |
369 | ctx->total += len; | 363 | ctx->total64 += len; |
370 | 364 | #if 0 | |
371 | /* Process all input. */ | 365 | remaining = 64 - bufpos; |
372 | while (len) { | 366 | |
373 | unsigned i = 64 - ctx->buflen; | 367 | /* Hash whole blocks */ |
374 | 368 | while (len >= remaining) { | |
375 | /* Copy data into aligned buffer. */ | 369 | memcpy(ctx->wbuffer + bufpos, buffer, remaining); |
376 | if (i > len) | 370 | buffer = (const char *)buffer + remaining; |
377 | i = len; | 371 | len -= remaining; |
378 | memcpy(ctx->buffer + ctx->buflen, buf, i); | 372 | remaining = 64; |
379 | len -= i; | 373 | bufpos = 0; |
380 | ctx->buflen += i; | 374 | md5_process_block64(ctx); |
381 | buf += i; | 375 | } |
382 | 376 | ||
383 | /* When buffer fills up, process it. */ | 377 | /* Save last, partial blosk */ |
384 | if (ctx->buflen == 64) { | 378 | memcpy(ctx->wbuffer + bufpos, buffer, len); |
385 | md5_hash_block(ctx->buffer, ctx); | 379 | #else |
386 | ctx->buflen = 0; | 380 | /* Tiny bit smaller code */ |
387 | } | 381 | while (1) { |
382 | remaining = 64 - bufpos; | ||
383 | if (remaining > len) | ||
384 | remaining = len; | ||
385 | /* Copy data into aligned buffer */ | ||
386 | memcpy(ctx->wbuffer + bufpos, buffer, remaining); | ||
387 | len -= remaining; | ||
388 | buffer = (const char *)buffer + remaining; | ||
389 | bufpos += remaining; | ||
390 | /* clever way to do "if (bufpos != 64) break; ... ; bufpos = 0;" */ | ||
391 | bufpos -= 64; | ||
392 | if (bufpos != 0) | ||
393 | break; | ||
394 | /* Buffer is filled up, process it */ | ||
395 | md5_process_block64(ctx); | ||
396 | /*bufpos = 0; - already is */ | ||
388 | } | 397 | } |
398 | #endif | ||
389 | } | 399 | } |
390 | 400 | ||
391 | /* Process the remaining bytes in the buffer and put result from CTX | 401 | /* Process the remaining bytes in the buffer and put result from CTX |
@@ -393,26 +403,31 @@ void FAST_FUNC md5_hash(const void *buffer, size_t len, md5_ctx_t *ctx) | |||
393 | * endian byte order, so that a byte-wise output yields to the wanted | 403 | * endian byte order, so that a byte-wise output yields to the wanted |
394 | * ASCII representation of the message digest. | 404 | * ASCII representation of the message digest. |
395 | */ | 405 | */ |
396 | void FAST_FUNC md5_end(void *resbuf, md5_ctx_t *ctx) | 406 | void FAST_FUNC md5_end(md5_ctx_t *ctx, void *resbuf) |
397 | { | 407 | { |
398 | char *buf = ctx->buffer; | 408 | unsigned bufpos = ctx->total64 & 63; |
399 | int i; | 409 | /* Pad the buffer to the next 64-byte boundary with 0x80,0,0,0... */ |
400 | 410 | ctx->wbuffer[bufpos++] = 0x80; | |
401 | /* Pad data to block size. */ | 411 | |
402 | buf[ctx->buflen++] = 0x80; | 412 | /* This loop iterates either once or twice, no more, no less */ |
403 | memset(buf + ctx->buflen, 0, 128 - ctx->buflen); | 413 | while (1) { |
404 | 414 | unsigned remaining = 64 - bufpos; | |
405 | /* Put the 64-bit file length in *bits* at the end of the buffer. */ | 415 | memset(ctx->wbuffer + bufpos, 0, remaining); |
406 | ctx->total <<= 3; | 416 | /* Do we have enough space for the length count? */ |
407 | if (ctx->buflen > 56) | 417 | if (remaining >= 8) { |
408 | buf += 64; | 418 | /* Store the 64-bit counter of bits in the buffer in BE format */ |
409 | for (i = 0; i < 8; i++) | 419 | uint64_t t = ctx->total64 << 3; |
410 | buf[56 + i] = ctx->total >> (i*8); | 420 | unsigned i; |
411 | 421 | for (i = 0; i < 8; i++) { | |
412 | /* Process last bytes. */ | 422 | ctx->wbuffer[56 + i] = t; |
413 | if (buf != ctx->buffer) | 423 | t >>= 8; |
414 | md5_hash_block(ctx->buffer, ctx); | 424 | } |
415 | md5_hash_block(buf, ctx); | 425 | } |
426 | md5_process_block64(ctx); | ||
427 | if (remaining >= 8) | ||
428 | break; | ||
429 | bufpos = 0; | ||
430 | } | ||
416 | 431 | ||
417 | /* The MD5 result is in little endian byte order. | 432 | /* The MD5 result is in little endian byte order. |
418 | * We (ab)use the fact that A-D are consecutive in memory. | 433 | * We (ab)use the fact that A-D are consecutive in memory. |
diff --git a/libbb/procps.c b/libbb/procps.c index 7ffcd8dbc..ec43b221e 100644 --- a/libbb/procps.c +++ b/libbb/procps.c | |||
@@ -121,7 +121,7 @@ void FAST_FUNC free_procps_scan(procps_status_t* sp) | |||
121 | free(sp); | 121 | free(sp); |
122 | } | 122 | } |
123 | 123 | ||
124 | #if ENABLE_FEATURE_TOPMEM | 124 | #if ENABLE_FEATURE_TOPMEM || ENABLE_PMAP |
125 | static unsigned long fast_strtoul_16(char **endptr) | 125 | static unsigned long fast_strtoul_16(char **endptr) |
126 | { | 126 | { |
127 | unsigned char c; | 127 | unsigned char c; |
diff --git a/libbb/pw_encrypt_md5.c b/libbb/pw_encrypt_md5.c index 58964b567..889e09cab 100644 --- a/libbb/pw_encrypt_md5.c +++ b/libbb/pw_encrypt_md5.c | |||
@@ -92,10 +92,10 @@ md5_crypt(char result[MD5_OUT_BUFSIZE], const unsigned char *pw, const unsigned | |||
92 | /* Hash. the password first, since that is what is most unknown */ | 92 | /* Hash. the password first, since that is what is most unknown */ |
93 | md5_begin(&ctx); | 93 | md5_begin(&ctx); |
94 | pw_len = strlen((char*)pw); | 94 | pw_len = strlen((char*)pw); |
95 | md5_hash(pw, pw_len, &ctx); | 95 | md5_hash(&ctx, pw, pw_len); |
96 | 96 | ||
97 | /* Then the salt including "$1$" */ | 97 | /* Then the salt including "$1$" */ |
98 | md5_hash(salt, sl, &ctx); | 98 | md5_hash(&ctx, salt, sl); |
99 | 99 | ||
100 | /* Copy salt to result; skip "$1$" */ | 100 | /* Copy salt to result; skip "$1$" */ |
101 | memcpy(result, salt, sl); | 101 | memcpy(result, salt, sl); |
@@ -105,19 +105,19 @@ md5_crypt(char result[MD5_OUT_BUFSIZE], const unsigned char *pw, const unsigned | |||
105 | 105 | ||
106 | /* Then just as many characters of the MD5(pw, salt, pw) */ | 106 | /* Then just as many characters of the MD5(pw, salt, pw) */ |
107 | md5_begin(&ctx1); | 107 | md5_begin(&ctx1); |
108 | md5_hash(pw, pw_len, &ctx1); | 108 | md5_hash(&ctx1, pw, pw_len); |
109 | md5_hash(salt, sl, &ctx1); | 109 | md5_hash(&ctx1, salt, sl); |
110 | md5_hash(pw, pw_len, &ctx1); | 110 | md5_hash(&ctx1, pw, pw_len); |
111 | md5_end(final, &ctx1); | 111 | md5_end(&ctx1, final); |
112 | for (pl = pw_len; pl > 0; pl -= 16) | 112 | for (pl = pw_len; pl > 0; pl -= 16) |
113 | md5_hash(final, pl > 16 ? 16 : pl, &ctx); | 113 | md5_hash(&ctx, final, pl > 16 ? 16 : pl); |
114 | 114 | ||
115 | /* Then something really weird... */ | 115 | /* Then something really weird... */ |
116 | memset(final, 0, sizeof(final)); | 116 | memset(final, 0, sizeof(final)); |
117 | for (i = pw_len; i; i >>= 1) { | 117 | for (i = pw_len; i; i >>= 1) { |
118 | md5_hash(((i & 1) ? final : (const unsigned char *) pw), 1, &ctx); | 118 | md5_hash(&ctx, ((i & 1) ? final : (const unsigned char *) pw), 1); |
119 | } | 119 | } |
120 | md5_end(final, &ctx); | 120 | md5_end(&ctx, final); |
121 | 121 | ||
122 | /* And now, just to make sure things don't run too fast. | 122 | /* And now, just to make sure things don't run too fast. |
123 | * On a 60 Mhz Pentium this takes 34 msec, so you would | 123 | * On a 60 Mhz Pentium this takes 34 msec, so you would |
@@ -126,21 +126,21 @@ md5_crypt(char result[MD5_OUT_BUFSIZE], const unsigned char *pw, const unsigned | |||
126 | for (i = 0; i < 1000; i++) { | 126 | for (i = 0; i < 1000; i++) { |
127 | md5_begin(&ctx1); | 127 | md5_begin(&ctx1); |
128 | if (i & 1) | 128 | if (i & 1) |
129 | md5_hash(pw, pw_len, &ctx1); | 129 | md5_hash(&ctx1, pw, pw_len); |
130 | else | 130 | else |
131 | md5_hash(final, 16, &ctx1); | 131 | md5_hash(&ctx1, final, 16); |
132 | 132 | ||
133 | if (i % 3) | 133 | if (i % 3) |
134 | md5_hash(salt, sl, &ctx1); | 134 | md5_hash(&ctx1, salt, sl); |
135 | 135 | ||
136 | if (i % 7) | 136 | if (i % 7) |
137 | md5_hash(pw, pw_len, &ctx1); | 137 | md5_hash(&ctx1, pw, pw_len); |
138 | 138 | ||
139 | if (i & 1) | 139 | if (i & 1) |
140 | md5_hash(final, 16, &ctx1); | 140 | md5_hash(&ctx1, final, 16); |
141 | else | 141 | else |
142 | md5_hash(pw, pw_len, &ctx1); | 142 | md5_hash(&ctx1, pw, pw_len); |
143 | md5_end(final, &ctx1); | 143 | md5_end(&ctx1, final); |
144 | } | 144 | } |
145 | 145 | ||
146 | p = result + sl + 4; /* 12 bytes max (sl is up to 8 bytes) */ | 146 | p = result + sl + 4; /* 12 bytes max (sl is up to 8 bytes) */ |
diff --git a/libbb/sha1.c b/libbb/sha1.c index beeb70cf6..d79291148 100644 --- a/libbb/sha1.c +++ b/libbb/sha1.c | |||
@@ -30,11 +30,29 @@ | |||
30 | 30 | ||
31 | #include "libbb.h" | 31 | #include "libbb.h" |
32 | 32 | ||
33 | #define rotl32(x,n) (((x) << (n)) | ((x) >> (32 - (n)))) | 33 | /* gcc 4.2.1 optimizes rotr64 better with inline than with macro |
34 | #define rotr32(x,n) (((x) >> (n)) | ((x) << (32 - (n)))) | 34 | * (for rotX32, there is no difference). Why? My guess is that |
35 | /* for sha512: */ | 35 | * macro requires clever common subexpression elimination heuristics |
36 | #define rotr64(x,n) (((x) >> (n)) | ((x) << (64 - (n)))) | 36 | * in gcc, while inline basically forces it to happen. |
37 | */ | ||
38 | //#define rotl32(x,n) (((x) << (n)) | ((x) >> (32 - (n)))) | ||
39 | static ALWAYS_INLINE uint32_t rotl32(uint32_t x, unsigned n) | ||
40 | { | ||
41 | return (x << n) | (x >> (32 - n)); | ||
42 | } | ||
43 | //#define rotr32(x,n) (((x) >> (n)) | ((x) << (32 - (n)))) | ||
44 | static ALWAYS_INLINE uint32_t rotr32(uint32_t x, unsigned n) | ||
45 | { | ||
46 | return (x >> n) | (x << (32 - n)); | ||
47 | } | ||
48 | /* rotr64 in needed for sha512 only: */ | ||
49 | //#define rotr64(x,n) (((x) >> (n)) | ((x) << (64 - (n)))) | ||
50 | static ALWAYS_INLINE uint64_t rotr64(uint64_t x, unsigned n) | ||
51 | { | ||
52 | return (x >> n) | (x << (64 - n)); | ||
53 | } | ||
37 | #if BB_LITTLE_ENDIAN | 54 | #if BB_LITTLE_ENDIAN |
55 | /* ALWAYS_INLINE below would hurt code size, using plain inline: */ | ||
38 | static inline uint64_t hton64(uint64_t v) | 56 | static inline uint64_t hton64(uint64_t v) |
39 | { | 57 | { |
40 | return (((uint64_t)htonl(v)) << 32) | htonl(v >> 32); | 58 | return (((uint64_t)htonl(v)) << 32) | htonl(v >> 32); |
@@ -44,14 +62,6 @@ static inline uint64_t hton64(uint64_t v) | |||
44 | #endif | 62 | #endif |
45 | #define ntoh64(v) hton64(v) | 63 | #define ntoh64(v) hton64(v) |
46 | 64 | ||
47 | /* To check alignment gcc has an appropriate operator. Other | ||
48 | compilers don't. */ | ||
49 | #if defined(__GNUC__) && __GNUC__ >= 2 | ||
50 | # define UNALIGNED_P(p,type) (((uintptr_t) p) % __alignof__(type) != 0) | ||
51 | #else | ||
52 | # define UNALIGNED_P(p,type) (((uintptr_t) p) % sizeof(type) != 0) | ||
53 | #endif | ||
54 | |||
55 | 65 | ||
56 | /* Some arch headers have conflicting defines */ | 66 | /* Some arch headers have conflicting defines */ |
57 | #undef ch | 67 | #undef ch |
@@ -65,11 +75,8 @@ static void FAST_FUNC sha1_process_block64(sha1_ctx_t *ctx) | |||
65 | uint32_t W[80], a, b, c, d, e; | 75 | uint32_t W[80], a, b, c, d, e; |
66 | const uint32_t *words = (uint32_t*) ctx->wbuffer; | 76 | const uint32_t *words = (uint32_t*) ctx->wbuffer; |
67 | 77 | ||
68 | for (t = 0; t < 16; ++t) { | 78 | for (t = 0; t < 16; ++t) |
69 | W[t] = ntohl(*words); | 79 | W[t] = ntohl(words[t]); |
70 | words++; | ||
71 | } | ||
72 | |||
73 | for (/*t = 16*/; t < 80; ++t) { | 80 | for (/*t = 16*/; t < 80; ++t) { |
74 | uint32_t T = W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]; | 81 | uint32_t T = W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]; |
75 | W[t] = rotl32(T, 1); | 82 | W[t] = rotl32(T, 1); |
@@ -190,11 +197,8 @@ static void FAST_FUNC sha256_process_block64(sha256_ctx_t *ctx) | |||
190 | #define R1(x) (rotr32(x, 17) ^ rotr32(x, 19) ^ (x >> 10)) | 197 | #define R1(x) (rotr32(x, 17) ^ rotr32(x, 19) ^ (x >> 10)) |
191 | 198 | ||
192 | /* Compute the message schedule according to FIPS 180-2:6.2.2 step 2. */ | 199 | /* Compute the message schedule according to FIPS 180-2:6.2.2 step 2. */ |
193 | for (t = 0; t < 16; ++t) { | 200 | for (t = 0; t < 16; ++t) |
194 | W[t] = ntohl(*words); | 201 | W[t] = ntohl(words[t]); |
195 | words++; | ||
196 | } | ||
197 | |||
198 | for (/*t = 16*/; t < 64; ++t) | 202 | for (/*t = 16*/; t < 64; ++t) |
199 | W[t] = R1(W[t - 2]) + W[t - 7] + R0(W[t - 15]) + W[t - 16]; | 203 | W[t] = R1(W[t - 2]) + W[t - 7] + R0(W[t - 15]) + W[t - 16]; |
200 | 204 | ||
@@ -269,10 +273,8 @@ static void FAST_FUNC sha512_process_block128(sha512_ctx_t *ctx) | |||
269 | #define R1(x) (rotr64(x, 19) ^ rotr64(x, 61) ^ (x >> 6)) | 273 | #define R1(x) (rotr64(x, 19) ^ rotr64(x, 61) ^ (x >> 6)) |
270 | 274 | ||
271 | /* Compute the message schedule according to FIPS 180-2:6.3.2 step 2. */ | 275 | /* Compute the message schedule according to FIPS 180-2:6.3.2 step 2. */ |
272 | for (t = 0; t < 16; ++t) { | 276 | for (t = 0; t < 16; ++t) |
273 | W[t] = ntoh64(*words); | 277 | W[t] = ntoh64(words[t]); |
274 | words++; | ||
275 | } | ||
276 | for (/*t = 16*/; t < 80; ++t) | 278 | for (/*t = 16*/; t < 80; ++t) |
277 | W[t] = R1(W[t - 2]) + W[t - 7] + R0(W[t - 15]) + W[t - 16]; | 279 | W[t] = R1(W[t - 2]) + W[t - 7] + R0(W[t - 15]) + W[t - 16]; |
278 | 280 | ||
@@ -327,7 +329,9 @@ static const uint32_t init256[] = { | |||
327 | 0x510e527f, | 329 | 0x510e527f, |
328 | 0x9b05688c, | 330 | 0x9b05688c, |
329 | 0x1f83d9ab, | 331 | 0x1f83d9ab, |
330 | 0x5be0cd19 | 332 | 0x5be0cd19, |
333 | 0, | ||
334 | 0, | ||
331 | }; | 335 | }; |
332 | static const uint32_t init512_lo[] = { | 336 | static const uint32_t init512_lo[] = { |
333 | 0xf3bcc908, | 337 | 0xf3bcc908, |
@@ -337,7 +341,9 @@ static const uint32_t init512_lo[] = { | |||
337 | 0xade682d1, | 341 | 0xade682d1, |
338 | 0x2b3e6c1f, | 342 | 0x2b3e6c1f, |
339 | 0xfb41bd6b, | 343 | 0xfb41bd6b, |
340 | 0x137e2179 | 344 | 0x137e2179, |
345 | 0, | ||
346 | 0, | ||
341 | }; | 347 | }; |
342 | 348 | ||
343 | /* Initialize structure containing state of computation. | 349 | /* Initialize structure containing state of computation. |
@@ -345,7 +351,7 @@ static const uint32_t init512_lo[] = { | |||
345 | void FAST_FUNC sha256_begin(sha256_ctx_t *ctx) | 351 | void FAST_FUNC sha256_begin(sha256_ctx_t *ctx) |
346 | { | 352 | { |
347 | memcpy(ctx->hash, init256, sizeof(init256)); | 353 | memcpy(ctx->hash, init256, sizeof(init256)); |
348 | ctx->total64 = 0; | 354 | /*ctx->total64 = 0; - done by extending init256 with two 32-bit zeros */ |
349 | ctx->process_block = sha256_process_block64; | 355 | ctx->process_block = sha256_process_block64; |
350 | } | 356 | } |
351 | 357 | ||
@@ -354,36 +360,61 @@ void FAST_FUNC sha256_begin(sha256_ctx_t *ctx) | |||
354 | void FAST_FUNC sha512_begin(sha512_ctx_t *ctx) | 360 | void FAST_FUNC sha512_begin(sha512_ctx_t *ctx) |
355 | { | 361 | { |
356 | int i; | 362 | int i; |
357 | for (i = 0; i < 8; i++) | 363 | /* Two extra iterations zero out ctx->total64[] */ |
364 | for (i = 0; i < 8+2; i++) | ||
358 | ctx->hash[i] = ((uint64_t)(init256[i]) << 32) + init512_lo[i]; | 365 | ctx->hash[i] = ((uint64_t)(init256[i]) << 32) + init512_lo[i]; |
359 | ctx->total64[0] = ctx->total64[1] = 0; | 366 | /*ctx->total64[0] = ctx->total64[1] = 0; - already done */ |
360 | } | 367 | } |
361 | 368 | ||
362 | 369 | ||
363 | /* Used also for sha256 */ | 370 | /* Used also for sha256 */ |
364 | void FAST_FUNC sha1_hash(const void *buffer, size_t len, sha1_ctx_t *ctx) | 371 | void FAST_FUNC sha1_hash(sha1_ctx_t *ctx, const void *buffer, size_t len) |
365 | { | 372 | { |
366 | unsigned in_buf = ctx->total64 & 63; | 373 | unsigned bufpos = ctx->total64 & 63; |
367 | unsigned add = 64 - in_buf; | 374 | unsigned remaining; |
368 | 375 | ||
369 | ctx->total64 += len; | 376 | ctx->total64 += len; |
370 | 377 | #if 0 | |
371 | while (len >= add) { /* transfer whole blocks while possible */ | 378 | remaining = 64 - bufpos; |
372 | memcpy(ctx->wbuffer + in_buf, buffer, add); | 379 | |
373 | buffer = (const char *)buffer + add; | 380 | /* Hash whole blocks */ |
374 | len -= add; | 381 | while (len >= remaining) { |
375 | add = 64; | 382 | memcpy(ctx->wbuffer + bufpos, buffer, remaining); |
376 | in_buf = 0; | 383 | buffer = (const char *)buffer + remaining; |
384 | len -= remaining; | ||
385 | remaining = 64; | ||
386 | bufpos = 0; | ||
377 | ctx->process_block(ctx); | 387 | ctx->process_block(ctx); |
378 | } | 388 | } |
379 | 389 | ||
380 | memcpy(ctx->wbuffer + in_buf, buffer, len); | 390 | /* Save last, partial blosk */ |
391 | memcpy(ctx->wbuffer + bufpos, buffer, len); | ||
392 | #else | ||
393 | /* Tiny bit smaller code */ | ||
394 | while (1) { | ||
395 | remaining = 64 - bufpos; | ||
396 | if (remaining > len) | ||
397 | remaining = len; | ||
398 | /* Copy data into aligned buffer */ | ||
399 | memcpy(ctx->wbuffer + bufpos, buffer, remaining); | ||
400 | len -= remaining; | ||
401 | buffer = (const char *)buffer + remaining; | ||
402 | bufpos += remaining; | ||
403 | /* clever way to do "if (bufpos != 64) break; ... ; bufpos = 0;" */ | ||
404 | bufpos -= 64; | ||
405 | if (bufpos != 0) | ||
406 | break; | ||
407 | /* Buffer is filled up, process it */ | ||
408 | ctx->process_block(ctx); | ||
409 | /*bufpos = 0; - already is */ | ||
410 | } | ||
411 | #endif | ||
381 | } | 412 | } |
382 | 413 | ||
383 | void FAST_FUNC sha512_hash(const void *buffer, size_t len, sha512_ctx_t *ctx) | 414 | void FAST_FUNC sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len) |
384 | { | 415 | { |
385 | unsigned in_buf = ctx->total64[0] & 127; | 416 | unsigned bufpos = ctx->total64[0] & 127; |
386 | unsigned add = 128 - in_buf; | 417 | unsigned remaining; |
387 | 418 | ||
388 | /* First increment the byte count. FIPS 180-2 specifies the possible | 419 | /* First increment the byte count. FIPS 180-2 specifies the possible |
389 | length of the file up to 2^128 _bits_. | 420 | length of the file up to 2^128 _bits_. |
@@ -391,36 +422,57 @@ void FAST_FUNC sha512_hash(const void *buffer, size_t len, sha512_ctx_t *ctx) | |||
391 | ctx->total64[0] += len; | 422 | ctx->total64[0] += len; |
392 | if (ctx->total64[0] < len) | 423 | if (ctx->total64[0] < len) |
393 | ctx->total64[1]++; | 424 | ctx->total64[1]++; |
394 | 425 | #if 0 | |
395 | while (len >= add) { /* transfer whole blocks while possible */ | 426 | remaining = 128 - bufpos; |
396 | memcpy(ctx->wbuffer + in_buf, buffer, add); | 427 | |
397 | buffer = (const char *)buffer + add; | 428 | /* Hash whole blocks */ |
398 | len -= add; | 429 | while (len >= remaining) { |
399 | add = 128; | 430 | memcpy(ctx->wbuffer + bufpos, buffer, remaining); |
400 | in_buf = 0; | 431 | buffer = (const char *)buffer + remaining; |
432 | len -= remaining; | ||
433 | remaining = 128; | ||
434 | bufpos = 0; | ||
401 | sha512_process_block128(ctx); | 435 | sha512_process_block128(ctx); |
402 | } | 436 | } |
403 | 437 | ||
404 | memcpy(ctx->wbuffer + in_buf, buffer, len); | 438 | /* Save last, partial blosk */ |
439 | memcpy(ctx->wbuffer + bufpos, buffer, len); | ||
440 | #else | ||
441 | while (1) { | ||
442 | remaining = 128 - bufpos; | ||
443 | if (remaining > len) | ||
444 | remaining = len; | ||
445 | /* Copy data into aligned buffer */ | ||
446 | memcpy(ctx->wbuffer + bufpos, buffer, remaining); | ||
447 | len -= remaining; | ||
448 | buffer = (const char *)buffer + remaining; | ||
449 | bufpos += remaining; | ||
450 | /* clever way to do "if (bufpos != 128) break; ... ; bufpos = 0;" */ | ||
451 | bufpos -= 128; | ||
452 | if (bufpos != 0) | ||
453 | break; | ||
454 | /* Buffer is filled up, process it */ | ||
455 | sha512_process_block128(ctx); | ||
456 | /*bufpos = 0; - already is */ | ||
457 | } | ||
458 | #endif | ||
405 | } | 459 | } |
406 | 460 | ||
407 | 461 | ||
408 | /* Used also for sha256 */ | 462 | /* Used also for sha256 */ |
409 | void FAST_FUNC sha1_end(void *resbuf, sha1_ctx_t *ctx) | 463 | void FAST_FUNC sha1_end(sha1_ctx_t *ctx, void *resbuf) |
410 | { | 464 | { |
411 | unsigned pad, in_buf; | 465 | unsigned bufpos = ctx->total64 & 63; |
412 | 466 | ||
413 | in_buf = ctx->total64 & 63; | ||
414 | /* Pad the buffer to the next 64-byte boundary with 0x80,0,0,0... */ | 467 | /* Pad the buffer to the next 64-byte boundary with 0x80,0,0,0... */ |
415 | ctx->wbuffer[in_buf++] = 0x80; | 468 | ctx->wbuffer[bufpos++] = 0x80; |
416 | 469 | ||
417 | /* This loop iterates either once or twice, no more, no less */ | 470 | /* This loop iterates either once or twice, no more, no less */ |
418 | while (1) { | 471 | while (1) { |
419 | pad = 64 - in_buf; | 472 | unsigned remaining = 64 - bufpos; |
420 | memset(ctx->wbuffer + in_buf, 0, pad); | 473 | memset(ctx->wbuffer + bufpos, 0, remaining); |
421 | in_buf = 0; | ||
422 | /* Do we have enough space for the length count? */ | 474 | /* Do we have enough space for the length count? */ |
423 | if (pad >= 8) { | 475 | if (remaining >= 8) { |
424 | /* Store the 64-bit counter of bits in the buffer in BE format */ | 476 | /* Store the 64-bit counter of bits in the buffer in BE format */ |
425 | uint64_t t = ctx->total64 << 3; | 477 | uint64_t t = ctx->total64 << 3; |
426 | t = hton64(t); | 478 | t = hton64(t); |
@@ -428,35 +480,32 @@ void FAST_FUNC sha1_end(void *resbuf, sha1_ctx_t *ctx) | |||
428 | *(uint64_t *) (&ctx->wbuffer[64 - 8]) = t; | 480 | *(uint64_t *) (&ctx->wbuffer[64 - 8]) = t; |
429 | } | 481 | } |
430 | ctx->process_block(ctx); | 482 | ctx->process_block(ctx); |
431 | if (pad >= 8) | 483 | if (remaining >= 8) |
432 | break; | 484 | break; |
485 | bufpos = 0; | ||
433 | } | 486 | } |
434 | 487 | ||
435 | in_buf = (ctx->process_block == sha1_process_block64) ? 5 : 8; | 488 | bufpos = (ctx->process_block == sha1_process_block64) ? 5 : 8; |
436 | /* This way we do not impose alignment constraints on resbuf: */ | 489 | /* This way we do not impose alignment constraints on resbuf: */ |
437 | if (BB_LITTLE_ENDIAN) { | 490 | if (BB_LITTLE_ENDIAN) { |
438 | unsigned i; | 491 | unsigned i; |
439 | for (i = 0; i < in_buf; ++i) | 492 | for (i = 0; i < bufpos; ++i) |
440 | ctx->hash[i] = htonl(ctx->hash[i]); | 493 | ctx->hash[i] = htonl(ctx->hash[i]); |
441 | } | 494 | } |
442 | memcpy(resbuf, ctx->hash, sizeof(ctx->hash[0]) * in_buf); | 495 | memcpy(resbuf, ctx->hash, sizeof(ctx->hash[0]) * bufpos); |
443 | } | 496 | } |
444 | 497 | ||
445 | void FAST_FUNC sha512_end(void *resbuf, sha512_ctx_t *ctx) | 498 | void FAST_FUNC sha512_end(sha512_ctx_t *ctx, void *resbuf) |
446 | { | 499 | { |
447 | unsigned pad, in_buf; | 500 | unsigned bufpos = ctx->total64[0] & 127; |
448 | 501 | ||
449 | in_buf = ctx->total64[0] & 127; | 502 | /* Pad the buffer to the next 128-byte boundary with 0x80,0,0,0... */ |
450 | /* Pad the buffer to the next 128-byte boundary with 0x80,0,0,0... | 503 | ctx->wbuffer[bufpos++] = 0x80; |
451 | * (FIPS 180-2:5.1.2) | ||
452 | */ | ||
453 | ctx->wbuffer[in_buf++] = 0x80; | ||
454 | 504 | ||
455 | while (1) { | 505 | while (1) { |
456 | pad = 128 - in_buf; | 506 | unsigned remaining = 128 - bufpos; |
457 | memset(ctx->wbuffer + in_buf, 0, pad); | 507 | memset(ctx->wbuffer + bufpos, 0, remaining); |
458 | in_buf = 0; | 508 | if (remaining >= 16) { |
459 | if (pad >= 16) { | ||
460 | /* Store the 128-bit counter of bits in the buffer in BE format */ | 509 | /* Store the 128-bit counter of bits in the buffer in BE format */ |
461 | uint64_t t; | 510 | uint64_t t; |
462 | t = ctx->total64[0] << 3; | 511 | t = ctx->total64[0] << 3; |
@@ -467,8 +516,9 @@ void FAST_FUNC sha512_end(void *resbuf, sha512_ctx_t *ctx) | |||
467 | *(uint64_t *) (&ctx->wbuffer[128 - 16]) = t; | 516 | *(uint64_t *) (&ctx->wbuffer[128 - 16]) = t; |
468 | } | 517 | } |
469 | sha512_process_block128(ctx); | 518 | sha512_process_block128(ctx); |
470 | if (pad >= 16) | 519 | if (remaining >= 16) |
471 | break; | 520 | break; |
521 | bufpos = 0; | ||
472 | } | 522 | } |
473 | 523 | ||
474 | if (BB_LITTLE_ENDIAN) { | 524 | if (BB_LITTLE_ENDIAN) { |
diff --git a/libbb/uuencode.c b/libbb/uuencode.c index 181f49de0..03e708fd5 100644 --- a/libbb/uuencode.c +++ b/libbb/uuencode.c | |||
@@ -1,6 +1,8 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | 1 | /* vi: set sw=4 ts=4: */ |
2 | /* | 2 | /* |
3 | * Copyright 2006 Rob Landley <rob@landley.net> | 3 | * Copyright 2003, Glenn McGrath |
4 | * Copyright 2006, Rob Landley <rob@landley.net> | ||
5 | * Copyright 2010, Denys Vlasenko | ||
4 | * | 6 | * |
5 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
6 | */ | 8 | */ |
@@ -69,3 +71,75 @@ void FAST_FUNC bb_uuencode(char *p, const void *src, int length, const char *tbl | |||
69 | length++; | 71 | length++; |
70 | } | 72 | } |
71 | } | 73 | } |
74 | |||
75 | /* | ||
76 | * Decode base64 encoded stream. | ||
77 | * Can stop on EOF, specified char, or on uuencode-style "====" line: | ||
78 | * flags argument controls it. | ||
79 | */ | ||
80 | void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags) | ||
81 | { | ||
82 | /* Note that EOF _can_ be passed as exit_char too */ | ||
83 | #define exit_char ((int)(signed char)flags) | ||
84 | #define uu_style_end (flags & BASE64_FLAG_UU_STOP) | ||
85 | |||
86 | int term_count = 0; | ||
87 | |||
88 | while (1) { | ||
89 | unsigned char translated[4]; | ||
90 | int count = 0; | ||
91 | |||
92 | /* Process one group of 4 chars */ | ||
93 | while (count < 4) { | ||
94 | char *table_ptr; | ||
95 | int ch; | ||
96 | |||
97 | /* Get next _valid_ character. | ||
98 | * bb_uuenc_tbl_base64[] contains this string: | ||
99 | * 0 1 2 3 4 5 6 | ||
100 | * 012345678901234567890123456789012345678901234567890123456789012345 | ||
101 | * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n" | ||
102 | */ | ||
103 | do { | ||
104 | ch = fgetc(src_stream); | ||
105 | if (ch == exit_char && count == 0) | ||
106 | return; | ||
107 | if (ch == EOF) | ||
108 | bb_error_msg_and_die("truncated base64 input"); | ||
109 | table_ptr = strchr(bb_uuenc_tbl_base64, ch); | ||
110 | //TODO: add BASE64_FLAG_foo to die on bad char? | ||
111 | //Note that then we may need to still allow '\r' (for mail processing) | ||
112 | } while (!table_ptr); | ||
113 | |||
114 | /* Convert encoded character to decimal */ | ||
115 | ch = table_ptr - bb_uuenc_tbl_base64; | ||
116 | |||
117 | if (ch == 65 /* '\n' */) { | ||
118 | /* Terminating "====" line? */ | ||
119 | if (uu_style_end && term_count == 4) | ||
120 | return; /* yes */ | ||
121 | term_count = 0; | ||
122 | continue; | ||
123 | } | ||
124 | /* ch is 64 if char was '=', otherwise 0..63 */ | ||
125 | translated[count] = ch & 63; /* 64 -> 0 */ | ||
126 | if (ch == 64) { | ||
127 | term_count++; | ||
128 | break; | ||
129 | } | ||
130 | count++; | ||
131 | term_count = 0; | ||
132 | } | ||
133 | |||
134 | /* Merge 6 bit chars to 8 bit. | ||
135 | * count can be < 4 when we decode the tail: | ||
136 | * "eQ==" -> "y", not "y NUL NUL" | ||
137 | */ | ||
138 | if (count > 1) | ||
139 | fputc(translated[0] << 2 | translated[1] >> 4, dst_stream); | ||
140 | if (count > 2) | ||
141 | fputc(translated[1] << 4 | translated[2] >> 2, dst_stream); | ||
142 | if (count > 3) | ||
143 | fputc(translated[2] << 6 | translated[3], dst_stream); | ||
144 | } /* while (1) */ | ||
145 | } | ||
diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c index ae950f94f..8e60e2165 100644 --- a/libbb/xfuncs_printf.c +++ b/libbb/xfuncs_printf.c | |||
@@ -134,7 +134,7 @@ int FAST_FUNC xopen3(const char *pathname, int flags, int mode) | |||
134 | return ret; | 134 | return ret; |
135 | } | 135 | } |
136 | 136 | ||
137 | // Die if we can't open an existing file and return a fd. | 137 | // Die if we can't open a file and return a fd. |
138 | int FAST_FUNC xopen(const char *pathname, int flags) | 138 | int FAST_FUNC xopen(const char *pathname, int flags) |
139 | { | 139 | { |
140 | return xopen3(pathname, flags, 0666); | 140 | return xopen3(pathname, flags, 0666); |
diff --git a/loginutils/Config.src b/loginutils/Config.src index 5d497c4dc..8158bce74 100644 --- a/loginutils/Config.src +++ b/loginutils/Config.src | |||
@@ -93,41 +93,18 @@ config USE_BB_CRYPT_SHA | |||
93 | With this option off, login will fail password check for any | 93 | With this option off, login will fail password check for any |
94 | user which has password encrypted with these algorithms. | 94 | user which has password encrypted with these algorithms. |
95 | 95 | ||
96 | config ADDGROUP | 96 | config ADDUSER |
97 | bool "addgroup" | 97 | bool "adduser" |
98 | default y | 98 | default y |
99 | help | 99 | help |
100 | Utility for creating a new group account. | 100 | Utility for creating a new user account. |
101 | 101 | ||
102 | config FEATURE_ADDGROUP_LONG_OPTIONS | 102 | config FEATURE_ADDUSER_LONG_OPTIONS |
103 | bool "Enable long options" | 103 | bool "Enable long options" |
104 | default y | 104 | default y |
105 | depends on ADDGROUP && LONG_OPTS | 105 | depends on ADDUSER && LONG_OPTS |
106 | help | ||
107 | Support long options for the addgroup applet. | ||
108 | |||
109 | config FEATURE_ADDUSER_TO_GROUP | ||
110 | bool "Support for adding users to groups" | ||
111 | default y | ||
112 | depends on ADDGROUP | ||
113 | help | ||
114 | If called with two non-option arguments, | ||
115 | addgroup will add an existing user to an | ||
116 | existing group. | ||
117 | |||
118 | config DELGROUP | ||
119 | bool "delgroup" | ||
120 | default y | ||
121 | help | ||
122 | Utility for deleting a group account. | ||
123 | |||
124 | config FEATURE_DEL_USER_FROM_GROUP | ||
125 | bool "Support for removing users from groups" | ||
126 | default y | ||
127 | depends on DELGROUP | ||
128 | help | 106 | help |
129 | If called with two non-option arguments, deluser | 107 | Support long options for the adduser applet. |
130 | or delgroup will remove an user from a specified group. | ||
131 | 108 | ||
132 | config FEATURE_CHECK_NAMES | 109 | config FEATURE_CHECK_NAMES |
133 | bool "Enable sanity check on user/group names in adduser and addgroup" | 110 | bool "Enable sanity check on user/group names in adduser and addgroup" |
@@ -141,19 +118,6 @@ config FEATURE_CHECK_NAMES | |||
141 | For compatibility with Samba machine accounts "$" is also supported | 118 | For compatibility with Samba machine accounts "$" is also supported |
142 | at the end of the user or group name. | 119 | at the end of the user or group name. |
143 | 120 | ||
144 | config ADDUSER | ||
145 | bool "adduser" | ||
146 | default y | ||
147 | help | ||
148 | Utility for creating a new user account. | ||
149 | |||
150 | config FEATURE_ADDUSER_LONG_OPTIONS | ||
151 | bool "Enable long options" | ||
152 | default y | ||
153 | depends on ADDUSER && LONG_OPTS | ||
154 | help | ||
155 | Support long options for the adduser applet. | ||
156 | |||
157 | config FIRST_SYSTEM_ID | 121 | config FIRST_SYSTEM_ID |
158 | int "First valid system uid or gid for adduser and addgroup" | 122 | int "First valid system uid or gid for adduser and addgroup" |
159 | depends on ADDUSER || ADDGROUP | 123 | depends on ADDUSER || ADDGROUP |
@@ -170,12 +134,48 @@ config LAST_SYSTEM_ID | |||
170 | help | 134 | help |
171 | Last valid system uid or gid for adduser and addgroup | 135 | Last valid system uid or gid for adduser and addgroup |
172 | 136 | ||
137 | config ADDGROUP | ||
138 | bool "addgroup" | ||
139 | default y | ||
140 | help | ||
141 | Utility for creating a new group account. | ||
142 | |||
143 | config FEATURE_ADDGROUP_LONG_OPTIONS | ||
144 | bool "Enable long options" | ||
145 | default y | ||
146 | depends on ADDGROUP && LONG_OPTS | ||
147 | help | ||
148 | Support long options for the addgroup applet. | ||
149 | |||
150 | config FEATURE_ADDUSER_TO_GROUP | ||
151 | bool "Support for adding users to groups" | ||
152 | default y | ||
153 | depends on ADDGROUP | ||
154 | help | ||
155 | If called with two non-option arguments, | ||
156 | addgroup will add an existing user to an | ||
157 | existing group. | ||
158 | |||
173 | config DELUSER | 159 | config DELUSER |
174 | bool "deluser" | 160 | bool "deluser" |
175 | default y | 161 | default y |
176 | help | 162 | help |
177 | Utility for deleting a user account. | 163 | Utility for deleting a user account. |
178 | 164 | ||
165 | config DELGROUP | ||
166 | bool "delgroup" | ||
167 | default y | ||
168 | help | ||
169 | Utility for deleting a group account. | ||
170 | |||
171 | config FEATURE_DEL_USER_FROM_GROUP | ||
172 | bool "Support for removing users from groups" | ||
173 | default y | ||
174 | depends on DELGROUP | ||
175 | help | ||
176 | If called with two non-option arguments, deluser | ||
177 | or delgroup will remove an user from a specified group. | ||
178 | |||
179 | config GETTY | 179 | config GETTY |
180 | bool "getty" | 180 | bool "getty" |
181 | default y | 181 | default y |
diff --git a/loginutils/deluser.c b/loginutils/deluser.c index e234d6678..08ca266d0 100644 --- a/loginutils/deluser.c +++ b/loginutils/deluser.c | |||
@@ -11,20 +11,13 @@ | |||
11 | */ | 11 | */ |
12 | #include "libbb.h" | 12 | #include "libbb.h" |
13 | 13 | ||
14 | static int del_line_matching(char **args, const char *filename) | ||
15 | { | ||
16 | if (ENABLE_FEATURE_DEL_USER_FROM_GROUP && args[2]) { | ||
17 | return update_passwd(filename, args[2], NULL, args[1]); | ||
18 | } | ||
19 | return update_passwd(filename, args[1], NULL, NULL); | ||
20 | } | ||
21 | |||
22 | int deluser_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 14 | int deluser_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
23 | int deluser_main(int argc, char **argv) | 15 | int deluser_main(int argc, char **argv) |
24 | { | 16 | { |
25 | if (argc != 2 | 17 | if (argc != 2 |
26 | && (!ENABLE_FEATURE_DEL_USER_FROM_GROUP | 18 | && (!ENABLE_FEATURE_DEL_USER_FROM_GROUP |
27 | || (applet_name[3] != 'g' || argc != 3)) | 19 | || applet_name[3] != 'g' |
20 | || argc != 3) | ||
28 | ) { | 21 | ) { |
29 | bb_show_usage(); | 22 | bb_show_usage(); |
30 | } | 23 | } |
@@ -32,25 +25,30 @@ int deluser_main(int argc, char **argv) | |||
32 | if (geteuid()) | 25 | if (geteuid()) |
33 | bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); | 26 | bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); |
34 | 27 | ||
35 | if ((ENABLE_FEATURE_DEL_USER_FROM_GROUP && argc != 3) | 28 | if (ENABLE_DELUSER && applet_name[3] == 'u') { |
36 | || ENABLE_DELUSER | 29 | /* deluser USER */ |
37 | || (ENABLE_DELGROUP && ENABLE_DESKTOP) | 30 | if (update_passwd(bb_path_passwd_file, argv[1], NULL, NULL) < 0) |
38 | ) { | 31 | return EXIT_FAILURE; |
39 | if (ENABLE_DELUSER | 32 | if (ENABLE_FEATURE_SHADOWPASSWDS) |
40 | && (!ENABLE_DELGROUP || applet_name[3] == 'u') | 33 | if (update_passwd(bb_path_shadow_file, argv[1], NULL, NULL) < 0) |
41 | ) { | ||
42 | if (del_line_matching(argv, bb_path_passwd_file) < 0) | ||
43 | return EXIT_FAILURE; | 34 | return EXIT_FAILURE; |
44 | if (ENABLE_FEATURE_SHADOWPASSWDS) { | 35 | } else if (ENABLE_DELGROUP) { |
45 | del_line_matching(argv, bb_path_shadow_file); | 36 | /* delgroup ... */ |
46 | } | 37 | if (!ENABLE_FEATURE_DEL_USER_FROM_GROUP || argc != 3) { |
47 | } else if (ENABLE_DESKTOP && ENABLE_DELGROUP && getpwnam(argv[1])) | 38 | /* delgroup GROUP */ |
48 | bb_error_msg_and_die("can't remove primary group of user %s", argv[1]); | 39 | if (update_passwd(bb_path_group_file, argv[1], NULL, NULL) < 0) |
49 | } | 40 | return EXIT_FAILURE; |
50 | if (del_line_matching(argv, bb_path_group_file) < 0) | 41 | if (ENABLE_FEATURE_SHADOWPASSWDS) |
51 | return EXIT_FAILURE; | 42 | if (update_passwd(bb_path_gshadow_file, argv[1], NULL, NULL) < 0) |
52 | if (ENABLE_FEATURE_SHADOWPASSWDS) { | 43 | return EXIT_FAILURE; |
53 | del_line_matching(argv, bb_path_gshadow_file); | 44 | } else { |
45 | /* delgroup USER GROUP */ | ||
46 | if (update_passwd(bb_path_group_file, argv[2], NULL, argv[1]) < 0) | ||
47 | return EXIT_FAILURE; | ||
48 | if (ENABLE_FEATURE_SHADOWPASSWDS) | ||
49 | if (update_passwd(bb_path_gshadow_file, argv[2], NULL, argv[1]) < 0) | ||
50 | return EXIT_FAILURE; | ||
51 | } | ||
54 | } | 52 | } |
55 | return EXIT_SUCCESS; | 53 | return EXIT_SUCCESS; |
56 | } | 54 | } |
diff --git a/mailutils/mail.c b/mailutils/mail.c index 8e52a3efc..9b4bebce5 100644 --- a/mailutils/mail.c +++ b/mailutils/mail.c | |||
@@ -116,16 +116,15 @@ void FAST_FUNC encode_base64(char *fname, const char *text, const char *eol) | |||
116 | SRC_BUF_SIZE = 45, /* This *MUST* be a multiple of 3 */ | 116 | SRC_BUF_SIZE = 45, /* This *MUST* be a multiple of 3 */ |
117 | DST_BUF_SIZE = 4 * ((SRC_BUF_SIZE + 2) / 3), | 117 | DST_BUF_SIZE = 4 * ((SRC_BUF_SIZE + 2) / 3), |
118 | }; | 118 | }; |
119 | |||
120 | #define src_buf text | 119 | #define src_buf text |
120 | char src[SRC_BUF_SIZE]; | ||
121 | FILE *fp = fp; | 121 | FILE *fp = fp; |
122 | ssize_t len = len; | 122 | ssize_t len = len; |
123 | char dst_buf[DST_BUF_SIZE + 1]; | 123 | char dst_buf[DST_BUF_SIZE + 1]; |
124 | 124 | ||
125 | if (fname) { | 125 | if (fname) { |
126 | fp = (NOT_LONE_DASH(fname)) ? xfopen_for_read(fname) : (FILE *)text; | 126 | fp = (NOT_LONE_DASH(fname)) ? xfopen_for_read(fname) : (FILE *)text; |
127 | src_buf = bb_common_bufsiz1; | 127 | src_buf = src; |
128 | // N.B. strlen(NULL) segfaults! | ||
129 | } else if (text) { | 128 | } else if (text) { |
130 | // though we do not call uuencode(NULL, NULL) explicitly | 129 | // though we do not call uuencode(NULL, NULL) explicitly |
131 | // still we do not want to break things suddenly | 130 | // still we do not want to break things suddenly |
@@ -161,73 +160,6 @@ void FAST_FUNC encode_base64(char *fname, const char *text, const char *eol) | |||
161 | #undef src_buf | 160 | #undef src_buf |
162 | } | 161 | } |
163 | 162 | ||
164 | void FAST_FUNC decode_base64(FILE *src_stream, FILE *dst_stream) | ||
165 | { | ||
166 | int term_count = 1; | ||
167 | |||
168 | while (1) { | ||
169 | char translated[4]; | ||
170 | int count = 0; | ||
171 | |||
172 | while (count < 4) { | ||
173 | char *table_ptr; | ||
174 | int ch; | ||
175 | |||
176 | /* Get next _valid_ character. | ||
177 | * global vector bb_uuenc_tbl_base64[] contains this string: | ||
178 | * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n" | ||
179 | */ | ||
180 | do { | ||
181 | ch = fgetc(src_stream); | ||
182 | if (ch == EOF) { | ||
183 | bb_error_msg_and_die(bb_msg_read_error); | ||
184 | } | ||
185 | // - means end of MIME section | ||
186 | if ('-' == ch) { | ||
187 | // push it back | ||
188 | ungetc(ch, src_stream); | ||
189 | return; | ||
190 | } | ||
191 | table_ptr = strchr(bb_uuenc_tbl_base64, ch); | ||
192 | } while (table_ptr == NULL); | ||
193 | |||
194 | /* Convert encoded character to decimal */ | ||
195 | ch = table_ptr - bb_uuenc_tbl_base64; | ||
196 | |||
197 | if (*table_ptr == '=') { | ||
198 | if (term_count == 0) { | ||
199 | translated[count] = '\0'; | ||
200 | break; | ||
201 | } | ||
202 | term_count++; | ||
203 | } else if (*table_ptr == '\n') { | ||
204 | /* Check for terminating line */ | ||
205 | if (term_count == 5) { | ||
206 | return; | ||
207 | } | ||
208 | term_count = 1; | ||
209 | continue; | ||
210 | } else { | ||
211 | translated[count] = ch; | ||
212 | count++; | ||
213 | term_count = 0; | ||
214 | } | ||
215 | } | ||
216 | |||
217 | /* Merge 6 bit chars to 8 bit */ | ||
218 | if (count > 1) { | ||
219 | fputc(translated[0] << 2 | translated[1] >> 4, dst_stream); | ||
220 | } | ||
221 | if (count > 2) { | ||
222 | fputc(translated[1] << 4 | translated[2] >> 2, dst_stream); | ||
223 | } | ||
224 | if (count > 3) { | ||
225 | fputc(translated[2] << 6 | translated[3], dst_stream); | ||
226 | } | ||
227 | } | ||
228 | } | ||
229 | |||
230 | |||
231 | /* | 163 | /* |
232 | * get username and password from a file descriptor | 164 | * get username and password from a file descriptor |
233 | */ | 165 | */ |
diff --git a/mailutils/mail.h b/mailutils/mail.h index bb747c4c5..e0048fbfa 100644 --- a/mailutils/mail.h +++ b/mailutils/mail.h | |||
@@ -32,4 +32,3 @@ void FAST_FUNC get_cred_or_die(int fd); | |||
32 | const FAST_FUNC char *command(const char *fmt, const char *param); | 32 | const FAST_FUNC char *command(const char *fmt, const char *param); |
33 | 33 | ||
34 | void FAST_FUNC encode_base64(char *fname, const char *text, const char *eol); | 34 | void FAST_FUNC encode_base64(char *fname, const char *text, const char *eol); |
35 | void FAST_FUNC decode_base64(FILE *src_stream, FILE *dst_stream); | ||
diff --git a/mailutils/mime.c b/mailutils/mime.c index 44c7d0216..682cf4536 100644 --- a/mailutils/mime.c +++ b/mailutils/mime.c | |||
@@ -225,7 +225,7 @@ static int parse(const char *boundary, char **argv) | |||
225 | // prepare unique string pattern | 225 | // prepare unique string pattern |
226 | uniq = xasprintf("%%llu.%u.%s", (unsigned)getpid(), safe_gethostname()); | 226 | uniq = xasprintf("%%llu.%u.%s", (unsigned)getpid(), safe_gethostname()); |
227 | 227 | ||
228 | //bb_info_msg("PARSE[%s]", terminator); | 228 | //bb_info_msg("PARSE[%s]", uniq); |
229 | 229 | ||
230 | while ((line = xmalloc_fgets_str(stdin, "\r\n\r\n")) != NULL) { | 230 | while ((line = xmalloc_fgets_str(stdin, "\r\n\r\n")) != NULL) { |
231 | 231 | ||
@@ -306,7 +306,7 @@ static int parse(const char *boundary, char **argv) | |||
306 | 306 | ||
307 | // dump to fp | 307 | // dump to fp |
308 | if (0 == strcasecmp(encoding, "base64")) { | 308 | if (0 == strcasecmp(encoding, "base64")) { |
309 | decode_base64(stdin, fp); | 309 | read_base64(stdin, fp, '-'); |
310 | } else if (0 != strcasecmp(encoding, "7bit") | 310 | } else if (0 != strcasecmp(encoding, "7bit") |
311 | && 0 != strcasecmp(encoding, "8bit") | 311 | && 0 != strcasecmp(encoding, "8bit") |
312 | ) { | 312 | ) { |
diff --git a/mailutils/popmaildir.c b/mailutils/popmaildir.c index f37db03d5..77ec71129 100644 --- a/mailutils/popmaildir.c +++ b/mailutils/popmaildir.c | |||
@@ -109,9 +109,9 @@ int popmaildir_main(int argc UNUSED_PARAM, char **argv) | |||
109 | s[1] = '\0'; | 109 | s[1] = '\0'; |
110 | // get md5 sum of "<stamp>password" string | 110 | // get md5 sum of "<stamp>password" string |
111 | md5_begin(&md5.ctx); | 111 | md5_begin(&md5.ctx); |
112 | md5_hash(buf, strlen(buf), &md5.ctx); | 112 | md5_hash(&md5.ctx, buf, strlen(buf)); |
113 | md5_hash(G.pass, strlen(G.pass), &md5.ctx); | 113 | md5_hash(&md5.ctx, G.pass, strlen(G.pass)); |
114 | md5_end(res, &md5.ctx); | 114 | md5_end(&md5.ctx, res); |
115 | *bin2hex(md5.hex, (char*)res, 16) = '\0'; | 115 | *bin2hex(md5.hex, (char*)res, 16) = '\0'; |
116 | // APOP | 116 | // APOP |
117 | s = xasprintf("%s %s", G.user, md5.hex); | 117 | s = xasprintf("%s %s", G.user, md5.hex); |
diff --git a/mailutils/sendmail.c b/mailutils/sendmail.c index 59591ee4b..ec97cf8af 100644 --- a/mailutils/sendmail.c +++ b/mailutils/sendmail.c | |||
@@ -221,12 +221,12 @@ int sendmail_main(int argc UNUSED_PARAM, char **argv) | |||
221 | 221 | ||
222 | // analyze headers | 222 | // analyze headers |
223 | // To: or Cc: headers add recipients | 223 | // To: or Cc: headers add recipients |
224 | if (0 == strncasecmp("To: ", s, 4) || 0 == strncasecmp("Bcc: " + 1, s, 4)) { | 224 | if (0 == strncasecmp("To:", s, 3) || 0 == strncasecmp("Bcc:" + 1, s, 3)) { |
225 | rcptto(sane_address(s+4)); | 225 | rcptto(sane_address(s+3)); |
226 | goto addheader; | 226 | goto addheader; |
227 | // Bcc: header adds blind copy (hidden) recipient | 227 | // Bcc: header adds blind copy (hidden) recipient |
228 | } else if (0 == strncasecmp("Bcc: ", s, 5)) { | 228 | } else if (0 == strncasecmp("Bcc:", s, 4)) { |
229 | rcptto(sane_address(s+5)); | 229 | rcptto(sane_address(s+4)); |
230 | free(s); | 230 | free(s); |
231 | // N.B. Bcc: vanishes from headers! | 231 | // N.B. Bcc: vanishes from headers! |
232 | 232 | ||
diff --git a/miscutils/Config.src b/miscutils/Config.src index 151f61bcc..4912daf88 100644 --- a/miscutils/Config.src +++ b/miscutils/Config.src | |||
@@ -136,7 +136,6 @@ config CHRT | |||
136 | config CROND | 136 | config CROND |
137 | bool "crond" | 137 | bool "crond" |
138 | default y | 138 | default y |
139 | select FEATURE_SUID | ||
140 | select FEATURE_SYSLOG | 139 | select FEATURE_SYSLOG |
141 | help | 140 | help |
142 | Crond is a background daemon that parses individual crontab | 141 | Crond is a background daemon that parses individual crontab |
diff --git a/miscutils/man.c b/miscutils/man.c index 2d3776cf3..b356e726f 100644 --- a/miscutils/man.c +++ b/miscutils/man.c | |||
@@ -182,16 +182,21 @@ int man_main(int argc UNUSED_PARAM, char **argv) | |||
182 | pager = "more"; | 182 | pager = "more"; |
183 | } | 183 | } |
184 | 184 | ||
185 | /* Parse man.conf[ig] */ | 185 | /* Parse man.conf[ig] or man_db.conf */ |
186 | /* man version 1.6f uses man.config */ | 186 | /* man version 1.6f uses man.config */ |
187 | /* man-db implementation of man uses man_db.conf */ | ||
187 | parser = config_open2("/etc/man.config", fopen_for_read); | 188 | parser = config_open2("/etc/man.config", fopen_for_read); |
188 | if (!parser) | 189 | if (!parser) |
189 | parser = config_open2("/etc/man.conf", fopen_for_read); | 190 | parser = config_open2("/etc/man.conf", fopen_for_read); |
191 | if (!parser) | ||
192 | parser = config_open2("/etc/man_db.conf", fopen_for_read); | ||
190 | 193 | ||
191 | while (config_read(parser, token, 2, 0, "# \t", PARSE_NORMAL)) { | 194 | while (config_read(parser, token, 2, 0, "# \t", PARSE_NORMAL)) { |
192 | if (!token[1]) | 195 | if (!token[1]) |
193 | continue; | 196 | continue; |
194 | if (strcmp("MANPATH", token[0]) == 0) { | 197 | if (strcmp("MANDATORY_MANPATH"+10, token[0]) == 0 /* "MANPATH"? */ |
198 | || strcmp("MANDATORY_MANPATH", token[0]) == 0 | ||
199 | ) { | ||
195 | char *path = token[1]; | 200 | char *path = token[1]; |
196 | while (*path) { | 201 | while (*path) { |
197 | char *next_path; | 202 | char *next_path; |
diff --git a/miscutils/nandwrite.c b/miscutils/nandwrite.c index f42242687..6c85ea346 100644 --- a/miscutils/nandwrite.c +++ b/miscutils/nandwrite.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * nandwrite.c - ported to busybox from mtd-utils | 2 | * nandwrite and nanddump ported to busybox from mtd-utils |
3 | * | 3 | * |
4 | * Author: Baruch Siach <baruch@tkos.co.il>, Orex Computed Radiography | 4 | * Author: Baruch Siach <baruch@tkos.co.il>, Orex Computed Radiography |
5 | * | 5 | * |
@@ -9,8 +9,10 @@ | |||
9 | */ | 9 | */ |
10 | 10 | ||
11 | //applet:IF_NANDWRITE(APPLET(nandwrite, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) | 11 | //applet:IF_NANDWRITE(APPLET(nandwrite, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) |
12 | //applet:IF_NANDWRITE(APPLET_ODDNAME(nanddump, nandwrite, _BB_DIR_USR_SBIN, _BB_SUID_DROP, nanddump)) | ||
12 | 13 | ||
13 | //kbuild:lib-$(CONFIG_NANDWRITE) += nandwrite.o | 14 | //kbuild:lib-$(CONFIG_NANDWRITE) += nandwrite.o |
15 | //kbuild:lib-$(CONFIG_NANDDUMP) += nandwrite.o | ||
14 | 16 | ||
15 | //config:config NANDWRITE | 17 | //config:config NANDWRITE |
16 | //config: bool "nandwrite" | 18 | //config: bool "nandwrite" |
@@ -18,9 +20,13 @@ | |||
18 | //config: depends on PLATFORM_LINUX | 20 | //config: depends on PLATFORM_LINUX |
19 | //config: help | 21 | //config: help |
20 | //config: Write to the specified MTD device, with bad blocks awareness | 22 | //config: Write to the specified MTD device, with bad blocks awareness |
21 | 23 | //config: | |
22 | #include "libbb.h" | 24 | //config:config NANDDUMP |
23 | #include <mtd/mtd-user.h> | 25 | //config: bool "nanddump" |
26 | //config: default n | ||
27 | //config: depends on PLATFORM_LINUX | ||
28 | //config: help | ||
29 | //config: Dump the content of raw NAND chip | ||
24 | 30 | ||
25 | //usage:#define nandwrite_trivial_usage | 31 | //usage:#define nandwrite_trivial_usage |
26 | //usage: "[-p] [-s ADDR] MTD_DEVICE [FILE]" | 32 | //usage: "[-p] [-s ADDR] MTD_DEVICE [FILE]" |
@@ -30,18 +36,65 @@ | |||
30 | //usage: "\n -p Pad to page size" | 36 | //usage: "\n -p Pad to page size" |
31 | //usage: "\n -s ADDR Start address" | 37 | //usage: "\n -s ADDR Start address" |
32 | 38 | ||
39 | //usage:#define nanddump_trivial_usage | ||
40 | //usage: "[-o] [-b] [-s ADDR] [-f FILE] MTD_DEVICE" | ||
41 | //usage:#define nanddump_full_usage "\n\n" | ||
42 | //usage: "Dump the sepcified MTD device\n" | ||
43 | //usage: "\nOptions:" | ||
44 | //usage: "\n -o Omit oob data" | ||
45 | //usage: "\n -b Omit bad block from the dump" | ||
46 | //usage: "\n -s ADDR Start address" | ||
47 | //usage: "\n -l LEN Length" | ||
48 | //usage: "\n -f FILE Dump to file ('-' for stdout)" | ||
49 | |||
50 | #include "libbb.h" | ||
51 | #include <mtd/mtd-user.h> | ||
52 | |||
53 | #define IS_NANDDUMP (ENABLE_NANDDUMP && (!ENABLE_NANDWRITE || (applet_name[4] == 'd'))) | ||
54 | #define IS_NANDWRITE (ENABLE_NANDWRITE && (!ENABLE_NANDDUMP || (applet_name[4] != 'd'))) | ||
55 | |||
56 | #define OPT_p (1 << 0) /* nandwrite only */ | ||
57 | #define OPT_o (1 << 0) /* nanddump only */ | ||
58 | #define OPT_s (1 << 1) | ||
59 | #define OPT_b (1 << 2) | ||
60 | #define OPT_f (1 << 3) | ||
61 | #define OPT_l (1 << 4) | ||
62 | |||
63 | #define NAND_MAX_OOBSIZE 256 | ||
64 | /* helper for writing out 0xff for bad blocks pad */ | ||
65 | static void dump_bad(struct mtd_info_user *meminfo, unsigned len, int oob) | ||
66 | { | ||
67 | unsigned char buf[meminfo->writesize]; | ||
68 | unsigned count; | ||
69 | |||
70 | /* round len to the next page */ | ||
71 | len = (len | ~(meminfo->writesize - 1)) + 1; | ||
72 | |||
73 | memset(buf, 0xff, sizeof(buf)); | ||
74 | for (count = 0; count < len; count += meminfo->writesize) { | ||
75 | xwrite(STDOUT_FILENO, buf, meminfo->writesize); | ||
76 | if (oob) | ||
77 | xwrite(STDOUT_FILENO, buf, meminfo->oobsize); | ||
78 | } | ||
79 | } | ||
80 | |||
33 | static unsigned next_good_eraseblock(int fd, struct mtd_info_user *meminfo, | 81 | static unsigned next_good_eraseblock(int fd, struct mtd_info_user *meminfo, |
34 | unsigned block_offset) | 82 | unsigned block_offset) |
35 | { | 83 | { |
36 | while (1) { | 84 | while (1) { |
37 | loff_t offs; | 85 | loff_t offs; |
38 | if (block_offset >= meminfo->size) | 86 | |
39 | bb_error_msg_and_die("not enough space in MTD device"); | 87 | if (block_offset >= meminfo->size) { |
88 | if (IS_NANDWRITE) | ||
89 | bb_error_msg_and_die("not enough space in MTD device"); | ||
90 | return block_offset; /* let the caller exit */ | ||
91 | } | ||
40 | offs = block_offset; | 92 | offs = block_offset; |
41 | if (xioctl(fd, MEMGETBADBLOCK, &offs) == 0) | 93 | if (xioctl(fd, MEMGETBADBLOCK, &offs) == 0) |
42 | return block_offset; | 94 | return block_offset; |
43 | /* ioctl returned 1 => "bad block" */ | 95 | /* ioctl returned 1 => "bad block" */ |
44 | printf("Skipping bad block at 0x%08x\n", block_offset); | 96 | if (IS_NANDWRITE) |
97 | printf("Skipping bad block at 0x%08x\n", block_offset); | ||
45 | block_offset += meminfo->erasesize; | 98 | block_offset += meminfo->erasesize; |
46 | } | 99 | } |
47 | } | 100 | } |
@@ -49,31 +102,49 @@ static unsigned next_good_eraseblock(int fd, struct mtd_info_user *meminfo, | |||
49 | int nandwrite_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 102 | int nandwrite_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
50 | int nandwrite_main(int argc UNUSED_PARAM, char **argv) | 103 | int nandwrite_main(int argc UNUSED_PARAM, char **argv) |
51 | { | 104 | { |
105 | /* Buffer for OOB data */ | ||
106 | unsigned char oobbuf[NAND_MAX_OOBSIZE]; | ||
52 | unsigned opts; | 107 | unsigned opts; |
53 | int fd; | 108 | int fd; |
54 | ssize_t cnt; | 109 | ssize_t cnt; |
55 | unsigned mtdoffset, meminfo_writesize, blockstart; | 110 | unsigned mtdoffset, meminfo_writesize, blockstart, limit; |
111 | unsigned end_addr = ~0; | ||
56 | struct mtd_info_user meminfo; | 112 | struct mtd_info_user meminfo; |
113 | struct mtd_oob_buf oob; | ||
57 | unsigned char *filebuf; | 114 | unsigned char *filebuf; |
58 | const char *opt_s = "0"; | 115 | const char *opt_s = "0", *opt_f = "-", *opt_l; |
59 | enum { | 116 | |
60 | OPT_p = (1 << 0), | 117 | if (IS_NANDDUMP) { |
61 | OPT_s = (1 << 1), | 118 | opt_complementary = "=1"; |
62 | }; | 119 | opts = getopt32(argv, "os:bf:l:", &opt_s, &opt_f, &opt_l); |
63 | 120 | } else { /* nandwrite */ | |
64 | opt_complementary = "-1:?2"; | 121 | opt_complementary = "-1:?2"; |
65 | opts = getopt32(argv, "ps:", &opt_s); | 122 | opts = getopt32(argv, "ps:", &opt_s); |
123 | } | ||
66 | argv += optind; | 124 | argv += optind; |
67 | 125 | ||
68 | if (argv[1]) | 126 | if (IS_NANDWRITE && argv[1]) |
69 | xmove_fd(xopen_stdin(argv[1]), STDIN_FILENO); | 127 | opt_f = argv[1]; |
128 | if (!LONE_DASH(opt_f)) { | ||
129 | int tmp_fd = xopen(opt_f, | ||
130 | IS_NANDDUMP ? O_WRONLY | O_TRUNC | O_CREAT : O_RDONLY | ||
131 | ); | ||
132 | xmove_fd(tmp_fd, IS_NANDDUMP ? STDOUT_FILENO : STDIN_FILENO); | ||
133 | } | ||
70 | 134 | ||
71 | fd = xopen(argv[0], O_RDWR); | 135 | fd = xopen(argv[0], O_RDWR); |
72 | xioctl(fd, MEMGETINFO, &meminfo); | 136 | xioctl(fd, MEMGETINFO, &meminfo); |
73 | 137 | ||
74 | mtdoffset = bb_strtou(opt_s, NULL, 0); | 138 | oob.start = 0; |
75 | if (errno) | 139 | oob.length = meminfo.oobsize; |
76 | bb_error_msg_and_die("invalid number '%s'", opt_s); | 140 | oob.ptr = oobbuf; |
141 | |||
142 | mtdoffset = xstrtou(opt_s, 0); | ||
143 | if (IS_NANDDUMP && (opts & OPT_l)) { | ||
144 | unsigned length = xstrtou(opt_l, 0); | ||
145 | if (length < meminfo.size - mtdoffset) | ||
146 | end_addr = mtdoffset + length; | ||
147 | } | ||
77 | 148 | ||
78 | /* Pull it into a CPU register (hopefully) - smaller code that way */ | 149 | /* Pull it into a CPU register (hopefully) - smaller code that way */ |
79 | meminfo_writesize = meminfo.writesize; | 150 | meminfo_writesize = meminfo.writesize; |
@@ -91,20 +162,39 @@ int nandwrite_main(int argc UNUSED_PARAM, char **argv) | |||
91 | * bad. | 162 | * bad. |
92 | */ | 163 | */ |
93 | tmp = next_good_eraseblock(fd, &meminfo, blockstart); | 164 | tmp = next_good_eraseblock(fd, &meminfo, blockstart); |
94 | if (tmp != blockstart) /* bad block(s), advance mtdoffset */ | 165 | if (tmp != blockstart) { |
166 | /* bad block(s), advance mtdoffset */ | ||
167 | if (IS_NANDDUMP & !(opts & OPT_b)) { | ||
168 | int bad_len = MIN(tmp, end_addr) - mtdoffset; | ||
169 | dump_bad(&meminfo, bad_len, !(opts & OPT_o)); | ||
170 | } | ||
95 | mtdoffset = tmp; | 171 | mtdoffset = tmp; |
172 | } | ||
96 | } | 173 | } |
97 | 174 | ||
98 | cnt = -1; | 175 | cnt = -1; |
99 | while (mtdoffset < meminfo.size) { | 176 | limit = MIN(meminfo.size, end_addr); |
177 | while (mtdoffset < limit) { | ||
178 | int input_fd = IS_NANDWRITE ? STDIN_FILENO : fd; | ||
179 | int output_fd = IS_NANDWRITE ? fd : STDOUT_FILENO; | ||
180 | |||
100 | blockstart = mtdoffset & ~(meminfo.erasesize - 1); | 181 | blockstart = mtdoffset & ~(meminfo.erasesize - 1); |
101 | if (blockstart == mtdoffset) { | 182 | if (blockstart == mtdoffset) { |
102 | /* starting a new eraseblock */ | 183 | /* starting a new eraseblock */ |
103 | mtdoffset = next_good_eraseblock(fd, &meminfo, blockstart); | 184 | mtdoffset = next_good_eraseblock(fd, &meminfo, blockstart); |
104 | printf("Writing at 0x%08x\n", mtdoffset); | 185 | if (IS_NANDWRITE) |
186 | printf("Writing at 0x%08x\n", mtdoffset); | ||
187 | else if (mtdoffset > blockstart) { | ||
188 | int bad_len = MIN(mtdoffset, limit) - blockstart; | ||
189 | dump_bad(&meminfo, bad_len, !(opts & OPT_o)); | ||
190 | } | ||
191 | if (mtdoffset >= limit) | ||
192 | break; | ||
105 | } | 193 | } |
194 | xlseek(fd, mtdoffset, SEEK_SET); | ||
195 | |||
106 | /* get some more data from input */ | 196 | /* get some more data from input */ |
107 | cnt = full_read(STDIN_FILENO, filebuf, meminfo_writesize); | 197 | cnt = full_read(input_fd, filebuf, meminfo_writesize); |
108 | if (cnt == 0) { | 198 | if (cnt == 0) { |
109 | /* even with -p, we do not pad past the end of input | 199 | /* even with -p, we do not pad past the end of input |
110 | * (-p only zero-pads last incomplete page) | 200 | * (-p only zero-pads last incomplete page) |
@@ -112,20 +202,29 @@ int nandwrite_main(int argc UNUSED_PARAM, char **argv) | |||
112 | break; | 202 | break; |
113 | } | 203 | } |
114 | if (cnt < meminfo_writesize) { | 204 | if (cnt < meminfo_writesize) { |
205 | if (IS_NANDDUMP) | ||
206 | bb_error_msg_and_die("short read"); | ||
115 | if (!(opts & OPT_p)) | 207 | if (!(opts & OPT_p)) |
116 | bb_error_msg_and_die("input size is not rounded up to page size, " | 208 | bb_error_msg_and_die("input size is not rounded up to page size, " |
117 | "use -p to zero pad"); | 209 | "use -p to zero pad"); |
118 | /* zero pad to end of write block */ | 210 | /* zero pad to end of write block */ |
119 | memset(filebuf + cnt, 0, meminfo_writesize - cnt); | 211 | memset(filebuf + cnt, 0, meminfo_writesize - cnt); |
120 | } | 212 | } |
121 | xlseek(fd, mtdoffset, SEEK_SET); | 213 | xwrite(output_fd, filebuf, meminfo_writesize); |
122 | xwrite(fd, filebuf, meminfo_writesize); | 214 | |
215 | if (IS_NANDDUMP && !(opts & OPT_o)) { | ||
216 | /* Dump OOB data */ | ||
217 | oob.start = mtdoffset; | ||
218 | xioctl(fd, MEMREADOOB, &oob); | ||
219 | xwrite(output_fd, oobbuf, meminfo.oobsize); | ||
220 | } | ||
221 | |||
123 | mtdoffset += meminfo_writesize; | 222 | mtdoffset += meminfo_writesize; |
124 | if (cnt < meminfo_writesize) | 223 | if (cnt < meminfo_writesize) |
125 | break; | 224 | break; |
126 | } | 225 | } |
127 | 226 | ||
128 | if (cnt != 0) { | 227 | if (IS_NANDWRITE && cnt != 0) { |
129 | /* We filled entire MTD, but did we reach EOF on input? */ | 228 | /* We filled entire MTD, but did we reach EOF on input? */ |
130 | if (full_read(STDIN_FILENO, filebuf, meminfo_writesize) != 0) { | 229 | if (full_read(STDIN_FILENO, filebuf, meminfo_writesize) != 0) { |
131 | /* no */ | 230 | /* no */ |
diff --git a/modutils/depmod.c b/modutils/depmod.c index 006a7bcc1..85b64a229 100644 --- a/modutils/depmod.c +++ b/modutils/depmod.c | |||
@@ -8,6 +8,13 @@ | |||
8 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 8 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | //applet:IF_DEPMOD(APPLET(depmod, _BB_DIR_SBIN, _BB_SUID_DROP)) | ||
12 | |||
13 | //usage:#if !ENABLE_MODPROBE_SMALL | ||
14 | //usage:#define depmod_trivial_usage NOUSAGE_STR | ||
15 | //usage:#define depmod_full_usage "" | ||
16 | //usage:#endif | ||
17 | |||
11 | #include "libbb.h" | 18 | #include "libbb.h" |
12 | #include "modutils.h" | 19 | #include "modutils.h" |
13 | #include <sys/utsname.h> /* uname() */ | 20 | #include <sys/utsname.h> /* uname() */ |
@@ -144,6 +151,8 @@ static void xfreopen_write(const char *file, FILE *f) | |||
144 | * Print to stdout all the symbols each module depends on | 151 | * Print to stdout all the symbols each module depends on |
145 | * and the module's file name which provides that symbol. | 152 | * and the module's file name which provides that symbol. |
146 | * -r No-op | 153 | * -r No-op |
154 | * -u No-op | ||
155 | * -q No-op | ||
147 | * | 156 | * |
148 | * So far we only support: [-rn] [-b BASE] [VERSION] [MODFILES]... | 157 | * So far we only support: [-rn] [-b BASE] [VERSION] [MODFILES]... |
149 | * -aAeF are accepted but ignored. -vC are not accepted. | 158 | * -aAeF are accepted but ignored. -vC are not accepted. |
@@ -155,7 +164,10 @@ enum { | |||
155 | //OPT_e = (1 << 3), /* with -F, print unresolved symbols */ | 164 | //OPT_e = (1 << 3), /* with -F, print unresolved symbols */ |
156 | //OPT_F = (1 << 4), /* System.map that contains the symbols */ | 165 | //OPT_F = (1 << 4), /* System.map that contains the symbols */ |
157 | OPT_n = (1 << 5), /* dry-run, print to stdout only */ | 166 | OPT_n = (1 << 5), /* dry-run, print to stdout only */ |
158 | OPT_r = (1 << 6) /* Compat dummy. Linux Makefile uses it */ | 167 | OPT_r = (1 << 6), /* Compat dummy. Linux Makefile uses it */ |
168 | OPT_u = (1 << 7), /* -u,--unresolved-error: ignored */ | ||
169 | OPT_q = (1 << 8), /* -q,--quiet: ignored */ | ||
170 | OPT_C = (1 << 9), /* -C,--config etc_modules_conf: ignored */ | ||
159 | }; | 171 | }; |
160 | 172 | ||
161 | int depmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 173 | int depmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
@@ -167,7 +179,7 @@ int depmod_main(int argc UNUSED_PARAM, char **argv) | |||
167 | struct utsname uts; | 179 | struct utsname uts; |
168 | int tmp; | 180 | int tmp; |
169 | 181 | ||
170 | getopt32(argv, "aAb:eF:nr", &moddir_base, NULL); | 182 | getopt32(argv, "aAb:eF:nruqC:", &moddir_base, NULL, NULL); |
171 | argv += optind; | 183 | argv += optind; |
172 | 184 | ||
173 | /* goto modules location */ | 185 | /* goto modules location */ |
diff --git a/modutils/insmod.c b/modutils/insmod.c index 17fc18c09..7ec3cae47 100644 --- a/modutils/insmod.c +++ b/modutils/insmod.c | |||
@@ -7,16 +7,19 @@ | |||
7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | //applet:IF_INSMOD(APPLET(insmod, _BB_DIR_SBIN, _BB_SUID_DROP)) | ||
11 | |||
10 | #include "libbb.h" | 12 | #include "libbb.h" |
11 | #include "modutils.h" | 13 | #include "modutils.h" |
12 | 14 | ||
13 | /* 2.6 style insmod has no options and required filename | 15 | /* 2.6 style insmod has no options and required filename |
14 | * (not module name - .ko can't be omitted) */ | 16 | * (not module name - .ko can't be omitted) */ |
15 | 17 | ||
18 | //usage:#if !ENABLE_MODPROBE_SMALL | ||
16 | //usage:#define insmod_trivial_usage | 19 | //usage:#define insmod_trivial_usage |
17 | //usage: IF_FEATURE_2_4_MODULES("[OPTIONS] MODULE ") | 20 | //usage: IF_FEATURE_2_4_MODULES("[OPTIONS] MODULE ") |
18 | //usage: IF_NOT_FEATURE_2_4_MODULES("FILE ") | 21 | //usage: IF_NOT_FEATURE_2_4_MODULES("FILE ") |
19 | //usage: "[symbol=value]..." | 22 | //usage: "[SYMBOL=VALUE]..." |
20 | //usage:#define insmod_full_usage "\n\n" | 23 | //usage:#define insmod_full_usage "\n\n" |
21 | //usage: "Load the specified kernel modules into the kernel" | 24 | //usage: "Load the specified kernel modules into the kernel" |
22 | //usage: IF_FEATURE_2_4_MODULES( "\n" | 25 | //usage: IF_FEATURE_2_4_MODULES( "\n" |
@@ -31,6 +34,7 @@ | |||
31 | //usage: ) | 34 | //usage: ) |
32 | //usage: "\n -x Don't export externs" | 35 | //usage: "\n -x Don't export externs" |
33 | //usage: ) | 36 | //usage: ) |
37 | //usage:#endif | ||
34 | 38 | ||
35 | int insmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 39 | int insmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
36 | int insmod_main(int argc UNUSED_PARAM, char **argv) | 40 | int insmod_main(int argc UNUSED_PARAM, char **argv) |
diff --git a/modutils/lsmod.c b/modutils/lsmod.c index 9558a2510..ab7c11f2a 100644 --- a/modutils/lsmod.c +++ b/modutils/lsmod.c | |||
@@ -7,6 +7,16 @@ | |||
7 | * | 7 | * |
8 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 8 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
9 | */ | 9 | */ |
10 | |||
11 | //applet:IF_LSMOD(APPLET(lsmod, _BB_DIR_SBIN, _BB_SUID_DROP)) | ||
12 | |||
13 | //usage:#if !ENABLE_MODPROBE_SMALL | ||
14 | //usage:#define lsmod_trivial_usage | ||
15 | //usage: "" | ||
16 | //usage:#define lsmod_full_usage "\n\n" | ||
17 | //usage: "List the currently loaded kernel modules" | ||
18 | //usage:#endif | ||
19 | |||
10 | #include "libbb.h" | 20 | #include "libbb.h" |
11 | #include "unicode.h" | 21 | #include "unicode.h" |
12 | 22 | ||
diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c index 05f2c34eb..ec3ddfb8f 100644 --- a/modutils/modprobe-small.c +++ b/modutils/modprobe-small.c | |||
@@ -8,6 +8,12 @@ | |||
8 | * Licensed under GPLv2, see file LICENSE in this source tree. | 8 | * Licensed under GPLv2, see file LICENSE in this source tree. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | //applet:IF_MODPROBE_SMALL(APPLET(modprobe, _BB_DIR_SBIN, _BB_SUID_DROP)) | ||
12 | //applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(depmod, modprobe, _BB_DIR_SBIN, _BB_SUID_DROP, modprobe)) | ||
13 | //applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(insmod, modprobe, _BB_DIR_SBIN, _BB_SUID_DROP, modprobe)) | ||
14 | //applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(lsmod, modprobe, _BB_DIR_SBIN, _BB_SUID_DROP, modprobe)) | ||
15 | //applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(rmmod, modprobe, _BB_DIR_SBIN, _BB_SUID_DROP, modprobe)) | ||
16 | |||
11 | #include "libbb.h" | 17 | #include "libbb.h" |
12 | /* After libbb.h, since it needs sys/types.h on some systems */ | 18 | /* After libbb.h, since it needs sys/types.h on some systems */ |
13 | #include <sys/utsname.h> /* uname() */ | 19 | #include <sys/utsname.h> /* uname() */ |
@@ -18,10 +24,13 @@ extern int delete_module(const char *module, unsigned flags); | |||
18 | extern int query_module(const char *name, int which, void *buf, size_t bufsize, size_t *ret); | 24 | extern int query_module(const char *name, int which, void *buf, size_t bufsize, size_t *ret); |
19 | 25 | ||
20 | 26 | ||
21 | #define dbg1_error_msg(...) ((void)0) | 27 | #if 1 |
22 | #define dbg2_error_msg(...) ((void)0) | 28 | # define dbg1_error_msg(...) ((void)0) |
23 | //#define dbg1_error_msg(...) bb_error_msg(__VA_ARGS__) | 29 | # define dbg2_error_msg(...) ((void)0) |
24 | //#define dbg2_error_msg(...) bb_error_msg(__VA_ARGS__) | 30 | #else |
31 | # define dbg1_error_msg(...) bb_error_msg(__VA_ARGS__) | ||
32 | # define dbg2_error_msg(...) bb_error_msg(__VA_ARGS__) | ||
33 | #endif | ||
25 | 34 | ||
26 | #define DEPFILE_BB CONFIG_DEFAULT_DEPMOD_FILE".bb" | 35 | #define DEPFILE_BB CONFIG_DEFAULT_DEPMOD_FILE".bb" |
27 | 36 | ||
@@ -579,10 +588,9 @@ static void process_module(char *name, const char *cmdline_options) | |||
579 | 588 | ||
580 | /* rmmod? unload it by name */ | 589 | /* rmmod? unload it by name */ |
581 | if (is_rmmod) { | 590 | if (is_rmmod) { |
582 | if (delete_module(name, O_NONBLOCK | O_EXCL) != 0 | 591 | if (delete_module(name, O_NONBLOCK | O_EXCL) != 0) { |
583 | && !(option_mask32 & OPT_q) | 592 | if (!(option_mask32 & OPT_q)) |
584 | ) { | 593 | bb_perror_msg("remove '%s'", name); |
585 | bb_perror_msg("remove '%s'", name); | ||
586 | goto ret; | 594 | goto ret; |
587 | } | 595 | } |
588 | /* N.B. we do not stop here - | 596 | /* N.B. we do not stop here - |
@@ -594,9 +602,9 @@ static void process_module(char *name, const char *cmdline_options) | |||
594 | 602 | ||
595 | if (!info) { | 603 | if (!info) { |
596 | /* both dirscan and find_alias found nothing */ | 604 | /* both dirscan and find_alias found nothing */ |
597 | if (applet_name[0] != 'd') /* it wasn't depmod */ | 605 | if (!is_rmmod && applet_name[0] != 'd') /* it wasn't rmmod or depmod */ |
598 | bb_error_msg("module '%s' not found", name); | 606 | bb_error_msg("module '%s' not found", name); |
599 | //TODO: _and_die()? | 607 | //TODO: _and_die()? or should we continue (un)loading modules listed on cmdline? |
600 | goto ret; | 608 | goto ret; |
601 | } | 609 | } |
602 | 610 | ||
@@ -686,6 +694,46 @@ The following options are useful for people managing distributions: | |||
686 | */ | 694 | */ |
687 | 695 | ||
688 | //usage:#if ENABLE_MODPROBE_SMALL | 696 | //usage:#if ENABLE_MODPROBE_SMALL |
697 | |||
698 | //usage:#define depmod_trivial_usage NOUSAGE_STR | ||
699 | //usage:#define depmod_full_usage "" | ||
700 | |||
701 | //usage:#define lsmod_trivial_usage | ||
702 | //usage: "" | ||
703 | //usage:#define lsmod_full_usage "\n\n" | ||
704 | //usage: "List the currently loaded kernel modules" | ||
705 | |||
706 | //usage:#define insmod_trivial_usage | ||
707 | //usage: IF_FEATURE_2_4_MODULES("[OPTIONS] MODULE ") | ||
708 | //usage: IF_NOT_FEATURE_2_4_MODULES("FILE ") | ||
709 | //usage: "[SYMBOL=VALUE]..." | ||
710 | //usage:#define insmod_full_usage "\n\n" | ||
711 | //usage: "Load the specified kernel modules into the kernel" | ||
712 | //usage: IF_FEATURE_2_4_MODULES( "\n" | ||
713 | //usage: "\nOptions:" | ||
714 | //usage: "\n -f Force module to load into the wrong kernel version" | ||
715 | //usage: "\n -k Make module autoclean-able" | ||
716 | //usage: "\n -v Verbose" | ||
717 | //usage: "\n -q Quiet" | ||
718 | //usage: "\n -L Lock: prevent simultaneous loads" | ||
719 | //usage: IF_FEATURE_INSMOD_LOAD_MAP( | ||
720 | //usage: "\n -m Output load map to stdout" | ||
721 | //usage: ) | ||
722 | //usage: "\n -x Don't export externs" | ||
723 | //usage: ) | ||
724 | |||
725 | //usage:#define rmmod_trivial_usage | ||
726 | //usage: "[-wfa] [MODULE]..." | ||
727 | //usage:#define rmmod_full_usage "\n\n" | ||
728 | //usage: "Unload kernel modules\n" | ||
729 | //usage: "\nOptions:" | ||
730 | //usage: "\n -w Wait until the module is no longer used" | ||
731 | //usage: "\n -f Force unload" | ||
732 | //usage: "\n -a Remove all unused modules (recursively)" | ||
733 | //usage: | ||
734 | //usage:#define rmmod_example_usage | ||
735 | //usage: "$ rmmod tulip\n" | ||
736 | |||
689 | //usage:#define modprobe_trivial_usage | 737 | //usage:#define modprobe_trivial_usage |
690 | //usage: "[-qfwrsv] MODULE [symbol=value]..." | 738 | //usage: "[-qfwrsv] MODULE [symbol=value]..." |
691 | //usage:#define modprobe_full_usage "\n\n" | 739 | //usage:#define modprobe_full_usage "\n\n" |
@@ -696,7 +744,8 @@ The following options are useful for people managing distributions: | |||
696 | //usage: "\n -f Force" | 744 | //usage: "\n -f Force" |
697 | //usage: "\n -w Wait for unload" | 745 | //usage: "\n -w Wait for unload" |
698 | //usage: "\n -s Report via syslog instead of stderr" | 746 | //usage: "\n -s Report via syslog instead of stderr" |
699 | //usage:#endif /* ENABLE_MODPROBE_SMALL */ | 747 | |
748 | //usage:#endif | ||
700 | 749 | ||
701 | int modprobe_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 750 | int modprobe_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
702 | int modprobe_main(int argc UNUSED_PARAM, char **argv) | 751 | int modprobe_main(int argc UNUSED_PARAM, char **argv) |
@@ -811,8 +860,8 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) | |||
811 | /* Load/remove modules. | 860 | /* Load/remove modules. |
812 | * Only rmmod loops here, modprobe has only argv[0] */ | 861 | * Only rmmod loops here, modprobe has only argv[0] */ |
813 | do { | 862 | do { |
814 | process_module(*argv++, options); | 863 | process_module(*argv, options); |
815 | } while (*argv); | 864 | } while (*++argv); |
816 | 865 | ||
817 | if (ENABLE_FEATURE_CLEAN_UP) { | 866 | if (ENABLE_FEATURE_CLEAN_UP) { |
818 | IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(free(options);) | 867 | IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(free(options);) |
diff --git a/modutils/modprobe.c b/modutils/modprobe.c index ab35628f4..a5cf4babf 100644 --- a/modutils/modprobe.c +++ b/modutils/modprobe.c | |||
@@ -8,17 +8,7 @@ | |||
8 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 8 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | /* Note that unlike older versions of modules.dep/depmod (busybox and m-i-t), | 11 | //applet:IF_MODPROBE(APPLET(modprobe, _BB_DIR_SBIN, _BB_SUID_DROP)) |
12 | * we expect the full dependency list to be specified in modules.dep. | ||
13 | * Older versions would only export the direct dependency list. | ||
14 | */ | ||
15 | #include "libbb.h" | ||
16 | #include "modutils.h" | ||
17 | #include <sys/utsname.h> | ||
18 | #include <fnmatch.h> | ||
19 | |||
20 | //#define DBG(fmt, ...) bb_error_msg("%s: " fmt, __func__, ## __VA_ARGS__) | ||
21 | #define DBG(...) ((void)0) | ||
22 | 12 | ||
23 | //usage:#if !ENABLE_MODPROBE_SMALL | 13 | //usage:#if !ENABLE_MODPROBE_SMALL |
24 | //usage:#define modprobe_notes_usage | 14 | //usage:#define modprobe_notes_usage |
@@ -98,6 +88,19 @@ | |||
98 | //usage: ) | 88 | //usage: ) |
99 | //usage:#endif /* !ENABLE_MODPROBE_SMALL */ | 89 | //usage:#endif /* !ENABLE_MODPROBE_SMALL */ |
100 | 90 | ||
91 | #include "libbb.h" | ||
92 | #include "modutils.h" | ||
93 | #include <sys/utsname.h> | ||
94 | #include <fnmatch.h> | ||
95 | |||
96 | //#define DBG(fmt, ...) bb_error_msg("%s: " fmt, __func__, ## __VA_ARGS__) | ||
97 | #define DBG(...) ((void)0) | ||
98 | |||
99 | /* Note that unlike older versions of modules.dep/depmod (busybox and m-i-t), | ||
100 | * we expect the full dependency list to be specified in modules.dep. | ||
101 | * Older versions would only export the direct dependency list. | ||
102 | */ | ||
103 | |||
101 | /* Note that usage text doesn't document various 2.4 options | 104 | /* Note that usage text doesn't document various 2.4 options |
102 | * we pull in through INSMOD_OPTS define */ | 105 | * we pull in through INSMOD_OPTS define */ |
103 | 106 | ||
diff --git a/modutils/rmmod.c b/modutils/rmmod.c index aa1bb01d6..dde77731f 100644 --- a/modutils/rmmod.c +++ b/modutils/rmmod.c | |||
@@ -8,6 +8,21 @@ | |||
8 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 8 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | //applet:IF_RMMOD(APPLET(rmmod, _BB_DIR_SBIN, _BB_SUID_DROP)) | ||
12 | |||
13 | //usage:#if !ENABLE_MODPROBE_SMALL | ||
14 | //usage:#define rmmod_trivial_usage | ||
15 | //usage: "[-wfa] [MODULE]..." | ||
16 | //usage:#define rmmod_full_usage "\n\n" | ||
17 | //usage: "Unload kernel modules\n" | ||
18 | //usage: "\nOptions:" | ||
19 | //usage: "\n -w Wait until the module is no longer used" | ||
20 | //usage: "\n -f Force unload" | ||
21 | //usage: "\n -a Remove all unused modules (recursively)" | ||
22 | //usage:#define rmmod_example_usage | ||
23 | //usage: "$ rmmod tulip\n" | ||
24 | //usage:#endif | ||
25 | |||
11 | #include "libbb.h" | 26 | #include "libbb.h" |
12 | #include "modutils.h" | 27 | #include "modutils.h" |
13 | 28 | ||
diff --git a/networking/Config.src b/networking/Config.src index 9fc122bf3..6dd7df754 100644 --- a/networking/Config.src +++ b/networking/Config.src | |||
@@ -804,7 +804,7 @@ config TELNETD | |||
804 | 804 | ||
805 | mount -t devpts devpts /dev/pts | 805 | mount -t devpts devpts /dev/pts |
806 | 806 | ||
807 | You need to be sure that Busybox has LOGIN and | 807 | You need to be sure that busybox has LOGIN and |
808 | FEATURE_SUID enabled. And finally, you should make | 808 | FEATURE_SUID enabled. And finally, you should make |
809 | certain that Busybox has been installed setuid root: | 809 | certain that Busybox has been installed setuid root: |
810 | 810 | ||
diff --git a/networking/nbd-client.c b/networking/nbd-client.c new file mode 100644 index 000000000..5ac190c32 --- /dev/null +++ b/networking/nbd-client.c | |||
@@ -0,0 +1,153 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Rob Landley <rob@landley.net> | ||
3 | * | ||
4 | * Licensed under GPLv2, see file LICENSE in this source tree. | ||
5 | */ | ||
6 | #include "libbb.h" | ||
7 | #include <netinet/tcp.h> | ||
8 | #include <linux/fs.h> | ||
9 | |||
10 | //applet:IF_NBDCLIENT(APPLET_ODDNAME(nbd-client, nbdclient, _BB_DIR_USR_SBIN, _BB_SUID_DROP, nbdclient)) | ||
11 | |||
12 | //kbuild:lib-$(CONFIG_NBDCLIENT) += nbd-client.o | ||
13 | |||
14 | //config:config NBDCLIENT | ||
15 | //config: bool "nbd-client" | ||
16 | //config: default y | ||
17 | //config: help | ||
18 | //config: Network block device client | ||
19 | |||
20 | #define NBD_SET_SOCK _IO(0xab, 0) | ||
21 | #define NBD_SET_BLKSIZE _IO(0xab, 1) | ||
22 | #define NBD_SET_SIZE _IO(0xab, 2) | ||
23 | #define NBD_DO_IT _IO(0xab, 3) | ||
24 | #define NBD_CLEAR_SOCK _IO(0xab, 4) | ||
25 | #define NBD_CLEAR_QUEUE _IO(0xab, 5) | ||
26 | #define NBD_PRINT_DEBUG _IO(0xab, 6) | ||
27 | #define NBD_SET_SIZE_BLOCKS _IO(0xab, 7) | ||
28 | #define NBD_DISCONNECT _IO(0xab, 8) | ||
29 | #define NBD_SET_TIMEOUT _IO(0xab, 9) | ||
30 | |||
31 | //usage:#define nbdclient_trivial_usage | ||
32 | //usage: "HOST PORT BLOCKDEV" | ||
33 | //usage:#define nbdclient_full_usage "\n\n" | ||
34 | //usage: "Connect to HOST and provide a network block device on BLOCKDEV" | ||
35 | |||
36 | //TODO: more compat with nbd-client version 2.9.13 - | ||
37 | //Usage: nbd-client [bs=blocksize] [timeout=sec] host port nbd_device [-swap] [-persist] [-nofork] | ||
38 | //Or : nbd-client -d nbd_device | ||
39 | //Or : nbd-client -c nbd_device | ||
40 | //Default value for blocksize is 1024 (recommended for ethernet) | ||
41 | //Allowed values for blocksize are 512,1024,2048,4096 | ||
42 | //Note, that kernel 2.4.2 and older ones do not work correctly with | ||
43 | //blocksizes other than 1024 without patches | ||
44 | |||
45 | int nbdclient_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | ||
46 | int nbdclient_main(int argc, char **argv) | ||
47 | { | ||
48 | unsigned long timeout = 0; | ||
49 | int nofork = 0; | ||
50 | char *host, *port, *device; | ||
51 | struct nbd_header_t { | ||
52 | uint64_t magic1; // "NBDMAGIC" | ||
53 | uint64_t magic2; // 0x420281861253 big endian | ||
54 | uint64_t devsize; | ||
55 | uint32_t flags; | ||
56 | char data[124]; | ||
57 | } nbd_header; | ||
58 | struct bug_check { | ||
59 | char c[offsetof(struct nbd_header_t, data) == 8+8+8+4 ? 1 : -1]; | ||
60 | }; | ||
61 | |||
62 | // Parse command line stuff (just a stub now) | ||
63 | if (argc != 4) | ||
64 | bb_show_usage(); | ||
65 | |||
66 | #if !BB_MMU | ||
67 | bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS, argv); | ||
68 | #endif | ||
69 | |||
70 | host = argv[1]; | ||
71 | port = argv[2]; | ||
72 | device = argv[3]; | ||
73 | |||
74 | // Repeat until spanked (-persist behavior) | ||
75 | for (;;) { | ||
76 | int sock, nbd; | ||
77 | int ro; | ||
78 | |||
79 | // Make sure the /dev/nbd exists | ||
80 | nbd = xopen(device, O_RDWR); | ||
81 | |||
82 | // Find and connect to server | ||
83 | sock = create_and_connect_stream_or_die(host, xatou16(port)); | ||
84 | setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &const_int_1, sizeof(const_int_1)); | ||
85 | |||
86 | // Log on to the server | ||
87 | xread(sock, &nbd_header, 8+8+8+4 + 124); | ||
88 | if (memcmp(&nbd_header.magic1, "NBDMAGIC""\x00\x00\x42\x02\x81\x86\x12\x53", 16) != 0) | ||
89 | bb_error_msg_and_die("login failed"); | ||
90 | |||
91 | // Set 4k block size. Everything uses that these days | ||
92 | ioctl(nbd, NBD_SET_BLKSIZE, 4096); | ||
93 | ioctl(nbd, NBD_SET_SIZE_BLOCKS, SWAP_BE64(nbd_header.devsize) / 4096); | ||
94 | ioctl(nbd, NBD_CLEAR_SOCK); | ||
95 | |||
96 | // If the sucker was exported read only, respect that locally | ||
97 | ro = (nbd_header.flags & SWAP_BE32(2)) / SWAP_BE32(2); | ||
98 | if (ioctl(nbd, BLKROSET, &ro) < 0) | ||
99 | bb_perror_msg_and_die("BLKROSET"); | ||
100 | |||
101 | if (timeout) | ||
102 | if (ioctl(nbd, NBD_SET_TIMEOUT, timeout)) | ||
103 | bb_perror_msg_and_die("NBD_SET_TIMEOUT"); | ||
104 | if (ioctl(nbd, NBD_SET_SOCK, sock)) | ||
105 | bb_perror_msg_and_die("NBD_SET_SOCK"); | ||
106 | |||
107 | // if (swap) mlockall(MCL_CURRENT|MCL_FUTURE); | ||
108 | |||
109 | #if BB_MMU | ||
110 | // Open the device to force reread of the partition table. | ||
111 | // Need to do it in a separate process, since open(device) | ||
112 | // needs some other process to sit in ioctl(nbd, NBD_DO_IT). | ||
113 | if (fork() == 0) { | ||
114 | char *s = strrchr(device, '/'); | ||
115 | sprintf(nbd_header.data, "/sys/block/%.32s/pid", s ? s + 1 : device); | ||
116 | // Is it up yet? | ||
117 | for (;;) { | ||
118 | int fd = open(nbd_header.data, O_RDONLY); | ||
119 | if (fd >= 0) { | ||
120 | //close(fd); | ||
121 | break; | ||
122 | } | ||
123 | sleep(1); | ||
124 | } | ||
125 | open(device, O_RDONLY); | ||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | // Daemonize here | ||
130 | if (!nofork) { | ||
131 | daemon(0, 0); | ||
132 | nofork = 1; | ||
133 | } | ||
134 | #endif | ||
135 | |||
136 | // This turns us (the process that calls this ioctl) | ||
137 | // into a dedicated NBD request handler. | ||
138 | // We block here for a long time. | ||
139 | // When exactly ioctl returns? On a signal, | ||
140 | // or if someone does ioctl(NBD_DISCONNECT) [nbd-client -d]. | ||
141 | if (ioctl(nbd, NBD_DO_IT) >= 0 || errno == EBADR) { | ||
142 | // Flush queue and exit | ||
143 | ioctl(nbd, NBD_CLEAR_QUEUE); | ||
144 | ioctl(nbd, NBD_CLEAR_SOCK); | ||
145 | break; | ||
146 | } | ||
147 | |||
148 | close(sock); | ||
149 | close(nbd); | ||
150 | } | ||
151 | |||
152 | return 0; | ||
153 | } | ||
diff --git a/networking/nc_bloaty.c b/networking/nc_bloaty.c index 6b5b176c9..8594a67a6 100644 --- a/networking/nc_bloaty.c +++ b/networking/nc_bloaty.c | |||
@@ -57,7 +57,8 @@ | |||
57 | //usage:#define nc_trivial_usage | 57 | //usage:#define nc_trivial_usage |
58 | //usage: "[OPTIONS] HOST PORT - connect" | 58 | //usage: "[OPTIONS] HOST PORT - connect" |
59 | //usage: IF_NC_SERVER("\n" | 59 | //usage: IF_NC_SERVER("\n" |
60 | //usage: "nc [OPTIONS] -l -p PORT [HOST] [PORT] - listen") | 60 | //usage: "nc [OPTIONS] -l -p PORT [HOST] [PORT] - listen" |
61 | //usage: ) | ||
61 | //usage:#define nc_full_usage "\n\n" | 62 | //usage:#define nc_full_usage "\n\n" |
62 | //usage: "Options:" | 63 | //usage: "Options:" |
63 | //usage: "\n -e PROG Run PROG after connect (must be last)" | 64 | //usage: "\n -e PROG Run PROG after connect (must be last)" |
diff --git a/networking/ntpd.c b/networking/ntpd.c index 6707e9bdb..ca4afa045 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c | |||
@@ -1765,6 +1765,10 @@ recv_and_process_client_pkt(void /*int fd*/) | |||
1765 | /* this time was obtained between poll() and recv() */ | 1765 | /* this time was obtained between poll() and recv() */ |
1766 | msg.m_rectime = d_to_lfp(G.cur_time); | 1766 | msg.m_rectime = d_to_lfp(G.cur_time); |
1767 | msg.m_xmttime = d_to_lfp(gettime1900d()); /* this instant */ | 1767 | msg.m_xmttime = d_to_lfp(gettime1900d()); /* this instant */ |
1768 | if (G.peer_cnt == 0) { | ||
1769 | /* we have no peers: "stratum 1 server" mode. reftime = our own time */ | ||
1770 | G.reftime = G.cur_time; | ||
1771 | } | ||
1768 | msg.m_reftime = d_to_lfp(G.reftime); | 1772 | msg.m_reftime = d_to_lfp(G.reftime); |
1769 | msg.m_orgtime = query_xmttime; | 1773 | msg.m_orgtime = query_xmttime; |
1770 | msg.m_rootdelay = d_to_sfp(G.rootdelay); | 1774 | msg.m_rootdelay = d_to_sfp(G.rootdelay); |
@@ -1902,8 +1906,13 @@ static NOINLINE void ntp_init(char **argv) | |||
1902 | bb_show_usage(); | 1906 | bb_show_usage(); |
1903 | // if (opts & OPT_x) /* disable stepping, only slew is allowed */ | 1907 | // if (opts & OPT_x) /* disable stepping, only slew is allowed */ |
1904 | // G.time_was_stepped = 1; | 1908 | // G.time_was_stepped = 1; |
1905 | while (peers) | 1909 | if (peers) { |
1906 | add_peers(llist_pop(&peers)); | 1910 | while (peers) |
1911 | add_peers(llist_pop(&peers)); | ||
1912 | } else { | ||
1913 | /* -l but no peers: "stratum 1 server" mode */ | ||
1914 | G.stratum = 1; | ||
1915 | } | ||
1907 | if (!(opts & OPT_n)) { | 1916 | if (!(opts & OPT_n)) { |
1908 | bb_daemonize_or_rexec(DAEMON_DEVNULL_STDIO, argv); | 1917 | bb_daemonize_or_rexec(DAEMON_DEVNULL_STDIO, argv); |
1909 | logmode = LOGMODE_NONE; | 1918 | logmode = LOGMODE_NONE; |
diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c index 97ab4cdbb..b6b274d91 100644 --- a/networking/udhcp/common.c +++ b/networking/udhcp/common.c | |||
@@ -37,6 +37,7 @@ const struct dhcp_optflag dhcp_optflags[] = { | |||
37 | { OPTION_U8 , 0x17 }, /* DHCP_IP_TTL */ | 37 | { OPTION_U8 , 0x17 }, /* DHCP_IP_TTL */ |
38 | { OPTION_U16 , 0x1a }, /* DHCP_MTU */ | 38 | { OPTION_U16 , 0x1a }, /* DHCP_MTU */ |
39 | { OPTION_IP | OPTION_REQ, 0x1c }, /* DHCP_BROADCAST */ | 39 | { OPTION_IP | OPTION_REQ, 0x1c }, /* DHCP_BROADCAST */ |
40 | { OPTION_IP_PAIR | OPTION_LIST , 0x21 }, /* DHCP_ROUTES */ | ||
40 | { OPTION_STRING , 0x28 }, /* DHCP_NIS_DOMAIN */ | 41 | { OPTION_STRING , 0x28 }, /* DHCP_NIS_DOMAIN */ |
41 | { OPTION_IP | OPTION_LIST , 0x29 }, /* DHCP_NIS_SERVER */ | 42 | { OPTION_IP | OPTION_LIST , 0x29 }, /* DHCP_NIS_SERVER */ |
42 | { OPTION_IP | OPTION_LIST | OPTION_REQ, 0x2a }, /* DHCP_NTP_SERVER */ | 43 | { OPTION_IP | OPTION_LIST | OPTION_REQ, 0x2a }, /* DHCP_NTP_SERVER */ |
@@ -54,6 +55,7 @@ const struct dhcp_optflag dhcp_optflags[] = { | |||
54 | { OPTION_SIP_SERVERS , 0x78 }, /* DHCP_SIP_SERVERS */ | 55 | { OPTION_SIP_SERVERS , 0x78 }, /* DHCP_SIP_SERVERS */ |
55 | #endif | 56 | #endif |
56 | { OPTION_STATIC_ROUTES , 0x79 }, /* DHCP_STATIC_ROUTES */ | 57 | { OPTION_STATIC_ROUTES , 0x79 }, /* DHCP_STATIC_ROUTES */ |
58 | { OPTION_STATIC_ROUTES , 0xf9 }, /* DHCP_MS_STATIC_ROUTES */ | ||
57 | { OPTION_STRING , 0xfc }, /* DHCP_WPAD */ | 59 | { OPTION_STRING , 0xfc }, /* DHCP_WPAD */ |
58 | 60 | ||
59 | /* Options below have no match in dhcp_option_strings[], | 61 | /* Options below have no match in dhcp_option_strings[], |
@@ -95,6 +97,7 @@ const char dhcp_option_strings[] ALIGN1 = | |||
95 | "ipttl" "\0" /* DHCP_IP_TTL */ | 97 | "ipttl" "\0" /* DHCP_IP_TTL */ |
96 | "mtu" "\0" /* DHCP_MTU */ | 98 | "mtu" "\0" /* DHCP_MTU */ |
97 | "broadcast" "\0" /* DHCP_BROADCAST */ | 99 | "broadcast" "\0" /* DHCP_BROADCAST */ |
100 | "routes" "\0" /* DHCP_ROUTES */ | ||
98 | "nisdomain" "\0" /* DHCP_NIS_DOMAIN */ | 101 | "nisdomain" "\0" /* DHCP_NIS_DOMAIN */ |
99 | "nissrv" "\0" /* DHCP_NIS_SERVER */ | 102 | "nissrv" "\0" /* DHCP_NIS_SERVER */ |
100 | "ntpsrv" "\0" /* DHCP_NTP_SERVER */ | 103 | "ntpsrv" "\0" /* DHCP_NTP_SERVER */ |
@@ -114,6 +117,7 @@ const char dhcp_option_strings[] ALIGN1 = | |||
114 | // doesn't work in udhcpd.conf since OPTION_STATIC_ROUTES | 117 | // doesn't work in udhcpd.conf since OPTION_STATIC_ROUTES |
115 | // is not handled yet by "string->option" conversion code: | 118 | // is not handled yet by "string->option" conversion code: |
116 | "staticroutes" "\0"/* DHCP_STATIC_ROUTES */ | 119 | "staticroutes" "\0"/* DHCP_STATIC_ROUTES */ |
120 | "msstaticroutes""\0"/* DHCP_MS_STATIC_ROUTES */ | ||
117 | "wpad" "\0" /* DHCP_WPAD */ | 121 | "wpad" "\0" /* DHCP_WPAD */ |
118 | ; | 122 | ; |
119 | 123 | ||
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index c5abf17d5..9020b9c96 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h | |||
@@ -123,6 +123,7 @@ enum { | |||
123 | //#define DHCP_IP_TTL 0x17 | 123 | //#define DHCP_IP_TTL 0x17 |
124 | //#define DHCP_MTU 0x1a | 124 | //#define DHCP_MTU 0x1a |
125 | //#define DHCP_BROADCAST 0x1c | 125 | //#define DHCP_BROADCAST 0x1c |
126 | //#define DHCP_ROUTES 0x21 | ||
126 | //#define DHCP_NIS_DOMAIN 0x28 | 127 | //#define DHCP_NIS_DOMAIN 0x28 |
127 | //#define DHCP_NIS_SERVER 0x29 | 128 | //#define DHCP_NIS_SERVER 0x29 |
128 | //#define DHCP_NTP_SERVER 0x2a | 129 | //#define DHCP_NTP_SERVER 0x2a |
@@ -144,6 +145,7 @@ enum { | |||
144 | //#define DHCP_DOMAIN_SEARCH 0x77 /* RFC 3397. set of ASCIZ string, DNS-style compressed */ | 145 | //#define DHCP_DOMAIN_SEARCH 0x77 /* RFC 3397. set of ASCIZ string, DNS-style compressed */ |
145 | //#define DHCP_SIP_SERVERS 0x78 /* RFC 3361. flag byte, then: 0: domain names, 1: IP addrs */ | 146 | //#define DHCP_SIP_SERVERS 0x78 /* RFC 3361. flag byte, then: 0: domain names, 1: IP addrs */ |
146 | //#define DHCP_STATIC_ROUTES 0x79 /* RFC 3442. (mask,ip,router) tuples */ | 147 | //#define DHCP_STATIC_ROUTES 0x79 /* RFC 3442. (mask,ip,router) tuples */ |
148 | //#define DHCP_MS_STATIC_ROUTES 0xf9 /* Microsoft's pre-RFC 3442 code for 0x79? */ | ||
147 | //#define DHCP_WPAD 0xfc /* MSIE's Web Proxy Autodiscovery Protocol */ | 149 | //#define DHCP_WPAD 0xfc /* MSIE's Web Proxy Autodiscovery Protocol */ |
148 | #define DHCP_END 0xff | 150 | #define DHCP_END 0xff |
149 | 151 | ||
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index de1b79844..27d6ad1a8 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c | |||
@@ -89,6 +89,7 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_ | |||
89 | 89 | ||
90 | /* option points to OPT_DATA, need to go back and get OPT_LEN */ | 90 | /* option points to OPT_DATA, need to go back and get OPT_LEN */ |
91 | len = option[OPT_LEN - OPT_DATA]; | 91 | len = option[OPT_LEN - OPT_DATA]; |
92 | |||
92 | type = optflag->flags & OPTION_TYPE_MASK; | 93 | type = optflag->flags & OPTION_TYPE_MASK; |
93 | optlen = dhcp_option_lengths[type]; | 94 | optlen = dhcp_option_lengths[type]; |
94 | upper_length = len_of_option_as_string[type] * ((unsigned)len / (unsigned)optlen); | 95 | upper_length = len_of_option_as_string[type] * ((unsigned)len / (unsigned)optlen); |
@@ -97,17 +98,16 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_ | |||
97 | dest += sprintf(ret, "%s=", opt_name); | 98 | dest += sprintf(ret, "%s=", opt_name); |
98 | 99 | ||
99 | while (len >= optlen) { | 100 | while (len >= optlen) { |
101 | unsigned ip_ofs = 0; | ||
102 | |||
100 | switch (type) { | 103 | switch (type) { |
101 | case OPTION_IP_PAIR: | 104 | case OPTION_IP_PAIR: |
102 | dest += sprint_nip(dest, "", option); | 105 | dest += sprint_nip(dest, "", option); |
103 | *dest++ = '/'; | 106 | *dest++ = '/'; |
104 | option += 4; | 107 | ip_ofs = 4; |
105 | optlen = 4; | 108 | /* fall through */ |
106 | case OPTION_IP: | 109 | case OPTION_IP: |
107 | dest += sprint_nip(dest, "", option); | 110 | dest += sprint_nip(dest, "", option + ip_ofs); |
108 | // TODO: it can be a list only if (optflag->flags & OPTION_LIST). | ||
109 | // Should we bail out/warn if we see multi-ip option which is | ||
110 | // not allowed to be such? For example, DHCP_BROADCAST... | ||
111 | break; | 111 | break; |
112 | // case OPTION_BOOLEAN: | 112 | // case OPTION_BOOLEAN: |
113 | // dest += sprintf(dest, *option ? "yes" : "no"); | 113 | // dest += sprintf(dest, *option ? "yes" : "no"); |
@@ -218,7 +218,10 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_ | |||
218 | } /* switch */ | 218 | } /* switch */ |
219 | option += optlen; | 219 | option += optlen; |
220 | len -= optlen; | 220 | len -= optlen; |
221 | if (len <= 0) | 221 | // TODO: it can be a list only if (optflag->flags & OPTION_LIST). |
222 | // Should we bail out/warn if we see multi-ip option which is | ||
223 | // not allowed to be such (for example, DHCP_BROADCAST)? - | ||
224 | if (len <= 0 /* || !(optflag->flags & OPTION_LIST) */) | ||
222 | break; | 225 | break; |
223 | *dest++ = ' '; | 226 | *dest++ = ' '; |
224 | *dest = '\0'; | 227 | *dest = '\0'; |
diff --git a/networking/udhcp/dhcprelay.c b/networking/udhcp/dhcprelay.c index a2c7f359d..759a4ba03 100644 --- a/networking/udhcp/dhcprelay.c +++ b/networking/udhcp/dhcprelay.c | |||
@@ -11,9 +11,12 @@ | |||
11 | */ | 11 | */ |
12 | #include "common.h" | 12 | #include "common.h" |
13 | 13 | ||
14 | #define SERVER_PORT 67 | 14 | #define SERVER_PORT 67 |
15 | #define SELECT_TIMEOUT 5 /* select timeout in sec. */ | 15 | |
16 | #define MAX_LIFETIME 2*60 /* lifetime of an xid entry in sec. */ | 16 | /* lifetime of an xid entry in sec. */ |
17 | #define MAX_LIFETIME 2*60 | ||
18 | /* select timeout in sec. */ | ||
19 | #define SELECT_TIMEOUT (MAX_LIFETIME / 8) | ||
17 | 20 | ||
18 | /* This list holds information about clients. The xid_* functions manipulate this list. */ | 21 | /* This list holds information about clients. The xid_* functions manipulate this list. */ |
19 | struct xid_item { | 22 | struct xid_item { |
@@ -67,11 +70,11 @@ static struct xid_item *xid_find(uint32_t xid) | |||
67 | struct xid_item *item = dhcprelay_xid_list.next; | 70 | struct xid_item *item = dhcprelay_xid_list.next; |
68 | while (item != NULL) { | 71 | while (item != NULL) { |
69 | if (item->xid == xid) { | 72 | if (item->xid == xid) { |
70 | return item; | 73 | break; |
71 | } | 74 | } |
72 | item = item->next; | 75 | item = item->next; |
73 | } | 76 | } |
74 | return NULL; | 77 | return item; |
75 | } | 78 | } |
76 | 79 | ||
77 | static void xid_del(uint32_t xid) | 80 | static void xid_del(uint32_t xid) |
@@ -110,62 +113,72 @@ static int get_dhcp_packet_type(struct dhcp_packet *p) | |||
110 | } | 113 | } |
111 | 114 | ||
112 | /** | 115 | /** |
113 | * get_client_devices - parses the devices list | 116 | * make_iface_list - parses client/server interface names |
114 | * dev_list - comma separated list of devices | ||
115 | * returns array | 117 | * returns array |
116 | */ | 118 | */ |
117 | static char **get_client_devices(char *dev_list, int *client_number) | 119 | static char **make_iface_list(char **client_and_server_ifaces, int *client_number) |
118 | { | 120 | { |
119 | char *s, **client_dev; | 121 | char *s, **iface_list; |
120 | int i, cn; | 122 | int i, cn; |
121 | 123 | ||
122 | /* copy list */ | 124 | /* get number of items */ |
123 | dev_list = xstrdup(dev_list); | 125 | cn = 2; /* 1 server iface + at least 1 client one */ |
124 | 126 | s = client_and_server_ifaces[0]; /* list of client ifaces */ | |
125 | /* get number of items, replace ',' with NULs */ | ||
126 | s = dev_list; | ||
127 | cn = 1; | ||
128 | while (*s) { | 127 | while (*s) { |
129 | if (*s == ',') { | 128 | if (*s == ',') |
130 | *s = '\0'; | ||
131 | cn++; | 129 | cn++; |
132 | } | ||
133 | s++; | 130 | s++; |
134 | } | 131 | } |
135 | *client_number = cn; | 132 | *client_number = cn; |
136 | 133 | ||
137 | /* create vector of pointers */ | 134 | /* create vector of pointers */ |
138 | client_dev = xzalloc(cn * sizeof(*client_dev)); | 135 | iface_list = xzalloc(cn * sizeof(iface_list[0])); |
139 | client_dev[0] = dev_list; | 136 | |
137 | iface_list[0] = client_and_server_ifaces[1]; /* server iface */ | ||
138 | |||
140 | i = 1; | 139 | i = 1; |
141 | while (i != cn) { | 140 | s = xstrdup(client_and_server_ifaces[0]); /* list of client ifaces */ |
142 | client_dev[i] = client_dev[i - 1] + strlen(client_dev[i - 1]) + 1; | 141 | goto store_client_iface_name; |
143 | i++; | 142 | |
143 | while (i < cn) { | ||
144 | if (*s++ == ',') { | ||
145 | s[-1] = '\0'; | ||
146 | store_client_iface_name: | ||
147 | iface_list[i++] = s; | ||
148 | } | ||
144 | } | 149 | } |
145 | return client_dev; | 150 | |
151 | return iface_list; | ||
146 | } | 152 | } |
147 | 153 | ||
148 | /* Creates listen sockets (in fds) bound to client and server ifaces, | 154 | /* Creates listen sockets (in fds) bound to client and server ifaces, |
149 | * and returns numerically max fd. | 155 | * and returns numerically max fd. |
150 | */ | 156 | */ |
151 | static int init_sockets(char **client_ifaces, int num_clients, | 157 | static int init_sockets(char **iface_list, int num_clients, int *fds) |
152 | char *server_iface, int *fds) | ||
153 | { | 158 | { |
154 | int i, n; | 159 | int i, n; |
155 | 160 | ||
156 | /* talk to real server on bootps */ | 161 | n = 0; |
157 | fds[0] = udhcp_listen_socket(/*INADDR_ANY,*/ SERVER_PORT, server_iface); | 162 | for (i = 0; i < num_clients; i++) { |
158 | n = fds[0]; | 163 | fds[i] = udhcp_listen_socket(/*INADDR_ANY,*/ SERVER_PORT, iface_list[i]); |
159 | 164 | if (n < fds[i]) | |
160 | for (i = 1; i < num_clients; i++) { | ||
161 | /* listen for clients on bootps */ | ||
162 | fds[i] = udhcp_listen_socket(/*INADDR_ANY,*/ SERVER_PORT, client_ifaces[i-1]); | ||
163 | if (fds[i] > n) | ||
164 | n = fds[i]; | 165 | n = fds[i]; |
165 | } | 166 | } |
166 | return n; | 167 | return n; |
167 | } | 168 | } |
168 | 169 | ||
170 | static int sendto_ip4(int sock, const void *msg, int msg_len, struct sockaddr_in *to) | ||
171 | { | ||
172 | int err; | ||
173 | |||
174 | errno = 0; | ||
175 | err = sendto(sock, msg, msg_len, 0, (struct sockaddr*) to, sizeof(*to)); | ||
176 | err -= msg_len; | ||
177 | if (err) | ||
178 | bb_perror_msg("sendto"); | ||
179 | return err; | ||
180 | } | ||
181 | |||
169 | /** | 182 | /** |
170 | * pass_to_server() - forwards dhcp packets from client to server | 183 | * pass_to_server() - forwards dhcp packets from client to server |
171 | * p - packet to send | 184 | * p - packet to send |
@@ -174,7 +187,7 @@ static int init_sockets(char **client_ifaces, int num_clients, | |||
174 | static void pass_to_server(struct dhcp_packet *p, int packet_len, int client, int *fds, | 187 | static void pass_to_server(struct dhcp_packet *p, int packet_len, int client, int *fds, |
175 | struct sockaddr_in *client_addr, struct sockaddr_in *server_addr) | 188 | struct sockaddr_in *client_addr, struct sockaddr_in *server_addr) |
176 | { | 189 | { |
177 | int res, type; | 190 | int type; |
178 | 191 | ||
179 | /* check packet_type */ | 192 | /* check packet_type */ |
180 | type = get_dhcp_packet_type(p); | 193 | type = get_dhcp_packet_type(p); |
@@ -188,13 +201,12 @@ static void pass_to_server(struct dhcp_packet *p, int packet_len, int client, in | |||
188 | /* create new xid entry */ | 201 | /* create new xid entry */ |
189 | xid_add(p->xid, client_addr, client); | 202 | xid_add(p->xid, client_addr, client); |
190 | 203 | ||
191 | /* forward request to LAN (server) */ | 204 | /* forward request to server */ |
192 | errno = 0; | 205 | /* note that we send from fds[0] which is bound to SERVER_PORT (67). |
193 | res = sendto(fds[0], p, packet_len, 0, (struct sockaddr*)server_addr, | 206 | * IOW: we send _from_ SERVER_PORT! Although this may look strange, |
194 | sizeof(struct sockaddr_in)); | 207 | * RFC 1542 not only allows, but prescribes this for BOOTP relays. |
195 | if (res != packet_len) { | 208 | */ |
196 | bb_perror_msg("sendto"); | 209 | sendto_ip4(fds[0], p, packet_len, server_addr); |
197 | } | ||
198 | } | 210 | } |
199 | 211 | ||
200 | /** | 212 | /** |
@@ -203,7 +215,7 @@ static void pass_to_server(struct dhcp_packet *p, int packet_len, int client, in | |||
203 | */ | 215 | */ |
204 | static void pass_to_client(struct dhcp_packet *p, int packet_len, int *fds) | 216 | static void pass_to_client(struct dhcp_packet *p, int packet_len, int *fds) |
205 | { | 217 | { |
206 | int res, type; | 218 | int type; |
207 | struct xid_item *item; | 219 | struct xid_item *item; |
208 | 220 | ||
209 | /* check xid */ | 221 | /* check xid */ |
@@ -218,14 +230,12 @@ static void pass_to_client(struct dhcp_packet *p, int packet_len, int *fds) | |||
218 | return; | 230 | return; |
219 | } | 231 | } |
220 | 232 | ||
233 | //TODO: also do it if (p->flags & htons(BROADCAST_FLAG)) is set! | ||
221 | if (item->ip.sin_addr.s_addr == htonl(INADDR_ANY)) | 234 | if (item->ip.sin_addr.s_addr == htonl(INADDR_ANY)) |
222 | item->ip.sin_addr.s_addr = htonl(INADDR_BROADCAST); | 235 | item->ip.sin_addr.s_addr = htonl(INADDR_BROADCAST); |
223 | errno = 0; | 236 | |
224 | res = sendto(fds[item->client], p, packet_len, 0, (struct sockaddr*) &(item->ip), | 237 | if (sendto_ip4(fds[item->client], p, packet_len, &item->ip) != 0) { |
225 | sizeof(item->ip)); | 238 | return; /* send error occurred */ |
226 | if (res != packet_len) { | ||
227 | bb_perror_msg("sendto"); | ||
228 | return; | ||
229 | } | 239 | } |
230 | 240 | ||
231 | /* remove xid entry */ | 241 | /* remove xid entry */ |
@@ -235,36 +245,30 @@ static void pass_to_client(struct dhcp_packet *p, int packet_len, int *fds) | |||
235 | int dhcprelay_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 245 | int dhcprelay_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
236 | int dhcprelay_main(int argc, char **argv) | 246 | int dhcprelay_main(int argc, char **argv) |
237 | { | 247 | { |
238 | struct dhcp_packet dhcp_msg; | ||
239 | struct sockaddr_in server_addr; | 248 | struct sockaddr_in server_addr; |
240 | struct sockaddr_in client_addr; | 249 | char **iface_list; |
241 | fd_set rfds; | ||
242 | char **client_ifaces; | ||
243 | int *fds; | 250 | int *fds; |
244 | int num_sockets, max_socket; | 251 | int num_sockets, max_socket; |
245 | uint32_t our_nip; | 252 | uint32_t our_nip; |
246 | 253 | ||
247 | server_addr.sin_family = AF_INET; | 254 | server_addr.sin_family = AF_INET; |
255 | server_addr.sin_addr.s_addr = htonl(INADDR_BROADCAST); | ||
248 | server_addr.sin_port = htons(SERVER_PORT); | 256 | server_addr.sin_port = htons(SERVER_PORT); |
249 | 257 | ||
250 | /* dhcprelay client_iface1,client_iface2,... server_iface [server_IP] */ | 258 | /* dhcprelay CLIENT_IFACE1[,CLIENT_IFACE2...] SERVER_IFACE [SERVER_IP] */ |
251 | if (argc == 4) { | 259 | if (argc == 4) { |
252 | if (!inet_aton(argv[3], &server_addr.sin_addr)) | 260 | if (!inet_aton(argv[3], &server_addr.sin_addr)) |
253 | bb_perror_msg_and_die("bad server IP"); | 261 | bb_perror_msg_and_die("bad server IP"); |
254 | } else if (argc == 3) { | 262 | } else if (argc != 3) { |
255 | server_addr.sin_addr.s_addr = htonl(INADDR_BROADCAST); | ||
256 | } else { | ||
257 | bb_show_usage(); | 263 | bb_show_usage(); |
258 | } | 264 | } |
259 | 265 | ||
260 | /* Produce list of client ifaces */ | 266 | iface_list = make_iface_list(argv + 1, &num_sockets); |
261 | client_ifaces = get_client_devices(argv[1], &num_sockets); | ||
262 | 267 | ||
263 | num_sockets++; /* for server socket at fds[0] */ | ||
264 | fds = xmalloc(num_sockets * sizeof(fds[0])); | 268 | fds = xmalloc(num_sockets * sizeof(fds[0])); |
265 | 269 | ||
266 | /* Create sockets and bind one to every iface */ | 270 | /* Create sockets and bind one to every iface */ |
267 | max_socket = init_sockets(client_ifaces, num_sockets, argv[2], fds); | 271 | max_socket = init_sockets(iface_list, num_sockets, fds); |
268 | 272 | ||
269 | /* Get our IP on server_iface */ | 273 | /* Get our IP on server_iface */ |
270 | if (udhcp_read_interface(argv[2], NULL, &our_nip, NULL)) | 274 | if (udhcp_read_interface(argv[2], NULL, &our_nip, NULL)) |
@@ -272,11 +276,10 @@ int dhcprelay_main(int argc, char **argv) | |||
272 | 276 | ||
273 | /* Main loop */ | 277 | /* Main loop */ |
274 | while (1) { | 278 | while (1) { |
275 | //reinit stuff from time to time? go back to get_client_devices | 279 | // reinit stuff from time to time? go back to make_iface_list |
276 | //every N minutes? | 280 | // every N minutes? |
281 | fd_set rfds; | ||
277 | struct timeval tv; | 282 | struct timeval tv; |
278 | size_t packlen; | ||
279 | socklen_t addr_size; | ||
280 | int i; | 283 | int i; |
281 | 284 | ||
282 | FD_ZERO(&rfds); | 285 | FD_ZERO(&rfds); |
@@ -285,6 +288,9 @@ int dhcprelay_main(int argc, char **argv) | |||
285 | tv.tv_sec = SELECT_TIMEOUT; | 288 | tv.tv_sec = SELECT_TIMEOUT; |
286 | tv.tv_usec = 0; | 289 | tv.tv_usec = 0; |
287 | if (select(max_socket + 1, &rfds, NULL, NULL, &tv) > 0) { | 290 | if (select(max_socket + 1, &rfds, NULL, NULL, &tv) > 0) { |
291 | int packlen; | ||
292 | struct dhcp_packet dhcp_msg; | ||
293 | |||
288 | /* server */ | 294 | /* server */ |
289 | if (FD_ISSET(fds[0], &rfds)) { | 295 | if (FD_ISSET(fds[0], &rfds)) { |
290 | packlen = udhcp_recv_kernel_packet(&dhcp_msg, fds[0]); | 296 | packlen = udhcp_recv_kernel_packet(&dhcp_msg, fds[0]); |
@@ -292,24 +298,65 @@ int dhcprelay_main(int argc, char **argv) | |||
292 | pass_to_client(&dhcp_msg, packlen, fds); | 298 | pass_to_client(&dhcp_msg, packlen, fds); |
293 | } | 299 | } |
294 | } | 300 | } |
301 | |||
295 | /* clients */ | 302 | /* clients */ |
296 | for (i = 1; i < num_sockets; i++) { | 303 | for (i = 1; i < num_sockets; i++) { |
304 | struct sockaddr_in client_addr; | ||
305 | socklen_t addr_size; | ||
306 | |||
297 | if (!FD_ISSET(fds[i], &rfds)) | 307 | if (!FD_ISSET(fds[i], &rfds)) |
298 | continue; | 308 | continue; |
299 | addr_size = sizeof(struct sockaddr_in); | 309 | |
310 | addr_size = sizeof(client_addr); | ||
300 | packlen = recvfrom(fds[i], &dhcp_msg, sizeof(dhcp_msg), 0, | 311 | packlen = recvfrom(fds[i], &dhcp_msg, sizeof(dhcp_msg), 0, |
301 | (struct sockaddr *)(&client_addr), &addr_size); | 312 | (struct sockaddr *)(&client_addr), &addr_size); |
302 | if (packlen <= 0) | 313 | if (packlen <= 0) |
303 | continue; | 314 | continue; |
304 | 315 | ||
305 | /* Get our IP on corresponding client_iface */ | 316 | /* Get our IP on corresponding client_iface */ |
306 | //why? what if server can't route such IP? | 317 | // RFC 1542 |
307 | if (udhcp_read_interface(client_ifaces[i-1], NULL, &dhcp_msg.gateway_nip, NULL)) { | 318 | // 4.1 General BOOTP Processing for Relay Agents |
308 | /* Fall back to our server_iface's IP */ | 319 | // 4.1.1 BOOTREQUEST Messages |
309 | //this makes more sense! | 320 | // If the relay agent does decide to relay the request, it MUST examine |
321 | // the 'giaddr' ("gateway" IP address) field. If this field is zero, | ||
322 | // the relay agent MUST fill this field with the IP address of the | ||
323 | // interface on which the request was received. If the interface has | ||
324 | // more than one IP address logically associated with it, the relay | ||
325 | // agent SHOULD choose one IP address associated with that interface and | ||
326 | // use it consistently for all BOOTP messages it relays. If the | ||
327 | // 'giaddr' field contains some non-zero value, the 'giaddr' field MUST | ||
328 | // NOT be modified. The relay agent MUST NOT, under any circumstances, | ||
329 | // fill the 'giaddr' field with a broadcast address as is suggested in | ||
330 | // [1] (Section 8, sixth paragraph). | ||
331 | |||
332 | // but why? what if server can't route such IP? Client ifaces may be, say, NATed! | ||
333 | |||
334 | // 4.1.2 BOOTREPLY Messages | ||
335 | // BOOTP relay agents relay BOOTREPLY messages only to BOOTP clients. | ||
336 | // It is the responsibility of BOOTP servers to send BOOTREPLY messages | ||
337 | // directly to the relay agent identified in the 'giaddr' field. | ||
338 | // (yeah right, unless it is impossible... see comment above) | ||
339 | // Therefore, a relay agent may assume that all BOOTREPLY messages it | ||
340 | // receives are intended for BOOTP clients on its directly-connected | ||
341 | // networks. | ||
342 | // | ||
343 | // When a relay agent receives a BOOTREPLY message, it should examine | ||
344 | // the BOOTP 'giaddr', 'yiaddr', 'chaddr', 'htype', and 'hlen' fields. | ||
345 | // These fields should provide adequate information for the relay agent | ||
346 | // to deliver the BOOTREPLY message to the client. | ||
347 | // | ||
348 | // The 'giaddr' field can be used to identify the logical interface from | ||
349 | // which the reply must be sent (i.e., the host or router interface | ||
350 | // connected to the same network as the BOOTP client). If the content | ||
351 | // of the 'giaddr' field does not match one of the relay agent's | ||
352 | // directly-connected logical interfaces, the BOOTREPLY messsage MUST be | ||
353 | // silently discarded. | ||
354 | if (udhcp_read_interface(iface_list[i], NULL, &dhcp_msg.gateway_nip, NULL)) { | ||
355 | /* Fall back to our IP on server iface */ | ||
356 | // this makes more sense! | ||
310 | dhcp_msg.gateway_nip = our_nip; | 357 | dhcp_msg.gateway_nip = our_nip; |
311 | } | 358 | } |
312 | //maybe set dhcp_msg.flags |= BROADCAST_FLAG too? | 359 | // maybe dhcp_msg.hops++? drop packets with too many hops (RFC 1542 says 4 or 16)? |
313 | pass_to_server(&dhcp_msg, packlen, i, fds, &client_addr, &server_addr); | 360 | pass_to_server(&dhcp_msg, packlen, i, fds, &client_addr, &server_addr); |
314 | } | 361 | } |
315 | } | 362 | } |
diff --git a/procps/free.c b/procps/free.c index be65f46f1..efbac5ba6 100644 --- a/procps/free.c +++ b/procps/free.c | |||
@@ -11,47 +11,58 @@ | |||
11 | 11 | ||
12 | #include "libbb.h" | 12 | #include "libbb.h" |
13 | 13 | ||
14 | struct globals { | ||
15 | unsigned mem_unit; | ||
16 | #if ENABLE_DESKTOP | ||
17 | unsigned unit_steps; | ||
18 | # define G_unit_steps G.unit_steps | ||
19 | #else | ||
20 | # define G_unit_steps 10 | ||
21 | #endif | ||
22 | }; | ||
23 | #define G (*(struct globals*)&bb_common_bufsiz1) | ||
24 | #define INIT_G() do { } while (0) | ||
25 | |||
26 | |||
27 | static unsigned long long scale(unsigned long d) | ||
28 | { | ||
29 | return ((unsigned long long)d * G.mem_unit) >> G_unit_steps; | ||
30 | } | ||
31 | |||
32 | |||
14 | int free_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 33 | int free_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
15 | int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) | 34 | int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) |
16 | { | 35 | { |
17 | struct sysinfo info; | 36 | struct sysinfo info; |
18 | unsigned mem_unit; | 37 | |
38 | INIT_G(); | ||
19 | 39 | ||
20 | #if ENABLE_DESKTOP | 40 | #if ENABLE_DESKTOP |
21 | if (argv[1] && argv[1][0] == '-') | 41 | G.unit_steps = 10; |
22 | bb_show_usage(); | 42 | if (argv[1] && argv[1][0] == '-') { |
43 | switch (argv[1][1]) { | ||
44 | case 'b': | ||
45 | G.unit_steps = 0; | ||
46 | break; | ||
47 | case 'k': /* 2^10 */ | ||
48 | /* G.unit_steps = 10; - already is */ | ||
49 | break; | ||
50 | case 'm': /* 2^(2*10) */ | ||
51 | G.unit_steps = 20; | ||
52 | break; | ||
53 | case 'g': /* 2^(3*10) */ | ||
54 | G.unit_steps = 30; | ||
55 | break; | ||
56 | default: | ||
57 | bb_show_usage(); | ||
58 | } | ||
59 | } | ||
23 | #endif | 60 | #endif |
24 | 61 | ||
25 | sysinfo(&info); | 62 | sysinfo(&info); |
26 | 63 | ||
27 | /* Kernels prior to 2.4.x will return info.mem_unit==0, so cope... */ | 64 | /* Kernels prior to 2.4.x will return info.mem_unit==0, so cope... */ |
28 | mem_unit = 1; | 65 | G.mem_unit = (info.mem_unit ? info.mem_unit : 1); |
29 | if (info.mem_unit != 0) { | ||
30 | mem_unit = info.mem_unit; | ||
31 | } | ||
32 | |||
33 | /* Convert values to kbytes */ | ||
34 | if (mem_unit == 1) { | ||
35 | info.totalram >>= 10; | ||
36 | info.freeram >>= 10; | ||
37 | #if BB_MMU | ||
38 | info.totalswap >>= 10; | ||
39 | info.freeswap >>= 10; | ||
40 | #endif | ||
41 | info.sharedram >>= 10; | ||
42 | info.bufferram >>= 10; | ||
43 | } else { | ||
44 | mem_unit >>= 10; | ||
45 | /* TODO: Make all this stuff not overflow when mem >= 4 Tb */ | ||
46 | info.totalram *= mem_unit; | ||
47 | info.freeram *= mem_unit; | ||
48 | #if BB_MMU | ||
49 | info.totalswap *= mem_unit; | ||
50 | info.freeswap *= mem_unit; | ||
51 | #endif | ||
52 | info.sharedram *= mem_unit; | ||
53 | info.bufferram *= mem_unit; | ||
54 | } | ||
55 | 66 | ||
56 | printf(" %13s%13s%13s%13s%13s\n", | 67 | printf(" %13s%13s%13s%13s%13s\n", |
57 | "total", | 68 | "total", |
@@ -63,30 +74,33 @@ int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) | |||
63 | * /proc/meminfo instead and get "Cached: NNN kB" from there. | 74 | * /proc/meminfo instead and get "Cached: NNN kB" from there. |
64 | */ | 75 | */ |
65 | ); | 76 | ); |
66 | #define FIELDS_5 "%13lu%13lu%13lu%13lu%13lu\n" | 77 | |
67 | #define FIELDS_3 (FIELDS_5 + 2*5) | 78 | #define FIELDS_5 "%13llu%13llu%13llu%13llu%13llu\n" |
68 | #define FIELDS_2 (FIELDS_5 + 3*5) | 79 | #define FIELDS_3 (FIELDS_5 + 2*6) |
80 | #define FIELDS_2 (FIELDS_5 + 3*6) | ||
81 | |||
69 | printf("Mem: "); | 82 | printf("Mem: "); |
70 | printf(FIELDS_5, | 83 | printf(FIELDS_5, |
71 | info.totalram, | 84 | scale(info.totalram), |
72 | info.totalram - info.freeram, | 85 | scale(info.totalram - info.freeram), |
73 | info.freeram, | 86 | scale(info.freeram), |
74 | info.sharedram, info.bufferram | 87 | scale(info.sharedram), |
88 | scale(info.bufferram) | ||
75 | ); | 89 | ); |
76 | /* Show alternate, more meaningful busy/free numbers by counting | 90 | /* Show alternate, more meaningful busy/free numbers by counting |
77 | * buffer cache as free memory (make it "-/+ buffers/cache" | 91 | * buffer cache as free memory (make it "-/+ buffers/cache" |
78 | * if/when we add support for "cached" column): */ | 92 | * if/when we add support for "cached" column): */ |
79 | printf("-/+ buffers: "); | 93 | printf("-/+ buffers: "); |
80 | printf(FIELDS_2, | 94 | printf(FIELDS_2, |
81 | info.totalram - info.freeram - info.bufferram, | 95 | scale(info.totalram - info.freeram - info.bufferram), |
82 | info.freeram + info.bufferram | 96 | scale(info.freeram + info.bufferram) |
83 | ); | 97 | ); |
84 | #if BB_MMU | 98 | #if BB_MMU |
85 | printf("Swap:"); | 99 | printf("Swap:"); |
86 | printf(FIELDS_3, | 100 | printf(FIELDS_3, |
87 | info.totalswap, | 101 | scale(info.totalswap), |
88 | info.totalswap - info.freeswap, | 102 | scale(info.totalswap - info.freeswap), |
89 | info.freeswap | 103 | scale(info.freeswap) |
90 | ); | 104 | ); |
91 | #endif | 105 | #endif |
92 | return EXIT_SUCCESS; | 106 | return EXIT_SUCCESS; |
diff --git a/runit/Kbuild.src b/runit/Kbuild.src index d38bad20f..0fce95507 100644 --- a/runit/Kbuild.src +++ b/runit/Kbuild.src | |||
@@ -8,10 +8,10 @@ lib-y:= | |||
8 | 8 | ||
9 | INSERT | 9 | INSERT |
10 | 10 | ||
11 | lib-$(CONFIG_RUNSV) += runsv.o runit_lib.o | 11 | lib-$(CONFIG_RUNSV) += runsv.o |
12 | lib-$(CONFIG_RUNSVDIR) += runsvdir.o runit_lib.o | 12 | lib-$(CONFIG_RUNSVDIR) += runsvdir.o |
13 | lib-$(CONFIG_SV) += sv.o runit_lib.o | 13 | lib-$(CONFIG_SV) += sv.o |
14 | lib-$(CONFIG_SVLOGD) += svlogd.o runit_lib.o | 14 | lib-$(CONFIG_SVLOGD) += svlogd.o |
15 | lib-$(CONFIG_CHPST) += chpst.o | 15 | lib-$(CONFIG_CHPST) += chpst.o |
16 | 16 | ||
17 | lib-$(CONFIG_ENVDIR) += chpst.o | 17 | lib-$(CONFIG_ENVDIR) += chpst.o |
diff --git a/runit/runit_lib.c b/runit/runit_lib.c deleted file mode 100644 index 8182a909a..000000000 --- a/runit/runit_lib.c +++ /dev/null | |||
@@ -1,275 +0,0 @@ | |||
1 | /* | ||
2 | Copyright (c) 2001-2006, Gerrit Pape | ||
3 | All rights reserved. | ||
4 | |||
5 | Redistribution and use in source and binary forms, with or without | ||
6 | modification, are permitted provided that the following conditions are met: | ||
7 | |||
8 | 1. Redistributions of source code must retain the above copyright notice, | ||
9 | this list of conditions and the following disclaimer. | ||
10 | 2. Redistributions in binary form must reproduce the above copyright | ||
11 | notice, this list of conditions and the following disclaimer in the | ||
12 | documentation and/or other materials provided with the distribution. | ||
13 | 3. The name of the author may not be used to endorse or promote products | ||
14 | derived from this software without specific prior written permission. | ||
15 | |||
16 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
17 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
18 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO | ||
19 | EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
20 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
21 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | ||
22 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||
23 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||
24 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | ||
25 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | /* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */ | ||
29 | /* Collected into one file from runit's many tiny files */ | ||
30 | /* TODO: review, eliminate unneeded stuff, move good stuff to libbb */ | ||
31 | |||
32 | #include <sys/poll.h> | ||
33 | #include <sys/file.h> | ||
34 | #include "libbb.h" | ||
35 | #include "runit_lib.h" | ||
36 | |||
37 | #ifdef UNUSED | ||
38 | unsigned byte_chr(char *s,unsigned n,int c) | ||
39 | { | ||
40 | char ch; | ||
41 | char *t; | ||
42 | |||
43 | ch = c; | ||
44 | t = s; | ||
45 | for (;;) { | ||
46 | if (!n) break; | ||
47 | if (*t == ch) break; | ||
48 | ++t; | ||
49 | --n; | ||
50 | } | ||
51 | return t - s; | ||
52 | } | ||
53 | |||
54 | static /* as it isn't used anywhere else */ | ||
55 | void tai_pack(char *s, const struct tai *t) | ||
56 | { | ||
57 | uint64_t x; | ||
58 | |||
59 | x = t->x; | ||
60 | s[7] = x & 255; x >>= 8; | ||
61 | s[6] = x & 255; x >>= 8; | ||
62 | s[5] = x & 255; x >>= 8; | ||
63 | s[4] = x & 255; x >>= 8; | ||
64 | s[3] = x & 255; x >>= 8; | ||
65 | s[2] = x & 255; x >>= 8; | ||
66 | s[1] = x & 255; x >>= 8; | ||
67 | s[0] = x; | ||
68 | } | ||
69 | |||
70 | void tai_unpack(const char *s,struct tai *t) | ||
71 | { | ||
72 | uint64_t x; | ||
73 | |||
74 | x = (unsigned char) s[0]; | ||
75 | x <<= 8; x += (unsigned char) s[1]; | ||
76 | x <<= 8; x += (unsigned char) s[2]; | ||
77 | x <<= 8; x += (unsigned char) s[3]; | ||
78 | x <<= 8; x += (unsigned char) s[4]; | ||
79 | x <<= 8; x += (unsigned char) s[5]; | ||
80 | x <<= 8; x += (unsigned char) s[6]; | ||
81 | x <<= 8; x += (unsigned char) s[7]; | ||
82 | t->x = x; | ||
83 | } | ||
84 | |||
85 | |||
86 | void taia_add(struct taia *t,const struct taia *u,const struct taia *v) | ||
87 | { | ||
88 | t->sec.x = u->sec.x + v->sec.x; | ||
89 | t->nano = u->nano + v->nano; | ||
90 | t->atto = u->atto + v->atto; | ||
91 | if (t->atto > 999999999UL) { | ||
92 | t->atto -= 1000000000UL; | ||
93 | ++t->nano; | ||
94 | } | ||
95 | if (t->nano > 999999999UL) { | ||
96 | t->nano -= 1000000000UL; | ||
97 | ++t->sec.x; | ||
98 | } | ||
99 | } | ||
100 | |||
101 | int taia_less(const struct taia *t, const struct taia *u) | ||
102 | { | ||
103 | if (t->sec.x < u->sec.x) return 1; | ||
104 | if (t->sec.x > u->sec.x) return 0; | ||
105 | if (t->nano < u->nano) return 1; | ||
106 | if (t->nano > u->nano) return 0; | ||
107 | return t->atto < u->atto; | ||
108 | } | ||
109 | |||
110 | void taia_now(struct taia *t) | ||
111 | { | ||
112 | struct timeval now; | ||
113 | gettimeofday(&now, NULL); | ||
114 | tai_unix(&t->sec, now.tv_sec); | ||
115 | t->nano = 1000 * now.tv_usec + 500; | ||
116 | t->atto = 0; | ||
117 | } | ||
118 | |||
119 | /* UNUSED | ||
120 | void taia_pack(char *s, const struct taia *t) | ||
121 | { | ||
122 | unsigned long x; | ||
123 | |||
124 | tai_pack(s, &t->sec); | ||
125 | s += 8; | ||
126 | |||
127 | x = t->atto; | ||
128 | s[7] = x & 255; x >>= 8; | ||
129 | s[6] = x & 255; x >>= 8; | ||
130 | s[5] = x & 255; x >>= 8; | ||
131 | s[4] = x; | ||
132 | x = t->nano; | ||
133 | s[3] = x & 255; x >>= 8; | ||
134 | s[2] = x & 255; x >>= 8; | ||
135 | s[1] = x & 255; x >>= 8; | ||
136 | s[0] = x; | ||
137 | } | ||
138 | */ | ||
139 | |||
140 | void taia_sub(struct taia *t, const struct taia *u, const struct taia *v) | ||
141 | { | ||
142 | unsigned long unano = u->nano; | ||
143 | unsigned long uatto = u->atto; | ||
144 | |||
145 | t->sec.x = u->sec.x - v->sec.x; | ||
146 | t->nano = unano - v->nano; | ||
147 | t->atto = uatto - v->atto; | ||
148 | if (t->atto > uatto) { | ||
149 | t->atto += 1000000000UL; | ||
150 | --t->nano; | ||
151 | } | ||
152 | if (t->nano > unano) { | ||
153 | t->nano += 1000000000UL; | ||
154 | --t->sec.x; | ||
155 | } | ||
156 | } | ||
157 | |||
158 | /* XXX: breaks tai encapsulation */ | ||
159 | void taia_uint(struct taia *t, unsigned s) | ||
160 | { | ||
161 | t->sec.x = s; | ||
162 | t->nano = 0; | ||
163 | t->atto = 0; | ||
164 | } | ||
165 | |||
166 | static | ||
167 | uint64_t taia2millisec(const struct taia *t) | ||
168 | { | ||
169 | return (t->sec.x * 1000) + (t->nano / 1000000); | ||
170 | } | ||
171 | |||
172 | void iopause(iopause_fd *x, unsigned len, struct taia *deadline, struct taia *stamp) | ||
173 | { | ||
174 | int millisecs; | ||
175 | int i; | ||
176 | |||
177 | if (taia_less(deadline, stamp)) | ||
178 | millisecs = 0; | ||
179 | else { | ||
180 | uint64_t m; | ||
181 | struct taia t; | ||
182 | t = *stamp; | ||
183 | taia_sub(&t, deadline, &t); | ||
184 | millisecs = m = taia2millisec(&t); | ||
185 | if (m > 1000) millisecs = 1000; | ||
186 | millisecs += 20; | ||
187 | } | ||
188 | |||
189 | for (i = 0; i < len; ++i) | ||
190 | x[i].revents = 0; | ||
191 | |||
192 | poll(x, len, millisecs); | ||
193 | /* XXX: some kernels apparently need x[0] even if len is 0 */ | ||
194 | /* XXX: how to handle EAGAIN? are kernels really this dumb? */ | ||
195 | /* XXX: how to handle EINVAL? when exactly can this happen? */ | ||
196 | } | ||
197 | #endif | ||
198 | |||
199 | int lock_ex(int fd) | ||
200 | { | ||
201 | return flock(fd, LOCK_EX); | ||
202 | } | ||
203 | |||
204 | int lock_exnb(int fd) | ||
205 | { | ||
206 | return flock(fd, LOCK_EX | LOCK_NB); | ||
207 | } | ||
208 | |||
209 | #ifdef UNUSED | ||
210 | int open_append(const char *fn) | ||
211 | { | ||
212 | return open(fn, O_WRONLY | O_NDELAY | O_APPEND | O_CREAT, 0600); | ||
213 | } | ||
214 | |||
215 | int open_trunc(const char *fn) | ||
216 | { | ||
217 | return open(fn, O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT, 0644); | ||
218 | } | ||
219 | #endif | ||
220 | |||
221 | int open_read(const char *fn) | ||
222 | { | ||
223 | return open(fn, O_RDONLY|O_NDELAY); | ||
224 | } | ||
225 | |||
226 | int open_write(const char *fn) | ||
227 | { | ||
228 | return open(fn, O_WRONLY|O_NDELAY); | ||
229 | } | ||
230 | |||
231 | unsigned FAST_FUNC pmatch(const char *p, const char *s, unsigned len) | ||
232 | { | ||
233 | for (;;) { | ||
234 | char c = *p++; | ||
235 | if (!c) return !len; | ||
236 | switch (c) { | ||
237 | case '*': | ||
238 | c = *p; | ||
239 | if (!c) return 1; | ||
240 | for (;;) { | ||
241 | if (!len) return 0; | ||
242 | if (*s == c) break; | ||
243 | ++s; | ||
244 | --len; | ||
245 | } | ||
246 | continue; | ||
247 | case '+': | ||
248 | c = *p++; | ||
249 | if (c != *s) return 0; | ||
250 | for (;;) { | ||
251 | if (!len) return 1; | ||
252 | if (*s != c) break; | ||
253 | ++s; | ||
254 | --len; | ||
255 | } | ||
256 | continue; | ||
257 | /* | ||
258 | case '?': | ||
259 | if (*p == '?') { | ||
260 | if (*s != '?') return 0; | ||
261 | ++p; | ||
262 | } | ||
263 | ++s; --len; | ||
264 | continue; | ||
265 | */ | ||
266 | default: | ||
267 | if (!len) return 0; | ||
268 | if (*s != c) return 0; | ||
269 | ++s; | ||
270 | --len; | ||
271 | continue; | ||
272 | } | ||
273 | } | ||
274 | return 0; | ||
275 | } | ||
diff --git a/runit/runit_lib.h b/runit/runit_lib.h index d8304aca6..c36ea4ca5 100644 --- a/runit/runit_lib.h +++ b/runit/runit_lib.h | |||
@@ -27,59 +27,6 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
27 | 27 | ||
28 | PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN | 28 | PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN |
29 | 29 | ||
30 | //extern unsigned byte_chr(char *s,unsigned n,int c); | ||
31 | // | ||
32 | //struct tai { | ||
33 | // uint64_t x; | ||
34 | //}; | ||
35 | // | ||
36 | //#define tai_unix(t,u) ((void) ((t)->x = 0x400000000000000aULL + (uint64_t) (u))) | ||
37 | // | ||
38 | //#define TAI_PACK 8 | ||
39 | //extern void tai_unpack(const char *,struct tai *); | ||
40 | // | ||
41 | //extern void tai_uint(struct tai *,unsigned); | ||
42 | // | ||
43 | //struct taia { | ||
44 | // struct tai sec; | ||
45 | // unsigned long nano; /* 0...999999999 */ | ||
46 | // unsigned long atto; /* 0...999999999 */ | ||
47 | //}; | ||
48 | // | ||
49 | //extern void taia_now(struct taia *); | ||
50 | // | ||
51 | //extern void taia_add(struct taia *,const struct taia *,const struct taia *); | ||
52 | //extern void taia_addsec(struct taia *,const struct taia *,int); | ||
53 | //extern void taia_sub(struct taia *,const struct taia *,const struct taia *); | ||
54 | //extern void taia_half(struct taia *,const struct taia *); | ||
55 | //extern int taia_less(const struct taia *,const struct taia *); | ||
56 | // | ||
57 | //#define TAIA_PACK 16 | ||
58 | //extern void taia_pack(char *,const struct taia *); | ||
59 | // | ||
60 | //extern void taia_uint(struct taia *,unsigned); | ||
61 | // | ||
62 | //typedef struct pollfd iopause_fd; | ||
63 | //#define IOPAUSE_READ POLLIN | ||
64 | //#define IOPAUSE_WRITE POLLOUT | ||
65 | // | ||
66 | //extern void iopause(iopause_fd *,unsigned,struct taia *,struct taia *); | ||
67 | |||
68 | extern int lock_ex(int); | ||
69 | //extern int lock_un(int); | ||
70 | extern int lock_exnb(int); | ||
71 | |||
72 | extern int open_read(const char *); | ||
73 | extern int open_write(const char *); | ||
74 | //extern int open_excl(const char *); | ||
75 | //extern int open_append(const char *); | ||
76 | //extern int open_trunc(const char *); | ||
77 | |||
78 | extern unsigned FAST_FUNC pmatch(const char *, const char *, unsigned); | ||
79 | |||
80 | //#define str_diff(s,t) strcmp((s), (t)) | ||
81 | #define str_equal(s,t) (!strcmp((s), (t))) | ||
82 | |||
83 | /* | 30 | /* |
84 | * runsv / supervise / sv stuff | 31 | * runsv / supervise / sv stuff |
85 | */ | 32 | */ |
diff --git a/runit/runsv.c b/runit/runsv.c index 6bb6ec886..ebb031837 100644 --- a/runit/runsv.c +++ b/runit/runsv.c | |||
@@ -524,7 +524,7 @@ int runsv_main(int argc UNUSED_PARAM, char **argv) | |||
524 | } | 524 | } |
525 | svd[0].fdlock = xopen3("log/supervise/lock"+4, | 525 | svd[0].fdlock = xopen3("log/supervise/lock"+4, |
526 | O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600); | 526 | O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600); |
527 | if (lock_exnb(svd[0].fdlock) == -1) | 527 | if (flock(svd[0].fdlock, LOCK_EX | LOCK_NB) == -1) |
528 | fatal_cannot("lock supervise/lock"); | 528 | fatal_cannot("lock supervise/lock"); |
529 | close_on_exec_on(svd[0].fdlock); | 529 | close_on_exec_on(svd[0].fdlock); |
530 | if (haslog) { | 530 | if (haslog) { |
@@ -548,7 +548,7 @@ int runsv_main(int argc UNUSED_PARAM, char **argv) | |||
548 | } | 548 | } |
549 | svd[1].fdlock = xopen3("log/supervise/lock", | 549 | svd[1].fdlock = xopen3("log/supervise/lock", |
550 | O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600); | 550 | O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600); |
551 | if (lock_ex(svd[1].fdlock) == -1) | 551 | if (flock(svd[1].fdlock, LOCK_EX) == -1) |
552 | fatal_cannot("lock log/supervise/lock"); | 552 | fatal_cannot("lock log/supervise/lock"); |
553 | close_on_exec_on(svd[1].fdlock); | 553 | close_on_exec_on(svd[1].fdlock); |
554 | } | 554 | } |
@@ -618,7 +618,7 @@ int runsv_main(int argc UNUSED_PARAM, char **argv) | |||
618 | pidchanged = 1; | 618 | pidchanged = 1; |
619 | svd[0].ctrl &= ~C_TERM; | 619 | svd[0].ctrl &= ~C_TERM; |
620 | if (svd[0].state != S_FINISH) { | 620 | if (svd[0].state != S_FINISH) { |
621 | fd = open_read("finish"); | 621 | fd = open("finish", O_RDONLY|O_NDELAY); |
622 | if (fd != -1) { | 622 | if (fd != -1) { |
623 | close(fd); | 623 | close(fd); |
624 | svd[0].state = S_FINISH; | 624 | svd[0].state = S_FINISH; |
diff --git a/runit/runsvdir.c b/runit/runsvdir.c index 71fde757e..e77eeff04 100644 --- a/runit/runsvdir.c +++ b/runit/runsvdir.c | |||
@@ -276,7 +276,7 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv) | |||
276 | } | 276 | } |
277 | run: | 277 | run: |
278 | #endif | 278 | #endif |
279 | curdir = open_read("."); | 279 | curdir = open(".", O_RDONLY|O_NDELAY); |
280 | if (curdir == -1) | 280 | if (curdir == -1) |
281 | fatal2_cannot("open current directory", ""); | 281 | fatal2_cannot("open current directory", ""); |
282 | close_on_exec_on(curdir); | 282 | close_on_exec_on(curdir); |
diff --git a/runit/sv.c b/runit/sv.c index 3f76a2d47..c420a91a6 100644 --- a/runit/sv.c +++ b/runit/sv.c | |||
@@ -176,6 +176,9 @@ struct globals { | |||
176 | #define INIT_G() do { } while (0) | 176 | #define INIT_G() do { } while (0) |
177 | 177 | ||
178 | 178 | ||
179 | #define str_equal(s,t) (!strcmp((s), (t))) | ||
180 | |||
181 | |||
179 | static void fatal_cannot(const char *m1) NORETURN; | 182 | static void fatal_cannot(const char *m1) NORETURN; |
180 | static void fatal_cannot(const char *m1) | 183 | static void fatal_cannot(const char *m1) |
181 | { | 184 | { |
@@ -221,7 +224,7 @@ static int svstatus_get(void) | |||
221 | { | 224 | { |
222 | int fd, r; | 225 | int fd, r; |
223 | 226 | ||
224 | fd = open_write("supervise/ok"); | 227 | fd = open("supervise/ok", O_WRONLY|O_NDELAY); |
225 | if (fd == -1) { | 228 | if (fd == -1) { |
226 | if (errno == ENODEV) { | 229 | if (errno == ENODEV) { |
227 | *acts == 'x' ? ok("runsv not running") | 230 | *acts == 'x' ? ok("runsv not running") |
@@ -232,7 +235,7 @@ static int svstatus_get(void) | |||
232 | return -1; | 235 | return -1; |
233 | } | 236 | } |
234 | close(fd); | 237 | close(fd); |
235 | fd = open_read("supervise/status"); | 238 | fd = open("supervise/status", O_RDONLY|O_NDELAY); |
236 | if (fd == -1) { | 239 | if (fd == -1) { |
237 | warn("can't open supervise/status"); | 240 | warn("can't open supervise/status"); |
238 | return -1; | 241 | return -1; |
@@ -397,7 +400,7 @@ static int control(const char *a) | |||
397 | if (svstatus.want == *a) | 400 | if (svstatus.want == *a) |
398 | return 0; | 401 | return 0; |
399 | */ | 402 | */ |
400 | fd = open_write("supervise/control"); | 403 | fd = open("supervise/control", O_WRONLY|O_NDELAY); |
401 | if (fd == -1) { | 404 | if (fd == -1) { |
402 | if (errno != ENODEV) | 405 | if (errno != ENODEV) |
403 | warn("can't open supervise/control"); | 406 | warn("can't open supervise/control"); |
@@ -446,7 +449,7 @@ int sv_main(int argc UNUSED_PARAM, char **argv) | |||
446 | 449 | ||
447 | tnow = time(NULL) + 0x400000000000000aULL; | 450 | tnow = time(NULL) + 0x400000000000000aULL; |
448 | tstart = tnow; | 451 | tstart = tnow; |
449 | curdir = open_read("."); | 452 | curdir = open(".", O_RDONLY|O_NDELAY); |
450 | if (curdir == -1) | 453 | if (curdir == -1) |
451 | fatal_cannot("open current directory"); | 454 | fatal_cannot("open current directory"); |
452 | 455 | ||
diff --git a/runit/svlogd.c b/runit/svlogd.c index 1f0a77cc2..052806c25 100644 --- a/runit/svlogd.c +++ b/runit/svlogd.c | |||
@@ -261,6 +261,52 @@ static char* wstrdup(const char *str) | |||
261 | return s; | 261 | return s; |
262 | } | 262 | } |
263 | 263 | ||
264 | static unsigned pmatch(const char *p, const char *s, unsigned len) | ||
265 | { | ||
266 | for (;;) { | ||
267 | char c = *p++; | ||
268 | if (!c) return !len; | ||
269 | switch (c) { | ||
270 | case '*': | ||
271 | c = *p; | ||
272 | if (!c) return 1; | ||
273 | for (;;) { | ||
274 | if (!len) return 0; | ||
275 | if (*s == c) break; | ||
276 | ++s; | ||
277 | --len; | ||
278 | } | ||
279 | continue; | ||
280 | case '+': | ||
281 | c = *p++; | ||
282 | if (c != *s) return 0; | ||
283 | for (;;) { | ||
284 | if (!len) return 1; | ||
285 | if (*s != c) break; | ||
286 | ++s; | ||
287 | --len; | ||
288 | } | ||
289 | continue; | ||
290 | /* | ||
291 | case '?': | ||
292 | if (*p == '?') { | ||
293 | if (*s != '?') return 0; | ||
294 | ++p; | ||
295 | } | ||
296 | ++s; --len; | ||
297 | continue; | ||
298 | */ | ||
299 | default: | ||
300 | if (!len) return 0; | ||
301 | if (*s != c) return 0; | ||
302 | ++s; | ||
303 | --len; | ||
304 | continue; | ||
305 | } | ||
306 | } | ||
307 | return 0; | ||
308 | } | ||
309 | |||
264 | /*** ex fmt_ptime.[ch] ***/ | 310 | /*** ex fmt_ptime.[ch] ***/ |
265 | 311 | ||
266 | /* NUL terminated */ | 312 | /* NUL terminated */ |
@@ -342,7 +388,7 @@ static void processorstart(struct logdir *ld) | |||
342 | ld->fnsave[26] = 't'; /* <- that's why we need sv_ch! */ | 388 | ld->fnsave[26] = 't'; /* <- that's why we need sv_ch! */ |
343 | fd = xopen(ld->fnsave, O_WRONLY|O_NDELAY|O_TRUNC|O_CREAT); | 389 | fd = xopen(ld->fnsave, O_WRONLY|O_NDELAY|O_TRUNC|O_CREAT); |
344 | xmove_fd(fd, 1); | 390 | xmove_fd(fd, 1); |
345 | fd = open_read("state"); | 391 | fd = open("state", O_RDONLY|O_NDELAY); |
346 | if (fd == -1) { | 392 | if (fd == -1) { |
347 | if (errno != ENOENT) | 393 | if (errno != ENOENT) |
348 | bb_perror_msg_and_die(FATAL"can't %s processor %s", "open state for", ld->name); | 394 | bb_perror_msg_and_die(FATAL"can't %s processor %s", "open state for", ld->name); |
@@ -626,7 +672,7 @@ static NOINLINE unsigned logdir_open(struct logdir *ld, const char *fn) | |||
626 | } | 672 | } |
627 | ld->fdlock = open("lock", O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600); | 673 | ld->fdlock = open("lock", O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600); |
628 | if ((ld->fdlock == -1) | 674 | if ((ld->fdlock == -1) |
629 | || (lock_exnb(ld->fdlock) == -1) | 675 | || (flock(ld->fdlock, LOCK_EX | LOCK_NB) == -1) |
630 | ) { | 676 | ) { |
631 | logdir_close(ld); | 677 | logdir_close(ld); |
632 | warn2("can't lock directory", (char*)fn); | 678 | warn2("can't lock directory", (char*)fn); |
diff --git a/shell/ash.c b/shell/ash.c index f1f044cbf..45ec13097 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -5766,25 +5766,17 @@ redirectsafe(union node *redir, int flags) | |||
5766 | static arith_t | 5766 | static arith_t |
5767 | ash_arith(const char *s) | 5767 | ash_arith(const char *s) |
5768 | { | 5768 | { |
5769 | arith_eval_hooks_t math_hooks; | 5769 | arith_state_t math_state; |
5770 | arith_t result; | 5770 | arith_t result; |
5771 | int errcode = 0; | ||
5772 | 5771 | ||
5773 | math_hooks.lookupvar = lookupvar; | 5772 | math_state.lookupvar = lookupvar; |
5774 | math_hooks.setvar = setvar2; | 5773 | math_state.setvar = setvar2; |
5775 | //math_hooks.endofname = endofname; | 5774 | //math_state.endofname = endofname; |
5776 | 5775 | ||
5777 | INT_OFF; | 5776 | INT_OFF; |
5778 | result = arith(s, &errcode, &math_hooks); | 5777 | result = arith(&math_state, s); |
5779 | if (errcode < 0) { | 5778 | if (math_state.errmsg) |
5780 | if (errcode == -3) | 5779 | ash_msg_and_raise_error(math_state.errmsg); |
5781 | ash_msg_and_raise_error("exponent less than 0"); | ||
5782 | if (errcode == -2) | ||
5783 | ash_msg_and_raise_error("divide by zero"); | ||
5784 | if (errcode == -5) | ||
5785 | ash_msg_and_raise_error("expression recursion loop detected"); | ||
5786 | raise_error_syntax(s); | ||
5787 | } | ||
5788 | INT_ON; | 5780 | INT_ON; |
5789 | 5781 | ||
5790 | return result; | 5782 | return result; |
@@ -5848,7 +5840,7 @@ cvtnum(arith_t num) | |||
5848 | int len; | 5840 | int len; |
5849 | 5841 | ||
5850 | expdest = makestrspace(32, expdest); | 5842 | expdest = makestrspace(32, expdest); |
5851 | len = fmtstr(expdest, 32, arith_t_fmt, num); | 5843 | len = fmtstr(expdest, 32, ARITH_FMT, num); |
5852 | STADJUST(len, expdest); | 5844 | STADJUST(len, expdest); |
5853 | return len; | 5845 | return len; |
5854 | } | 5846 | } |
@@ -8624,7 +8616,7 @@ static int evalstring(char *s, int mask); | |||
8624 | 8616 | ||
8625 | /* Called to execute a trap. | 8617 | /* Called to execute a trap. |
8626 | * Single callsite - at the end of evaltree(). | 8618 | * Single callsite - at the end of evaltree(). |
8627 | * If we return non-zero, exaltree raises EXEXIT exception. | 8619 | * If we return non-zero, evaltree raises EXEXIT exception. |
8628 | * | 8620 | * |
8629 | * Perhaps we should avoid entering new trap handlers | 8621 | * Perhaps we should avoid entering new trap handlers |
8630 | * while we are executing a trap handler. [is it a TODO?] | 8622 | * while we are executing a trap handler. [is it a TODO?] |
@@ -8814,11 +8806,15 @@ evaltree(union node *n, int flags) | |||
8814 | 8806 | ||
8815 | out: | 8807 | out: |
8816 | exception_handler = savehandler; | 8808 | exception_handler = savehandler; |
8809 | |||
8817 | out1: | 8810 | out1: |
8811 | /* Order of checks below is important: | ||
8812 | * signal handlers trigger before exit caused by "set -e". | ||
8813 | */ | ||
8814 | if (pending_sig && dotrap()) | ||
8815 | goto exexit; | ||
8818 | if (checkexit & exitstatus) | 8816 | if (checkexit & exitstatus) |
8819 | evalskip |= SKIPEVAL; | 8817 | evalskip |= SKIPEVAL; |
8820 | else if (pending_sig && dotrap()) | ||
8821 | goto exexit; | ||
8822 | 8818 | ||
8823 | if (flags & EV_EXIT) { | 8819 | if (flags & EV_EXIT) { |
8824 | exexit: | 8820 | exexit: |
@@ -9212,7 +9208,7 @@ poplocalvars(void) | |||
9212 | while ((lvp = localvars) != NULL) { | 9208 | while ((lvp = localvars) != NULL) { |
9213 | localvars = lvp->next; | 9209 | localvars = lvp->next; |
9214 | vp = lvp->vp; | 9210 | vp = lvp->vp; |
9215 | TRACE(("poplocalvar %s\n", vp ? vp->text : "-")); | 9211 | TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-")); |
9216 | if (vp == NULL) { /* $- saved */ | 9212 | if (vp == NULL) { /* $- saved */ |
9217 | memcpy(optlist, lvp->text, sizeof(optlist)); | 9213 | memcpy(optlist, lvp->text, sizeof(optlist)); |
9218 | free((char*)lvp->text); | 9214 | free((char*)lvp->text); |
@@ -13383,7 +13379,7 @@ init(void) | |||
13383 | /* bash re-enables SIGHUP which is SIG_IGNed on entry. | 13379 | /* bash re-enables SIGHUP which is SIG_IGNed on entry. |
13384 | * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$" | 13380 | * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$" |
13385 | */ | 13381 | */ |
13386 | signal(SIGHUP, SIG_DFL); | 13382 | signal(SIGHUP, SIG_DFL); |
13387 | 13383 | ||
13388 | /* from var.c: */ | 13384 | /* from var.c: */ |
13389 | { | 13385 | { |
@@ -13598,10 +13594,12 @@ int ash_main(int argc UNUSED_PARAM, char **argv) | |||
13598 | if (e == EXERROR) | 13594 | if (e == EXERROR) |
13599 | exitstatus = 2; | 13595 | exitstatus = 2; |
13600 | s = state; | 13596 | s = state; |
13601 | if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) | 13597 | if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) { |
13602 | exitshell(); | 13598 | exitshell(); |
13603 | if (e == EXINT) | 13599 | } |
13600 | if (e == EXINT) { | ||
13604 | outcslow('\n', stderr); | 13601 | outcslow('\n', stderr); |
13602 | } | ||
13605 | 13603 | ||
13606 | popstackmark(&smark); | 13604 | popstackmark(&smark); |
13607 | FORCE_INT_ON; /* enable interrupts */ | 13605 | FORCE_INT_ON; /* enable interrupts */ |
@@ -13705,6 +13703,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv) | |||
13705 | _mcleanup(); | 13703 | _mcleanup(); |
13706 | } | 13704 | } |
13707 | #endif | 13705 | #endif |
13706 | TRACE(("End of main reached\n")); | ||
13708 | exitshell(); | 13707 | exitshell(); |
13709 | /* NOTREACHED */ | 13708 | /* NOTREACHED */ |
13710 | } | 13709 | } |
diff --git a/shell/ash_test/ash-arith/arith.right b/shell/ash_test/ash-arith/arith.right index 3ea7ce680..9b9ca8e2f 100644 --- a/shell/ash_test/ash-arith/arith.right +++ b/shell/ash_test/ash-arith/arith.right | |||
@@ -55,28 +55,28 @@ Format: 'expected actual' | |||
55 | 30 30 | 55 | 30 30 |
56 | 20 20 | 56 | 20 20 |
57 | 30 30 | 57 | 30 30 |
58 | ./arith.tests: line 117: syntax error: 1 ? 20 : x+=2 | 58 | ./arith.tests: line 117: arithmetic syntax error |
59 | 6 6 | 59 | 6 6 |
60 | 6,5,3 6,5,3 | 60 | 6,5,3 6,5,3 |
61 | 263 263 | 61 | 263 263 |
62 | 255 255 | 62 | 255 255 |
63 | 40 40 | 63 | 40 40 |
64 | ./arith.tests: line 163: syntax error: 7 = 43 | 64 | ./arith.tests: line 163: arithmetic syntax error |
65 | ./arith.tests: line 165: divide by zero | 65 | ./arith.tests: line 165: divide by zero |
66 | ./arith.tests: let: line 166: syntax error: jv += $iv | 66 | ./arith.tests: let: line 166: arithmetic syntax error |
67 | ./arith.tests: line 167: syntax error: jv += $iv | 67 | ./arith.tests: line 167: arithmetic syntax error |
68 | ./arith.tests: let: line 168: syntax error: rv = 7 + (43 * 6 | 68 | ./arith.tests: let: line 168: arithmetic syntax error |
69 | abc | 69 | abc |
70 | def | 70 | def |
71 | ghi | 71 | ghi |
72 | ./arith.tests: line 191: syntax error: ( 4 + A ) + 4 | 72 | ./arith.tests: line 191: arithmetic syntax error |
73 | 16 16 | 73 | 16 16 |
74 | ./arith.tests: line 196: syntax error: 4 ? : 3 + 5 | 74 | ./arith.tests: line 196: arithmetic syntax error |
75 | ./arith.tests: line 197: syntax error: 1 ? 20 | 75 | ./arith.tests: line 197: malformed ?: operator |
76 | ./arith.tests: line 198: syntax error: 4 ? 20 : | 76 | ./arith.tests: line 198: arithmetic syntax error |
77 | 9 9 | 77 | 9 9 |
78 | ./arith.tests: line 205: syntax error: 0 && B=42 | 78 | ./arith.tests: line 205: arithmetic syntax error |
79 | ./arith.tests: line 208: syntax error: 1 || B=88 | 79 | ./arith.tests: line 208: arithmetic syntax error |
80 | 9 9 | 80 | 9 9 |
81 | 9 9 | 81 | 9 9 |
82 | 9 9 | 82 | 9 9 |
@@ -97,18 +97,18 @@ ghi | |||
97 | 3 3 | 97 | 3 3 |
98 | 4 4 | 98 | 4 4 |
99 | 4 4 | 99 | 4 4 |
100 | ./arith.tests: line 257: syntax error: 7-- | 100 | ./arith.tests: line 257: arithmetic syntax error |
101 | ./arith.tests: line 259: syntax error: --x=7 | 101 | ./arith.tests: line 259: arithmetic syntax error |
102 | ./arith.tests: line 260: syntax error: ++x=7 | 102 | ./arith.tests: line 260: arithmetic syntax error |
103 | ./arith.tests: line 262: syntax error: x++=7 | 103 | ./arith.tests: line 262: arithmetic syntax error |
104 | ./arith.tests: line 263: syntax error: x--=7 | 104 | ./arith.tests: line 263: arithmetic syntax error |
105 | 4 4 | 105 | 4 4 |
106 | 7 7 | 106 | 7 7 |
107 | -7 -7 | 107 | -7 -7 |
108 | ./arith1.sub: line 2: syntax error: 4-- | 108 | ./arith1.sub: line 2: arithmetic syntax error |
109 | ./arith1.sub: line 3: syntax error: 4++ | 109 | ./arith1.sub: line 3: arithmetic syntax error |
110 | ./arith1.sub: line 4: syntax error: 4 -- | 110 | ./arith1.sub: line 4: arithmetic syntax error |
111 | ./arith1.sub: line 5: syntax error: 4 ++ | 111 | ./arith1.sub: line 5: arithmetic syntax error |
112 | 6 6 | 112 | 6 6 |
113 | 3 3 | 113 | 3 3 |
114 | 7 7 | 114 | 7 7 |
@@ -119,19 +119,19 @@ ghi | |||
119 | 2 2 | 119 | 2 2 |
120 | -2 -2 | 120 | -2 -2 |
121 | 1 1 | 121 | 1 1 |
122 | ./arith1.sub: line 37: syntax error: +++7 | 122 | ./arith1.sub: line 37: arithmetic syntax error |
123 | ./arith2.sub: line 2: syntax error: --7 | 123 | ./arith2.sub: line 2: arithmetic syntax error |
124 | ./arith2.sub: line 3: syntax error: ++7 | 124 | ./arith2.sub: line 3: arithmetic syntax error |
125 | ./arith2.sub: line 4: syntax error: -- 7 | 125 | ./arith2.sub: line 4: arithmetic syntax error |
126 | ./arith2.sub: line 5: syntax error: ++ 7 | 126 | ./arith2.sub: line 5: arithmetic syntax error |
127 | 5 5 | 127 | 5 5 |
128 | 1 1 | 128 | 1 1 |
129 | 4 4 | 129 | 4 4 |
130 | 0 0 | 130 | 0 0 |
131 | ./arith2.sub: line 42: syntax error: -- - 7 | 131 | ./arith2.sub: line 42: arithmetic syntax error |
132 | ./arith2.sub: line 47: syntax error: ++ + 7 | 132 | ./arith2.sub: line 47: arithmetic syntax error |
133 | 8 12 | 133 | 8 12 |
134 | ./arith.tests: line 290: syntax error: a b | 134 | ./arith.tests: line 290: arithmetic syntax error |
135 | 42 | 135 | 42 |
136 | 42 | 136 | 42 |
137 | 42 | 137 | 42 |
diff --git a/shell/ash_test/ash-signals/signal8.right b/shell/ash_test/ash-signals/signal8.right new file mode 100644 index 000000000..39572f30e --- /dev/null +++ b/shell/ash_test/ash-signals/signal8.right | |||
@@ -0,0 +1,3 @@ | |||
1 | Removing traps | ||
2 | End of exit_func | ||
3 | Done: 0 | ||
diff --git a/shell/ash_test/ash-signals/signal8.tests b/shell/ash_test/ash-signals/signal8.tests new file mode 100755 index 000000000..731af7477 --- /dev/null +++ b/shell/ash_test/ash-signals/signal8.tests | |||
@@ -0,0 +1,18 @@ | |||
1 | "$THIS_SH" -c ' | ||
2 | exit_func() { | ||
3 | echo "Removing traps" | ||
4 | trap - EXIT TERM INT | ||
5 | echo "End of exit_func" | ||
6 | } | ||
7 | set -e | ||
8 | trap exit_func EXIT TERM INT | ||
9 | sleep 2 | ||
10 | exit 77 | ||
11 | ' & | ||
12 | |||
13 | sleep 1 | ||
14 | # BUG: ash kills -PGRP, but in non-interactive shell we do not create pgrps! | ||
15 | # In this case, bash kills by PID, not PGRP. | ||
16 | kill -TERM %1 | ||
17 | wait | ||
18 | echo Done: $? | ||
diff --git a/shell/ash_test/ash-signals/signal9.right b/shell/ash_test/ash-signals/signal9.right new file mode 100644 index 000000000..39572f30e --- /dev/null +++ b/shell/ash_test/ash-signals/signal9.right | |||
@@ -0,0 +1,3 @@ | |||
1 | Removing traps | ||
2 | End of exit_func | ||
3 | Done: 0 | ||
diff --git a/shell/ash_test/ash-signals/signal9.tests b/shell/ash_test/ash-signals/signal9.tests new file mode 100755 index 000000000..18e71012b --- /dev/null +++ b/shell/ash_test/ash-signals/signal9.tests | |||
@@ -0,0 +1,21 @@ | |||
1 | # Note: the inner script is a test which checks for a different bug | ||
2 | # (ordering between INT handler and exit on "set -e"), | ||
3 | # but so far I did not figure out how to simulate it non-interactively. | ||
4 | |||
5 | "$THIS_SH" -c ' | ||
6 | exit_func() { | ||
7 | echo "Removing traps" | ||
8 | trap - EXIT TERM INT | ||
9 | echo "End of exit_func" | ||
10 | } | ||
11 | set -e | ||
12 | trap exit_func EXIT TERM INT | ||
13 | sleep 2 | ||
14 | exit 77 | ||
15 | ' & | ||
16 | |||
17 | child=$! | ||
18 | sleep 1 | ||
19 | kill -TERM $child | ||
20 | wait | ||
21 | echo Done: $? | ||
diff --git a/shell/hush.c b/shell/hush.c index 752efd0c8..75083dc2e 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -8,6 +8,8 @@ | |||
8 | * Copyright (C) 2000,2001 Larry Doolittle <larry@doolittle.boa.org> | 8 | * Copyright (C) 2000,2001 Larry Doolittle <larry@doolittle.boa.org> |
9 | * Copyright (C) 2008,2009 Denys Vlasenko <vda.linux@googlemail.com> | 9 | * Copyright (C) 2008,2009 Denys Vlasenko <vda.linux@googlemail.com> |
10 | * | 10 | * |
11 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | ||
12 | * | ||
11 | * Credits: | 13 | * Credits: |
12 | * The parser routines proper are all original material, first | 14 | * The parser routines proper are all original material, first |
13 | * written Dec 2000 and Jan 2001 by Larry Doolittle. The | 15 | * written Dec 2000 and Jan 2001 by Larry Doolittle. The |
@@ -50,7 +52,6 @@ | |||
50 | * | 52 | * |
51 | * Bash compat TODO: | 53 | * Bash compat TODO: |
52 | * redirection of stdout+stderr: &> and >& | 54 | * redirection of stdout+stderr: &> and >& |
53 | * brace expansion: one/{two,three,four} | ||
54 | * reserved words: function select | 55 | * reserved words: function select |
55 | * advanced test: [[ ]] | 56 | * advanced test: [[ ]] |
56 | * process substitution: <(list) and >(list) | 57 | * process substitution: <(list) and >(list) |
@@ -63,7 +64,9 @@ | |||
63 | * The EXPR is evaluated according to ARITHMETIC EVALUATION. | 64 | * The EXPR is evaluated according to ARITHMETIC EVALUATION. |
64 | * This is exactly equivalent to let "EXPR". | 65 | * This is exactly equivalent to let "EXPR". |
65 | * $[EXPR]: synonym for $((EXPR)) | 66 | * $[EXPR]: synonym for $((EXPR)) |
66 | * export builtin should be special, its arguments are assignments | 67 | * |
68 | * Won't do: | ||
69 | * In bash, export builtin is special, its arguments are assignments | ||
67 | * and therefore expansion of them should be "one-word" expansion: | 70 | * and therefore expansion of them should be "one-word" expansion: |
68 | * $ export i=`echo 'a b'` # export has one arg: "i=a b" | 71 | * $ export i=`echo 'a b'` # export has one arg: "i=a b" |
69 | * compare with: | 72 | * compare with: |
@@ -77,8 +80,6 @@ | |||
77 | * aaa bbb | 80 | * aaa bbb |
78 | * $ "export" i=`echo 'aaa bbb'`; echo "$i" | 81 | * $ "export" i=`echo 'aaa bbb'`; echo "$i" |
79 | * aaa | 82 | * aaa |
80 | * | ||
81 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | ||
82 | */ | 83 | */ |
83 | #include "busybox.h" /* for APPLET_IS_NOFORK/NOEXEC */ | 84 | #include "busybox.h" /* for APPLET_IS_NOFORK/NOEXEC */ |
84 | #include <malloc.h> /* for malloc_trim */ | 85 | #include <malloc.h> /* for malloc_trim */ |
@@ -119,8 +120,8 @@ | |||
119 | //config: | 120 | //config: |
120 | //config: It will compile and work on no-mmu systems. | 121 | //config: It will compile and work on no-mmu systems. |
121 | //config: | 122 | //config: |
122 | //config: It does not handle select, aliases, brace expansion, | 123 | //config: It does not handle select, aliases, tilde expansion, |
123 | //config: tilde expansion, &>file and >&file redirection of stdout+stderr. | 124 | //config: &>file and >&file redirection of stdout+stderr. |
124 | //config: | 125 | //config: |
125 | //config:config HUSH_BASH_COMPAT | 126 | //config:config HUSH_BASH_COMPAT |
126 | //config: bool "bash-compatible extensions" | 127 | //config: bool "bash-compatible extensions" |
@@ -129,6 +130,13 @@ | |||
129 | //config: help | 130 | //config: help |
130 | //config: Enable bash-compatible extensions. | 131 | //config: Enable bash-compatible extensions. |
131 | //config: | 132 | //config: |
133 | //config:config HUSH_BRACE_EXPANSION | ||
134 | //config: bool "Brace expansion" | ||
135 | //config: default y | ||
136 | //config: depends on HUSH_BASH_COMPAT | ||
137 | //config: help | ||
138 | //config: Enable {abc,def} extension. | ||
139 | //config: | ||
132 | //config:config HUSH_HELP | 140 | //config:config HUSH_HELP |
133 | //config: bool "help builtin" | 141 | //config: bool "help builtin" |
134 | //config: default y | 142 | //config: default y |
@@ -391,18 +399,10 @@ enum { | |||
391 | RES_SNTX | 399 | RES_SNTX |
392 | }; | 400 | }; |
393 | 401 | ||
394 | enum { | ||
395 | EXP_FLAG_GLOB = 0x200, | ||
396 | EXP_FLAG_ESC_GLOB_CHARS = 0x100, | ||
397 | EXP_FLAG_SINGLEWORD = 0x80, /* must be 0x80 */ | ||
398 | }; | ||
399 | |||
400 | typedef struct o_string { | 402 | typedef struct o_string { |
401 | char *data; | 403 | char *data; |
402 | int length; /* position where data is appended */ | 404 | int length; /* position where data is appended */ |
403 | int maxlen; | 405 | int maxlen; |
404 | /* Protect newly added chars against globbing | ||
405 | * (by prepending \ to *, ?, [, \) */ | ||
406 | int o_expflags; | 406 | int o_expflags; |
407 | /* At least some part of the string was inside '' or "", | 407 | /* At least some part of the string was inside '' or "", |
408 | * possibly empty one: word"", wo''rd etc. */ | 408 | * possibly empty one: word"", wo''rd etc. */ |
@@ -411,10 +411,18 @@ typedef struct o_string { | |||
411 | smallint o_assignment; /* 0:maybe, 1:yes, 2:no */ | 411 | smallint o_assignment; /* 0:maybe, 1:yes, 2:no */ |
412 | } o_string; | 412 | } o_string; |
413 | enum { | 413 | enum { |
414 | MAYBE_ASSIGNMENT = 0, | 414 | EXP_FLAG_SINGLEWORD = 0x80, /* must be 0x80 */ |
415 | EXP_FLAG_GLOB = 0x2, | ||
416 | /* Protect newly added chars against globbing | ||
417 | * by prepending \ to *, ?, [, \ */ | ||
418 | EXP_FLAG_ESC_GLOB_CHARS = 0x1, | ||
419 | }; | ||
420 | enum { | ||
421 | MAYBE_ASSIGNMENT = 0, | ||
415 | DEFINITELY_ASSIGNMENT = 1, | 422 | DEFINITELY_ASSIGNMENT = 1, |
416 | NOT_ASSIGNMENT = 2, | 423 | NOT_ASSIGNMENT = 2, |
417 | WORD_IS_KEYWORD = 3, /* not assigment, but next word may be: "if v=xyz cmd;" */ | 424 | /* Not an assigment, but next word may be: "if v=xyz cmd;" */ |
425 | WORD_IS_KEYWORD = 3, | ||
418 | }; | 426 | }; |
419 | /* Used for initialization: o_string foo = NULL_O_STRING; */ | 427 | /* Used for initialization: o_string foo = NULL_O_STRING; */ |
420 | #define NULL_O_STRING { NULL } | 428 | #define NULL_O_STRING { NULL } |
@@ -707,8 +715,7 @@ struct globals { | |||
707 | #endif | 715 | #endif |
708 | const char *ifs; | 716 | const char *ifs; |
709 | const char *cwd; | 717 | const char *cwd; |
710 | struct variable *top_var; /* = &G.shell_ver (set in main()) */ | 718 | struct variable *top_var; |
711 | struct variable shell_ver; | ||
712 | char **expanded_assignments; | 719 | char **expanded_assignments; |
713 | #if ENABLE_HUSH_FUNCTIONS | 720 | #if ENABLE_HUSH_FUNCTIONS |
714 | struct function *top_func; | 721 | struct function *top_func; |
@@ -2001,26 +2008,8 @@ static void o_addstr_with_NUL(o_string *o, const char *str) | |||
2001 | o_addblock(o, str, strlen(str) + 1); | 2008 | o_addblock(o, str, strlen(str) + 1); |
2002 | } | 2009 | } |
2003 | 2010 | ||
2004 | static void o_addblock_duplicate_backslash(o_string *o, const char *str, int len) | ||
2005 | { | ||
2006 | while (len) { | ||
2007 | len--; | ||
2008 | o_addchr(o, *str); | ||
2009 | if (*str++ == '\\') { | ||
2010 | /* \z -> \\\z; \<eol> -> \\<eol> */ | ||
2011 | o_addchr(o, '\\'); | ||
2012 | if (len) { | ||
2013 | len--; | ||
2014 | o_addchr(o, '\\'); | ||
2015 | o_addchr(o, *str++); | ||
2016 | } | ||
2017 | } | ||
2018 | } | ||
2019 | } | ||
2020 | |||
2021 | #undef HUSH_BRACE_EXP | ||
2022 | /* | 2011 | /* |
2023 | * HUSH_BRACE_EXP code needs corresponding quoting on variable expansion side. | 2012 | * HUSH_BRACE_EXPANSION code needs corresponding quoting on variable expansion side. |
2024 | * Currently, "v='{q,w}'; echo $v" erroneously expands braces in $v. | 2013 | * Currently, "v='{q,w}'; echo $v" erroneously expands braces in $v. |
2025 | * Apparently, on unquoted $v bash still does globbing | 2014 | * Apparently, on unquoted $v bash still does globbing |
2026 | * ("v='*.txt'; echo $v" prints all .txt files), | 2015 | * ("v='*.txt'; echo $v" prints all .txt files), |
@@ -2030,7 +2019,7 @@ static void o_addblock_duplicate_backslash(o_string *o, const char *str, int len | |||
2030 | * We have only second one. | 2019 | * We have only second one. |
2031 | */ | 2020 | */ |
2032 | 2021 | ||
2033 | #ifdef HUSH_BRACE_EXP | 2022 | #if ENABLE_HUSH_BRACE_EXPANSION |
2034 | # define MAYBE_BRACES "{}" | 2023 | # define MAYBE_BRACES "{}" |
2035 | #else | 2024 | #else |
2036 | # define MAYBE_BRACES "" | 2025 | # define MAYBE_BRACES "" |
@@ -2198,7 +2187,7 @@ static int o_get_last_ptr(o_string *o, int n) | |||
2198 | return ((int)(uintptr_t)list[n-1]) + string_start; | 2187 | return ((int)(uintptr_t)list[n-1]) + string_start; |
2199 | } | 2188 | } |
2200 | 2189 | ||
2201 | #ifdef HUSH_BRACE_EXP | 2190 | #if ENABLE_HUSH_BRACE_EXPANSION |
2202 | /* There in a GNU extension, GLOB_BRACE, but it is not usable: | 2191 | /* There in a GNU extension, GLOB_BRACE, but it is not usable: |
2203 | * first, it processes even {a} (no commas), second, | 2192 | * first, it processes even {a} (no commas), second, |
2204 | * I didn't manage to make it return strings when they don't match | 2193 | * I didn't manage to make it return strings when they don't match |
@@ -2394,7 +2383,7 @@ static int perform_glob(o_string *o, int n) | |||
2394 | return n; | 2383 | return n; |
2395 | } | 2384 | } |
2396 | 2385 | ||
2397 | #else /* !HUSH_BRACE_EXP */ | 2386 | #else /* !HUSH_BRACE_EXPANSION */ |
2398 | 2387 | ||
2399 | /* Helper */ | 2388 | /* Helper */ |
2400 | static int glob_needed(const char *s) | 2389 | static int glob_needed(const char *s) |
@@ -2471,7 +2460,7 @@ static int perform_glob(o_string *o, int n) | |||
2471 | return n; | 2460 | return n; |
2472 | } | 2461 | } |
2473 | 2462 | ||
2474 | #endif /* !HUSH_BRACE_EXP */ | 2463 | #endif /* !HUSH_BRACE_EXPANSION */ |
2475 | 2464 | ||
2476 | /* If o->o_expflags & EXP_FLAG_GLOB, glob the string so far remembered. | 2465 | /* If o->o_expflags & EXP_FLAG_GLOB, glob the string so far remembered. |
2477 | * Otherwise, just finish current list[] and start new */ | 2466 | * Otherwise, just finish current list[] and start new */ |
@@ -4388,6 +4377,37 @@ static int process_command_subs(o_string *dest, const char *s); | |||
4388 | * followed by strings themselves. | 4377 | * followed by strings themselves. |
4389 | * Caller can deallocate entire list by single free(list). */ | 4378 | * Caller can deallocate entire list by single free(list). */ |
4390 | 4379 | ||
4380 | /* A horde of its helpers come first: */ | ||
4381 | |||
4382 | static void o_addblock_duplicate_backslash(o_string *o, const char *str, int len) | ||
4383 | { | ||
4384 | while (--len >= 0) { | ||
4385 | char c = *str++; | ||
4386 | |||
4387 | #if ENABLE_HUSH_BRACE_EXPANSION | ||
4388 | if (c == '{' || c == '}') { | ||
4389 | /* { -> \{, } -> \} */ | ||
4390 | o_addchr(o, '\\'); | ||
4391 | /* And now we want to add { or } and continue: | ||
4392 | * o_addchr(o, c); | ||
4393 | * continue; | ||
4394 | * luckily, just falling throught achieves this. | ||
4395 | */ | ||
4396 | } | ||
4397 | #endif | ||
4398 | o_addchr(o, c); | ||
4399 | if (c == '\\') { | ||
4400 | /* \z -> \\\z; \<eol> -> \\<eol> */ | ||
4401 | o_addchr(o, '\\'); | ||
4402 | if (len) { | ||
4403 | len--; | ||
4404 | o_addchr(o, '\\'); | ||
4405 | o_addchr(o, *str++); | ||
4406 | } | ||
4407 | } | ||
4408 | } | ||
4409 | } | ||
4410 | |||
4391 | /* Store given string, finalizing the word and starting new one whenever | 4411 | /* Store given string, finalizing the word and starting new one whenever |
4392 | * we encounter IFS char(s). This is used for expanding variable values. | 4412 | * we encounter IFS char(s). This is used for expanding variable values. |
4393 | * End-of-string does NOT finalize word: think about 'echo -$VAR-' */ | 4413 | * End-of-string does NOT finalize word: think about 'echo -$VAR-' */ |
@@ -4396,9 +4416,9 @@ static int expand_on_ifs(o_string *output, int n, const char *str) | |||
4396 | while (1) { | 4416 | while (1) { |
4397 | int word_len = strcspn(str, G.ifs); | 4417 | int word_len = strcspn(str, G.ifs); |
4398 | if (word_len) { | 4418 | if (word_len) { |
4399 | if (!(output->o_expflags & EXP_FLAG_GLOB)) | 4419 | if (!(output->o_expflags & EXP_FLAG_GLOB)) { |
4400 | o_addblock(output, str, word_len); | 4420 | o_addblock(output, str, word_len); |
4401 | else { | 4421 | } else { |
4402 | /* Protect backslashes against globbing up :) | 4422 | /* Protect backslashes against globbing up :) |
4403 | * Example: "v='\*'; echo b$v" prints "b\*" | 4423 | * Example: "v='\*'; echo b$v" prints "b\*" |
4404 | * (and does not try to glob on "*") | 4424 | * (and does not try to glob on "*") |
@@ -4461,18 +4481,22 @@ static char *encode_then_expand_string(const char *str, int process_bkslash, int | |||
4461 | } | 4481 | } |
4462 | 4482 | ||
4463 | #if ENABLE_SH_MATH_SUPPORT | 4483 | #if ENABLE_SH_MATH_SUPPORT |
4464 | static arith_t expand_and_evaluate_arith(const char *arg, int *errcode_p) | 4484 | static arith_t expand_and_evaluate_arith(const char *arg, const char **errmsg_p) |
4465 | { | 4485 | { |
4466 | arith_eval_hooks_t hooks; | 4486 | arith_state_t math_state; |
4467 | arith_t res; | 4487 | arith_t res; |
4468 | char *exp_str; | 4488 | char *exp_str; |
4469 | 4489 | ||
4470 | hooks.lookupvar = get_local_var_value; | 4490 | math_state.lookupvar = get_local_var_value; |
4471 | hooks.setvar = set_local_var_from_halves; | 4491 | math_state.setvar = set_local_var_from_halves; |
4472 | //hooks.endofname = endofname; | 4492 | //math_state.endofname = endofname; |
4473 | exp_str = encode_then_expand_string(arg, /*process_bkslash:*/ 1, /*unbackslash:*/ 1); | 4493 | exp_str = encode_then_expand_string(arg, /*process_bkslash:*/ 1, /*unbackslash:*/ 1); |
4474 | res = arith(exp_str ? exp_str : arg, errcode_p, &hooks); | 4494 | res = arith(&math_state, exp_str ? exp_str : arg); |
4475 | free(exp_str); | 4495 | free(exp_str); |
4496 | if (errmsg_p) | ||
4497 | *errmsg_p = math_state.errmsg; | ||
4498 | if (math_state.errmsg) | ||
4499 | die_if_script(math_state.errmsg); | ||
4476 | return res; | 4500 | return res; |
4477 | } | 4501 | } |
4478 | #endif | 4502 | #endif |
@@ -4713,24 +4737,28 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha | |||
4713 | * var:N<SPECIAL_VAR_SYMBOL>M<SPECIAL_VAR_SYMBOL> | 4737 | * var:N<SPECIAL_VAR_SYMBOL>M<SPECIAL_VAR_SYMBOL> |
4714 | */ | 4738 | */ |
4715 | arith_t beg, len; | 4739 | arith_t beg, len; |
4716 | int errcode = 0; | 4740 | const char *errmsg; |
4717 | 4741 | ||
4718 | beg = expand_and_evaluate_arith(exp_word, &errcode); | 4742 | beg = expand_and_evaluate_arith(exp_word, &errmsg); |
4743 | if (errmsg) | ||
4744 | goto arith_err; | ||
4719 | debug_printf_varexp("beg:'%s'=%lld\n", exp_word, (long long)beg); | 4745 | debug_printf_varexp("beg:'%s'=%lld\n", exp_word, (long long)beg); |
4720 | *p++ = SPECIAL_VAR_SYMBOL; | 4746 | *p++ = SPECIAL_VAR_SYMBOL; |
4721 | exp_word = p; | 4747 | exp_word = p; |
4722 | p = strchr(p, SPECIAL_VAR_SYMBOL); | 4748 | p = strchr(p, SPECIAL_VAR_SYMBOL); |
4723 | *p = '\0'; | 4749 | *p = '\0'; |
4724 | len = expand_and_evaluate_arith(exp_word, &errcode); | 4750 | len = expand_and_evaluate_arith(exp_word, &errmsg); |
4751 | if (errmsg) | ||
4752 | goto arith_err; | ||
4725 | debug_printf_varexp("len:'%s'=%lld\n", exp_word, (long long)len); | 4753 | debug_printf_varexp("len:'%s'=%lld\n", exp_word, (long long)len); |
4726 | 4754 | if (len >= 0) { /* bash compat: len < 0 is illegal */ | |
4727 | if (errcode >= 0 && len >= 0) { /* bash compat: len < 0 is illegal */ | ||
4728 | if (beg < 0) /* bash compat */ | 4755 | if (beg < 0) /* bash compat */ |
4729 | beg = 0; | 4756 | beg = 0; |
4730 | debug_printf_varexp("from val:'%s'\n", val); | 4757 | debug_printf_varexp("from val:'%s'\n", val); |
4731 | if (len == 0 || !val || beg >= strlen(val)) | 4758 | if (len == 0 || !val || beg >= strlen(val)) { |
4732 | val = ""; | 4759 | arith_err: |
4733 | else { | 4760 | val = NULL; |
4761 | } else { | ||
4734 | /* Paranoia. What if user entered 9999999999999 | 4762 | /* Paranoia. What if user entered 9999999999999 |
4735 | * which fits in arith_t but not int? */ | 4763 | * which fits in arith_t but not int? */ |
4736 | if (len >= INT_MAX) | 4764 | if (len >= INT_MAX) |
@@ -4742,7 +4770,7 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha | |||
4742 | #endif | 4770 | #endif |
4743 | { | 4771 | { |
4744 | die_if_script("malformed ${%s:...}", var); | 4772 | die_if_script("malformed ${%s:...}", var); |
4745 | val = ""; | 4773 | val = NULL; |
4746 | } | 4774 | } |
4747 | } else { /* one of "-=+?" */ | 4775 | } else { /* one of "-=+?" */ |
4748 | /* Standard-mandated substitution ops: | 4776 | /* Standard-mandated substitution ops: |
@@ -4925,30 +4953,13 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) | |||
4925 | #if ENABLE_SH_MATH_SUPPORT | 4953 | #if ENABLE_SH_MATH_SUPPORT |
4926 | case '+': { /* <SPECIAL_VAR_SYMBOL>+cmd<SPECIAL_VAR_SYMBOL> */ | 4954 | case '+': { /* <SPECIAL_VAR_SYMBOL>+cmd<SPECIAL_VAR_SYMBOL> */ |
4927 | arith_t res; | 4955 | arith_t res; |
4928 | int errcode; | ||
4929 | 4956 | ||
4930 | arg++; /* skip '+' */ | 4957 | arg++; /* skip '+' */ |
4931 | *p = '\0'; /* replace trailing <SPECIAL_VAR_SYMBOL> */ | 4958 | *p = '\0'; /* replace trailing <SPECIAL_VAR_SYMBOL> */ |
4932 | debug_printf_subst("ARITH '%s' first_ch %x\n", arg, first_ch); | 4959 | debug_printf_subst("ARITH '%s' first_ch %x\n", arg, first_ch); |
4933 | res = expand_and_evaluate_arith(arg, &errcode); | 4960 | res = expand_and_evaluate_arith(arg, NULL); |
4934 | 4961 | debug_printf_subst("ARITH RES '"ARITH_FMT"'\n", res); | |
4935 | if (errcode < 0) { | 4962 | sprintf(arith_buf, ARITH_FMT, res); |
4936 | const char *msg = "error in arithmetic"; | ||
4937 | switch (errcode) { | ||
4938 | case -3: | ||
4939 | msg = "exponent less than 0"; | ||
4940 | break; | ||
4941 | case -2: | ||
4942 | msg = "divide by 0"; | ||
4943 | break; | ||
4944 | case -5: | ||
4945 | msg = "expression recursion loop detected"; | ||
4946 | break; | ||
4947 | } | ||
4948 | die_if_script(msg); | ||
4949 | } | ||
4950 | debug_printf_subst("ARITH RES '"arith_t_fmt"'\n", res); | ||
4951 | sprintf(arith_buf, arith_t_fmt, res); | ||
4952 | val = arith_buf; | 4963 | val = arith_buf; |
4953 | break; | 4964 | break; |
4954 | } | 4965 | } |
@@ -7346,6 +7357,7 @@ int hush_main(int argc, char **argv) | |||
7346 | unsigned builtin_argc; | 7357 | unsigned builtin_argc; |
7347 | char **e; | 7358 | char **e; |
7348 | struct variable *cur_var; | 7359 | struct variable *cur_var; |
7360 | struct variable shell_ver; | ||
7349 | 7361 | ||
7350 | INIT_G(); | 7362 | INIT_G(); |
7351 | if (EXIT_SUCCESS) /* if EXIT_SUCCESS == 0, it is already done */ | 7363 | if (EXIT_SUCCESS) /* if EXIT_SUCCESS == 0, it is already done */ |
@@ -7354,12 +7366,13 @@ int hush_main(int argc, char **argv) | |||
7354 | G.argv0_for_re_execing = argv[0]; | 7366 | G.argv0_for_re_execing = argv[0]; |
7355 | #endif | 7367 | #endif |
7356 | /* Deal with HUSH_VERSION */ | 7368 | /* Deal with HUSH_VERSION */ |
7357 | G.shell_ver.flg_export = 1; | 7369 | memset(&shell_ver, 0, sizeof(shell_ver)); |
7358 | G.shell_ver.flg_read_only = 1; | 7370 | shell_ver.flg_export = 1; |
7371 | shell_ver.flg_read_only = 1; | ||
7359 | /* Code which handles ${var<op>...} needs writable values for all variables, | 7372 | /* Code which handles ${var<op>...} needs writable values for all variables, |
7360 | * therefore we xstrdup: */ | 7373 | * therefore we xstrdup: */ |
7361 | G.shell_ver.varstr = xstrdup(hush_version_str), | 7374 | shell_ver.varstr = xstrdup(hush_version_str), |
7362 | G.top_var = &G.shell_ver; | 7375 | G.top_var = &shell_ver; |
7363 | /* Create shell local variables from the values | 7376 | /* Create shell local variables from the values |
7364 | * currently living in the environment */ | 7377 | * currently living in the environment */ |
7365 | debug_printf_env("unsetenv '%s'\n", "HUSH_VERSION"); | 7378 | debug_printf_env("unsetenv '%s'\n", "HUSH_VERSION"); |
@@ -7378,8 +7391,8 @@ int hush_main(int argc, char **argv) | |||
7378 | e++; | 7391 | e++; |
7379 | } | 7392 | } |
7380 | /* (Re)insert HUSH_VERSION into env (AFTER we scanned the env!) */ | 7393 | /* (Re)insert HUSH_VERSION into env (AFTER we scanned the env!) */ |
7381 | debug_printf_env("putenv '%s'\n", G.shell_ver.varstr); | 7394 | debug_printf_env("putenv '%s'\n", shell_ver.varstr); |
7382 | putenv(G.shell_ver.varstr); | 7395 | putenv(shell_ver.varstr); |
7383 | 7396 | ||
7384 | /* Export PWD */ | 7397 | /* Export PWD */ |
7385 | set_pwd_var(/*exp:*/ 1); | 7398 | set_pwd_var(/*exp:*/ 1); |
diff --git a/shell/hush_test/hush-arith/arith.right b/shell/hush_test/hush-arith/arith.right index 718c26ad0..8a201fb3b 100644 --- a/shell/hush_test/hush-arith/arith.right +++ b/shell/hush_test/hush-arith/arith.right | |||
@@ -61,7 +61,7 @@ check that the unevaluated part of the ternary operator does not do evaluation o | |||
61 | 20 20 | 61 | 20 20 |
62 | 30 30 | 62 | 30 30 |
63 | check precedence of assignment vs. conditional operator | 63 | check precedence of assignment vs. conditional operator |
64 | hush: error in arithmetic | 64 | hush: arithmetic syntax error |
65 | check precedence of assignment vs. conditional operator | 65 | check precedence of assignment vs. conditional operator |
66 | associativity of assignment-operator operator | 66 | associativity of assignment-operator operator |
67 | 6 6 | 67 | 6 6 |
@@ -70,22 +70,22 @@ octal, hex | |||
70 | 263 263 | 70 | 263 263 |
71 | 255 255 | 71 | 255 255 |
72 | 40 40 | 72 | 40 40 |
73 | hush: error in arithmetic | 73 | hush: arithmetic syntax error |
74 | hush: divide by 0 | 74 | hush: divide by zero |
75 | hush: can't execute 'let': No such file or directory | 75 | hush: can't execute 'let': No such file or directory |
76 | hush: error in arithmetic | 76 | hush: arithmetic syntax error |
77 | hush: can't execute 'let': No such file or directory | 77 | hush: can't execute 'let': No such file or directory |
78 | abc | 78 | abc |
79 | def | 79 | def |
80 | ghi | 80 | ghi |
81 | hush: error in arithmetic | 81 | hush: arithmetic syntax error |
82 | 16 16 | 82 | 16 16 |
83 | hush: error in arithmetic | 83 | hush: arithmetic syntax error |
84 | hush: error in arithmetic | 84 | hush: malformed ?: operator |
85 | hush: error in arithmetic | 85 | hush: arithmetic syntax error |
86 | 9 9 | 86 | 9 9 |
87 | hush: error in arithmetic | 87 | hush: arithmetic syntax error |
88 | hush: error in arithmetic | 88 | hush: arithmetic syntax error |
89 | 9 9 | 89 | 9 9 |
90 | 9 9 | 90 | 9 9 |
91 | 9 9 | 91 | 9 9 |
@@ -106,18 +106,18 @@ hush: error in arithmetic | |||
106 | 3 3 | 106 | 3 3 |
107 | 4 4 | 107 | 4 4 |
108 | 4 4 | 108 | 4 4 |
109 | hush: error in arithmetic | 109 | hush: arithmetic syntax error |
110 | hush: error in arithmetic | 110 | hush: arithmetic syntax error |
111 | hush: error in arithmetic | 111 | hush: arithmetic syntax error |
112 | hush: error in arithmetic | 112 | hush: arithmetic syntax error |
113 | hush: error in arithmetic | 113 | hush: arithmetic syntax error |
114 | 4 4 | 114 | 4 4 |
115 | 7 7 | 115 | 7 7 |
116 | -7 -7 | 116 | -7 -7 |
117 | hush: error in arithmetic | 117 | hush: arithmetic syntax error |
118 | hush: error in arithmetic | 118 | hush: arithmetic syntax error |
119 | hush: error in arithmetic | 119 | hush: arithmetic syntax error |
120 | hush: error in arithmetic | 120 | hush: arithmetic syntax error |
121 | 6 6 | 121 | 6 6 |
122 | 3 3 | 122 | 3 3 |
123 | 7 7 | 123 | 7 7 |
@@ -128,19 +128,19 @@ hush: error in arithmetic | |||
128 | 2 2 | 128 | 2 2 |
129 | -2 -2 | 129 | -2 -2 |
130 | 1 1 | 130 | 1 1 |
131 | hush: error in arithmetic | 131 | hush: arithmetic syntax error |
132 | hush: error in arithmetic | 132 | hush: arithmetic syntax error |
133 | hush: error in arithmetic | 133 | hush: arithmetic syntax error |
134 | hush: error in arithmetic | 134 | hush: arithmetic syntax error |
135 | hush: error in arithmetic | 135 | hush: arithmetic syntax error |
136 | 5 5 | 136 | 5 5 |
137 | 1 1 | 137 | 1 1 |
138 | 4 4 | 138 | 4 4 |
139 | 0 0 | 139 | 0 0 |
140 | hush: error in arithmetic | 140 | hush: arithmetic syntax error |
141 | hush: error in arithmetic | 141 | hush: arithmetic syntax error |
142 | 8 12 | 142 | 8 12 |
143 | hush: error in arithmetic | 143 | hush: arithmetic syntax error |
144 | 42 | 144 | 42 |
145 | 42 | 145 | 42 |
146 | 42 | 146 | 42 |
diff --git a/shell/hush_test/hush-glob/bash_brace1.right b/shell/hush_test/hush-glob/bash_brace1.right new file mode 100644 index 000000000..63365c9e4 --- /dev/null +++ b/shell/hush_test/hush-glob/bash_brace1.right | |||
@@ -0,0 +1,4 @@ | |||
1 | bash_brace1.tests | ||
2 | *{b,b}race1.t* | ||
3 | bash_brace1.tests bash_brace1.tests | ||
4 | Done: 0 | ||
diff --git a/shell/hush_test/hush-glob/bash_brace1.tests b/shell/hush_test/hush-glob/bash_brace1.tests new file mode 100755 index 000000000..eb2f0e974 --- /dev/null +++ b/shell/hush_test/hush-glob/bash_brace1.tests | |||
@@ -0,0 +1,10 @@ | |||
1 | # unquoted $v should be globbed: | ||
2 | v='*brace1.t*'; echo $v | ||
3 | |||
4 | # ...but not brace expanded: | ||
5 | v='*{b,b}race1.t*'; echo $v | ||
6 | |||
7 | # whereas direct brces are expanded: | ||
8 | echo *{b,b}race1.t* | ||
9 | |||
10 | echo Done: $? | ||
diff --git a/shell/math.c b/shell/math.c index a4c55a4d0..760645d0f 100644 --- a/shell/math.c +++ b/shell/math.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * arithmetic code ripped out of ash shell for code sharing | 2 | * Arithmetic code ripped out of ash shell for code sharing. |
3 | * | 3 | * |
4 | * This code is derived from software contributed to Berkeley by | 4 | * This code is derived from software contributed to Berkeley by |
5 | * Kenneth Almquist. | 5 | * Kenneth Almquist. |
@@ -26,43 +26,41 @@ | |||
26 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 26 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
27 | */ | 27 | */ |
28 | /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com> | 28 | /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com> |
29 | 29 | * | |
30 | Permission is hereby granted, free of charge, to any person obtaining | 30 | * Permission is hereby granted, free of charge, to any person obtaining |
31 | a copy of this software and associated documentation files (the | 31 | * a copy of this software and associated documentation files (the |
32 | "Software"), to deal in the Software without restriction, including | 32 | * "Software"), to deal in the Software without restriction, including |
33 | without limitation the rights to use, copy, modify, merge, publish, | 33 | * without limitation the rights to use, copy, modify, merge, publish, |
34 | distribute, sublicense, and/or sell copies of the Software, and to | 34 | * distribute, sublicense, and/or sell copies of the Software, and to |
35 | permit persons to whom the Software is furnished to do so, subject to | 35 | * permit persons to whom the Software is furnished to do so, subject to |
36 | the following conditions: | 36 | * the following conditions: |
37 | 37 | * | |
38 | The above copyright notice and this permission notice shall be | 38 | * The above copyright notice and this permission notice shall be |
39 | included in all copies or substantial portions of the Software. | 39 | * included in all copies or substantial portions of the Software. |
40 | 40 | * | |
41 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | 41 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
42 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | 42 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
43 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | 43 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
44 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | 44 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |
45 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | 45 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
46 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | 46 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
47 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | 47 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
48 | */ | 48 | */ |
49 | 49 | ||
50 | /* This is my infix parser/evaluator. It is optimized for size, intended | 50 | /* This is my infix parser/evaluator. It is optimized for size, intended |
51 | * as a replacement for yacc-based parsers. However, it may well be faster | 51 | * as a replacement for yacc-based parsers. However, it may well be faster |
52 | * than a comparable parser written in yacc. The supported operators are | 52 | * than a comparable parser written in yacc. The supported operators are |
53 | * listed in #defines below. Parens, order of operations, and error handling | 53 | * listed in #defines below. Parens, order of operations, and error handling |
54 | * are supported. This code is thread safe. The exact expression format should | 54 | * are supported. This code is thread safe. The exact expression format should |
55 | * be that which POSIX specifies for shells. */ | 55 | * be that which POSIX specifies for shells. |
56 | 56 | * | |
57 | /* The code uses a simple two-stack algorithm. See | 57 | * The code uses a simple two-stack algorithm. See |
58 | * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html | 58 | * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html |
59 | * for a detailed explanation of the infix-to-postfix algorithm on which | 59 | * for a detailed explanation of the infix-to-postfix algorithm on which |
60 | * this is based (this code differs in that it applies operators immediately | 60 | * this is based (this code differs in that it applies operators immediately |
61 | * to the stack instead of adding them to a queue to end up with an | 61 | * to the stack instead of adding them to a queue to end up with an |
62 | * expression). */ | 62 | * expression). |
63 | 63 | */ | |
64 | /* To use the routine, call it with an expression string and error return | ||
65 | * pointer */ | ||
66 | 64 | ||
67 | /* | 65 | /* |
68 | * Aug 24, 2001 Manuel Novoa III | 66 | * Aug 24, 2001 Manuel Novoa III |
@@ -104,28 +102,23 @@ | |||
104 | * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru> | 102 | * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru> |
105 | * | 103 | * |
106 | * - allow access to variable, | 104 | * - allow access to variable, |
107 | * used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6) | 105 | * use recursive value indirection: c="2*2"; a="c"; echo $((a+=2)) produce 6 |
108 | * - realize assign syntax (VAR=expr, +=, *= etc) | 106 | * - implement assign syntax (VAR=expr, +=, *= etc) |
109 | * - realize exponentiation (** operator) | 107 | * - implement exponentiation (** operator) |
110 | * - realize comma separated - expr, expr | 108 | * - implement comma separated - expr, expr |
111 | * - realise ++expr --expr expr++ expr-- | 109 | * - implement ++expr --expr expr++ expr-- |
112 | * - realise expr ? expr : expr (but, second expr calculate always) | 110 | * - implement expr ? expr : expr (but second expr is always calculated) |
113 | * - allow hexadecimal and octal numbers | 111 | * - allow hexadecimal and octal numbers |
114 | * - was restored loses XOR operator | 112 | * - restore lost XOR operator |
115 | * - remove one goto label, added three ;-) | 113 | * - protect $((num num)) as true zero expr (Manuel's error) |
116 | * - protect $((num num)) as true zero expr (Manuel`s error) | ||
117 | * - always use special isspace(), see comment from bash ;-) | 114 | * - always use special isspace(), see comment from bash ;-) |
118 | */ | 115 | */ |
119 | #include "libbb.h" | 116 | #include "libbb.h" |
120 | #include "math.h" | 117 | #include "math.h" |
121 | 118 | ||
122 | #define a_e_h_t arith_eval_hooks_t | 119 | #define lookupvar (math_state->lookupvar) |
123 | #define lookupvar (math_hooks->lookupvar) | 120 | #define setvar (math_state->setvar ) |
124 | #define setvar (math_hooks->setvar ) | 121 | //#define endofname (math_state->endofname) |
125 | //#define endofname (math_hooks->endofname) | ||
126 | |||
127 | #define arith_isspace(arithval) \ | ||
128 | (arithval == ' ' || arithval == '\n' || arithval == '\t') | ||
129 | 122 | ||
130 | typedef unsigned char operator; | 123 | typedef unsigned char operator; |
131 | 124 | ||
@@ -133,181 +126,199 @@ typedef unsigned char operator; | |||
133 | * precedence, and 3 high bits are an ID unique across operators of that | 126 | * precedence, and 3 high bits are an ID unique across operators of that |
134 | * precedence. The ID portion is so that multiple operators can have the | 127 | * precedence. The ID portion is so that multiple operators can have the |
135 | * same precedence, ensuring that the leftmost one is evaluated first. | 128 | * same precedence, ensuring that the leftmost one is evaluated first. |
136 | * Consider * and /. */ | 129 | * Consider * and / |
137 | 130 | */ | |
138 | #define tok_decl(prec,id) (((id)<<5)|(prec)) | 131 | #define tok_decl(prec,id) (((id)<<5) | (prec)) |
139 | #define PREC(op) ((op) & 0x1F) | 132 | #define PREC(op) ((op) & 0x1F) |
140 | |||
141 | #define TOK_LPAREN tok_decl(0,0) | ||
142 | 133 | ||
143 | #define TOK_COMMA tok_decl(1,0) | 134 | #define TOK_LPAREN tok_decl(0,0) |
144 | 135 | ||
145 | #define TOK_ASSIGN tok_decl(2,0) | 136 | #define TOK_COMMA tok_decl(1,0) |
146 | #define TOK_AND_ASSIGN tok_decl(2,1) | ||
147 | #define TOK_OR_ASSIGN tok_decl(2,2) | ||
148 | #define TOK_XOR_ASSIGN tok_decl(2,3) | ||
149 | #define TOK_PLUS_ASSIGN tok_decl(2,4) | ||
150 | #define TOK_MINUS_ASSIGN tok_decl(2,5) | ||
151 | #define TOK_LSHIFT_ASSIGN tok_decl(2,6) | ||
152 | #define TOK_RSHIFT_ASSIGN tok_decl(2,7) | ||
153 | 137 | ||
154 | #define TOK_MUL_ASSIGN tok_decl(3,0) | 138 | /* All assignments are right associative and have the same precedence, |
155 | #define TOK_DIV_ASSIGN tok_decl(3,1) | 139 | * but there are 11 of them, which doesn't fit into 3 bits for unique id. |
156 | #define TOK_REM_ASSIGN tok_decl(3,2) | 140 | * Abusing another precedence level: |
141 | */ | ||
142 | #define TOK_ASSIGN tok_decl(2,0) | ||
143 | #define TOK_AND_ASSIGN tok_decl(2,1) | ||
144 | #define TOK_OR_ASSIGN tok_decl(2,2) | ||
145 | #define TOK_XOR_ASSIGN tok_decl(2,3) | ||
146 | #define TOK_PLUS_ASSIGN tok_decl(2,4) | ||
147 | #define TOK_MINUS_ASSIGN tok_decl(2,5) | ||
148 | #define TOK_LSHIFT_ASSIGN tok_decl(2,6) | ||
149 | #define TOK_RSHIFT_ASSIGN tok_decl(2,7) | ||
157 | 150 | ||
158 | /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */ | 151 | #define TOK_MUL_ASSIGN tok_decl(3,0) |
159 | #define convert_prec_is_assing(prec) do { if (prec == 3) prec = 2; } while (0) | 152 | #define TOK_DIV_ASSIGN tok_decl(3,1) |
153 | #define TOK_REM_ASSIGN tok_decl(3,2) | ||
160 | 154 | ||
161 | /* conditional is right associativity too */ | 155 | #define fix_assignment_prec(prec) do { if (prec == 3) prec = 2; } while (0) |
162 | #define TOK_CONDITIONAL tok_decl(4,0) | ||
163 | #define TOK_CONDITIONAL_SEP tok_decl(4,1) | ||
164 | 156 | ||
165 | #define TOK_OR tok_decl(5,0) | 157 | /* Ternary conditional operator is right associative too */ |
158 | #define TOK_CONDITIONAL tok_decl(4,0) | ||
159 | #define TOK_CONDITIONAL_SEP tok_decl(4,1) | ||
166 | 160 | ||
167 | #define TOK_AND tok_decl(6,0) | 161 | #define TOK_OR tok_decl(5,0) |
168 | 162 | ||
169 | #define TOK_BOR tok_decl(7,0) | 163 | #define TOK_AND tok_decl(6,0) |
170 | 164 | ||
171 | #define TOK_BXOR tok_decl(8,0) | 165 | #define TOK_BOR tok_decl(7,0) |
172 | 166 | ||
173 | #define TOK_BAND tok_decl(9,0) | 167 | #define TOK_BXOR tok_decl(8,0) |
174 | 168 | ||
175 | #define TOK_EQ tok_decl(10,0) | 169 | #define TOK_BAND tok_decl(9,0) |
176 | #define TOK_NE tok_decl(10,1) | ||
177 | 170 | ||
178 | #define TOK_LT tok_decl(11,0) | 171 | #define TOK_EQ tok_decl(10,0) |
179 | #define TOK_GT tok_decl(11,1) | 172 | #define TOK_NE tok_decl(10,1) |
180 | #define TOK_GE tok_decl(11,2) | ||
181 | #define TOK_LE tok_decl(11,3) | ||
182 | 173 | ||
183 | #define TOK_LSHIFT tok_decl(12,0) | 174 | #define TOK_LT tok_decl(11,0) |
184 | #define TOK_RSHIFT tok_decl(12,1) | 175 | #define TOK_GT tok_decl(11,1) |
176 | #define TOK_GE tok_decl(11,2) | ||
177 | #define TOK_LE tok_decl(11,3) | ||
185 | 178 | ||
186 | #define TOK_ADD tok_decl(13,0) | 179 | #define TOK_LSHIFT tok_decl(12,0) |
187 | #define TOK_SUB tok_decl(13,1) | 180 | #define TOK_RSHIFT tok_decl(12,1) |
188 | 181 | ||
189 | #define TOK_MUL tok_decl(14,0) | 182 | #define TOK_ADD tok_decl(13,0) |
190 | #define TOK_DIV tok_decl(14,1) | 183 | #define TOK_SUB tok_decl(13,1) |
191 | #define TOK_REM tok_decl(14,2) | ||
192 | 184 | ||
193 | /* exponent is right associativity */ | 185 | #define TOK_MUL tok_decl(14,0) |
194 | #define TOK_EXPONENT tok_decl(15,1) | 186 | #define TOK_DIV tok_decl(14,1) |
187 | #define TOK_REM tok_decl(14,2) | ||
195 | 188 | ||
196 | /* For now unary operators. */ | 189 | /* Exponent is right associative */ |
197 | #define UNARYPREC 16 | 190 | #define TOK_EXPONENT tok_decl(15,1) |
198 | #define TOK_BNOT tok_decl(UNARYPREC,0) | ||
199 | #define TOK_NOT tok_decl(UNARYPREC,1) | ||
200 | 191 | ||
201 | #define TOK_UMINUS tok_decl(UNARYPREC+1,0) | 192 | /* Unary operators */ |
202 | #define TOK_UPLUS tok_decl(UNARYPREC+1,1) | 193 | #define UNARYPREC 16 |
194 | #define TOK_BNOT tok_decl(UNARYPREC,0) | ||
195 | #define TOK_NOT tok_decl(UNARYPREC,1) | ||
203 | 196 | ||
204 | #define PREC_PRE (UNARYPREC+2) | 197 | #define TOK_UMINUS tok_decl(UNARYPREC+1,0) |
198 | #define TOK_UPLUS tok_decl(UNARYPREC+1,1) | ||
205 | 199 | ||
206 | #define TOK_PRE_INC tok_decl(PREC_PRE, 0) | 200 | #define PREC_PRE (UNARYPREC+2) |
207 | #define TOK_PRE_DEC tok_decl(PREC_PRE, 1) | ||
208 | 201 | ||
209 | #define PREC_POST (UNARYPREC+3) | 202 | #define TOK_PRE_INC tok_decl(PREC_PRE, 0) |
203 | #define TOK_PRE_DEC tok_decl(PREC_PRE, 1) | ||
210 | 204 | ||
211 | #define TOK_POST_INC tok_decl(PREC_POST, 0) | 205 | #define PREC_POST (UNARYPREC+3) |
212 | #define TOK_POST_DEC tok_decl(PREC_POST, 1) | ||
213 | 206 | ||
214 | #define SPEC_PREC (UNARYPREC+4) | 207 | #define TOK_POST_INC tok_decl(PREC_POST, 0) |
208 | #define TOK_POST_DEC tok_decl(PREC_POST, 1) | ||
215 | 209 | ||
216 | #define TOK_NUM tok_decl(SPEC_PREC, 0) | 210 | #define SPEC_PREC (UNARYPREC+4) |
217 | #define TOK_RPAREN tok_decl(SPEC_PREC, 1) | ||
218 | 211 | ||
219 | #define NUMPTR (*numstackptr) | 212 | #define TOK_NUM tok_decl(SPEC_PREC, 0) |
213 | #define TOK_RPAREN tok_decl(SPEC_PREC, 1) | ||
220 | 214 | ||
221 | static int | 215 | static int |
222 | tok_have_assign(operator op) | 216 | is_assign_op(operator op) |
223 | { | 217 | { |
224 | operator prec = PREC(op); | 218 | operator prec = PREC(op); |
225 | 219 | fix_assignment_prec(prec); | |
226 | convert_prec_is_assing(prec); | 220 | return prec == PREC(TOK_ASSIGN) |
227 | return (prec == PREC(TOK_ASSIGN) || | 221 | || prec == PREC_PRE |
228 | prec == PREC_PRE || prec == PREC_POST); | 222 | || prec == PREC_POST; |
229 | } | 223 | } |
230 | 224 | ||
231 | static int | 225 | static int |
232 | is_right_associativity(operator prec) | 226 | is_right_associative(operator prec) |
233 | { | 227 | { |
234 | return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT) | 228 | return prec == PREC(TOK_ASSIGN) |
235 | || prec == PREC(TOK_CONDITIONAL)); | 229 | || prec == PREC(TOK_EXPONENT) |
230 | || prec == PREC(TOK_CONDITIONAL); | ||
236 | } | 231 | } |
237 | 232 | ||
233 | |||
238 | typedef struct { | 234 | typedef struct { |
239 | arith_t val; | 235 | arith_t val; |
240 | arith_t contidional_second_val; | 236 | /* We acquire second_val only when "expr1 : expr2" part |
241 | char contidional_second_val_initialized; | 237 | * of ternary ?: op is evaluated. |
242 | char *var; /* if NULL then is regular number, | 238 | * We treat ?: as two binary ops: (expr ? (expr1 : expr2)). |
243 | else is variable name */ | 239 | * ':' produces a new value which has two parts, val and second_val; |
244 | } v_n_t; | 240 | * then '?' selects one of them based on its left side. |
245 | 241 | */ | |
246 | typedef struct chk_var_recursive_looped_t { | 242 | arith_t second_val; |
243 | char second_val_present; | ||
244 | /* If NULL then it's just a number, else it's a named variable */ | ||
245 | char *var; | ||
246 | } var_or_num_t; | ||
247 | |||
248 | typedef struct remembered_name { | ||
249 | struct remembered_name *next; | ||
247 | const char *var; | 250 | const char *var; |
248 | struct chk_var_recursive_looped_t *next; | 251 | } remembered_name; |
249 | } chk_var_recursive_looped_t; | ||
250 | 252 | ||
251 | static chk_var_recursive_looped_t *prev_chk_var_recursive; | ||
252 | 253 | ||
253 | static int | 254 | static arith_t FAST_FUNC |
254 | arith_lookup_val(v_n_t *t, a_e_h_t *math_hooks) | 255 | evaluate_string(arith_state_t *math_state, const char *expr); |
256 | |||
257 | static const char* | ||
258 | arith_lookup_val(arith_state_t *math_state, var_or_num_t *t) | ||
255 | { | 259 | { |
256 | if (t->var) { | 260 | if (t->var) { |
257 | const char *p = lookupvar(t->var); | 261 | const char *p = lookupvar(t->var); |
258 | |||
259 | if (p) { | 262 | if (p) { |
260 | int errcode; | 263 | remembered_name *cur; |
261 | 264 | remembered_name cur_save; | |
262 | /* recursive try as expression */ | ||
263 | chk_var_recursive_looped_t *cur; | ||
264 | chk_var_recursive_looped_t cur_save; | ||
265 | 265 | ||
266 | for (cur = prev_chk_var_recursive; cur; cur = cur->next) { | 266 | /* did we already see this name? |
267 | * testcase: a=b; b=a; echo $((a)) | ||
268 | */ | ||
269 | for (cur = math_state->list_of_recursed_names; cur; cur = cur->next) { | ||
267 | if (strcmp(cur->var, t->var) == 0) { | 270 | if (strcmp(cur->var, t->var) == 0) { |
268 | /* expression recursion loop detected */ | 271 | /* Yes */ |
269 | return -5; | 272 | return "expression recursion loop detected"; |
270 | } | 273 | } |
271 | } | 274 | } |
272 | /* save current lookuped var name */ | 275 | |
273 | cur = prev_chk_var_recursive; | 276 | /* push current var name */ |
277 | cur = math_state->list_of_recursed_names; | ||
274 | cur_save.var = t->var; | 278 | cur_save.var = t->var; |
275 | cur_save.next = cur; | 279 | cur_save.next = cur; |
276 | prev_chk_var_recursive = &cur_save; | 280 | math_state->list_of_recursed_names = &cur_save; |
281 | |||
282 | /* recursively evaluate p as expression */ | ||
283 | t->val = evaluate_string(math_state, p); | ||
277 | 284 | ||
278 | t->val = arith (p, &errcode, math_hooks); | 285 | /* pop current var name */ |
279 | /* restore previous ptr after recursiving */ | 286 | math_state->list_of_recursed_names = cur; |
280 | prev_chk_var_recursive = cur; | 287 | |
281 | return errcode; | 288 | return math_state->errmsg; |
282 | } | 289 | } |
283 | /* allow undefined var as 0 */ | 290 | /* treat undefined var as 0 */ |
284 | t->val = 0; | 291 | t->val = 0; |
285 | } | 292 | } |
286 | return 0; | 293 | return 0; |
287 | } | 294 | } |
288 | 295 | ||
289 | /* "applying" a token means performing it on the top elements on the integer | 296 | /* "Applying" a token means performing it on the top elements on the integer |
290 | * stack. For a unary operator it will only change the top element, but a | 297 | * stack. For an unary operator it will only change the top element, but a |
291 | * binary operator will pop two arguments and push a result */ | 298 | * binary operator will pop two arguments and push the result */ |
292 | static NOINLINE int | 299 | static NOINLINE const char* |
293 | arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr, a_e_h_t *math_hooks) | 300 | arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_or_num_t **numstackptr) |
294 | { | 301 | { |
295 | v_n_t *numptr_m1; | 302 | #define NUMPTR (*numstackptr) |
296 | arith_t numptr_val, rez; | 303 | |
297 | int ret_arith_lookup_val; | 304 | var_or_num_t *top_of_stack; |
305 | arith_t rez; | ||
306 | const char *err; | ||
298 | 307 | ||
299 | /* There is no operator that can work without arguments */ | 308 | /* There is no operator that can work without arguments */ |
300 | if (NUMPTR == numstack) goto err; | 309 | if (NUMPTR == numstack) |
301 | numptr_m1 = NUMPTR - 1; | 310 | goto err; |
311 | |||
312 | top_of_stack = NUMPTR - 1; | ||
302 | 313 | ||
303 | /* check operand is var with noninteger value */ | 314 | /* Resolve name to value, if needed */ |
304 | ret_arith_lookup_val = arith_lookup_val(numptr_m1, math_hooks); | 315 | err = arith_lookup_val(math_state, top_of_stack); |
305 | if (ret_arith_lookup_val) | 316 | if (err) |
306 | return ret_arith_lookup_val; | 317 | return err; |
307 | 318 | ||
308 | rez = numptr_m1->val; | 319 | rez = top_of_stack->val; |
309 | if (op == TOK_UMINUS) | 320 | if (op == TOK_UMINUS) |
310 | rez *= -1; | 321 | rez = -rez; |
311 | else if (op == TOK_NOT) | 322 | else if (op == TOK_NOT) |
312 | rez = !rez; | 323 | rez = !rez; |
313 | else if (op == TOK_BNOT) | 324 | else if (op == TOK_BNOT) |
@@ -318,118 +329,123 @@ arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr, a_e_h_t *math_hoo | |||
318 | rez--; | 329 | rez--; |
319 | else if (op != TOK_UPLUS) { | 330 | else if (op != TOK_UPLUS) { |
320 | /* Binary operators */ | 331 | /* Binary operators */ |
332 | arith_t right_side_val; | ||
333 | char bad_second_val; | ||
321 | 334 | ||
322 | /* check and binary operators need two arguments */ | 335 | /* Binary operators need two arguments */ |
323 | if (numptr_m1 == numstack) goto err; | 336 | if (top_of_stack == numstack) |
324 | |||
325 | /* ... and they pop one */ | ||
326 | --NUMPTR; | ||
327 | numptr_val = rez; | ||
328 | if (op == TOK_CONDITIONAL) { | ||
329 | if (!numptr_m1->contidional_second_val_initialized) { | ||
330 | /* protect $((expr1 ? expr2)) without ": expr" */ | ||
331 | goto err; | ||
332 | } | ||
333 | rez = numptr_m1->contidional_second_val; | ||
334 | } else if (numptr_m1->contidional_second_val_initialized) { | ||
335 | /* protect $((expr1 : expr2)) without "expr ? " */ | ||
336 | goto err; | 337 | goto err; |
338 | /* ...and they pop one */ | ||
339 | NUMPTR = top_of_stack; /* this decrements NUMPTR */ | ||
340 | |||
341 | bad_second_val = top_of_stack->second_val_present; | ||
342 | if (op == TOK_CONDITIONAL) { /* ? operation */ | ||
343 | /* Make next if (...) protect against | ||
344 | * $((expr1 ? expr2)) - that is, missing ": expr" */ | ||
345 | bad_second_val = !bad_second_val; | ||
346 | } | ||
347 | if (bad_second_val) { | ||
348 | /* Protect against $((expr <not_?_op> expr1 : expr2)) */ | ||
349 | return "malformed ?: operator"; | ||
337 | } | 350 | } |
338 | numptr_m1 = NUMPTR - 1; | 351 | |
352 | top_of_stack--; /* now points to left side */ | ||
353 | |||
339 | if (op != TOK_ASSIGN) { | 354 | if (op != TOK_ASSIGN) { |
340 | /* check operand is var with noninteger value for not '=' */ | 355 | /* Resolve left side value (unless the op is '=') */ |
341 | ret_arith_lookup_val = arith_lookup_val(numptr_m1, math_hooks); | 356 | err = arith_lookup_val(math_state, top_of_stack); |
342 | if (ret_arith_lookup_val) | 357 | if (err) |
343 | return ret_arith_lookup_val; | 358 | return err; |
344 | } | 359 | } |
345 | if (op == TOK_CONDITIONAL) { | 360 | |
346 | numptr_m1->contidional_second_val = rez; | 361 | right_side_val = rez; |
362 | rez = top_of_stack->val; | ||
363 | if (op == TOK_CONDITIONAL) /* ? operation */ | ||
364 | rez = (rez ? right_side_val : top_of_stack[1].second_val); | ||
365 | else if (op == TOK_CONDITIONAL_SEP) { /* : operation */ | ||
366 | if (top_of_stack == numstack) { | ||
367 | /* Protect against $((expr : expr)) */ | ||
368 | return "malformed ?: operator"; | ||
369 | } | ||
370 | top_of_stack->second_val_present = op; | ||
371 | top_of_stack->second_val = right_side_val; | ||
347 | } | 372 | } |
348 | rez = numptr_m1->val; | 373 | else if (op == TOK_BOR || op == TOK_OR_ASSIGN) |
349 | if (op == TOK_BOR || op == TOK_OR_ASSIGN) | 374 | rez |= right_side_val; |
350 | rez |= numptr_val; | ||
351 | else if (op == TOK_OR) | 375 | else if (op == TOK_OR) |
352 | rez = numptr_val || rez; | 376 | rez = right_side_val || rez; |
353 | else if (op == TOK_BAND || op == TOK_AND_ASSIGN) | 377 | else if (op == TOK_BAND || op == TOK_AND_ASSIGN) |
354 | rez &= numptr_val; | 378 | rez &= right_side_val; |
355 | else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN) | 379 | else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN) |
356 | rez ^= numptr_val; | 380 | rez ^= right_side_val; |
357 | else if (op == TOK_AND) | 381 | else if (op == TOK_AND) |
358 | rez = rez && numptr_val; | 382 | rez = rez && right_side_val; |
359 | else if (op == TOK_EQ) | 383 | else if (op == TOK_EQ) |
360 | rez = (rez == numptr_val); | 384 | rez = (rez == right_side_val); |
361 | else if (op == TOK_NE) | 385 | else if (op == TOK_NE) |
362 | rez = (rez != numptr_val); | 386 | rez = (rez != right_side_val); |
363 | else if (op == TOK_GE) | 387 | else if (op == TOK_GE) |
364 | rez = (rez >= numptr_val); | 388 | rez = (rez >= right_side_val); |
365 | else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN) | 389 | else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN) |
366 | rez >>= numptr_val; | 390 | rez >>= right_side_val; |
367 | else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN) | 391 | else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN) |
368 | rez <<= numptr_val; | 392 | rez <<= right_side_val; |
369 | else if (op == TOK_GT) | 393 | else if (op == TOK_GT) |
370 | rez = (rez > numptr_val); | 394 | rez = (rez > right_side_val); |
371 | else if (op == TOK_LT) | 395 | else if (op == TOK_LT) |
372 | rez = (rez < numptr_val); | 396 | rez = (rez < right_side_val); |
373 | else if (op == TOK_LE) | 397 | else if (op == TOK_LE) |
374 | rez = (rez <= numptr_val); | 398 | rez = (rez <= right_side_val); |
375 | else if (op == TOK_MUL || op == TOK_MUL_ASSIGN) | 399 | else if (op == TOK_MUL || op == TOK_MUL_ASSIGN) |
376 | rez *= numptr_val; | 400 | rez *= right_side_val; |
377 | else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN) | 401 | else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN) |
378 | rez += numptr_val; | 402 | rez += right_side_val; |
379 | else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN) | 403 | else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN) |
380 | rez -= numptr_val; | 404 | rez -= right_side_val; |
381 | else if (op == TOK_ASSIGN || op == TOK_COMMA) | 405 | else if (op == TOK_ASSIGN || op == TOK_COMMA) |
382 | rez = numptr_val; | 406 | rez = right_side_val; |
383 | else if (op == TOK_CONDITIONAL_SEP) { | 407 | else if (op == TOK_EXPONENT) { |
384 | if (numptr_m1 == numstack) { | 408 | arith_t c; |
385 | /* protect $((expr : expr)) without "expr ? " */ | 409 | if (right_side_val < 0) |
386 | goto err; | 410 | return "exponent less than 0"; |
387 | } | 411 | c = 1; |
388 | numptr_m1->contidional_second_val_initialized = op; | 412 | while (--right_side_val >= 0) |
389 | numptr_m1->contidional_second_val = numptr_val; | 413 | c *= rez; |
390 | } else if (op == TOK_CONDITIONAL) { | 414 | rez = c; |
391 | rez = rez ? | 415 | } |
392 | numptr_val : numptr_m1->contidional_second_val; | 416 | else if (right_side_val == 0) |
393 | } else if (op == TOK_EXPONENT) { | 417 | return "divide by zero"; |
394 | if (numptr_val < 0) | ||
395 | return -3; /* exponent less than 0 */ | ||
396 | else { | ||
397 | arith_t c = 1; | ||
398 | |||
399 | if (numptr_val) | ||
400 | while (numptr_val--) | ||
401 | c *= rez; | ||
402 | rez = c; | ||
403 | } | ||
404 | } else if (numptr_val==0) /* zero divisor check */ | ||
405 | return -2; | ||
406 | else if (op == TOK_DIV || op == TOK_DIV_ASSIGN) | 418 | else if (op == TOK_DIV || op == TOK_DIV_ASSIGN) |
407 | rez /= numptr_val; | 419 | rez /= right_side_val; |
408 | else if (op == TOK_REM || op == TOK_REM_ASSIGN) | 420 | else if (op == TOK_REM || op == TOK_REM_ASSIGN) |
409 | rez %= numptr_val; | 421 | rez %= right_side_val; |
410 | } | 422 | } |
411 | if (tok_have_assign(op)) { | 423 | |
424 | if (is_assign_op(op)) { | ||
412 | char buf[sizeof(arith_t)*3 + 2]; | 425 | char buf[sizeof(arith_t)*3 + 2]; |
413 | 426 | ||
414 | if (numptr_m1->var == NULL) { | 427 | if (top_of_stack->var == NULL) { |
415 | /* Hmm, 1=2 ? */ | 428 | /* Hmm, 1=2 ? */ |
429 | //TODO: actually, bash allows ++7 but for some reason it evals to 7, not 8 | ||
416 | goto err; | 430 | goto err; |
417 | } | 431 | } |
418 | /* save to shell variable */ | 432 | /* Save to shell variable */ |
419 | sprintf(buf, arith_t_fmt, rez); | 433 | sprintf(buf, ARITH_FMT, rez); |
420 | setvar(numptr_m1->var, buf); | 434 | setvar(top_of_stack->var, buf); |
421 | /* after saving, make previous value for v++ or v-- */ | 435 | /* After saving, make previous value for v++ or v-- */ |
422 | if (op == TOK_POST_INC) | 436 | if (op == TOK_POST_INC) |
423 | rez--; | 437 | rez--; |
424 | else if (op == TOK_POST_DEC) | 438 | else if (op == TOK_POST_DEC) |
425 | rez++; | 439 | rez++; |
426 | } | 440 | } |
427 | numptr_m1->val = rez; | 441 | |
428 | /* protect geting var value, is number now */ | 442 | top_of_stack->val = rez; |
429 | numptr_m1->var = NULL; | 443 | /* Erase var name, it is just a number now */ |
430 | return 0; | 444 | top_of_stack->var = NULL; |
445 | return NULL; | ||
431 | err: | 446 | err: |
432 | return -1; | 447 | return "arithmetic syntax error"; |
448 | #undef NUMPTR | ||
433 | } | 449 | } |
434 | 450 | ||
435 | /* longest must be first */ | 451 | /* longest must be first */ |
@@ -476,8 +492,7 @@ static const char op_tokens[] ALIGN1 = { | |||
476 | '(', 0, TOK_LPAREN, | 492 | '(', 0, TOK_LPAREN, |
477 | 0 | 493 | 0 |
478 | }; | 494 | }; |
479 | /* ptr to ")" */ | 495 | #define ptr_to_rparen (&op_tokens[sizeof(op_tokens)-7]) |
480 | #define endexpression (&op_tokens[sizeof(op_tokens)-7]) | ||
481 | 496 | ||
482 | const char* FAST_FUNC | 497 | const char* FAST_FUNC |
483 | endofname(const char *name) | 498 | endofname(const char *name) |
@@ -491,35 +506,40 @@ endofname(const char *name) | |||
491 | return name; | 506 | return name; |
492 | } | 507 | } |
493 | 508 | ||
494 | arith_t | 509 | static arith_t FAST_FUNC |
495 | arith(const char *expr, int *perrcode, a_e_h_t *math_hooks) | 510 | evaluate_string(arith_state_t *math_state, const char *expr) |
496 | { | 511 | { |
497 | char arithval; /* Current character under analysis */ | 512 | operator lasttok; |
498 | operator lasttok, op; | 513 | const char *errmsg; |
499 | operator prec; | 514 | const char *start_expr = expr = skip_whitespace(expr); |
500 | operator *stack, *stackptr; | 515 | unsigned expr_len = strlen(expr) + 2; |
501 | const char *p = endexpression; | ||
502 | int errcode; | ||
503 | v_n_t *numstack, *numstackptr; | ||
504 | unsigned datasizes = strlen(expr) + 2; | ||
505 | |||
506 | /* Stack of integers */ | 516 | /* Stack of integers */ |
507 | /* The proof that there can be no more than strlen(startbuf)/2+1 integers | 517 | /* The proof that there can be no more than strlen(startbuf)/2+1 |
508 | * in any given correct or incorrect expression is left as an exercise to | 518 | * integers in any given correct or incorrect expression |
509 | * the reader. */ | 519 | * is left as an exercise to the reader. */ |
510 | numstackptr = numstack = alloca((datasizes / 2) * sizeof(numstack[0])); | 520 | var_or_num_t *const numstack = alloca((expr_len / 2) * sizeof(numstack[0])); |
521 | var_or_num_t *numstackptr = numstack; | ||
511 | /* Stack of operator tokens */ | 522 | /* Stack of operator tokens */ |
512 | stackptr = stack = alloca(datasizes * sizeof(stack[0])); | 523 | operator *const stack = alloca(expr_len * sizeof(stack[0])); |
524 | operator *stackptr = stack; | ||
513 | 525 | ||
514 | *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */ | 526 | /* Start with a left paren */ |
515 | *perrcode = errcode = 0; | 527 | *stackptr++ = lasttok = TOK_LPAREN; |
528 | errmsg = NULL; | ||
516 | 529 | ||
517 | while (1) { | 530 | while (1) { |
531 | const char *p; | ||
532 | operator op; | ||
533 | operator prec; | ||
534 | char arithval; | ||
535 | |||
536 | expr = skip_whitespace(expr); | ||
518 | arithval = *expr; | 537 | arithval = *expr; |
519 | if (arithval == 0) { | 538 | if (arithval == '\0') { |
520 | if (p == endexpression) { | 539 | if (expr == start_expr) { |
521 | /* Null expression. */ | 540 | /* Null expression */ |
522 | return 0; | 541 | numstack->val = 0; |
542 | goto ret; | ||
523 | } | 543 | } |
524 | 544 | ||
525 | /* This is only reached after all tokens have been extracted from the | 545 | /* This is only reached after all tokens have been extracted from the |
@@ -527,77 +547,80 @@ arith(const char *expr, int *perrcode, a_e_h_t *math_hooks) | |||
527 | * are to be applied in order. At the end, there should be a final | 547 | * are to be applied in order. At the end, there should be a final |
528 | * result on the integer stack */ | 548 | * result on the integer stack */ |
529 | 549 | ||
530 | if (expr != endexpression + 1) { | 550 | if (expr != ptr_to_rparen + 1) { |
531 | /* If we haven't done so already, */ | 551 | /* If we haven't done so already, |
532 | /* append a closing right paren */ | 552 | * append a closing right paren |
533 | expr = endexpression; | 553 | * and let the loop process it */ |
534 | /* and let the loop process it. */ | 554 | expr = ptr_to_rparen; |
535 | continue; | 555 | continue; |
536 | } | 556 | } |
537 | /* At this point, we're done with the expression. */ | 557 | /* At this point, we're done with the expression */ |
538 | if (numstackptr != numstack+1) { | 558 | if (numstackptr != numstack + 1) { |
539 | /* ... but if there isn't, it's bad */ | 559 | /* ...but if there isn't, it's bad */ |
540 | err: | 560 | goto err; |
541 | *perrcode = -1; | ||
542 | return *perrcode; | ||
543 | } | 561 | } |
544 | if (numstack->var) { | 562 | if (numstack->var) { |
545 | /* expression is $((var)) only, lookup now */ | 563 | /* expression is $((var)) only, lookup now */ |
546 | errcode = arith_lookup_val(numstack, math_hooks); | 564 | errmsg = arith_lookup_val(math_state, numstack); |
547 | } | 565 | } |
548 | ret: | 566 | goto ret; |
549 | *perrcode = errcode; | ||
550 | return numstack->val; | ||
551 | } | 567 | } |
552 | 568 | ||
553 | /* Continue processing the expression. */ | ||
554 | if (arith_isspace(arithval)) { | ||
555 | /* Skip whitespace */ | ||
556 | goto prologue; | ||
557 | } | ||
558 | p = endofname(expr); | 569 | p = endofname(expr); |
559 | if (p != expr) { | 570 | if (p != expr) { |
560 | size_t var_name_size = (p-expr) + 1; /* trailing zero */ | 571 | /* Name */ |
561 | 572 | size_t var_name_size = (p-expr) + 1; /* +1 for NUL */ | |
562 | numstackptr->var = alloca(var_name_size); | 573 | numstackptr->var = alloca(var_name_size); |
563 | safe_strncpy(numstackptr->var, expr, var_name_size); | 574 | safe_strncpy(numstackptr->var, expr, var_name_size); |
564 | expr = p; | 575 | expr = p; |
565 | num: | 576 | num: |
566 | numstackptr->contidional_second_val_initialized = 0; | 577 | numstackptr->second_val_present = 0; |
567 | numstackptr++; | 578 | numstackptr++; |
568 | lasttok = TOK_NUM; | 579 | lasttok = TOK_NUM; |
569 | continue; | 580 | continue; |
570 | } | 581 | } |
582 | |||
571 | if (isdigit(arithval)) { | 583 | if (isdigit(arithval)) { |
584 | /* Number */ | ||
572 | numstackptr->var = NULL; | 585 | numstackptr->var = NULL; |
573 | errno = 0; | 586 | errno = 0; |
574 | /* call strtoul[l]: */ | 587 | numstackptr->val = strto_arith_t(expr, (char**) &expr, 0); |
575 | numstackptr->val = strto_arith_t(expr, (char **) &expr, 0); | ||
576 | if (errno) | 588 | if (errno) |
577 | numstackptr->val = 0; /* bash compat */ | 589 | numstackptr->val = 0; /* bash compat */ |
578 | goto num; | 590 | goto num; |
579 | } | 591 | } |
580 | for (p = op_tokens; ; p++) { | ||
581 | const char *o; | ||
582 | 592 | ||
583 | if (*p == 0) { | 593 | /* Should be an operator */ |
584 | /* strange operator not found */ | 594 | p = op_tokens; |
585 | goto err; | 595 | while (1) { |
586 | } | 596 | // TODO: bash allows 7+++v, treats it as 7 + ++v |
587 | for (o = expr; *p && *o == *p; p++) | 597 | // we treat it as 7++ + v and reject |
588 | o++; | 598 | /* Compare expr to current op_tokens[] element */ |
589 | if (!*p) { | 599 | const char *e = expr; |
590 | /* found */ | 600 | while (1) { |
591 | expr = o - 1; | 601 | if (*p == '\0') { |
592 | break; | 602 | /* Match: operator is found */ |
603 | expr = e; | ||
604 | goto tok_found; | ||
605 | } | ||
606 | if (*p != *e) | ||
607 | break; | ||
608 | p++; | ||
609 | e++; | ||
593 | } | 610 | } |
594 | /* skip tail uncompared token */ | 611 | /* No match, go to next element of op_tokens[] */ |
595 | while (*p) | 612 | while (*p) |
596 | p++; | 613 | p++; |
597 | /* skip zero delim */ | 614 | p += 2; /* skip NUL and TOK_foo bytes */ |
598 | p++; | 615 | if (*p == '\0') { |
616 | /* No next element, operator not found */ | ||
617 | //math_state->syntax_error_at = expr; | ||
618 | goto err; | ||
619 | } | ||
599 | } | 620 | } |
600 | op = p[1]; | 621 | tok_found: |
622 | op = p[1]; /* fetch TOK_foo value */ | ||
623 | /* NB: expr now points past the operator */ | ||
601 | 624 | ||
602 | /* post grammar: a++ reduce to num */ | 625 | /* post grammar: a++ reduce to num */ |
603 | if (lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC) | 626 | if (lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC) |
@@ -626,13 +649,13 @@ arith(const char *expr, int *perrcode, a_e_h_t *math_hooks) | |||
626 | /* We don't want an unary operator to cause recursive descent on the | 649 | /* We don't want an unary operator to cause recursive descent on the |
627 | * stack, because there can be many in a row and it could cause an | 650 | * stack, because there can be many in a row and it could cause an |
628 | * operator to be evaluated before its argument is pushed onto the | 651 | * operator to be evaluated before its argument is pushed onto the |
629 | * integer stack. */ | 652 | * integer stack. |
630 | /* But for binary operators, "apply" everything on the operator | 653 | * But for binary operators, "apply" everything on the operator |
631 | * stack until we find an operator with a lesser priority than the | 654 | * stack until we find an operator with a lesser priority than the |
632 | * one we have just extracted. */ | 655 | * one we have just extracted. If op is right-associative, |
633 | /* Left paren is given the lowest priority so it will never be | 656 | * then stop "applying" on the equal priority too. |
657 | * Left paren is given the lowest priority so it will never be | ||
634 | * "applied" in this way. | 658 | * "applied" in this way. |
635 | * if associativity is right and priority eq, applied also skip | ||
636 | */ | 659 | */ |
637 | prec = PREC(op); | 660 | prec = PREC(op); |
638 | if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) { | 661 | if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) { |
@@ -642,41 +665,56 @@ arith(const char *expr, int *perrcode, a_e_h_t *math_hooks) | |||
642 | goto err; | 665 | goto err; |
643 | } | 666 | } |
644 | while (stackptr != stack) { | 667 | while (stackptr != stack) { |
668 | operator prev_op = *--stackptr; | ||
645 | if (op == TOK_RPAREN) { | 669 | if (op == TOK_RPAREN) { |
646 | /* The algorithm employed here is simple: while we don't | 670 | /* The algorithm employed here is simple: while we don't |
647 | * hit an open paren nor the bottom of the stack, pop | 671 | * hit an open paren nor the bottom of the stack, pop |
648 | * tokens and apply them */ | 672 | * tokens and apply them */ |
649 | if (stackptr[-1] == TOK_LPAREN) { | 673 | if (prev_op == TOK_LPAREN) { |
650 | --stackptr; | 674 | /* Any operator directly after a |
651 | /* Any operator directly after a */ | 675 | * close paren should consider itself binary */ |
652 | lasttok = TOK_NUM; | 676 | lasttok = TOK_NUM; |
653 | /* close paren should consider itself binary */ | 677 | goto next; |
654 | goto prologue; | ||
655 | } | 678 | } |
656 | } else { | 679 | } else { |
657 | operator prev_prec = PREC(stackptr[-1]); | 680 | operator prev_prec = PREC(prev_op); |
658 | 681 | fix_assignment_prec(prec); | |
659 | convert_prec_is_assing(prec); | 682 | fix_assignment_prec(prev_prec); |
660 | convert_prec_is_assing(prev_prec); | 683 | if (prev_prec < prec |
661 | if (prev_prec < prec) | 684 | || (prev_prec == prec && is_right_associative(prec)) |
662 | break; | 685 | ) { |
663 | /* check right assoc */ | 686 | stackptr++; |
664 | if (prev_prec == prec && is_right_associativity(prec)) | ||
665 | break; | 687 | break; |
688 | } | ||
666 | } | 689 | } |
667 | errcode = arith_apply(*--stackptr, numstack, &numstackptr, math_hooks); | 690 | errmsg = arith_apply(math_state, prev_op, numstack, &numstackptr); |
668 | if (errcode) goto ret; | 691 | if (errmsg) |
692 | goto err_with_custom_msg; | ||
669 | } | 693 | } |
670 | if (op == TOK_RPAREN) { | 694 | if (op == TOK_RPAREN) |
671 | goto err; | 695 | goto err; |
672 | } | ||
673 | } | 696 | } |
674 | 697 | ||
675 | /* Push this operator to the stack and remember it. */ | 698 | /* Push this operator to the stack and remember it */ |
676 | *stackptr++ = lasttok = op; | 699 | *stackptr++ = lasttok = op; |
677 | prologue: | 700 | next: ; |
678 | ++expr; | 701 | } /* while (1) */ |
679 | } /* while */ | 702 | |
703 | err: | ||
704 | errmsg = "arithmetic syntax error"; | ||
705 | err_with_custom_msg: | ||
706 | numstack->val = -1; | ||
707 | ret: | ||
708 | math_state->errmsg = errmsg; | ||
709 | return numstack->val; | ||
710 | } | ||
711 | |||
712 | arith_t FAST_FUNC | ||
713 | arith(arith_state_t *math_state, const char *expr) | ||
714 | { | ||
715 | math_state->errmsg = NULL; | ||
716 | math_state->list_of_recursed_names = NULL; | ||
717 | return evaluate_string(math_state, expr); | ||
680 | } | 718 | } |
681 | 719 | ||
682 | /* | 720 | /* |
diff --git a/shell/math.h b/shell/math.h index 96088b4d2..2d305eb12 100644 --- a/shell/math.h +++ b/shell/math.h | |||
@@ -9,67 +9,53 @@ | |||
9 | 9 | ||
10 | /* The math library has just one function: | 10 | /* The math library has just one function: |
11 | * | 11 | * |
12 | * arith_t arith(const char *expr, int *perrcode, arith_eval_hooks_t *hooks); | 12 | * arith_t arith(arith_state_t *state, const char *expr); |
13 | * | 13 | * |
14 | * The first argument is the math string to parse. All normal expansions must | 14 | * The expr argument is the math string to parse. All normal expansions must |
15 | * be done already. i.e. no dollar symbols should be present. | 15 | * be done already. i.e. no dollar symbols should be present. |
16 | * | 16 | * |
17 | * The second argument is a semi-detailed error description in case something | 17 | * The state argument is a pointer to a struct of hooks for your shell (see below), |
18 | * goes wrong in the parsing steps. Currently, those values are (for | 18 | * and an error message string (NULL if no error). |
19 | * compatibility, you should assume all negative values are errors): | ||
20 | * 0 - no errors (yay!) | ||
21 | * -1 - unspecified problem | ||
22 | * -2 - divide by zero | ||
23 | * -3 - exponent less than 0 | ||
24 | * -5 - expression recursion loop detected | ||
25 | * | 19 | * |
26 | * The third argument is a struct pointer of hooks for your shell (see below). | 20 | * The function returns the answer to the expression. So if you called it |
27 | * | 21 | * with the expression: |
28 | * The function returns the answer to the expression. So if you called it | 22 | * "1 + 2 + 3" |
29 | * with the expression: | 23 | * you would obviously get back 6. |
30 | * "1 + 2 + 3" | ||
31 | * You would obviously get back 6. | ||
32 | */ | 24 | */ |
33 | 25 | ||
34 | /* To add support to a shell, you need to implement three functions: | 26 | /* To add support to a shell, you need to implement three functions: |
35 | * | 27 | * |
36 | * lookupvar() - look up and return the value of a variable | 28 | * lookupvar() - look up and return the value of a variable |
37 | * | 29 | * |
38 | * If the shell does: | 30 | * If the shell does: |
39 | * foo=123 | 31 | * foo=123 |
40 | * Then the code: | 32 | * Then the code: |
41 | * const char *val = lookupvar("foo"); | 33 | * const char *val = lookupvar("foo"); |
42 | * Will result in val pointing to "123" | 34 | * will result in val pointing to "123" |
43 | * | 35 | * |
44 | * setvar() - set a variable to some value | 36 | * setvar() - set a variable to some value |
45 | * | 37 | * |
46 | * If the arithmetic expansion does something like: | 38 | * If the arithmetic expansion does something like: |
47 | * $(( i = 1)) | 39 | * $(( i = 1)) |
48 | * Then the math code will make a call like so: | 40 | * then the math code will make a call like so: |
49 | * setvar("i", "1", 0); | 41 | * setvar("i", "1", 0); |
50 | * The storage for the first two parameters are not allocated, so your | 42 | * The storage for the first two parameters are not allocated, so your |
51 | * shell implementation will most likely need to strdup() them to save. | 43 | * shell implementation will most likely need to strdup() them to save. |
52 | * | 44 | * |
53 | * endofname() - return the end of a variable name from input | 45 | * endofname() - return the end of a variable name from input |
54 | * | 46 | * |
55 | * The arithmetic code does not know about variable naming conventions. | 47 | * The arithmetic code does not know about variable naming conventions. |
56 | * So when it is given an experession, it knows something is not numeric, | 48 | * So when it is given an experession, it knows something is not numeric, |
57 | * but it is up to the shell to dictate what is a valid identifiers. | 49 | * but it is up to the shell to dictate what is a valid identifiers. |
58 | * So when it encounters something like: | 50 | * So when it encounters something like: |
59 | * $(( some_var + 123 )) | 51 | * $(( some_var + 123 )) |
60 | * It will make a call like so: | 52 | * It will make a call like so: |
61 | * end = endofname("some_var + 123"); | 53 | * end = endofname("some_var + 123"); |
62 | * So the shell needs to scan the input string and return a pointer to the | 54 | * So the shell needs to scan the input string and return a pointer to the |
63 | * first non-identifier string. In this case, it should return the input | 55 | * first non-identifier string. In this case, it should return the input |
64 | * pointer with an offset pointing to the first space. The typical | 56 | * pointer with an offset pointing to the first space. The typical |
65 | * implementation will return the offset of first char that does not match | 57 | * implementation will return the offset of first char that does not match |
66 | * the regex (in C locale): ^[a-zA-Z_][a-zA-Z_0-9]* | 58 | * the regex (in C locale): ^[a-zA-Z_][a-zA-Z_0-9]* |
67 | */ | ||
68 | |||
69 | /* To make your life easier when dealing with optional 64bit math support, | ||
70 | * rather than assume that the type is "signed long" and you can always | ||
71 | * use "%ld" to scan/print the value, use the arith_t helper defines. See | ||
72 | * below for the exact things that are available. | ||
73 | */ | 59 | */ |
74 | 60 | ||
75 | #ifndef SHELL_MATH_H | 61 | #ifndef SHELL_MATH_H |
@@ -79,11 +65,11 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN | |||
79 | 65 | ||
80 | #if ENABLE_SH_MATH_SUPPORT_64 | 66 | #if ENABLE_SH_MATH_SUPPORT_64 |
81 | typedef long long arith_t; | 67 | typedef long long arith_t; |
82 | #define arith_t_fmt "%lld" | 68 | #define ARITH_FMT "%lld" |
83 | #define strto_arith_t strtoull | 69 | #define strto_arith_t strtoull |
84 | #else | 70 | #else |
85 | typedef long arith_t; | 71 | typedef long arith_t; |
86 | #define arith_t_fmt "%ld" | 72 | #define ARITH_FMT "%ld" |
87 | #define strto_arith_t strtoul | 73 | #define strto_arith_t strtoul |
88 | #endif | 74 | #endif |
89 | 75 | ||
@@ -96,13 +82,15 @@ typedef const char* FAST_FUNC (*arith_var_lookup_t)(const char *name); | |||
96 | typedef void FAST_FUNC (*arith_var_set_t)(const char *name, const char *val); | 82 | typedef void FAST_FUNC (*arith_var_set_t)(const char *name, const char *val); |
97 | //typedef const char* FAST_FUNC (*arith_var_endofname_t)(const char *name); | 83 | //typedef const char* FAST_FUNC (*arith_var_endofname_t)(const char *name); |
98 | 84 | ||
99 | typedef struct arith_eval_hooks { | 85 | typedef struct arith_state_t { |
86 | const char *errmsg; | ||
100 | arith_var_lookup_t lookupvar; | 87 | arith_var_lookup_t lookupvar; |
101 | arith_var_set_t setvar; | 88 | arith_var_set_t setvar; |
102 | // arith_var_endofname_t endofname; | 89 | // arith_var_endofname_t endofname; |
103 | } arith_eval_hooks_t; | 90 | void *list_of_recursed_names; |
91 | } arith_state_t; | ||
104 | 92 | ||
105 | arith_t arith(const char *expr, int *perrcode, arith_eval_hooks_t*); | 93 | arith_t FAST_FUNC arith(arith_state_t *state, const char *expr); |
106 | 94 | ||
107 | POP_SAVED_FUNCTION_VISIBILITY | 95 | POP_SAVED_FUNCTION_VISIBILITY |
108 | 96 | ||
diff --git a/testsuite/awk.tests b/testsuite/awk.tests index 9e5e5a0f1..56b11ca46 100755 --- a/testsuite/awk.tests +++ b/testsuite/awk.tests | |||
@@ -24,6 +24,12 @@ testing "awk hex const 2" "awk '{ print or(0x80000000,1) }'" "2.14748e+09\n" "" | |||
24 | testing "awk oct const" "awk '{ print or(01234,1) }'" "669\n" "" "\n" | 24 | testing "awk oct const" "awk '{ print or(01234,1) }'" "669\n" "" "\n" |
25 | SKIP= | 25 | SKIP= |
26 | 26 | ||
27 | # check that "hex/oct integer" heuristic doesn't kick in on 00NN.NNN | ||
28 | testing "awk floating const with leading zeroes" \ | ||
29 | "awk '{ printf \"%f %f\n\", \"000.123\", \"009.123\" }'" \ | ||
30 | "0.123000 9.123000\n" \ | ||
31 | "" "\n" | ||
32 | |||
27 | # long field seps requiring regex | 33 | # long field seps requiring regex |
28 | testing "awk long field sep" "awk -F-- '{ print NF, length(\$NF), \$NF }'" \ | 34 | testing "awk long field sep" "awk -F-- '{ print NF, length(\$NF), \$NF }'" \ |
29 | "2 0 \n3 0 \n4 0 \n5 0 \n" \ | 35 | "2 0 \n3 0 \n4 0 \n5 0 \n" \ |
diff --git a/testsuite/cpio.tests b/testsuite/cpio.tests index 05b92dbe4..4cd441a60 100755 --- a/testsuite/cpio.tests +++ b/testsuite/cpio.tests | |||
@@ -116,6 +116,16 @@ link | |||
116 | " "" "" | 116 | " "" "" |
117 | SKIP= | 117 | SKIP= |
118 | 118 | ||
119 | # avoid 'not created: newer or same age file exists' message for directories | ||
120 | rm -rf cpio.testdir cpio.testdir2 2>/dev/null | ||
121 | mkdir cpio.testdir | ||
122 | testing "cpio extracts in existing directory" \ | ||
123 | "$ECHO -ne '$hexdump' | bzcat | cpio -id 2>&1; echo \$?" \ | ||
124 | "\ | ||
125 | 1 blocks | ||
126 | 0 | ||
127 | " "" "" | ||
128 | SKIP= | ||
119 | 129 | ||
120 | # Clean up | 130 | # Clean up |
121 | rm -rf cpio.testdir cpio.testdir2 2>/dev/null | 131 | rm -rf cpio.testdir cpio.testdir2 2>/dev/null |
diff --git a/testsuite/gunzip.tests b/testsuite/gunzip.tests index d7810044f..68c07555d 100755 --- a/testsuite/gunzip.tests +++ b/testsuite/gunzip.tests | |||
@@ -1,3 +1,3 @@ | |||
1 | #!/bin/sh | 1 | #!/bin/sh |
2 | 2 | ||
3 | . bunzip2.tests | 3 | . ./bunzip2.tests |
diff --git a/testsuite/md5sum.tests b/testsuite/md5sum.tests new file mode 100755 index 000000000..35ec67cb4 --- /dev/null +++ b/testsuite/md5sum.tests | |||
@@ -0,0 +1,38 @@ | |||
1 | #!/bin/sh | ||
2 | # Used by {ms5,shaN}sum | ||
3 | |||
4 | # We pipe texts 0...999 bytes long, {md5,shaN}sum them, | ||
5 | # then {md5,shaN}sum the resulting list. | ||
6 | # Then we compare the result with expected result. | ||
7 | # | ||
8 | # Here are the expected results: | ||
9 | # efe30c482e0b687e0cca0612f42ca29b | ||
10 | # d41337e834377140ae7f98460d71d908598ef04f | ||
11 | # 8e1d3ed57ebc130f0f72508446559eeae06451ae6d61b1e8ce46370cfb8963c3 | ||
12 | # fe413e0f177324d1353893ca0772ceba83fd41512ba63895a0eebb703ef9feac2fb4e92b2cb430b3bda41b46b0cb4ea8307190a5cc795157cfb680a9cd635d0f | ||
13 | |||
14 | if ! test "$1"; then | ||
15 | set -- md5sum efe30c482e0b687e0cca0612f42ca29b | ||
16 | fi | ||
17 | |||
18 | sum="$1" | ||
19 | expected="$2" | ||
20 | |||
21 | text="The quick brown fox jumps over the lazy dog" | ||
22 | text=`yes "$text" | head -c 9999` | ||
23 | |||
24 | result=`( | ||
25 | n=0 | ||
26 | while test $n -le 999; do | ||
27 | echo "$text" | head -c $n | "$sum" | ||
28 | : $((n++)) | ||
29 | done | "$sum" | ||
30 | )` | ||
31 | |||
32 | if test x"$result" = x"$expected -"; then | ||
33 | echo "PASS: $sum" | ||
34 | exit 0 | ||
35 | fi | ||
36 | |||
37 | echo "FAIL: $sum (r:$result exp:$expected)" | ||
38 | exit 1 | ||
diff --git a/testsuite/sha1sum.tests b/testsuite/sha1sum.tests new file mode 100755 index 000000000..a968fa87c --- /dev/null +++ b/testsuite/sha1sum.tests | |||
@@ -0,0 +1,3 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | . ./md5sum.tests sha1sum d41337e834377140ae7f98460d71d908598ef04f | ||
diff --git a/testsuite/sha256sum.tests b/testsuite/sha256sum.tests new file mode 100755 index 000000000..d2dd78f2a --- /dev/null +++ b/testsuite/sha256sum.tests | |||
@@ -0,0 +1,3 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | . ./md5sum.tests sha256sum 8e1d3ed57ebc130f0f72508446559eeae06451ae6d61b1e8ce46370cfb8963c3 | ||
diff --git a/testsuite/sha512sum.tests b/testsuite/sha512sum.tests new file mode 100755 index 000000000..3bc7cae4f --- /dev/null +++ b/testsuite/sha512sum.tests | |||
@@ -0,0 +1,3 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | . ./md5sum.tests sha512sum fe413e0f177324d1353893ca0772ceba83fd41512ba63895a0eebb703ef9feac2fb4e92b2cb430b3bda41b46b0cb4ea8307190a5cc795157cfb680a9cd635d0f | ||
diff --git a/util-linux/acpid.c b/util-linux/acpid.c index c3b3c8b0b..5a3bd5a6a 100644 --- a/util-linux/acpid.c +++ b/util-linux/acpid.c | |||
@@ -7,27 +7,58 @@ | |||
7 | * Licensed under GPLv2, see file LICENSE in this source tree. | 7 | * Licensed under GPLv2, see file LICENSE in this source tree. |
8 | */ | 8 | */ |
9 | #include "libbb.h" | 9 | #include "libbb.h" |
10 | 10 | #include <syslog.h> | |
11 | #include <linux/input.h> | 11 | #include <linux/input.h> |
12 | #ifndef EV_SW | ||
13 | # define EV_SW 0x05 | ||
14 | #endif | ||
15 | #ifndef EV_KEY | ||
16 | # define EV_KEY 0x01 | ||
17 | #endif | ||
18 | #ifndef SW_LID | ||
19 | # define SW_LID 0x00 | ||
20 | #endif | ||
21 | #ifndef SW_RFKILL_ALL | ||
22 | # define SW_RFKILL_ALL 0x03 | ||
23 | #endif | ||
24 | #ifndef KEY_POWER | ||
25 | # define KEY_POWER 116 /* SC System Power Down */ | ||
26 | #endif | ||
27 | #ifndef KEY_SLEEP | ||
28 | # define KEY_SLEEP 142 /* SC System Sleep */ | ||
29 | #endif | ||
30 | 12 | ||
13 | enum { | ||
14 | OPT_c = (1 << 0), | ||
15 | OPT_d = (1 << 1), | ||
16 | OPT_e = (1 << 2), | ||
17 | OPT_f = (1 << 3), | ||
18 | OPT_l = (1 << 4), | ||
19 | OPT_p = (1 << 5) * ENABLE_FEATURE_PIDFILE, | ||
20 | OPT_a = (1 << 6), | ||
21 | OPT_M = (1 << 7), | ||
22 | }; | ||
23 | |||
24 | struct acpi_event { | ||
25 | const char *s_type; | ||
26 | uint16_t n_type; | ||
27 | const char *s_code; | ||
28 | uint16_t n_code; | ||
29 | uint32_t value; | ||
30 | const char *desc; | ||
31 | }; | ||
32 | |||
33 | static const struct acpi_event f_evt_tab[] = { | ||
34 | { "EV_KEY", 0x01, "KEY_POWER", 116, 1, "button/power PWRF 00000080" }, | ||
35 | { "EV_KEY", 0x01, "KEY_POWER", 116, 1, "button/power PWRB 00000080" }, | ||
36 | }; | ||
37 | |||
38 | struct acpi_action { | ||
39 | const char *key; | ||
40 | const char *action; | ||
41 | }; | ||
42 | |||
43 | static const struct acpi_action f_act_tab[] = { | ||
44 | { "PWRF", "PWRF/00000080" }, | ||
45 | { "LID0", "LID/00000080" }, | ||
46 | }; | ||
47 | |||
48 | struct globals { | ||
49 | struct acpi_action *act_tab; | ||
50 | int n_act; | ||
51 | struct acpi_event *evt_tab; | ||
52 | int n_evt; | ||
53 | } FIX_ALIASING; | ||
54 | #define G (*ptr_to_globals) | ||
55 | #define act_tab (G.act_tab) | ||
56 | #define n_act (G.n_act ) | ||
57 | #define evt_tab (G.evt_tab) | ||
58 | #define n_evt (G.n_evt ) | ||
59 | #define INIT_G() do { \ | ||
60 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ | ||
61 | } while (0) | ||
31 | 62 | ||
32 | /* | 63 | /* |
33 | * acpid listens to ACPI events coming either in textual form | 64 | * acpid listens to ACPI events coming either in textual form |
@@ -48,7 +79,7 @@ static void process_event(const char *event) | |||
48 | const char *args[] = { "run-parts", handler, NULL }; | 79 | const char *args[] = { "run-parts", handler, NULL }; |
49 | 80 | ||
50 | // debug info | 81 | // debug info |
51 | if (option_mask32 & 8) { // -d | 82 | if (option_mask32 & OPT_d) { |
52 | bb_error_msg("%s", event); | 83 | bb_error_msg("%s", event); |
53 | } | 84 | } |
54 | 85 | ||
@@ -60,125 +91,204 @@ static void process_event(const char *event) | |||
60 | spawn((char **)args + (0==(st.st_mode & S_IFDIR))); | 91 | spawn((char **)args + (0==(st.st_mode & S_IFDIR))); |
61 | else | 92 | else |
62 | bb_simple_perror_msg(event); | 93 | bb_simple_perror_msg(event); |
94 | |||
63 | free(handler); | 95 | free(handler); |
64 | } | 96 | } |
65 | 97 | ||
98 | static const char *find_action(struct input_event *ev, const char *buf) | ||
99 | { | ||
100 | const char *action = NULL; | ||
101 | int i; | ||
102 | |||
103 | // map event | ||
104 | for (i = 0; i < n_evt; i++) { | ||
105 | if (ev) { | ||
106 | if (ev->type == evt_tab[i].n_type && ev->code == evt_tab[i].n_code && ev->value == evt_tab[i].value) { | ||
107 | action = evt_tab[i].desc; | ||
108 | break; | ||
109 | } | ||
110 | } | ||
111 | |||
112 | if (buf) { | ||
113 | if (strncmp(buf, evt_tab[i].desc, strlen(buf)) == 0) { | ||
114 | action = evt_tab[i].desc; | ||
115 | break; | ||
116 | } | ||
117 | } | ||
118 | } | ||
119 | |||
120 | // get action | ||
121 | if (action) { | ||
122 | for (i = 0; i < n_act; i++) { | ||
123 | if (strstr(action, act_tab[i].key)) { | ||
124 | action = act_tab[i].action; | ||
125 | break; | ||
126 | } | ||
127 | } | ||
128 | } | ||
129 | |||
130 | return action; | ||
131 | } | ||
132 | |||
133 | static void parse_conf_file(const char *filename) | ||
134 | { | ||
135 | parser_t *parser; | ||
136 | char *tokens[2]; | ||
137 | |||
138 | parser = config_open2(filename, fopen_for_read); | ||
139 | |||
140 | if (parser) { | ||
141 | while (config_read(parser, tokens, 2, 2, "# \t", PARSE_NORMAL)) { | ||
142 | act_tab = xrealloc_vector(act_tab, 1, n_act); | ||
143 | act_tab[n_act].key = xstrdup(tokens[0]); | ||
144 | act_tab[n_act].action = xstrdup(tokens[1]); | ||
145 | n_act++; | ||
146 | } | ||
147 | config_close(parser); | ||
148 | } else { | ||
149 | act_tab = (void*)f_act_tab; | ||
150 | n_act = ARRAY_SIZE(f_act_tab); | ||
151 | } | ||
152 | } | ||
153 | |||
154 | static void parse_map_file(const char *filename) | ||
155 | { | ||
156 | parser_t *parser; | ||
157 | char *tokens[6]; | ||
158 | |||
159 | parser = config_open2(filename, fopen_for_read); | ||
160 | |||
161 | if (parser) { | ||
162 | while (config_read(parser, tokens, 6, 6, "# \t", PARSE_NORMAL)) { | ||
163 | evt_tab = xrealloc_vector(evt_tab, 1, n_evt); | ||
164 | evt_tab[n_evt].s_type = xstrdup(tokens[0]); | ||
165 | evt_tab[n_evt].n_type = xstrtou(tokens[1], 16); | ||
166 | evt_tab[n_evt].s_code = xstrdup(tokens[2]); | ||
167 | evt_tab[n_evt].n_code = xatou16(tokens[3]); | ||
168 | evt_tab[n_evt].value = xatoi_positive(tokens[4]); | ||
169 | evt_tab[n_evt].desc = xstrdup(tokens[5]); | ||
170 | n_evt++; | ||
171 | } | ||
172 | config_close(parser); | ||
173 | } else { | ||
174 | evt_tab = (void*)f_evt_tab; | ||
175 | n_evt = ARRAY_SIZE(f_evt_tab); | ||
176 | } | ||
177 | } | ||
178 | |||
66 | /* | 179 | /* |
67 | * acpid [-c conf_dir] [-l log_file] [-e proc_event_file] [evdev_event_file...] | 180 | * acpid [-c conf_dir] [-r conf_file ] [-a map_file ] [-l log_file] [-e proc_event_file] |
68 | */ | 181 | */ |
69 | 182 | ||
70 | int acpid_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 183 | int acpid_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
71 | int acpid_main(int argc, char **argv) | 184 | int acpid_main(int argc UNUSED_PARAM, char **argv) |
72 | { | 185 | { |
186 | struct input_event ev; | ||
187 | int nfd; | ||
188 | int opts; | ||
73 | struct pollfd *pfd; | 189 | struct pollfd *pfd; |
74 | int i, nfd; | 190 | const char *opt_dir = "/etc/acpi"; |
75 | const char *opt_conf = "/etc/acpi"; | 191 | const char *opt_input = "/dev/input/event"; |
76 | const char *opt_input = "/proc/acpi/event"; | ||
77 | const char *opt_logfile = "/var/log/acpid.log"; | 192 | const char *opt_logfile = "/var/log/acpid.log"; |
193 | const char *opt_action = "/etc/acpid.conf"; | ||
194 | const char *opt_map = "/etc/acpi.map"; | ||
195 | #if ENABLE_FEATURE_PIDFILE | ||
196 | const char *opt_pidfile = "/var/run/acpid.pid"; | ||
197 | #endif | ||
198 | |||
199 | INIT_G(); | ||
78 | 200 | ||
79 | getopt32(argv, "c:e:l:d" | 201 | opt_complementary = "df:e--e"; |
80 | IF_FEATURE_ACPID_COMPAT("g:m:s:S:v"), | 202 | opts = getopt32(argv, "c:de:fl:p:a:M:" IF_FEATURE_ACPID_COMPAT("g:m:s:S:v"), |
81 | &opt_conf, &opt_input, &opt_logfile | 203 | &opt_dir, &opt_input, &opt_logfile, &opt_pidfile, &opt_action, &opt_map |
82 | IF_FEATURE_ACPID_COMPAT(, NULL, NULL, NULL, NULL, NULL) | 204 | IF_FEATURE_ACPID_COMPAT(, NULL, NULL, NULL, NULL) |
83 | ); | 205 | ); |
84 | 206 | ||
85 | // daemonize unless -d given | 207 | if (!(opts & OPT_f)) { |
86 | if (!(option_mask32 & 8)) { // ! -d | 208 | bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS, argv); |
87 | bb_daemonize_or_rexec(0, argv); | ||
88 | close(2); | ||
89 | xopen(opt_logfile, O_WRONLY | O_CREAT | O_TRUNC); | ||
90 | } | 209 | } |
91 | 210 | ||
92 | argv += optind; | 211 | if (!(opts & OPT_d)) { |
93 | argc -= optind; | 212 | openlog(applet_name, LOG_PID, LOG_DAEMON); |
213 | logmode = LOGMODE_SYSLOG | LOGMODE_STDIO; | ||
214 | } else { | ||
215 | xmove_fd(xopen(opt_logfile, O_WRONLY | O_CREAT | O_TRUNC), STDOUT_FILENO); | ||
216 | } | ||
94 | 217 | ||
95 | // goto configuration directory | 218 | parse_conf_file(opt_action); |
96 | xchdir(opt_conf); | 219 | parse_map_file(opt_map); |
97 | 220 | ||
98 | // prevent zombies | 221 | xchdir(opt_dir); |
99 | signal(SIGCHLD, SIG_IGN); | ||
100 | 222 | ||
101 | // no explicit evdev files given? -> use proc event interface | 223 | bb_signals((1 << SIGCHLD), SIG_IGN); |
102 | if (!*argv) { | 224 | bb_signals(BB_FATAL_SIGS, record_signo); |
103 | // proc_event file is just a "config" :) | ||
104 | char *token[4]; | ||
105 | parser_t *parser = config_open(opt_input); | ||
106 | 225 | ||
107 | // dispatch events | 226 | pfd = NULL; |
108 | while (config_read(parser, token, 4, 4, "\0 ", PARSE_NORMAL)) { | 227 | nfd = 0; |
109 | char *event = xasprintf("%s/%s", token[1], token[2]); | 228 | while (1) { |
110 | process_event(event); | 229 | int fd; |
111 | free(event); | 230 | char *dev_event; |
112 | } | ||
113 | 231 | ||
114 | if (ENABLE_FEATURE_CLEAN_UP) | 232 | dev_event = xasprintf((option_mask32 & OPT_e) ? "%s" : "%s%u", opt_input, nfd); |
115 | config_close(parser); | 233 | fd = open(dev_event, O_RDONLY | O_NONBLOCK); |
116 | return EXIT_SUCCESS; | 234 | if (fd < 0) { |
235 | if (nfd == 0) | ||
236 | bb_simple_perror_msg_and_die(dev_event); | ||
237 | break; | ||
238 | } | ||
239 | pfd = xrealloc_vector(pfd, 1, nfd); | ||
240 | pfd[nfd].fd = fd; | ||
241 | pfd[nfd].events = POLLIN; | ||
242 | nfd++; | ||
117 | } | 243 | } |
118 | 244 | ||
119 | // evdev files given, use evdev interface | 245 | write_pidfile(opt_pidfile); |
120 | |||
121 | // open event devices | ||
122 | pfd = xzalloc(sizeof(*pfd) * argc); | ||
123 | nfd = 0; | ||
124 | while (*argv) { | ||
125 | pfd[nfd].fd = open_or_warn(*argv++, O_RDONLY | O_NONBLOCK); | ||
126 | if (pfd[nfd].fd >= 0) | ||
127 | pfd[nfd++].events = POLLIN; | ||
128 | } | ||
129 | 246 | ||
130 | // dispatch events | 247 | while (poll(pfd, nfd, -1) > 0) { |
131 | while (/* !bb_got_signal && */ poll(pfd, nfd, -1) > 0) { | 248 | int i; |
132 | for (i = 0; i < nfd; i++) { | 249 | for (i = 0; i < nfd; i++) { |
133 | const char *event; | 250 | const char *event = NULL; |
134 | struct input_event ev; | ||
135 | 251 | ||
136 | if (!(pfd[i].revents & POLLIN)) | 252 | memset(&ev, 0, sizeof(ev)); |
137 | continue; | ||
138 | 253 | ||
139 | if (sizeof(ev) != full_read(pfd[i].fd, &ev, sizeof(ev))) | 254 | if (!(pfd[i].revents & POLLIN)) |
140 | continue; | ||
141 | //bb_info_msg("%d: %d %d %4d", i, ev.type, ev.code, ev.value); | ||
142 | |||
143 | // filter out unneeded events | ||
144 | if (ev.value != 1) | ||
145 | continue; | 255 | continue; |
146 | 256 | ||
147 | event = NULL; | 257 | if (option_mask32 & OPT_e) { |
258 | char *buf; | ||
259 | int len; | ||
148 | 260 | ||
149 | // N.B. we will conform to /proc/acpi/event | 261 | buf = xmalloc_reads(pfd[i].fd, NULL, NULL); |
150 | // naming convention when assigning event names | 262 | /* buf = "button/power PWRB 00000080 00000000" */ |
263 | len = strlen(buf) - 9; | ||
264 | if (len >= 0) | ||
265 | buf[len] = '\0'; | ||
266 | event = find_action(NULL, buf); | ||
267 | } else { | ||
268 | if (sizeof(ev) != full_read(pfd[i].fd, &ev, sizeof(ev))) | ||
269 | continue; | ||
151 | 270 | ||
152 | // TODO: do we want other events? | 271 | if (ev.value != 1 && ev.value != 0) |
272 | continue; | ||
153 | 273 | ||
154 | // power and sleep buttons delivered as keys pressed | 274 | event = find_action(&ev, NULL); |
155 | if (EV_KEY == ev.type) { | ||
156 | if (KEY_POWER == ev.code) | ||
157 | event = "PWRF/00000080"; | ||
158 | else if (KEY_SLEEP == ev.code) | ||
159 | event = "SLPB/00000080"; | ||
160 | } | ||
161 | // switches | ||
162 | else if (EV_SW == ev.type) { | ||
163 | if (SW_LID == ev.code) | ||
164 | event = "LID/00000080"; | ||
165 | else if (SW_RFKILL_ALL == ev.code) | ||
166 | event = "RFKILL"; | ||
167 | } | 275 | } |
168 | // filter out unneeded events | ||
169 | if (!event) | 276 | if (!event) |
170 | continue; | 277 | continue; |
171 | |||
172 | // spawn event handler | 278 | // spawn event handler |
173 | process_event(event); | 279 | process_event(event); |
174 | } | 280 | } |
175 | } | 281 | } |
176 | 282 | ||
177 | if (ENABLE_FEATURE_CLEAN_UP) { | 283 | if (ENABLE_FEATURE_CLEAN_UP) { |
178 | for (i = 0; i < nfd; i++) | 284 | while (nfd--) { |
179 | close(pfd[i].fd); | 285 | if (pfd[nfd].fd) { |
286 | close(pfd[nfd].fd); | ||
287 | } | ||
288 | } | ||
180 | free(pfd); | 289 | free(pfd); |
181 | } | 290 | } |
291 | remove_pidfile(opt_pidfile); | ||
182 | 292 | ||
183 | return EXIT_SUCCESS; | 293 | return EXIT_SUCCESS; |
184 | } | 294 | } |