diff options
author | Ron Yorston <rmy@pobox.com> | 2018-04-02 09:24:14 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2018-04-02 09:24:14 +0100 |
commit | 34a68d327b42c3c700e84cd475496985782290b1 (patch) | |
tree | 99bfe59cca420d26f01e81a7f41763f71b44d22c | |
parent | aff3c5bd7b6bdcfb97f63153ab839c5f55f16a12 (diff) | |
parent | e84212f8346741a2d4a04b40639c44fe519cf5a7 (diff) | |
download | busybox-w32-34a68d327b42c3c700e84cd475496985782290b1.tar.gz busybox-w32-34a68d327b42c3c700e84cd475496985782290b1.tar.bz2 busybox-w32-34a68d327b42c3c700e84cd475496985782290b1.zip |
Merge branch 'busybox' into merge
70 files changed, 799 insertions, 187 deletions
diff --git a/archival/cpio.c b/archival/cpio.c index 1d6cbd1e2..308ec1b25 100644 --- a/archival/cpio.c +++ b/archival/cpio.c | |||
@@ -508,6 +508,8 @@ int cpio_main(int argc UNUSED_PARAM, char **argv) | |||
508 | while (get_header_cpio(archive_handle) == EXIT_SUCCESS) | 508 | while (get_header_cpio(archive_handle) == EXIT_SUCCESS) |
509 | continue; | 509 | continue; |
510 | 510 | ||
511 | create_symlinks_from_list(archive_handle->symlink_placeholders); | ||
512 | |||
511 | if (archive_handle->cpio__blocks != (off_t)-1 | 513 | if (archive_handle->cpio__blocks != (off_t)-1 |
512 | && !(opt & OPT_QUIET) | 514 | && !(opt & OPT_QUIET) |
513 | ) { | 515 | ) { |
diff --git a/archival/libarchive/data_extract_to_command.c b/archival/libarchive/data_extract_to_command.c index 1114a95cb..0fcabb4a9 100644 --- a/archival/libarchive/data_extract_to_command.c +++ b/archival/libarchive/data_extract_to_command.c | |||
@@ -37,7 +37,7 @@ static const char *const tar_var[] = { | |||
37 | static void xputenv(char *str) | 37 | static void xputenv(char *str) |
38 | { | 38 | { |
39 | if (putenv(str)) | 39 | if (putenv(str)) |
40 | bb_error_msg_and_die(bb_msg_memory_exhausted); | 40 | bb_die_memory_exhausted(); |
41 | } | 41 | } |
42 | 42 | ||
43 | static void str2env(char *env[], int idx, const char *str) | 43 | static void str2env(char *env[], int idx, const char *str) |
diff --git a/archival/tar.c b/archival/tar.c index d0684b69e..308ce7701 100644 --- a/archival/tar.c +++ b/archival/tar.c | |||
@@ -792,7 +792,7 @@ static llist_t *append_file_list_to_list(llist_t *list) | |||
792 | //usage: IF_FEATURE_SEAMLESS_LZMA("a") | 792 | //usage: IF_FEATURE_SEAMLESS_LZMA("a") |
793 | //usage: IF_FEATURE_TAR_CREATE("h") | 793 | //usage: IF_FEATURE_TAR_CREATE("h") |
794 | //usage: IF_FEATURE_TAR_NOPRESERVE_TIME("m") | 794 | //usage: IF_FEATURE_TAR_NOPRESERVE_TIME("m") |
795 | //usage: "vO] " | 795 | //usage: "vokO] " |
796 | //usage: "[-f TARFILE] [-C DIR] " | 796 | //usage: "[-f TARFILE] [-C DIR] " |
797 | //usage: IF_FEATURE_TAR_FROM("[-T FILE] [-X FILE] "IF_FEATURE_TAR_LONG_OPTIONS("[--exclude PATTERN]... ")) | 797 | //usage: IF_FEATURE_TAR_FROM("[-T FILE] [-X FILE] "IF_FEATURE_TAR_LONG_OPTIONS("[--exclude PATTERN]... ")) |
798 | //usage: "[FILE]..." | 798 | //usage: "[FILE]..." |
@@ -809,6 +809,13 @@ static llist_t *append_file_list_to_list(llist_t *list) | |||
809 | //usage: "\n -f FILE Name of TARFILE ('-' for stdin/out)" | 809 | //usage: "\n -f FILE Name of TARFILE ('-' for stdin/out)" |
810 | //usage: "\n -C DIR Change to DIR before operation" | 810 | //usage: "\n -C DIR Change to DIR before operation" |
811 | //usage: "\n -v Verbose" | 811 | //usage: "\n -v Verbose" |
812 | //usage: "\n -O Extract to stdout" | ||
813 | //usage: IF_FEATURE_TAR_NOPRESERVE_TIME( | ||
814 | //usage: "\n -m Don't restore mtime" | ||
815 | //usage: ) | ||
816 | //usage: "\n -o Don't restore user:group" | ||
817 | ///////:-p - accepted but ignored, restores mode (aliases in GNU tar: --preserve-permissions, --same-permissions) | ||
818 | //usage: "\n -k Don't replace existing files" | ||
812 | //usage: IF_FEATURE_SEAMLESS_Z( | 819 | //usage: IF_FEATURE_SEAMLESS_Z( |
813 | //usage: "\n -Z (De)compress using compress" | 820 | //usage: "\n -Z (De)compress using compress" |
814 | //usage: ) | 821 | //usage: ) |
@@ -824,13 +831,9 @@ static llist_t *append_file_list_to_list(llist_t *list) | |||
824 | //usage: IF_FEATURE_SEAMLESS_LZMA( | 831 | //usage: IF_FEATURE_SEAMLESS_LZMA( |
825 | //usage: "\n -a (De)compress using lzma" | 832 | //usage: "\n -a (De)compress using lzma" |
826 | //usage: ) | 833 | //usage: ) |
827 | //usage: "\n -O Extract to stdout" | ||
828 | //usage: IF_FEATURE_TAR_CREATE( | 834 | //usage: IF_FEATURE_TAR_CREATE( |
829 | //usage: "\n -h Follow symlinks" | 835 | //usage: "\n -h Follow symlinks" |
830 | //usage: ) | 836 | //usage: ) |
831 | //usage: IF_FEATURE_TAR_NOPRESERVE_TIME( | ||
832 | //usage: "\n -m Don't restore mtime" | ||
833 | //usage: ) | ||
834 | //usage: IF_FEATURE_TAR_FROM( | 837 | //usage: IF_FEATURE_TAR_FROM( |
835 | //usage: "\n -T FILE File with names to include" | 838 | //usage: "\n -T FILE File with names to include" |
836 | //usage: "\n -X FILE File with glob patterns to exclude" | 839 | //usage: "\n -X FILE File with glob patterns to exclude" |
@@ -844,9 +847,6 @@ static llist_t *append_file_list_to_list(llist_t *list) | |||
844 | //usage: "$ tar -cf /tmp/tarball.tar /usr/local\n" | 847 | //usage: "$ tar -cf /tmp/tarball.tar /usr/local\n" |
845 | 848 | ||
846 | // Supported but aren't in --help: | 849 | // Supported but aren't in --help: |
847 | // o no-same-owner | ||
848 | // p same-permissions | ||
849 | // k keep-old | ||
850 | // no-recursion | 850 | // no-recursion |
851 | // numeric-owner | 851 | // numeric-owner |
852 | // no-same-permissions | 852 | // no-same-permissions |
diff --git a/coreutils/stat.c b/coreutils/stat.c index 41f6d103c..2944cdfcb 100644 --- a/coreutils/stat.c +++ b/coreutils/stat.c | |||
@@ -211,7 +211,7 @@ static const char *human_fstype(uint32_t f_type) | |||
211 | { 0x52654973, "reiserfs" }, | 211 | { 0x52654973, "reiserfs" }, |
212 | { 0x28cd3d45, "cramfs" }, | 212 | { 0x28cd3d45, "cramfs" }, |
213 | { 0x7275, "romfs" }, | 213 | { 0x7275, "romfs" }, |
214 | { 0x858458f6, "romfs" }, | 214 | { 0x858458f6, "ramfs" }, |
215 | { 0x73717368, "squashfs" }, | 215 | { 0x73717368, "squashfs" }, |
216 | { 0x62656572, "sysfs" }, | 216 | { 0x62656572, "sysfs" }, |
217 | { 0, "UNKNOWN" } | 217 | { 0, "UNKNOWN" } |
diff --git a/editors/sed.c b/editors/sed.c index bb2809d3c..bf8a11613 100644 --- a/editors/sed.c +++ b/editors/sed.c | |||
@@ -994,7 +994,7 @@ static void flush_append(char *last_puts_char) | |||
994 | static char *get_next_line(char *gets_char, char *last_puts_char) | 994 | static char *get_next_line(char *gets_char, char *last_puts_char) |
995 | { | 995 | { |
996 | char *temp = NULL; | 996 | char *temp = NULL; |
997 | int len; | 997 | size_t len; |
998 | char gc; | 998 | char gc; |
999 | 999 | ||
1000 | flush_append(last_puts_char); | 1000 | flush_append(last_puts_char); |
diff --git a/examples/var_service/README_distro_proposal.txt b/examples/var_service/README_distro_proposal.txt index ec887b4e1..f161406a7 100644 --- a/examples/var_service/README_distro_proposal.txt +++ b/examples/var_service/README_distro_proposal.txt | |||
@@ -246,7 +246,8 @@ relative to the system-wide service directory. | |||
246 | This proposal asks developers of other daemontools implementations | 246 | This proposal asks developers of other daemontools implementations |
247 | to add "svc" command to their projects] | 247 | to add "svc" command to their projects] |
248 | 248 | ||
249 | The "svok DIR" tool exits 0 if service is running, and nonzero if not. | 249 | The "svok DIR" tool exits 0 if service supervisor is running |
250 | (with service itself either running or stopped), and nonzero if not. | ||
250 | 251 | ||
251 | Other tools with different names and APIs may exist; however | 252 | Other tools with different names and APIs may exist; however |
252 | for portability scripts should use the above tools. | 253 | for portability scripts should use the above tools. |
diff --git a/examples/var_service/dnsmasq/README b/examples/var_service/dnsmasq/README new file mode 100644 index 000000000..a20740d6e --- /dev/null +++ b/examples/var_service/dnsmasq/README | |||
@@ -0,0 +1,10 @@ | |||
1 | Local DNS cache service. | ||
2 | |||
3 | This service is useful if you have more than 3 DNS servers, | ||
4 | or if you need a finer-grained control of which servers | ||
5 | can serve which domain. | ||
6 | |||
7 | To make programs use local DNS server, make sure | ||
8 | /etc/resolv.conf says: | ||
9 | |||
10 | nameserver 127.0.0.1 | ||
diff --git a/examples/var_service/dnsmasq/dnsmasq.conf b/examples/var_service/dnsmasq/dnsmasq.conf new file mode 100644 index 000000000..2cfb0fe81 --- /dev/null +++ b/examples/var_service/dnsmasq/dnsmasq.conf | |||
@@ -0,0 +1,76 @@ | |||
1 | keep-in-foreground | ||
2 | |||
3 | # "-" is stderr: | ||
4 | log-facility=- | ||
5 | |||
6 | # May also try log-queries=extra | ||
7 | log-queries | ||
8 | |||
9 | # No param = pidfile disabled: | ||
10 | pid-file | ||
11 | |||
12 | interface=lo | ||
13 | listen-address=127.0.0.1 | ||
14 | bind-interfaces | ||
15 | |||
16 | cache-size=999 | ||
17 | |||
18 | servers-file=/etc/dnsmasq_servers.conf | ||
19 | |||
20 | # Don’t read /etc/resolv.conf and /etc/hosts: | ||
21 | no-resolv | ||
22 | #no-hosts | ||
23 | |||
24 | # All reverse lookups for private IP ranges (ie 192.168.x.x, etc) | ||
25 | # which are not found in /etc/hosts or the DHCP leases file are | ||
26 | # answered with "no such domain" rather than being forwarded | ||
27 | # upstream. The set of prefixes affected is the list given in | ||
28 | # RFC6303. | ||
29 | #bogus-priv | ||
30 | |||
31 | #−T, --local-ttl=<time> | ||
32 | # When replying with information from /etc/hosts or configuration | ||
33 | # or the DHCP leases file dnsmasq by default sets the time-to-live | ||
34 | # field to zero, meaning that the requester should not itself | ||
35 | # cache the information. This is the correct thing to do in almost | ||
36 | # all situations. This option allows a time-to-live (in seconds) | ||
37 | # to be given for these replies. This will reduce the load on the | ||
38 | # server at the expense of clients using stale data under some | ||
39 | # circumstances. | ||
40 | local-ttl=67 | ||
41 | |||
42 | #--dhcp-ttl=<time> | ||
43 | # As for --local-ttl, but affects only replies with information | ||
44 | # from DHCP leases. If both are given, --dhcp-ttl applies for DHCP | ||
45 | # information, and --local-ttl for others. Setting this to zero | ||
46 | # eliminates the effect of --local-ttl for DHCP. | ||
47 | # | ||
48 | #--neg-ttl=<time> | ||
49 | # Negative replies from upstream servers normally contain time-to- | ||
50 | # live information in SOA records which dnsmasq uses for caching. | ||
51 | # If the replies from upstream servers omit this information, dns- | ||
52 | # masq does not cache the reply. This option gives a default value | ||
53 | # for time-to-live (in seconds) which dnsmasq uses to cache nega- | ||
54 | # tive replies even in the absence of an SOA record. | ||
55 | neg-ttl=67 | ||
56 | |||
57 | #--max-ttl=<time> | ||
58 | # Set a maximum TTL value that will be handed out to clients. The | ||
59 | # specified maximum TTL will be given to clients instead of the | ||
60 | # true TTL value if it is lower. The true TTL value is however | ||
61 | # kept in the cache to avoid flooding the upstream DNS servers. | ||
62 | # | ||
63 | #--max-cache-ttl=<time> | ||
64 | # Set a maximum TTL value for entries in the cache. | ||
65 | # | ||
66 | #--min-cache-ttl=<time> | ||
67 | # Extend short TTL values to the time given when caching them. | ||
68 | # Note that artificially extending TTL values is in general a bad | ||
69 | # idea, do not do it unless you have a good reason, and understand | ||
70 | # what you are doing. Dnsmasq limits the value of this option to | ||
71 | # one hour, unless recompiled. | ||
72 | min-cache-ttl=67 | ||
73 | |||
74 | #--auth-ttl=<time> | ||
75 | # Set the TTL value returned in answers from the authoritative | ||
76 | # server. | ||
diff --git a/examples/var_service/dnsmasq/log/run b/examples/var_service/dnsmasq/log/run new file mode 100755 index 000000000..69d74b73f --- /dev/null +++ b/examples/var_service/dnsmasq/log/run | |||
@@ -0,0 +1,21 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | user=logger | ||
4 | |||
5 | logdir="/var/log/service/`(cd ..;basename $PWD)`" | ||
6 | mkdir -p "$logdir" 2>/dev/null | ||
7 | chown -R "$user": "$logdir" | ||
8 | chmod -R go-rwxst,u+rwX "$logdir" | ||
9 | rm -rf logdir | ||
10 | ln -s "$logdir" logdir | ||
11 | |||
12 | # make this dir accessible to logger | ||
13 | chmod a+rX . | ||
14 | |||
15 | exec >/dev/null | ||
16 | exec 2>&1 | ||
17 | exec \ | ||
18 | env - PATH="$PATH" \ | ||
19 | softlimit \ | ||
20 | setuidgid "$user" \ | ||
21 | svlogd -tt "$logdir" | ||
diff --git a/examples/var_service/dnsmasq/p_log b/examples/var_service/dnsmasq/p_log new file mode 100755 index 000000000..a2521be05 --- /dev/null +++ b/examples/var_service/dnsmasq/p_log | |||
@@ -0,0 +1,4 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | cd log/logdir || exit 1 | ||
4 | cat @* current | $PAGER | ||
diff --git a/examples/var_service/dnsmasq/run b/examples/var_service/dnsmasq/run new file mode 100755 index 000000000..2ac94282f --- /dev/null +++ b/examples/var_service/dnsmasq/run | |||
@@ -0,0 +1,12 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | #exec >/dev/null | ||
4 | exec 2>&1 | ||
5 | exec </dev/null | ||
6 | |||
7 | echo "* Starting dnsmasq" | ||
8 | exec \ | ||
9 | env - PATH="$PATH" \ | ||
10 | softlimit \ | ||
11 | setuidgid root \ | ||
12 | dnsmasq -C dnsmasq.conf | ||
diff --git a/examples/var_service/dnsmasq/w_log b/examples/var_service/dnsmasq/w_log new file mode 100755 index 000000000..aa36ef13b --- /dev/null +++ b/examples/var_service/dnsmasq/w_log | |||
@@ -0,0 +1,4 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | cd log/logdir || exit 1 | ||
4 | watch -n2 'w=`ttysize w`; h=`ttysize h`; tail -$((h-3)) current 2>&1 | cut -b1-$((w-2))' | ||
diff --git a/examples/var_service/fw/etc/dnsmasq_servers.conf b/examples/var_service/fw/etc/dnsmasq_servers.conf new file mode 100644 index 000000000..68313605f --- /dev/null +++ b/examples/var_service/fw/etc/dnsmasq_servers.conf | |||
@@ -0,0 +1,38 @@ | |||
1 | #!/bin/bash | ||
2 | |||
3 | empty=true | ||
4 | |||
5 | prio=0 | ||
6 | i=0; while test "${if[$i]}"; do | ||
7 | test x"${dns_prio[$i]}" != x"" \ | ||
8 | && test "${dns_prio[$i]}" -gt "$prio" \ | ||
9 | && prio="${dns_prio[$i]}" | ||
10 | let i++; done | ||
11 | |||
12 | i=0; while test "${if[$i]}"; do | ||
13 | if test "${dnsmasq[$i]}"; then | ||
14 | for d in ${dnsmasq[$i]}; do | ||
15 | echo "$d" | ||
16 | empty=false | ||
17 | done | ||
18 | let i++; | ||
19 | continue | ||
20 | fi | ||
21 | # This iface has no dnsmasq-extended config. | ||
22 | # Use simple DNS names instead, if those exist. | ||
23 | for d in ${dns[$i]}; do | ||
24 | p="${dns_prio[$i]}" | ||
25 | test x"$p" == x"" && p=0 | ||
26 | test x"$p" == x"$prio" || continue | ||
27 | echo "server=$d" | ||
28 | empty=false | ||
29 | done | ||
30 | let i++; | ||
31 | done | ||
32 | |||
33 | # Use Google DNS servers if nothing else is configured | ||
34 | $empty && echo "server=8.8.8.8" | ||
35 | $empty && echo "server=8.8.4.4" | ||
36 | |||
37 | # SIGHUP: make dnsmasq reload config | ||
38 | sv h dnsmasq | ||
diff --git a/examples/var_service/ifplugd_if/run b/examples/var_service/ifplugd_if/run index c4f766e88..5d1d4e355 100755 --- a/examples/var_service/ifplugd_if/run +++ b/examples/var_service/ifplugd_if/run | |||
@@ -16,7 +16,7 @@ exec \ | |||
16 | env - PATH="$PATH" \ | 16 | env - PATH="$PATH" \ |
17 | softlimit \ | 17 | softlimit \ |
18 | setuidgid root \ | 18 | setuidgid root \ |
19 | ifplugd -apqns -t3 -u8 -d8 -i "$if" -r "$pwd/ifplugd_handler" | 19 | ifplugd -aqlns -t3 -u8 -d8 -i "$if" -r "$pwd/ifplugd_handler" |
20 | 20 | ||
21 | # We use -t3 to wake ifplugd up less often. | 21 | # We use -t3 to wake ifplugd up less often. |
22 | # If after three tests (3*3=9 > 8) link state seen to be different, | 22 | # If after three tests (3*3=9 > 8) link state seen to be different, |
@@ -24,19 +24,26 @@ ifplugd -apqns -t3 -u8 -d8 -i "$if" -r "$pwd/ifplugd_handler" | |||
24 | # IOW: short link losses will be ignored, longer ones | 24 | # IOW: short link losses will be ignored, longer ones |
25 | # will trigger DHCP reconfiguration and such (see handler code). | 25 | # will trigger DHCP reconfiguration and such (see handler code). |
26 | 26 | ||
27 | #-a Do not up interface automatically | 27 | # -l makes ifplugd run either "up" or "down" script on startup. |
28 | #-p Dont run script on daemon startup | 28 | # For example, if wired eth cable is unplugged, this stops dhcp service |
29 | #-q Dont run script on daemon quit | 29 | # from pointlessly trying to get a lease. |
30 | # -q means that stopping monitoring does not stop dhcp/zcip/etc: | ||
31 | # presumably, admin decided to control them manually. | ||
32 | |||
33 | #-a Don't up interface automatically | ||
34 | #-p Don't run "up" script on startup | ||
35 | #-q Don't run "down" script on exit | ||
36 | #-l Always run script on startup | ||
30 | #-n Do not daemonize | 37 | #-n Do not daemonize |
31 | #-s Do not log to syslog | 38 | #-s Do not log to syslog |
32 | #-t SECS Poll time in seconds | 39 | #-t SECS Poll time in seconds |
33 | #-u SECS Delay before running script after link up | 40 | #-u SECS Delay before running script after link up |
34 | #-d SECS Delay after link down | 41 | #-d SECS Delay after link down |
35 | #-i IFACE Interface | 42 | #-i IFACE Interface |
36 | #-r PROG Script to run | ||
37 | #-f/-F Treat link detection error as link down/link up (otherwise exit on error) | ||
38 | #-M Monitor creation/destruction of interface (otherwise it must exist) | 43 | #-M Monitor creation/destruction of interface (otherwise it must exist) |
44 | #-r PROG Script to run | ||
39 | #-x ARG Extra argument for script | 45 | #-x ARG Extra argument for script |
40 | #-I Dont exit on nonzero exit code from script | 46 | #-I Don't exit on nonzero exit code from script |
41 | #-l Run script on startup even if no cable is detected | 47 | #-f/-F Treat link detection error as link down/link up (otherwise exit on error) |
42 | #-m MODE API mode (mii, priv, ethtool, wlan, auto) | 48 | #-m MODE API mode (mii, priv, ethtool, wlan, auto) |
49 | #-k Kill running daemon | ||
diff --git a/findutils/grep.c b/findutils/grep.c index fc6de4b69..88de0d4ef 100644 --- a/findutils/grep.c +++ b/findutils/grep.c | |||
@@ -352,7 +352,7 @@ static int grep_file(FILE *file) | |||
352 | goto opt_f_not_found; | 352 | goto opt_f_not_found; |
353 | } else | 353 | } else |
354 | if (option_mask32 & OPT_w) { | 354 | if (option_mask32 & OPT_w) { |
355 | char c = (match != str) ? match[-1] : ' '; | 355 | char c = (match != line) ? match[-1] : ' '; |
356 | if (!isalnum(c) && c != '_') { | 356 | if (!isalnum(c) && c != '_') { |
357 | c = match[strlen(gl->pattern)]; | 357 | c = match[strlen(gl->pattern)]; |
358 | if (!c || (!isalnum(c) && c != '_')) | 358 | if (!c || (!isalnum(c) && c != '_')) |
diff --git a/include/libbb.h b/include/libbb.h index 244d85e84..af234e7b0 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -952,7 +952,7 @@ extern void xprint_and_close_file(FILE *file) FAST_FUNC; | |||
952 | * end of line. If end isn't NULL, length of the chunk is stored in it. | 952 | * end of line. If end isn't NULL, length of the chunk is stored in it. |
953 | * Returns NULL if EOF/error. | 953 | * Returns NULL if EOF/error. |
954 | */ | 954 | */ |
955 | extern char *bb_get_chunk_from_file(FILE *file, int *end) FAST_FUNC; | 955 | extern char *bb_get_chunk_from_file(FILE *file, size_t *end) FAST_FUNC; |
956 | /* Reads up to (and including) TERMINATING_STRING: */ | 956 | /* Reads up to (and including) TERMINATING_STRING: */ |
957 | extern char *xmalloc_fgets_str(FILE *file, const char *terminating_string) FAST_FUNC RETURNS_MALLOC; | 957 | extern char *xmalloc_fgets_str(FILE *file, const char *terminating_string) FAST_FUNC RETURNS_MALLOC; |
958 | /* Same, with limited max size, and returns the length (excluding NUL): */ | 958 | /* Same, with limited max size, and returns the length (excluding NUL): */ |
@@ -1325,20 +1325,21 @@ extern smallint syslog_level; | |||
1325 | extern smallint logmode; | 1325 | extern smallint logmode; |
1326 | extern uint8_t xfunc_error_retval; | 1326 | extern uint8_t xfunc_error_retval; |
1327 | extern void (*die_func)(void); | 1327 | extern void (*die_func)(void); |
1328 | extern void xfunc_die(void) NORETURN FAST_FUNC; | 1328 | void xfunc_die(void) NORETURN FAST_FUNC; |
1329 | extern void bb_show_usage(void) NORETURN FAST_FUNC; | 1329 | void bb_show_usage(void) NORETURN FAST_FUNC; |
1330 | extern void bb_error_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2))) FAST_FUNC; | 1330 | void bb_error_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2))) FAST_FUNC; |
1331 | extern void bb_error_msg_and_die(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2))) FAST_FUNC; | 1331 | void bb_error_msg_and_die(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2))) FAST_FUNC; |
1332 | extern void bb_perror_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2))) FAST_FUNC; | 1332 | void bb_perror_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2))) FAST_FUNC; |
1333 | extern void bb_simple_perror_msg(const char *s) FAST_FUNC; | 1333 | void bb_simple_perror_msg(const char *s) FAST_FUNC; |
1334 | extern void bb_perror_msg_and_die(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2))) FAST_FUNC; | 1334 | void bb_perror_msg_and_die(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2))) FAST_FUNC; |
1335 | extern void bb_simple_perror_msg_and_die(const char *s) NORETURN FAST_FUNC; | 1335 | void bb_simple_perror_msg_and_die(const char *s) NORETURN FAST_FUNC; |
1336 | extern void bb_herror_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2))) FAST_FUNC; | 1336 | void bb_herror_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2))) FAST_FUNC; |
1337 | extern void bb_herror_msg_and_die(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2))) FAST_FUNC; | 1337 | void bb_herror_msg_and_die(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2))) FAST_FUNC; |
1338 | extern void bb_perror_nomsg_and_die(void) NORETURN FAST_FUNC; | 1338 | void bb_perror_nomsg_and_die(void) NORETURN FAST_FUNC; |
1339 | extern void bb_perror_nomsg(void) FAST_FUNC; | 1339 | void bb_perror_nomsg(void) FAST_FUNC; |
1340 | extern void bb_verror_msg(const char *s, va_list p, const char *strerr) FAST_FUNC; | 1340 | void bb_verror_msg(const char *s, va_list p, const char *strerr) FAST_FUNC; |
1341 | extern void bb_logenv_override(void) FAST_FUNC; | 1341 | void bb_die_memory_exhausted(void) NORETURN FAST_FUNC; |
1342 | void bb_logenv_override(void) FAST_FUNC; | ||
1342 | 1343 | ||
1343 | /* We need to export XXX_main from libbusybox | 1344 | /* We need to export XXX_main from libbusybox |
1344 | * only if we build "individual" binaries | 1345 | * only if we build "individual" binaries |
diff --git a/libbb/get_line_from_file.c b/libbb/get_line_from_file.c index 4e09ddc80..09ccfba67 100644 --- a/libbb/get_line_from_file.c +++ b/libbb/get_line_from_file.c | |||
@@ -10,16 +10,19 @@ | |||
10 | */ | 10 | */ |
11 | #include "libbb.h" | 11 | #include "libbb.h" |
12 | 12 | ||
13 | char* FAST_FUNC bb_get_chunk_from_file(FILE *file, int *end) | 13 | char* FAST_FUNC bb_get_chunk_from_file(FILE *file, size_t *end) |
14 | { | 14 | { |
15 | int ch; | 15 | int ch; |
16 | unsigned idx = 0; | 16 | size_t idx = 0; |
17 | char *linebuf = NULL; | 17 | char *linebuf = NULL; |
18 | 18 | ||
19 | while ((ch = getc(file)) != EOF) { | 19 | while ((ch = getc(file)) != EOF) { |
20 | /* grow the line buffer as necessary */ | 20 | /* grow the line buffer as necessary */ |
21 | if (!(idx & 0xff)) | 21 | if (!(idx & 0xff)) { |
22 | if (idx == ((size_t)-1) - 0xff) | ||
23 | bb_die_memory_exhausted(); | ||
22 | linebuf = xrealloc(linebuf, idx + 0x100); | 24 | linebuf = xrealloc(linebuf, idx + 0x100); |
25 | } | ||
23 | linebuf[idx++] = (char) ch; | 26 | linebuf[idx++] = (char) ch; |
24 | if (ch == '\0') | 27 | if (ch == '\0') |
25 | break; | 28 | break; |
@@ -44,14 +47,12 @@ char* FAST_FUNC bb_get_chunk_from_file(FILE *file, int *end) | |||
44 | /* Get line, including trailing \n if any */ | 47 | /* Get line, including trailing \n if any */ |
45 | char* FAST_FUNC xmalloc_fgets(FILE *file) | 48 | char* FAST_FUNC xmalloc_fgets(FILE *file) |
46 | { | 49 | { |
47 | int i; | 50 | return bb_get_chunk_from_file(file, NULL); |
48 | |||
49 | return bb_get_chunk_from_file(file, &i); | ||
50 | } | 51 | } |
51 | /* Get line. Remove trailing \n */ | 52 | /* Get line. Remove trailing \n */ |
52 | char* FAST_FUNC xmalloc_fgetline(FILE *file) | 53 | char* FAST_FUNC xmalloc_fgetline(FILE *file) |
53 | { | 54 | { |
54 | int i; | 55 | size_t i; |
55 | char *c = bb_get_chunk_from_file(file, &i); | 56 | char *c = bb_get_chunk_from_file(file, &i); |
56 | 57 | ||
57 | if (i && c[--i] == '\n') | 58 | if (i && c[--i] == '\n') |
diff --git a/libbb/wfopen.c b/libbb/wfopen.c index 20fe18b23..1c7f7f3d7 100644 --- a/libbb/wfopen.c +++ b/libbb/wfopen.c | |||
@@ -42,7 +42,7 @@ static FILE* xfdopen_helper(unsigned fd_and_rw_bit) | |||
42 | { | 42 | { |
43 | FILE* fp = fdopen(fd_and_rw_bit >> 1, fd_and_rw_bit & 1 ? "w" : "r"); | 43 | FILE* fp = fdopen(fd_and_rw_bit >> 1, fd_and_rw_bit & 1 ? "w" : "r"); |
44 | if (!fp) | 44 | if (!fp) |
45 | bb_error_msg_and_die(bb_msg_memory_exhausted); | 45 | bb_die_memory_exhausted(); |
46 | return fp; | 46 | return fp; |
47 | } | 47 | } |
48 | FILE* FAST_FUNC xfdopen_for_read(int fd) | 48 | FILE* FAST_FUNC xfdopen_for_read(int fd) |
diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c index 43ae98065..e8c027f17 100644 --- a/libbb/xfuncs.c +++ b/libbb/xfuncs.c | |||
@@ -59,24 +59,23 @@ char* FAST_FUNC strncpy_IFNAMSIZ(char *dst, const char *src) | |||
59 | * A truncated result contains the first few digits of the result ala strncpy. | 59 | * A truncated result contains the first few digits of the result ala strncpy. |
60 | * Returns a pointer past last generated digit, does _not_ store NUL. | 60 | * Returns a pointer past last generated digit, does _not_ store NUL. |
61 | */ | 61 | */ |
62 | void BUG_sizeof(void); | ||
63 | char* FAST_FUNC utoa_to_buf(unsigned n, char *buf, unsigned buflen) | 62 | char* FAST_FUNC utoa_to_buf(unsigned n, char *buf, unsigned buflen) |
64 | { | 63 | { |
65 | unsigned i, out, res; | 64 | unsigned i, out, res; |
66 | 65 | ||
67 | if (buflen) { | 66 | if (buflen) { |
68 | out = 0; | 67 | out = 0; |
68 | |||
69 | BUILD_BUG_ON(sizeof(n) != 4 && sizeof(n) != 8); | ||
69 | if (sizeof(n) == 4) | 70 | if (sizeof(n) == 4) |
70 | // 2^32-1 = 4294967295 | 71 | // 2^32-1 = 4294967295 |
71 | i = 1000000000; | 72 | i = 1000000000; |
72 | #if UINT_MAX > 4294967295 /* prevents warning about "const too large" */ | 73 | #if UINT_MAX > 0xffffffff /* prevents warning about "const too large" */ |
73 | else | 74 | else |
74 | if (sizeof(n) == 8) | 75 | if (sizeof(n) == 8) |
75 | // 2^64-1 = 18446744073709551615 | 76 | // 2^64-1 = 18446744073709551615 |
76 | i = 10000000000000000000; | 77 | i = 10000000000000000000; |
77 | #endif | 78 | #endif |
78 | else | ||
79 | BUG_sizeof(); | ||
80 | for (; i; i /= 10) { | 79 | for (; i; i /= 10) { |
81 | res = n / i; | 80 | res = n / i; |
82 | n = n % i; | 81 | n = n % i; |
diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c index 7032e5f8f..21263ccfe 100644 --- a/libbb/xfuncs_printf.c +++ b/libbb/xfuncs_printf.c | |||
@@ -25,6 +25,11 @@ | |||
25 | * fail, so callers never need to check for errors. If it returned, it | 25 | * fail, so callers never need to check for errors. If it returned, it |
26 | * succeeded. */ | 26 | * succeeded. */ |
27 | 27 | ||
28 | void FAST_FUNC bb_die_memory_exhausted(void) | ||
29 | { | ||
30 | bb_error_msg_and_die(bb_msg_memory_exhausted); | ||
31 | } | ||
32 | |||
28 | #ifndef DMALLOC | 33 | #ifndef DMALLOC |
29 | /* dmalloc provides variants of these that do abort() on failure. | 34 | /* dmalloc provides variants of these that do abort() on failure. |
30 | * Since dmalloc's prototypes overwrite the impls here as they are | 35 | * Since dmalloc's prototypes overwrite the impls here as they are |
@@ -44,7 +49,7 @@ void* FAST_FUNC xmalloc(size_t size) | |||
44 | { | 49 | { |
45 | void *ptr = malloc(size); | 50 | void *ptr = malloc(size); |
46 | if (ptr == NULL && size != 0) | 51 | if (ptr == NULL && size != 0) |
47 | bb_error_msg_and_die(bb_msg_memory_exhausted); | 52 | bb_die_memory_exhausted(); |
48 | return ptr; | 53 | return ptr; |
49 | } | 54 | } |
50 | 55 | ||
@@ -55,7 +60,7 @@ void* FAST_FUNC xrealloc(void *ptr, size_t size) | |||
55 | { | 60 | { |
56 | ptr = realloc(ptr, size); | 61 | ptr = realloc(ptr, size); |
57 | if (ptr == NULL && size != 0) | 62 | if (ptr == NULL && size != 0) |
58 | bb_error_msg_and_die(bb_msg_memory_exhausted); | 63 | bb_die_memory_exhausted(); |
59 | return ptr; | 64 | return ptr; |
60 | } | 65 | } |
61 | #endif /* DMALLOC */ | 66 | #endif /* DMALLOC */ |
@@ -79,7 +84,7 @@ char* FAST_FUNC xstrdup(const char *s) | |||
79 | t = strdup(s); | 84 | t = strdup(s); |
80 | 85 | ||
81 | if (t == NULL) | 86 | if (t == NULL) |
82 | bb_error_msg_and_die(bb_msg_memory_exhausted); | 87 | bb_die_memory_exhausted(); |
83 | 88 | ||
84 | return t; | 89 | return t; |
85 | } | 90 | } |
@@ -327,14 +332,14 @@ char* FAST_FUNC xasprintf(const char *format, ...) | |||
327 | va_end(p); | 332 | va_end(p); |
328 | 333 | ||
329 | if (r < 0) | 334 | if (r < 0) |
330 | bb_error_msg_and_die(bb_msg_memory_exhausted); | 335 | bb_die_memory_exhausted(); |
331 | return string_ptr; | 336 | return string_ptr; |
332 | } | 337 | } |
333 | 338 | ||
334 | void FAST_FUNC xsetenv(const char *key, const char *value) | 339 | void FAST_FUNC xsetenv(const char *key, const char *value) |
335 | { | 340 | { |
336 | if (setenv(key, value, 1)) | 341 | if (setenv(key, value, 1)) |
337 | bb_error_msg_and_die(bb_msg_memory_exhausted); | 342 | bb_die_memory_exhausted(); |
338 | } | 343 | } |
339 | 344 | ||
340 | /* Handles "VAR=VAL" strings, even those which are part of environ | 345 | /* Handles "VAR=VAL" strings, even those which are part of environ |
diff --git a/miscutils/fbsplash.c b/miscutils/fbsplash.c index 5b2e5ac56..bc3c61055 100644 --- a/miscutils/fbsplash.c +++ b/miscutils/fbsplash.c | |||
@@ -54,7 +54,7 @@ | |||
54 | //usage: "\n -d Framebuffer device (default /dev/fb0)" | 54 | //usage: "\n -d Framebuffer device (default /dev/fb0)" |
55 | //usage: "\n -i Config file (var=value):" | 55 | //usage: "\n -i Config file (var=value):" |
56 | //usage: "\n BAR_LEFT,BAR_TOP,BAR_WIDTH,BAR_HEIGHT" | 56 | //usage: "\n BAR_LEFT,BAR_TOP,BAR_WIDTH,BAR_HEIGHT" |
57 | //usage: "\n BAR_R,BAR_G,BAR_B" | 57 | //usage: "\n BAR_R,BAR_G,BAR_B,IMG_LEFT,IMG_TOP" |
58 | //usage: "\n -f Control pipe (else exit after drawing image)" | 58 | //usage: "\n -f Control pipe (else exit after drawing image)" |
59 | //usage: "\n commands: 'NN' (% for progress bar) or 'exit'" | 59 | //usage: "\n commands: 'NN' (% for progress bar) or 'exit'" |
60 | 60 | ||
@@ -73,7 +73,7 @@ struct globals { | |||
73 | FILE *logfile_fd; // log file | 73 | FILE *logfile_fd; // log file |
74 | #endif | 74 | #endif |
75 | unsigned char *addr; // pointer to framebuffer memory | 75 | unsigned char *addr; // pointer to framebuffer memory |
76 | unsigned ns[7]; // n-parameters | 76 | unsigned ns[9]; // n-parameters |
77 | const char *image_filename; | 77 | const char *image_filename; |
78 | struct fb_var_screeninfo scr_var; | 78 | struct fb_var_screeninfo scr_var; |
79 | struct fb_fix_screeninfo scr_fix; | 79 | struct fb_fix_screeninfo scr_fix; |
@@ -95,6 +95,8 @@ struct globals { | |||
95 | #define nbar_colr ns[4] // progress bar color red component | 95 | #define nbar_colr ns[4] // progress bar color red component |
96 | #define nbar_colg ns[5] // progress bar color green component | 96 | #define nbar_colg ns[5] // progress bar color green component |
97 | #define nbar_colb ns[6] // progress bar color blue component | 97 | #define nbar_colb ns[6] // progress bar color blue component |
98 | #define img_posx ns[7] // image horizontal position | ||
99 | #define img_posy ns[8] // image vertical position | ||
98 | 100 | ||
99 | #if DEBUG | 101 | #if DEBUG |
100 | #define DEBUG_MESSAGE(strMessage, args...) \ | 102 | #define DEBUG_MESSAGE(strMessage, args...) \ |
@@ -426,10 +428,10 @@ static void fb_drawimage(void) | |||
426 | line_size = width*3; | 428 | line_size = width*3; |
427 | pixline = xmalloc(line_size); | 429 | pixline = xmalloc(line_size); |
428 | 430 | ||
429 | if (width > G.scr_var.xres) | 431 | if ((width + G.img_posx) > G.scr_var.xres) |
430 | width = G.scr_var.xres; | 432 | width = G.scr_var.xres - G.img_posx; |
431 | if (height > G.scr_var.yres) | 433 | if ((height + G.img_posy) > G.scr_var.yres) |
432 | height = G.scr_var.yres; | 434 | height = G.scr_var.yres - G.img_posy; |
433 | for (j = 0; j < height; j++) { | 435 | for (j = 0; j < height; j++) { |
434 | unsigned char *pixel; | 436 | unsigned char *pixel; |
435 | unsigned char *src; | 437 | unsigned char *src; |
@@ -437,7 +439,7 @@ static void fb_drawimage(void) | |||
437 | if (fread(pixline, 1, line_size, theme_file) != line_size) | 439 | if (fread(pixline, 1, line_size, theme_file) != line_size) |
438 | bb_error_msg_and_die("bad PPM file '%s'", G.image_filename); | 440 | bb_error_msg_and_die("bad PPM file '%s'", G.image_filename); |
439 | pixel = pixline; | 441 | pixel = pixline; |
440 | src = G.addr + j * G.scr_fix.line_length; | 442 | src = G.addr + (G.img_posy + j) * G.scr_fix.line_length + G.img_posx * G.bytes_per_pixel; |
441 | for (i = 0; i < width; i++) { | 443 | for (i = 0; i < width; i++) { |
442 | unsigned thispix = fb_pixel_value(pixel[0], pixel[1], pixel[2]); | 444 | unsigned thispix = fb_pixel_value(pixel[0], pixel[1], pixel[2]); |
443 | fb_write_pixel(src, thispix); | 445 | fb_write_pixel(src, thispix); |
@@ -460,6 +462,7 @@ static void init(const char *cfg_filename) | |||
460 | "BAR_WIDTH\0" "BAR_HEIGHT\0" | 462 | "BAR_WIDTH\0" "BAR_HEIGHT\0" |
461 | "BAR_LEFT\0" "BAR_TOP\0" | 463 | "BAR_LEFT\0" "BAR_TOP\0" |
462 | "BAR_R\0" "BAR_G\0" "BAR_B\0" | 464 | "BAR_R\0" "BAR_G\0" "BAR_B\0" |
465 | "IMG_LEFT\0" "IMG_TOP\0" | ||
463 | #if DEBUG | 466 | #if DEBUG |
464 | "DEBUG\0" | 467 | "DEBUG\0" |
465 | #endif | 468 | #endif |
@@ -472,10 +475,10 @@ static void init(const char *cfg_filename) | |||
472 | int i = index_in_strings(param_names, token[0]); | 475 | int i = index_in_strings(param_names, token[0]); |
473 | if (i < 0) | 476 | if (i < 0) |
474 | bb_error_msg_and_die("syntax error: %s", token[0]); | 477 | bb_error_msg_and_die("syntax error: %s", token[0]); |
475 | if (i >= 0 && i < 7) | 478 | if (i >= 0 && i < 9) |
476 | G.ns[i] = val; | 479 | G.ns[i] = val; |
477 | #if DEBUG | 480 | #if DEBUG |
478 | if (i == 7) { | 481 | if (i == 9) { |
479 | G.bdebug_messages = val; | 482 | G.bdebug_messages = val; |
480 | if (G.bdebug_messages) | 483 | if (G.bdebug_messages) |
481 | G.logfile_fd = xfopen_for_write("/tmp/fbsplash.log"); | 484 | G.logfile_fd = xfopen_for_write("/tmp/fbsplash.log"); |
diff --git a/networking/ifplugd.c b/networking/ifplugd.c index 9bc1a075f..5059eaf73 100644 --- a/networking/ifplugd.c +++ b/networking/ifplugd.c | |||
@@ -367,7 +367,7 @@ static void up_iface(void) | |||
367 | /* Let user know we mess up with interface */ | 367 | /* Let user know we mess up with interface */ |
368 | bb_error_msg("upping interface"); | 368 | bb_error_msg("upping interface"); |
369 | if (network_ioctl(SIOCSIFFLAGS, &ifrequest, "setting interface flags") < 0) { | 369 | if (network_ioctl(SIOCSIFFLAGS, &ifrequest, "setting interface flags") < 0) { |
370 | if (errno != ENODEV) | 370 | if (errno != ENODEV && errno != EADDRNOTAVAIL) |
371 | xfunc_die(); | 371 | xfunc_die(); |
372 | G.iface_exists = 0; | 372 | G.iface_exists = 0; |
373 | return; | 373 | return; |
diff --git a/networking/ifupdown.c b/networking/ifupdown.c index 534c9f0c7..5481134e5 100644 --- a/networking/ifupdown.c +++ b/networking/ifupdown.c | |||
@@ -138,6 +138,7 @@ | |||
138 | //usage: "\n -v Print out what would happen before doing it" | 138 | //usage: "\n -v Print out what would happen before doing it" |
139 | //usage: "\n -f Force deconfiguration" | 139 | //usage: "\n -f Force deconfiguration" |
140 | 140 | ||
141 | #include <net/if.h> | ||
141 | #include "libbb.h" | 142 | #include "libbb.h" |
142 | #include "common_bufsiz.h" | 143 | #include "common_bufsiz.h" |
143 | /* After libbb.h, since it needs sys/types.h on some systems */ | 144 | /* After libbb.h, since it needs sys/types.h on some systems */ |
@@ -503,6 +504,8 @@ static int FAST_FUNC static_up6(struct interface_defn_t *ifd, execfn *exec) | |||
503 | 504 | ||
504 | static int FAST_FUNC static_down6(struct interface_defn_t *ifd, execfn *exec) | 505 | static int FAST_FUNC static_down6(struct interface_defn_t *ifd, execfn *exec) |
505 | { | 506 | { |
507 | if (!if_nametoindex(ifd->iface)) | ||
508 | return 1; /* already gone */ | ||
506 | # if ENABLE_FEATURE_IFUPDOWN_IP | 509 | # if ENABLE_FEATURE_IFUPDOWN_IP |
507 | return execute("ip link set %iface% down", ifd, exec); | 510 | return execute("ip link set %iface% down", ifd, exec); |
508 | # else | 511 | # else |
@@ -598,6 +601,9 @@ static int FAST_FUNC static_up(struct interface_defn_t *ifd, execfn *exec) | |||
598 | static int FAST_FUNC static_down(struct interface_defn_t *ifd, execfn *exec) | 601 | static int FAST_FUNC static_down(struct interface_defn_t *ifd, execfn *exec) |
599 | { | 602 | { |
600 | int result; | 603 | int result; |
604 | |||
605 | if (!if_nametoindex(ifd->iface)) | ||
606 | return 2; /* already gone */ | ||
601 | # if ENABLE_FEATURE_IFUPDOWN_IP | 607 | # if ENABLE_FEATURE_IFUPDOWN_IP |
602 | /* Optional "label LBL" is necessary if interface is an alias (eth0:0), | 608 | /* Optional "label LBL" is necessary if interface is an alias (eth0:0), |
603 | * otherwise "ip addr flush dev eth0:0" flushes all addresses on eth0. | 609 | * otherwise "ip addr flush dev eth0:0" flushes all addresses on eth0. |
diff --git a/networking/libiproute/iplink.c b/networking/libiproute/iplink.c index 2aa8b683b..9c164a71d 100644 --- a/networking/libiproute/iplink.c +++ b/networking/libiproute/iplink.c | |||
@@ -161,7 +161,7 @@ static int get_address(char *dev, int *htype) | |||
161 | 161 | ||
162 | s = xsocket(PF_PACKET, SOCK_DGRAM, 0); | 162 | s = xsocket(PF_PACKET, SOCK_DGRAM, 0); |
163 | 163 | ||
164 | memset(&ifr, 0, sizeof(ifr)); | 164 | /*memset(&ifr, 0, sizeof(ifr)); - SIOCGIFINDEX does not need to clear all */ |
165 | strncpy_IFNAMSIZ(ifr.ifr_name, dev); | 165 | strncpy_IFNAMSIZ(ifr.ifr_name, dev); |
166 | xioctl(s, SIOCGIFINDEX, &ifr); | 166 | xioctl(s, SIOCGIFINDEX, &ifr); |
167 | 167 | ||
diff --git a/networking/netstat.c b/networking/netstat.c index 33281e333..f6bcd44ba 100644 --- a/networking/netstat.c +++ b/networking/netstat.c | |||
@@ -397,8 +397,11 @@ static char *ip_port_str(struct sockaddr *addr, int port, const char *proto, int | |||
397 | /* Code which used "*" for INADDR_ANY is removed: it's ambiguous | 397 | /* Code which used "*" for INADDR_ANY is removed: it's ambiguous |
398 | * in IPv6, while "0.0.0.0" is not. */ | 398 | * in IPv6, while "0.0.0.0" is not. */ |
399 | 399 | ||
400 | host = numeric ? xmalloc_sockaddr2dotted_noport(addr) | 400 | host = NULL; |
401 | : xmalloc_sockaddr2host_noport(addr); | 401 | if (!numeric) |
402 | host = xmalloc_sockaddr2host_noport(addr); | ||
403 | if (!host) | ||
404 | host = xmalloc_sockaddr2dotted_noport(addr); | ||
402 | 405 | ||
403 | host_port = xasprintf("%s:%s", host, get_sname(htons(port), proto, numeric)); | 406 | host_port = xasprintf("%s:%s", host, get_sname(htons(port), proto, numeric)); |
404 | free(host); | 407 | free(host); |
diff --git a/networking/route.c b/networking/route.c index 6edc0f6d7..8387ce1bb 100644 --- a/networking/route.c +++ b/networking/route.c | |||
@@ -444,7 +444,7 @@ static NOINLINE void INET6_setroute(int action, char **args) | |||
444 | 444 | ||
445 | if (devname) { | 445 | if (devname) { |
446 | struct ifreq ifr; | 446 | struct ifreq ifr; |
447 | memset(&ifr, 0, sizeof(ifr)); | 447 | /*memset(&ifr, 0, sizeof(ifr)); - SIOCGIFINDEX does not need to clear all */ |
448 | strncpy_IFNAMSIZ(ifr.ifr_name, devname); | 448 | strncpy_IFNAMSIZ(ifr.ifr_name, devname); |
449 | xioctl(skfd, SIOCGIFINDEX, &ifr); | 449 | xioctl(skfd, SIOCGIFINDEX, &ifr); |
450 | rt.rtmsg_ifindex = ifr.ifr_ifindex; | 450 | rt.rtmsg_ifindex = ifr.ifr_ifindex; |
diff --git a/networking/ssl_client.c b/networking/ssl_client.c index e56d82fc1..49aec6b99 100644 --- a/networking/ssl_client.c +++ b/networking/ssl_client.c | |||
@@ -41,7 +41,6 @@ int ssl_client_main(int argc UNUSED_PARAM, char **argv) | |||
41 | tls = new_tls_state(); | 41 | tls = new_tls_state(); |
42 | #if !ENABLE_PLATFORM_MINGW32 | 42 | #if !ENABLE_PLATFORM_MINGW32 |
43 | opt = getopt32(argv, "es:+r:+n:", &tls->ofd, &tls->ifd, &sni); | 43 | opt = getopt32(argv, "es:+r:+n:", &tls->ofd, &tls->ifd, &sni); |
44 | |||
45 | if (!(opt & (1<<2))) { | 44 | if (!(opt & (1<<2))) { |
46 | /* -r N defaults to -s N */ | 45 | /* -r N defaults to -s N */ |
47 | tls->ifd = tls->ofd; | 46 | tls->ifd = tls->ofd; |
diff --git a/networking/udhcp/d6_socket.c b/networking/udhcp/d6_socket.c index 315c8d98a..6ad53a9c2 100644 --- a/networking/udhcp/d6_socket.c +++ b/networking/udhcp/d6_socket.c | |||
@@ -63,7 +63,7 @@ int FAST_FUNC d6_read_interface(const char *interface, int *ifindex, struct in6_ | |||
63 | struct ifreq ifr; | 63 | struct ifreq ifr; |
64 | int fd; | 64 | int fd; |
65 | 65 | ||
66 | memset(&ifr, 0, sizeof(ifr)); | 66 | /*memset(&ifr, 0, sizeof(ifr)); - SIOCGIFINDEX does not need to clear all */ |
67 | strncpy_IFNAMSIZ(ifr.ifr_name, interface); | 67 | strncpy_IFNAMSIZ(ifr.ifr_name, interface); |
68 | fd = xsocket(AF_INET6, SOCK_RAW, IPPROTO_RAW); | 68 | fd = xsocket(AF_INET6, SOCK_RAW, IPPROTO_RAW); |
69 | if (ioctl(fd, SIOCGIFINDEX, &ifr) == 0) { | 69 | if (ioctl(fd, SIOCGIFINDEX, &ifr) == 0) { |
diff --git a/networking/wget.c b/networking/wget.c index 194bf457a..aaa068ba9 100644 --- a/networking/wget.c +++ b/networking/wget.c | |||
@@ -409,7 +409,7 @@ static FILE *open_socket(len_and_sockaddr *lsa) | |||
409 | /* hopefully it understands what ESPIPE means... */ | 409 | /* hopefully it understands what ESPIPE means... */ |
410 | fp = fdopen(fd, "r+"); | 410 | fp = fdopen(fd, "r+"); |
411 | if (!fp) | 411 | if (!fp) |
412 | bb_perror_msg_and_die(bb_msg_memory_exhausted); | 412 | bb_die_memory_exhausted(); |
413 | 413 | ||
414 | return fp; | 414 | return fp; |
415 | } | 415 | } |
@@ -1146,7 +1146,7 @@ static void download_one_url(const char *url) | |||
1146 | # endif | 1146 | # endif |
1147 | sfp = fdopen(fd, "r+"); | 1147 | sfp = fdopen(fd, "r+"); |
1148 | if (!sfp) | 1148 | if (!sfp) |
1149 | bb_perror_msg_and_die(bb_msg_memory_exhausted); | 1149 | bb_die_memory_exhausted(); |
1150 | goto socket_opened; | 1150 | goto socket_opened; |
1151 | } | 1151 | } |
1152 | sfp = open_socket(lsa); | 1152 | sfp = open_socket(lsa); |
diff --git a/procps/top.c b/procps/top.c index 075c96c27..1b49a5e6b 100644 --- a/procps/top.c +++ b/procps/top.c | |||
@@ -1157,7 +1157,7 @@ int top_main(int argc UNUSED_PARAM, char **argv) | |||
1157 | #endif | 1157 | #endif |
1158 | 1158 | ||
1159 | while (scan_mask != EXIT_MASK) { | 1159 | while (scan_mask != EXIT_MASK) { |
1160 | unsigned new_mask; | 1160 | IF_FEATURE_TOP_INTERACTIVE(unsigned new_mask;) |
1161 | procps_status_t *p = NULL; | 1161 | procps_status_t *p = NULL; |
1162 | 1162 | ||
1163 | if (OPT_BATCH_MODE) { | 1163 | if (OPT_BATCH_MODE) { |
diff --git a/runit/sv.c b/runit/sv.c index dc5dcceb3..86d181872 100644 --- a/runit/sv.c +++ b/runit/sv.c | |||
@@ -163,7 +163,7 @@ Exit Codes | |||
163 | //config:config SV_DEFAULT_SERVICE_DIR | 163 | //config:config SV_DEFAULT_SERVICE_DIR |
164 | //config: string "Default directory for services" | 164 | //config: string "Default directory for services" |
165 | //config: default "/var/service" | 165 | //config: default "/var/service" |
166 | //config: depends on SV | 166 | //config: depends on SV || SVC || SVOK |
167 | //config: help | 167 | //config: help |
168 | //config: Default directory for services. | 168 | //config: Default directory for services. |
169 | //config: Defaults to "/var/service" | 169 | //config: Defaults to "/var/service" |
@@ -173,13 +173,22 @@ Exit Codes | |||
173 | //config: default y | 173 | //config: default y |
174 | //config: help | 174 | //config: help |
175 | //config: svc controls the state of services monitored by the runsv supervisor. | 175 | //config: svc controls the state of services monitored by the runsv supervisor. |
176 | //config: It is comaptible with daemontools command with the same name. | 176 | //config: It is compatible with daemontools command with the same name. |
177 | //config: | ||
178 | //config:config SVOK | ||
179 | //config: bool "svok" | ||
180 | //config: default y | ||
181 | //config: help | ||
182 | //config: svok checks whether runsv supervisor is running. | ||
183 | //config: It is compatible with daemontools command with the same name. | ||
177 | 184 | ||
178 | //applet:IF_SV( APPLET_NOEXEC(sv, sv, BB_DIR_USR_BIN, BB_SUID_DROP, sv )) | 185 | //applet:IF_SV( APPLET_NOEXEC(sv, sv, BB_DIR_USR_BIN, BB_SUID_DROP, sv )) |
179 | //applet:IF_SVC(APPLET_NOEXEC(svc, svc, BB_DIR_USR_BIN, BB_SUID_DROP, svc)) | 186 | //applet:IF_SVC( APPLET_NOEXEC(svc, svc, BB_DIR_USR_BIN, BB_SUID_DROP, svc )) |
187 | //applet:IF_SVOK(APPLET_NOEXEC(svok, svok, BB_DIR_USR_BIN, BB_SUID_DROP, svok)) | ||
180 | 188 | ||
181 | //kbuild:lib-$(CONFIG_SV) += sv.o | 189 | //kbuild:lib-$(CONFIG_SV) += sv.o |
182 | //kbuild:lib-$(CONFIG_SVC) += sv.o | 190 | //kbuild:lib-$(CONFIG_SVC) += sv.o |
191 | //kbuild:lib-$(CONFIG_SVOK) += sv.o | ||
183 | 192 | ||
184 | #include <sys/file.h> | 193 | #include <sys/file.h> |
185 | #include "libbb.h" | 194 | #include "libbb.h" |
@@ -615,7 +624,7 @@ static int sv(char **argv) | |||
615 | service = argv; | 624 | service = argv; |
616 | while ((x = *service) != NULL) { | 625 | while ((x = *service) != NULL) { |
617 | if (x[0] != '/' && x[0] != '.' | 626 | if (x[0] != '/' && x[0] != '.' |
618 | && x[0] != '\0' && x[strlen(x) - 1] != '/' | 627 | && !last_char_is(x, '/') |
619 | ) { | 628 | ) { |
620 | if (chdir(varservice) == -1) | 629 | if (chdir(varservice) == -1) |
621 | goto chdir_failed_0; | 630 | goto chdir_failed_0; |
@@ -742,3 +751,41 @@ int svc_main(int argc UNUSED_PARAM, char **argv) | |||
742 | return 0; | 751 | return 0; |
743 | } | 752 | } |
744 | #endif | 753 | #endif |
754 | |||
755 | //usage:#define svok_trivial_usage | ||
756 | //usage: "SERVICE_DIR" | ||
757 | //usage:#define svok_full_usage "\n\n" | ||
758 | //usage: "Check whether runsv supervisor is running.\n" | ||
759 | //usage: "Exit code is 0 if it does, 100 if it does not,\n" | ||
760 | //usage: "111 (with error message) if SERVICE_DIR does not exist." | ||
761 | #if ENABLE_SVOK | ||
762 | int svok_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | ||
763 | int svok_main(int argc UNUSED_PARAM, char **argv) | ||
764 | { | ||
765 | const char *dir = argv[1]; | ||
766 | |||
767 | if (!dir) | ||
768 | bb_show_usage(); | ||
769 | |||
770 | xfunc_error_retval = 111; | ||
771 | |||
772 | /* | ||
773 | * daemontools has no concept of "default service dir", runit does. | ||
774 | * Let's act as runit. | ||
775 | */ | ||
776 | if (dir[0] != '/' && dir[0] != '.' | ||
777 | && !last_char_is(dir, '/') | ||
778 | ) { | ||
779 | xchdir(CONFIG_SV_DEFAULT_SERVICE_DIR); | ||
780 | } | ||
781 | |||
782 | xchdir(dir); | ||
783 | if (open("supervise/ok", O_WRONLY) < 0) { | ||
784 | if (errno == ENOENT || errno == ENXIO) | ||
785 | return 100; | ||
786 | bb_perror_msg_and_die("can't open '%s'", "supervise/ok"); | ||
787 | } | ||
788 | |||
789 | return 0; | ||
790 | } | ||
791 | #endif | ||
diff --git a/shell/ash.c b/shell/ash.c index 2ab46576c..7448b668a 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -282,6 +282,12 @@ typedef long arith_t; | |||
282 | # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__ | 282 | # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__ |
283 | #endif | 283 | #endif |
284 | 284 | ||
285 | #ifndef F_DUPFD_CLOEXEC | ||
286 | # define F_DUPFD_CLOEXEC F_DUPFD | ||
287 | #endif | ||
288 | #ifndef O_CLOEXEC | ||
289 | # define O_CLOEXEC 0 | ||
290 | #endif | ||
285 | #ifndef PIPE_BUF | 291 | #ifndef PIPE_BUF |
286 | # define PIPE_BUF 4096 /* amount of buffering in a pipe */ | 292 | # define PIPE_BUF 4096 /* amount of buffering in a pipe */ |
287 | #endif | 293 | #endif |
@@ -4196,12 +4202,13 @@ setjobctl(int on) | |||
4196 | goto out; | 4202 | goto out; |
4197 | } | 4203 | } |
4198 | /* fd is a tty at this point */ | 4204 | /* fd is a tty at this point */ |
4199 | fd = fcntl(fd, F_DUPFD, 10); | 4205 | fd = fcntl(fd, F_DUPFD_CLOEXEC, 10); |
4200 | if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */ | 4206 | if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */ |
4201 | close(ofd); | 4207 | close(ofd); |
4202 | if (fd < 0) | 4208 | if (fd < 0) |
4203 | goto out; /* F_DUPFD failed */ | 4209 | goto out; /* F_DUPFD failed */ |
4204 | close_on_exec_on(fd); | 4210 | if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */ |
4211 | close_on_exec_on(fd); | ||
4205 | while (1) { /* while we are in the background */ | 4212 | while (1) { /* while we are in the background */ |
4206 | pgrp = tcgetpgrp(fd); | 4213 | pgrp = tcgetpgrp(fd); |
4207 | if (pgrp < 0) { | 4214 | if (pgrp < 0) { |
@@ -5791,13 +5798,14 @@ savefd(int from) | |||
5791 | int newfd; | 5798 | int newfd; |
5792 | int err; | 5799 | int err; |
5793 | 5800 | ||
5794 | newfd = fcntl(from, F_DUPFD, 10); | 5801 | newfd = fcntl(from, F_DUPFD_CLOEXEC, 10); |
5795 | err = newfd < 0 ? errno : 0; | 5802 | err = newfd < 0 ? errno : 0; |
5796 | if (err != EBADF) { | 5803 | if (err != EBADF) { |
5797 | if (err) | 5804 | if (err) |
5798 | ash_msg_and_raise_perror("%d", from); | 5805 | ash_msg_and_raise_perror("%d", from); |
5799 | close(from); | 5806 | close(from); |
5800 | fcntl(newfd, F_SETFD, FD_CLOEXEC); | 5807 | if (F_DUPFD_CLOEXEC == F_DUPFD) |
5808 | close_on_exec_on(newfd); | ||
5801 | } | 5809 | } |
5802 | 5810 | ||
5803 | return newfd; | 5811 | return newfd; |
@@ -5815,12 +5823,15 @@ dup2_or_raise(int from, int to) | |||
5815 | return newfd; | 5823 | return newfd; |
5816 | } | 5824 | } |
5817 | static int | 5825 | static int |
5818 | fcntl_F_DUPFD(int fd, int avoid_fd) | 5826 | dup_CLOEXEC(int fd, int avoid_fd) |
5819 | { | 5827 | { |
5820 | int newfd; | 5828 | int newfd; |
5821 | repeat: | 5829 | repeat: |
5822 | newfd = fcntl(fd, F_DUPFD, avoid_fd + 1); | 5830 | newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1); |
5823 | if (newfd < 0) { | 5831 | if (newfd >= 0) { |
5832 | if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */ | ||
5833 | close_on_exec_on(newfd); | ||
5834 | } else { /* newfd < 0 */ | ||
5824 | if (errno == EBUSY) | 5835 | if (errno == EBUSY) |
5825 | goto repeat; | 5836 | goto repeat; |
5826 | if (errno == EINTR) | 5837 | if (errno == EINTR) |
@@ -5833,7 +5844,7 @@ xdup_CLOEXEC_and_close(int fd, int avoid_fd) | |||
5833 | { | 5844 | { |
5834 | int newfd; | 5845 | int newfd; |
5835 | repeat: | 5846 | repeat: |
5836 | newfd = fcntl(fd, F_DUPFD, avoid_fd + 1); | 5847 | newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1); |
5837 | if (newfd < 0) { | 5848 | if (newfd < 0) { |
5838 | if (errno == EBUSY) | 5849 | if (errno == EBUSY) |
5839 | goto repeat; | 5850 | goto repeat; |
@@ -5844,7 +5855,8 @@ xdup_CLOEXEC_and_close(int fd, int avoid_fd) | |||
5844 | return fd; | 5855 | return fd; |
5845 | ash_msg_and_raise_perror("%d", newfd); | 5856 | ash_msg_and_raise_perror("%d", newfd); |
5846 | } | 5857 | } |
5847 | fcntl(newfd, F_SETFD, FD_CLOEXEC); | 5858 | if (F_DUPFD_CLOEXEC == F_DUPFD) |
5859 | close_on_exec_on(newfd); | ||
5848 | close(fd); | 5860 | close(fd); |
5849 | return newfd; | 5861 | return newfd; |
5850 | } | 5862 | } |
@@ -5936,7 +5948,7 @@ save_fd_on_redirect(int fd, int avoid_fd, struct redirtab *sq) | |||
5936 | for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) { | 5948 | for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) { |
5937 | /* If we collide with an already moved fd... */ | 5949 | /* If we collide with an already moved fd... */ |
5938 | if (fd == sq->two_fd[i].moved_to) { | 5950 | if (fd == sq->two_fd[i].moved_to) { |
5939 | new_fd = fcntl_F_DUPFD(fd, avoid_fd); | 5951 | new_fd = dup_CLOEXEC(fd, avoid_fd); |
5940 | sq->two_fd[i].moved_to = new_fd; | 5952 | sq->two_fd[i].moved_to = new_fd; |
5941 | TRACE(("redirect_fd %d: already busy, moving to %d\n", fd, new_fd)); | 5953 | TRACE(("redirect_fd %d: already busy, moving to %d\n", fd, new_fd)); |
5942 | if (new_fd < 0) /* what? */ | 5954 | if (new_fd < 0) /* what? */ |
@@ -5951,7 +5963,7 @@ save_fd_on_redirect(int fd, int avoid_fd, struct redirtab *sq) | |||
5951 | } | 5963 | } |
5952 | 5964 | ||
5953 | /* If this fd is open, we move and remember it; if it's closed, new_fd = CLOSED (-1) */ | 5965 | /* If this fd is open, we move and remember it; if it's closed, new_fd = CLOSED (-1) */ |
5954 | new_fd = fcntl_F_DUPFD(fd, avoid_fd); | 5966 | new_fd = dup_CLOEXEC(fd, avoid_fd); |
5955 | TRACE(("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, new_fd)); | 5967 | TRACE(("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, new_fd)); |
5956 | if (new_fd < 0) { | 5968 | if (new_fd < 0) { |
5957 | if (errno != EBADF) | 5969 | if (errno != EBADF) |
@@ -7559,7 +7571,7 @@ varvalue(char *name, int varflags, int flags, int *quotedp) | |||
7559 | case '-': | 7571 | case '-': |
7560 | expdest = makestrspace(NOPTS, expdest); | 7572 | expdest = makestrspace(NOPTS, expdest); |
7561 | for (i = NOPTS - 1; i >= 0; i--) { | 7573 | for (i = NOPTS - 1; i >= 0; i--) { |
7562 | if (optlist[i]) { | 7574 | if (optlist[i] && optletters(i)) { |
7563 | USTPUTC(optletters(i), expdest); | 7575 | USTPUTC(optletters(i), expdest); |
7564 | len++; | 7576 | len++; |
7565 | } | 7577 | } |
@@ -7806,13 +7818,13 @@ hasmeta(const char *p) | |||
7806 | p = strpbrk(p, chars); | 7818 | p = strpbrk(p, chars); |
7807 | if (!p) | 7819 | if (!p) |
7808 | break; | 7820 | break; |
7809 | switch ((unsigned char) *p) { | 7821 | switch ((unsigned char)*p) { |
7810 | case CTLQUOTEMARK: | 7822 | case CTLQUOTEMARK: |
7811 | for (;;) { | 7823 | for (;;) { |
7812 | p++; | 7824 | p++; |
7813 | if (*p == CTLQUOTEMARK) | 7825 | if ((unsigned char)*p == CTLQUOTEMARK) |
7814 | break; | 7826 | break; |
7815 | if (*p == CTLESC) | 7827 | if ((unsigned char)*p == CTLESC) |
7816 | p++; | 7828 | p++; |
7817 | if (*p == '\0') /* huh? */ | 7829 | if (*p == '\0') /* huh? */ |
7818 | return 0; | 7830 | return 0; |
@@ -11262,7 +11274,7 @@ setinputfile(const char *fname, int flags) | |||
11262 | int fd; | 11274 | int fd; |
11263 | 11275 | ||
11264 | INT_OFF; | 11276 | INT_OFF; |
11265 | fd = open(fname, O_RDONLY); | 11277 | fd = open(fname, O_RDONLY | O_CLOEXEC); |
11266 | if (fd < 0) { | 11278 | if (fd < 0) { |
11267 | if (flags & INPUT_NOFILE_OK) | 11279 | if (flags & INPUT_NOFILE_OK) |
11268 | goto out; | 11280 | goto out; |
@@ -11271,8 +11283,9 @@ setinputfile(const char *fname, int flags) | |||
11271 | } | 11283 | } |
11272 | if (fd < 10) | 11284 | if (fd < 10) |
11273 | fd = savefd(fd); | 11285 | fd = savefd(fd); |
11274 | else | 11286 | else if (O_CLOEXEC == 0) /* old libc */ |
11275 | close_on_exec_on(fd); | 11287 | close_on_exec_on(fd); |
11288 | |||
11276 | setinputfd(fd, flags & INPUT_PUSH_FILE); | 11289 | setinputfd(fd, flags & INPUT_PUSH_FILE); |
11277 | out: | 11290 | out: |
11278 | INT_ON; | 11291 | INT_ON; |
@@ -12595,6 +12608,12 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) | |||
12595 | break; | 12608 | break; |
12596 | #endif | 12609 | #endif |
12597 | case CBQUOTE: /* '`' */ | 12610 | case CBQUOTE: /* '`' */ |
12611 | if (checkkwd & CHKEOFMARK) { | ||
12612 | quotef = 1; | ||
12613 | USTPUTC('`', out); | ||
12614 | break; | ||
12615 | } | ||
12616 | |||
12598 | PARSEBACKQOLD(); | 12617 | PARSEBACKQOLD(); |
12599 | break; | 12618 | break; |
12600 | case CENDFILE: | 12619 | case CENDFILE: |
@@ -12727,7 +12746,7 @@ parseredir: { | |||
12727 | np = stzalloc(sizeof(struct nfile)); | 12746 | np = stzalloc(sizeof(struct nfile)); |
12728 | if (c == '>') { | 12747 | if (c == '>') { |
12729 | np->nfile.fd = 1; | 12748 | np->nfile.fd = 1; |
12730 | c = pgetc(); | 12749 | c = pgetc_eatbnl(); |
12731 | if (c == '>') | 12750 | if (c == '>') |
12732 | np->type = NAPPEND; | 12751 | np->type = NAPPEND; |
12733 | else if (c == '|') | 12752 | else if (c == '|') |
@@ -12749,7 +12768,7 @@ parseredir: { | |||
12749 | #endif | 12768 | #endif |
12750 | else { /* c == '<' */ | 12769 | else { /* c == '<' */ |
12751 | /*np->nfile.fd = 0; - stzalloc did it */ | 12770 | /*np->nfile.fd = 0; - stzalloc did it */ |
12752 | c = pgetc(); | 12771 | c = pgetc_eatbnl(); |
12753 | switch (c) { | 12772 | switch (c) { |
12754 | case '<': | 12773 | case '<': |
12755 | if (sizeof(struct nfile) != sizeof(struct nhere)) { | 12774 | if (sizeof(struct nfile) != sizeof(struct nhere)) { |
@@ -12759,7 +12778,7 @@ parseredir: { | |||
12759 | np->type = NHERE; | 12778 | np->type = NHERE; |
12760 | heredoc = stzalloc(sizeof(struct heredoc)); | 12779 | heredoc = stzalloc(sizeof(struct heredoc)); |
12761 | heredoc->here = np; | 12780 | heredoc->here = np; |
12762 | c = pgetc(); | 12781 | c = pgetc_eatbnl(); |
12763 | if (c == '-') { | 12782 | if (c == '-') { |
12764 | heredoc->striptabs = 1; | 12783 | heredoc->striptabs = 1; |
12765 | } else { | 12784 | } else { |
@@ -12989,23 +13008,13 @@ parsebackq: { | |||
12989 | int pc; | 13008 | int pc; |
12990 | 13009 | ||
12991 | setprompt_if(needprompt, 2); | 13010 | setprompt_if(needprompt, 2); |
12992 | pc = pgetc(); | 13011 | pc = pgetc_eatbnl(); |
12993 | switch (pc) { | 13012 | switch (pc) { |
12994 | case '`': | 13013 | case '`': |
12995 | goto done; | 13014 | goto done; |
12996 | 13015 | ||
12997 | case '\\': | 13016 | case '\\': |
12998 | pc = pgetc(); | 13017 | pc = pgetc(); /* or pgetc_eatbnl()? why (example)? */ |
12999 | if (pc == '\n') { | ||
13000 | nlprompt(); | ||
13001 | /* | ||
13002 | * If eating a newline, avoid putting | ||
13003 | * the newline into the new character | ||
13004 | * stream (via the STPUTC after the | ||
13005 | * switch). | ||
13006 | */ | ||
13007 | continue; | ||
13008 | } | ||
13009 | if (pc != '\\' && pc != '`' && pc != '$' | 13018 | if (pc != '\\' && pc != '`' && pc != '$' |
13010 | && (!dblquote || pc != '"') | 13019 | && (!dblquote || pc != '"') |
13011 | ) { | 13020 | ) { |
@@ -13137,7 +13146,7 @@ xxreadtoken(void) | |||
13137 | } | 13146 | } |
13138 | setprompt_if(needprompt, 2); | 13147 | setprompt_if(needprompt, 2); |
13139 | for (;;) { /* until token or start of word found */ | 13148 | for (;;) { /* until token or start of word found */ |
13140 | c = pgetc(); | 13149 | c = pgetc_eatbnl(); |
13141 | if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA)) | 13150 | if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA)) |
13142 | continue; | 13151 | continue; |
13143 | 13152 | ||
@@ -13146,11 +13155,7 @@ xxreadtoken(void) | |||
13146 | continue; | 13155 | continue; |
13147 | pungetc(); | 13156 | pungetc(); |
13148 | } else if (c == '\\') { | 13157 | } else if (c == '\\') { |
13149 | if (pgetc() != '\n') { | 13158 | break; /* return readtoken1(...) */ |
13150 | pungetc(); | ||
13151 | break; /* return readtoken1(...) */ | ||
13152 | } | ||
13153 | nlprompt(); | ||
13154 | } else { | 13159 | } else { |
13155 | const char *p; | 13160 | const char *p; |
13156 | 13161 | ||
@@ -13165,7 +13170,7 @@ xxreadtoken(void) | |||
13165 | break; /* return readtoken1(...) */ | 13170 | break; /* return readtoken1(...) */ |
13166 | 13171 | ||
13167 | if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) { | 13172 | if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) { |
13168 | int cc = pgetc(); | 13173 | int cc = pgetc_eatbnl(); |
13169 | if (cc == c) { /* double occurrence? */ | 13174 | if (cc == c) { /* double occurrence? */ |
13170 | p += xxreadtoken_doubles + 1; | 13175 | p += xxreadtoken_doubles + 1; |
13171 | } else { | 13176 | } else { |
@@ -13197,7 +13202,7 @@ xxreadtoken(void) | |||
13197 | } | 13202 | } |
13198 | setprompt_if(needprompt, 2); | 13203 | setprompt_if(needprompt, 2); |
13199 | for (;;) { /* until token or start of word found */ | 13204 | for (;;) { /* until token or start of word found */ |
13200 | c = pgetc(); | 13205 | c = pgetc_eatbnl(); |
13201 | switch (c) { | 13206 | switch (c) { |
13202 | case ' ': case '\t': | 13207 | case ' ': case '\t': |
13203 | IF_ASH_ALIAS(case PEOA:) | 13208 | IF_ASH_ALIAS(case PEOA:) |
@@ -13207,30 +13212,23 @@ xxreadtoken(void) | |||
13207 | continue; | 13212 | continue; |
13208 | pungetc(); | 13213 | pungetc(); |
13209 | continue; | 13214 | continue; |
13210 | case '\\': | ||
13211 | if (pgetc() == '\n') { | ||
13212 | nlprompt(); | ||
13213 | continue; | ||
13214 | } | ||
13215 | pungetc(); | ||
13216 | goto breakloop; | ||
13217 | case '\n': | 13215 | case '\n': |
13218 | nlnoprompt(); | 13216 | nlnoprompt(); |
13219 | RETURN(TNL); | 13217 | RETURN(TNL); |
13220 | case PEOF: | 13218 | case PEOF: |
13221 | RETURN(TEOF); | 13219 | RETURN(TEOF); |
13222 | case '&': | 13220 | case '&': |
13223 | if (pgetc() == '&') | 13221 | if (pgetc_eatbnl() == '&') |
13224 | RETURN(TAND); | 13222 | RETURN(TAND); |
13225 | pungetc(); | 13223 | pungetc(); |
13226 | RETURN(TBACKGND); | 13224 | RETURN(TBACKGND); |
13227 | case '|': | 13225 | case '|': |
13228 | if (pgetc() == '|') | 13226 | if (pgetc_eatbnl() == '|') |
13229 | RETURN(TOR); | 13227 | RETURN(TOR); |
13230 | pungetc(); | 13228 | pungetc(); |
13231 | RETURN(TPIPE); | 13229 | RETURN(TPIPE); |
13232 | case ';': | 13230 | case ';': |
13233 | if (pgetc() == ';') | 13231 | if (pgetc_eatbnl() == ';') |
13234 | RETURN(TENDCASE); | 13232 | RETURN(TENDCASE); |
13235 | pungetc(); | 13233 | pungetc(); |
13236 | RETURN(TSEMI); | 13234 | RETURN(TSEMI); |
@@ -13238,11 +13236,9 @@ xxreadtoken(void) | |||
13238 | RETURN(TLP); | 13236 | RETURN(TLP); |
13239 | case ')': | 13237 | case ')': |
13240 | RETURN(TRP); | 13238 | RETURN(TRP); |
13241 | default: | ||
13242 | goto breakloop; | ||
13243 | } | 13239 | } |
13240 | break; | ||
13244 | } | 13241 | } |
13245 | breakloop: | ||
13246 | return readtoken1(c, BASESYNTAX, (char *)NULL, 0); | 13242 | return readtoken1(c, BASESYNTAX, (char *)NULL, 0); |
13247 | #undef RETURN | 13243 | #undef RETURN |
13248 | } | 13244 | } |
diff --git a/shell/ash_test/ash-heredoc/heredoc_backquote1.right b/shell/ash_test/ash-heredoc/heredoc_backquote1.right new file mode 100644 index 000000000..0be2a3296 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredoc_backquote1.right | |||
@@ -0,0 +1,5 @@ | |||
1 | heredoc1 | ||
2 | Ok1:0 | ||
3 | heredoc2 | ||
4 | EO`false`F | ||
5 | Ok2:0 | ||
diff --git a/shell/ash_test/ash-heredoc/heredoc_backquote1.tests b/shell/ash_test/ash-heredoc/heredoc_backquote1.tests new file mode 100755 index 000000000..ec3d8fe1d --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredoc_backquote1.tests | |||
@@ -0,0 +1,10 @@ | |||
1 | cat <<EO`true`F | ||
2 | heredoc1 | ||
3 | EO`true`F | ||
4 | echo Ok1:$? | ||
5 | |||
6 | cat <<EO`true`F | ||
7 | heredoc2 | ||
8 | EO`false`F | ||
9 | EO`true`F | ||
10 | echo Ok2:$? | ||
diff --git a/shell/ash_test/ash-heredoc/heredoc_backslash1.right b/shell/ash_test/ash-heredoc/heredoc_backslash1.right new file mode 100644 index 000000000..6a6114821 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredoc_backslash1.right | |||
@@ -0,0 +1,43 @@ | |||
1 | Quoted heredoc: | ||
2 | a\ | ||
3 | b | ||
4 | a\\ | ||
5 | b | ||
6 | 123456 -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- | ||
7 | -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- | ||
8 | 123456 `echo v'-$a-\t-\\-\"-\'-\`-\--\z-\*-\?-'` | ||
9 | 123456 $(echo v'-$a-\t-\\-\"-\'-\`-\--\z-\*-\?-') | ||
10 | c\ | ||
11 | |||
12 | Unquoted heredoc: | ||
13 | a b | ||
14 | a\ | ||
15 | b | ||
16 | 123456 -qwerty-\t-\-\"-\'-`-\--\z-\*-\?- | ||
17 | -qwerty-\t-\-\"-\'-`-\--\z-\*-\?- | ||
18 | 123456 v-$a-\t-\-\"-\x-`-\--\z-\*-\?- | ||
19 | 123456 v-$a-\t-\\-\"-\x-\`-\--\z-\*-\?- | ||
20 | cEOF2 | ||
21 | |||
22 | Quoted -heredoc: | ||
23 | a\ | ||
24 | b | ||
25 | a\\ | ||
26 | b | ||
27 | 123456 -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- | ||
28 | -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- | ||
29 | 123456 `echo v'-$a-\t-\\-\"-\'-\`-\--\z-\*-\?-'` | ||
30 | 123456 $(echo v'-$a-\t-\\-\"-\'-\`-\--\z-\*-\?-') | ||
31 | c\ | ||
32 | |||
33 | Unquoted -heredoc: | ||
34 | a b | ||
35 | a\ | ||
36 | b | ||
37 | 123456 -qwerty-\t-\-\"-\'-`-\--\z-\*-\?- | ||
38 | -qwerty-\t-\-\"-\'-`-\--\z-\*-\?- | ||
39 | 123456 v-$a-\t-\-\"-\x-`-\--\z-\*-\?- | ||
40 | 123456 v-$a-\t-\\-\"-\x-\`-\--\z-\*-\?- | ||
41 | cEOF4 | ||
42 | |||
43 | Done: 0 | ||
diff --git a/shell/ash_test/ash-heredoc/heredoc_backslash1.tests b/shell/ash_test/ash-heredoc/heredoc_backslash1.tests new file mode 100755 index 000000000..501af5490 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredoc_backslash1.tests | |||
@@ -0,0 +1,70 @@ | |||
1 | # Test for correct handling of backslashes. | ||
2 | # Note that some lines in each heredoc start with a tab. | ||
3 | |||
4 | a=qwerty | ||
5 | |||
6 | echo Quoted heredoc: | ||
7 | cat <<"EOF1" | ||
8 | a\ | ||
9 | b | ||
10 | a\\ | ||
11 | b | ||
12 | 123456 -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- | ||
13 | -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- | ||
14 | 123456 `echo v'-$a-\t-\\-\"-\'-\`-\--\z-\*-\?-'` | ||
15 | 123456 $(echo v'-$a-\t-\\-\"-\'-\`-\--\z-\*-\?-') | ||
16 | c\ | ||
17 | EOF1 | ||
18 | echo | ||
19 | |||
20 | echo Unquoted heredoc: | ||
21 | cat <<EOF2 | ||
22 | a\ | ||
23 | b | ||
24 | a\\ | ||
25 | b | ||
26 | 123456 -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- | ||
27 | -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- | ||
28 | 123456 `echo v'-$a-\t-\\-\"-\x-\`-\--\z-\*-\?-'` | ||
29 | 123456 $(echo v'-$a-\t-\\-\"-\x-\`-\--\z-\*-\?-') | ||
30 | c\ | ||
31 | EOF2 | ||
32 | EOF2 | ||
33 | echo | ||
34 | |||
35 | echo Quoted -heredoc: | ||
36 | cat <<-"EOF3" | ||
37 | a\ | ||
38 | b | ||
39 | a\\ | ||
40 | b | ||
41 | 123456 -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- | ||
42 | -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- | ||
43 | 123456 `echo v'-$a-\t-\\-\"-\'-\`-\--\z-\*-\?-'` | ||
44 | 123456 $(echo v'-$a-\t-\\-\"-\'-\`-\--\z-\*-\?-') | ||
45 | c\ | ||
46 | EOF3 | ||
47 | # In -heredoc case the marker is detected even if it is indented. | ||
48 | echo | ||
49 | |||
50 | echo Unquoted -heredoc: | ||
51 | cat <<-EOF4 | ||
52 | a\ | ||
53 | b | ||
54 | a\\ | ||
55 | b | ||
56 | 123456 -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- | ||
57 | -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- | ||
58 | 123456 `echo v'-$a-\t-\\-\"-\x-\`-\--\z-\*-\?-'` | ||
59 | 123456 $(echo v'-$a-\t-\\-\"-\x-\`-\--\z-\*-\?-') | ||
60 | c\ | ||
61 | EOF4 | ||
62 | EOF4 | ||
63 | # The marker is not detected if preceding line ends in backslash. | ||
64 | # TODO: marker should be detected even if it is split by line continuation: | ||
65 | # EOF\ | ||
66 | # 4 | ||
67 | # but currently hush doesn't do it. (Tab before "4" is not allowed, though.) | ||
68 | echo | ||
69 | |||
70 | echo "Done: $?" | ||
diff --git a/shell/ash_test/ash-heredoc/heredoc_bkslash_newline1.right b/shell/ash_test/ash-heredoc/heredoc_bkslash_newline1.right new file mode 100644 index 000000000..fdb7ebd03 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredoc_bkslash_newline1.right | |||
@@ -0,0 +1,8 @@ | |||
1 | heredoc0 | ||
2 | Ok0:0 | ||
3 | heredoc1 | ||
4 | Ok1:0 | ||
5 | heredoc2 | ||
6 | Ok2:0 | ||
7 | heredoc3 | ||
8 | Ok4:0 | ||
diff --git a/shell/ash_test/ash-heredoc/heredoc_bkslash_newline1.tests b/shell/ash_test/ash-heredoc/heredoc_bkslash_newline1.tests new file mode 100755 index 000000000..584edd0e4 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredoc_bkslash_newline1.tests | |||
@@ -0,0 +1,25 @@ | |||
1 | cat <\ | ||
2 | <\ | ||
3 | EOF | ||
4 | heredoc0 | ||
5 | EOF | ||
6 | echo Ok0:$? | ||
7 | |||
8 | cat <<\ | ||
9 | EOF | ||
10 | heredoc1 | ||
11 | EOF | ||
12 | echo Ok1:$? | ||
13 | |||
14 | cat <<\ | ||
15 | - EOF | ||
16 | heredoc2 | ||
17 | EOF | ||
18 | echo Ok2:$? | ||
19 | |||
20 | cat <\ | ||
21 | <\ | ||
22 | - EOF | ||
23 | heredoc3 | ||
24 | EOF | ||
25 | echo Ok4:$? | ||
diff --git a/shell/ash_test/ash-parsing/bkslash_newline1.right b/shell/ash_test/ash-parsing/bkslash_newline1.right new file mode 100644 index 000000000..97ea0c197 --- /dev/null +++ b/shell/ash_test/ash-parsing/bkslash_newline1.right | |||
@@ -0,0 +1,4 @@ | |||
1 | and1 | ||
2 | and2 | ||
3 | or1 | ||
4 | ok | ||
diff --git a/shell/ash_test/ash-parsing/bkslash_newline1.tests b/shell/ash_test/ash-parsing/bkslash_newline1.tests new file mode 100755 index 000000000..6e374c4fb --- /dev/null +++ b/shell/ash_test/ash-parsing/bkslash_newline1.tests | |||
@@ -0,0 +1,8 @@ | |||
1 | echo and1 &\ | ||
2 | & echo and2 | ||
3 | |||
4 | echo or1 |\ | ||
5 | | echo NOT SHOWN | ||
6 | |||
7 | case w in a) echo SKIP;\ | ||
8 | ; w) echo ok;; esac; | ||
diff --git a/shell/ash_test/ash-parsing/bkslash_newline2.right b/shell/ash_test/ash-parsing/bkslash_newline2.right new file mode 100644 index 000000000..c863c5453 --- /dev/null +++ b/shell/ash_test/ash-parsing/bkslash_newline2.right | |||
@@ -0,0 +1,4 @@ | |||
1 | Line with one backslash: | ||
2 | \ | ||
3 | |||
4 | Ok:0 | ||
diff --git a/shell/ash_test/ash-parsing/bkslash_newline2.tests b/shell/ash_test/ash-parsing/bkslash_newline2.tests new file mode 100755 index 000000000..47d63042d --- /dev/null +++ b/shell/ash_test/ash-parsing/bkslash_newline2.tests | |||
@@ -0,0 +1,4 @@ | |||
1 | echo Line with one backslash: | ||
2 | echo '\ | ||
3 | ' | ||
4 | echo Ok:$? | ||
diff --git a/shell/ash_test/ash-quoting/dollar_repl_slash_bash2.right b/shell/ash_test/ash-quoting/dollar_repl_slash_bash2.right new file mode 100644 index 000000000..2aead7129 --- /dev/null +++ b/shell/ash_test/ash-quoting/dollar_repl_slash_bash2.right | |||
@@ -0,0 +1 @@ | |||
\/a\/bc\/def\/file | |||
diff --git a/shell/ash_test/ash-quoting/dollar_repl_slash_bash2.tests b/shell/ash_test/ash-quoting/dollar_repl_slash_bash2.tests new file mode 100755 index 000000000..64ca0c170 --- /dev/null +++ b/shell/ash_test/ash-quoting/dollar_repl_slash_bash2.tests | |||
@@ -0,0 +1,2 @@ | |||
1 | var="/a/bc/def/file" | ||
2 | echo "${var//\//\\/}" | ||
diff --git a/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_1.right b/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_1.right new file mode 100644 index 000000000..46ab7f5d1 --- /dev/null +++ b/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_1.right | |||
@@ -0,0 +1,5 @@ | |||
1 | /proc/self/fd | ||
2 | /proc/self/fd/0 | ||
3 | /proc/self/fd/1 | ||
4 | /proc/self/fd/2 | ||
5 | /proc/self/fd/3 | ||
diff --git a/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_1.tests b/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_1.tests new file mode 100755 index 000000000..544c810e3 --- /dev/null +++ b/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_1.tests | |||
@@ -0,0 +1,6 @@ | |||
1 | # The "find" should not see "saved" (duplicated) fd #1 | ||
2 | # Explicitly use bbox find, since other implementations of "find" | ||
3 | # may open other descriptors as well. | ||
4 | busybox find /proc/self/fd >tmp_$$.out | ||
5 | cat tmp_$$.out | ||
6 | rm -f tmp_$$.out | ||
diff --git a/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_2.right b/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_2.right new file mode 100644 index 000000000..46ab7f5d1 --- /dev/null +++ b/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_2.right | |||
@@ -0,0 +1,5 @@ | |||
1 | /proc/self/fd | ||
2 | /proc/self/fd/0 | ||
3 | /proc/self/fd/1 | ||
4 | /proc/self/fd/2 | ||
5 | /proc/self/fd/3 | ||
diff --git a/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_2.tests b/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_2.tests new file mode 100755 index 000000000..43777cade --- /dev/null +++ b/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_2.tests | |||
@@ -0,0 +1,6 @@ | |||
1 | # The "find" should not see "saved" (duplicated) fd #1 | ||
2 | # Explicitly use bbox find, since other implementations of "find" | ||
3 | # may open other descriptors as well. | ||
4 | { busybox find /proc/self/fd; } >tmp_$$.out | ||
5 | cat tmp_$$.out | ||
6 | rm -f tmp_$$.out | ||
diff --git a/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_3.right b/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_3.right new file mode 100644 index 000000000..46ab7f5d1 --- /dev/null +++ b/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_3.right | |||
@@ -0,0 +1,5 @@ | |||
1 | /proc/self/fd | ||
2 | /proc/self/fd/0 | ||
3 | /proc/self/fd/1 | ||
4 | /proc/self/fd/2 | ||
5 | /proc/self/fd/3 | ||
diff --git a/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_3.tests b/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_3.tests new file mode 100755 index 000000000..0a21173bd --- /dev/null +++ b/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_3.tests | |||
@@ -0,0 +1,6 @@ | |||
1 | # The "find" should not see "saved" (duplicated) fd #1 | ||
2 | # Explicitly use bbox find, since other implementations of "find" | ||
3 | # may open other descriptors as well. | ||
4 | { busybox find /proc/self/fd; true; } >tmp_$$.out | ||
5 | cat tmp_$$.out | ||
6 | rm -f tmp_$$.out | ||
diff --git a/shell/ash_test/ash-vars/var_LINENO1.right b/shell/ash_test/ash-vars/var_LINENO1.right new file mode 100644 index 000000000..31e1a4478 --- /dev/null +++ b/shell/ash_test/ash-vars/var_LINENO1.right | |||
@@ -0,0 +1,8 @@ | |||
1 | 2:2 | ||
2 | 3:3 | ||
3 | 4:4 | ||
4 | 5:5 | ||
5 | 2:2 | ||
6 | 3:3 | ||
7 | 4:4 | ||
8 | 5:5 | ||
diff --git a/shell/ash_test/ash-vars/var_LINENO1.tests b/shell/ash_test/ash-vars/var_LINENO1.tests new file mode 100755 index 000000000..775861e64 --- /dev/null +++ b/shell/ash_test/ash-vars/var_LINENO1.tests | |||
@@ -0,0 +1,6 @@ | |||
1 | env | grep ^LINENO | ||
2 | echo 2:$LINENO | ||
3 | echo 3:$LINENO >&2 \ | ||
4 | | { sleep 0.1; echo 4:$LINENO; } | ||
5 | echo 5:$LINENO | ||
6 | test "$1" || . ./var_LINENO1.tests norepeat | ||
diff --git a/shell/hush.c b/shell/hush.c index 6e64efb70..06fe0e405 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -1501,12 +1501,15 @@ static void free_strings(char **strings) | |||
1501 | free(strings); | 1501 | free(strings); |
1502 | } | 1502 | } |
1503 | 1503 | ||
1504 | static int fcntl_F_DUPFD(int fd, int avoid_fd) | 1504 | static int dup_CLOEXEC(int fd, int avoid_fd) |
1505 | { | 1505 | { |
1506 | int newfd; | 1506 | int newfd; |
1507 | repeat: | 1507 | repeat: |
1508 | newfd = fcntl(fd, F_DUPFD, avoid_fd + 1); | 1508 | newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1); |
1509 | if (newfd < 0) { | 1509 | if (newfd >= 0) { |
1510 | if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */ | ||
1511 | fcntl(newfd, F_SETFD, FD_CLOEXEC); | ||
1512 | } else { /* newfd < 0 */ | ||
1510 | if (errno == EBUSY) | 1513 | if (errno == EBUSY) |
1511 | goto repeat; | 1514 | goto repeat; |
1512 | if (errno == EINTR) | 1515 | if (errno == EINTR) |
@@ -2691,6 +2694,42 @@ static int i_peek2(struct in_str *i) | |||
2691 | return ch; | 2694 | return ch; |
2692 | } | 2695 | } |
2693 | 2696 | ||
2697 | static int i_getch_and_eat_bkslash_nl(struct in_str *input) | ||
2698 | { | ||
2699 | for (;;) { | ||
2700 | int ch, ch2; | ||
2701 | |||
2702 | ch = i_getch(input); | ||
2703 | if (ch != '\\') | ||
2704 | return ch; | ||
2705 | ch2 = i_peek(input); | ||
2706 | if (ch2 != '\n') | ||
2707 | return ch; | ||
2708 | /* backslash+newline, skip it */ | ||
2709 | i_getch(input); | ||
2710 | } | ||
2711 | } | ||
2712 | |||
2713 | /* Note: this function _eats_ \<newline> pairs, safe to use plain | ||
2714 | * i_getch() after it instead of i_getch_and_eat_bkslash_nl(). | ||
2715 | */ | ||
2716 | static int i_peek_and_eat_bkslash_nl(struct in_str *input) | ||
2717 | { | ||
2718 | for (;;) { | ||
2719 | int ch, ch2; | ||
2720 | |||
2721 | ch = i_peek(input); | ||
2722 | if (ch != '\\') | ||
2723 | return ch; | ||
2724 | ch2 = i_peek2(input); | ||
2725 | if (ch2 != '\n') | ||
2726 | return ch; | ||
2727 | /* backslash+newline, skip it */ | ||
2728 | i_getch(input); | ||
2729 | i_getch(input); | ||
2730 | } | ||
2731 | } | ||
2732 | |||
2694 | static void setup_file_in_str(struct in_str *i, FILE *f) | 2733 | static void setup_file_in_str(struct in_str *i, FILE *f) |
2695 | { | 2734 | { |
2696 | memset(i, 0, sizeof(*i)); | 2735 | memset(i, 0, sizeof(*i)); |
@@ -3119,7 +3158,7 @@ static int glob_brace(char *pattern, o_string *o, int n) | |||
3119 | return o_save_ptr_helper(o, n); | 3158 | return o_save_ptr_helper(o, n); |
3120 | } | 3159 | } |
3121 | if (gr == GLOB_NOSPACE) | 3160 | if (gr == GLOB_NOSPACE) |
3122 | bb_error_msg_and_die(bb_msg_memory_exhausted); | 3161 | bb_die_memory_exhausted(); |
3123 | /* GLOB_ABORTED? Only happens with GLOB_ERR flag, | 3162 | /* GLOB_ABORTED? Only happens with GLOB_ERR flag, |
3124 | * but we didn't specify it. Paranoia again. */ | 3163 | * but we didn't specify it. Paranoia again. */ |
3125 | bb_error_msg_and_die("glob error %d on '%s'", gr, pattern); | 3164 | bb_error_msg_and_die("glob error %d on '%s'", gr, pattern); |
@@ -3221,7 +3260,7 @@ static int perform_glob(o_string *o, int n) | |||
3221 | goto literal; | 3260 | goto literal; |
3222 | } | 3261 | } |
3223 | if (gr == GLOB_NOSPACE) | 3262 | if (gr == GLOB_NOSPACE) |
3224 | bb_error_msg_and_die(bb_msg_memory_exhausted); | 3263 | bb_die_memory_exhausted(); |
3225 | /* GLOB_ABORTED? Only happens with GLOB_ERR flag, | 3264 | /* GLOB_ABORTED? Only happens with GLOB_ERR flag, |
3226 | * but we didn't specify it. Paranoia again. */ | 3265 | * but we didn't specify it. Paranoia again. */ |
3227 | bb_error_msg_and_die("glob error %d on '%s'", gr, pattern); | 3266 | bb_error_msg_and_die("glob error %d on '%s'", gr, pattern); |
@@ -3812,16 +3851,28 @@ static int done_word(o_string *word, struct parse_context *ctx) | |||
3812 | if (ctx->pending_redirect) { | 3851 | if (ctx->pending_redirect) { |
3813 | /* We do not glob in e.g. >*.tmp case. bash seems to glob here | 3852 | /* We do not glob in e.g. >*.tmp case. bash seems to glob here |
3814 | * only if run as "bash", not "sh" */ | 3853 | * only if run as "bash", not "sh" */ |
3815 | /* http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html | 3854 | /* http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html |
3816 | * "2.7 Redirection | 3855 | * "2.7 Redirection |
3817 | * ...the word that follows the redirection operator | 3856 | * If the redirection operator is "<<" or "<<-", the word |
3818 | * shall be subjected to tilde expansion, parameter expansion, | 3857 | * that follows the redirection operator shall be |
3819 | * command substitution, arithmetic expansion, and quote | 3858 | * subjected to quote removal; it is unspecified whether |
3820 | * removal. Pathname expansion shall not be performed | 3859 | * any of the other expansions occur. For the other |
3860 | * redirection operators, the word that follows the | ||
3861 | * redirection operator shall be subjected to tilde | ||
3862 | * expansion, parameter expansion, command substitution, | ||
3863 | * arithmetic expansion, and quote removal. | ||
3864 | * Pathname expansion shall not be performed | ||
3821 | * on the word by a non-interactive shell; an interactive | 3865 | * on the word by a non-interactive shell; an interactive |
3822 | * shell may perform it, but shall do so only when | 3866 | * shell may perform it, but shall do so only when |
3823 | * the expansion would result in one word." | 3867 | * the expansion would result in one word." |
3824 | */ | 3868 | */ |
3869 | //bash does not do parameter/command substitution or arithmetic expansion | ||
3870 | //for _heredoc_ redirection word: these constructs look for exact eof marker | ||
3871 | // as written: | ||
3872 | // <<EOF$t | ||
3873 | // <<EOF$((1)) | ||
3874 | // <<EOF`true` [this case also makes heredoc "quoted", a-la <<"EOF". Probably bash-4.3.43 bug] | ||
3875 | |||
3825 | ctx->pending_redirect->rd_filename = xstrdup(word->data); | 3876 | ctx->pending_redirect->rd_filename = xstrdup(word->data); |
3826 | /* Cater for >\file case: | 3877 | /* Cater for >\file case: |
3827 | * >\a creates file a; >\\a, >"\a", >"\\a" create file \a | 3878 | * >\a creates file a; >\\a, >"\a", >"\\a" create file \a |
@@ -4011,7 +4062,7 @@ static int parse_redirect(struct parse_context *ctx, | |||
4011 | if (dup_num == REDIRFD_SYNTAX_ERR) | 4062 | if (dup_num == REDIRFD_SYNTAX_ERR) |
4012 | return 1; | 4063 | return 1; |
4013 | } else { | 4064 | } else { |
4014 | int ch = i_peek(input); | 4065 | int ch = i_peek_and_eat_bkslash_nl(input); |
4015 | dup_num = (ch == '-'); /* HEREDOC_SKIPTABS bit is 1 */ | 4066 | dup_num = (ch == '-'); /* HEREDOC_SKIPTABS bit is 1 */ |
4016 | if (dup_num) { /* <<-... */ | 4067 | if (dup_num) { /* <<-... */ |
4017 | ch = i_getch(input); | 4068 | ch = i_getch(input); |
@@ -4021,7 +4072,7 @@ static int parse_redirect(struct parse_context *ctx, | |||
4021 | } | 4072 | } |
4022 | 4073 | ||
4023 | if (style == REDIRECT_OVERWRITE && dup_num == REDIRFD_TO_FILE) { | 4074 | if (style == REDIRECT_OVERWRITE && dup_num == REDIRFD_TO_FILE) { |
4024 | int ch = i_peek(input); | 4075 | int ch = i_peek_and_eat_bkslash_nl(input); |
4025 | if (ch == '|') { | 4076 | if (ch == '|') { |
4026 | /* >|FILE redirect ("clobbering" >). | 4077 | /* >|FILE redirect ("clobbering" >). |
4027 | * Since we do not support "set -o noclobber" yet, | 4078 | * Since we do not support "set -o noclobber" yet, |
@@ -4189,6 +4240,7 @@ static int fetch_heredocs(int heredoc_cnt, struct parse_context *ctx, struct in_ | |||
4189 | 4240 | ||
4190 | redir->rd_type = REDIRECT_HEREDOC2; | 4241 | redir->rd_type = REDIRECT_HEREDOC2; |
4191 | /* redir->rd_dup is (ab)used to indicate <<- */ | 4242 | /* redir->rd_dup is (ab)used to indicate <<- */ |
4243 | bb_error_msg("redir->rd_filename:'%s'", redir->rd_filename); | ||
4192 | p = fetch_till_str(&ctx->as_string, input, | 4244 | p = fetch_till_str(&ctx->as_string, input, |
4193 | redir->rd_filename, redir->rd_dup); | 4245 | redir->rd_filename, redir->rd_dup); |
4194 | if (!p) { | 4246 | if (!p) { |
@@ -4340,39 +4392,6 @@ static int parse_group(o_string *dest, struct parse_context *ctx, | |||
4340 | /* command remains "open", available for possible redirects */ | 4392 | /* command remains "open", available for possible redirects */ |
4341 | } | 4393 | } |
4342 | 4394 | ||
4343 | static int i_getch_and_eat_bkslash_nl(struct in_str *input) | ||
4344 | { | ||
4345 | for (;;) { | ||
4346 | int ch, ch2; | ||
4347 | |||
4348 | ch = i_getch(input); | ||
4349 | if (ch != '\\') | ||
4350 | return ch; | ||
4351 | ch2 = i_peek(input); | ||
4352 | if (ch2 != '\n') | ||
4353 | return ch; | ||
4354 | /* backslash+newline, skip it */ | ||
4355 | i_getch(input); | ||
4356 | } | ||
4357 | } | ||
4358 | |||
4359 | static int i_peek_and_eat_bkslash_nl(struct in_str *input) | ||
4360 | { | ||
4361 | for (;;) { | ||
4362 | int ch, ch2; | ||
4363 | |||
4364 | ch = i_peek(input); | ||
4365 | if (ch != '\\') | ||
4366 | return ch; | ||
4367 | ch2 = i_peek2(input); | ||
4368 | if (ch2 != '\n') | ||
4369 | return ch; | ||
4370 | /* backslash+newline, skip it */ | ||
4371 | i_getch(input); | ||
4372 | i_getch(input); | ||
4373 | } | ||
4374 | } | ||
4375 | |||
4376 | #if ENABLE_HUSH_TICK || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_DOLLAR_OPS | 4395 | #if ENABLE_HUSH_TICK || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_DOLLAR_OPS |
4377 | /* Subroutines for copying $(...) and `...` things */ | 4396 | /* Subroutines for copying $(...) and `...` things */ |
4378 | static int add_till_backquote(o_string *dest, struct in_str *input, int in_dquote); | 4397 | static int add_till_backquote(o_string *dest, struct in_str *input, int in_dquote); |
@@ -4974,8 +4993,14 @@ static struct pipe *parse_stream(char **pstring, | |||
4974 | nommu_addchr(&ctx.as_string, ch); | 4993 | nommu_addchr(&ctx.as_string, ch); |
4975 | 4994 | ||
4976 | next = '\0'; | 4995 | next = '\0'; |
4977 | if (ch != '\n') | 4996 | if (ch != '\n') { |
4978 | next = i_peek(input); | 4997 | next = i_peek(input); |
4998 | /* Can't use i_peek_and_eat_bkslash_nl(input) here: | ||
4999 | * echo '\ | ||
5000 | * ' | ||
5001 | * will break. | ||
5002 | */ | ||
5003 | } | ||
4979 | 5004 | ||
4980 | is_special = "{}<>;&|()#'" /* special outside of "str" */ | 5005 | is_special = "{}<>;&|()#'" /* special outside of "str" */ |
4981 | "\\$\"" IF_HUSH_TICK("`") /* always special */ | 5006 | "\\$\"" IF_HUSH_TICK("`") /* always special */ |
@@ -5178,6 +5203,8 @@ static struct pipe *parse_stream(char **pstring, | |||
5178 | goto parse_error; | 5203 | goto parse_error; |
5179 | } | 5204 | } |
5180 | redir_style = REDIRECT_OVERWRITE; | 5205 | redir_style = REDIRECT_OVERWRITE; |
5206 | if (next == '\\') | ||
5207 | next = i_peek_and_eat_bkslash_nl(input); | ||
5181 | if (next == '>') { | 5208 | if (next == '>') { |
5182 | redir_style = REDIRECT_APPEND; | 5209 | redir_style = REDIRECT_APPEND; |
5183 | ch = i_getch(input); | 5210 | ch = i_getch(input); |
@@ -5198,6 +5225,8 @@ static struct pipe *parse_stream(char **pstring, | |||
5198 | goto parse_error; | 5225 | goto parse_error; |
5199 | } | 5226 | } |
5200 | redir_style = REDIRECT_INPUT; | 5227 | redir_style = REDIRECT_INPUT; |
5228 | if (next == '\\') | ||
5229 | next = i_peek_and_eat_bkslash_nl(input); | ||
5201 | if (next == '<') { | 5230 | if (next == '<') { |
5202 | redir_style = REDIRECT_HEREDOC; | 5231 | redir_style = REDIRECT_HEREDOC; |
5203 | heredoc_cnt++; | 5232 | heredoc_cnt++; |
@@ -5365,7 +5394,7 @@ static struct pipe *parse_stream(char **pstring, | |||
5365 | /* Eat multiple semicolons, detect | 5394 | /* Eat multiple semicolons, detect |
5366 | * whether it means something special */ | 5395 | * whether it means something special */ |
5367 | while (1) { | 5396 | while (1) { |
5368 | ch = i_peek(input); | 5397 | ch = i_peek_and_eat_bkslash_nl(input); |
5369 | if (ch != ';') | 5398 | if (ch != ';') |
5370 | break; | 5399 | break; |
5371 | ch = i_getch(input); | 5400 | ch = i_getch(input); |
@@ -5387,6 +5416,8 @@ static struct pipe *parse_stream(char **pstring, | |||
5387 | if (done_word(&dest, &ctx)) { | 5416 | if (done_word(&dest, &ctx)) { |
5388 | goto parse_error; | 5417 | goto parse_error; |
5389 | } | 5418 | } |
5419 | if (next == '\\') | ||
5420 | next = i_peek_and_eat_bkslash_nl(input); | ||
5390 | if (next == '&') { | 5421 | if (next == '&') { |
5391 | ch = i_getch(input); | 5422 | ch = i_getch(input); |
5392 | nommu_addchr(&ctx.as_string, ch); | 5423 | nommu_addchr(&ctx.as_string, ch); |
@@ -5403,6 +5434,8 @@ static struct pipe *parse_stream(char **pstring, | |||
5403 | if (ctx.ctx_res_w == RES_MATCH) | 5434 | if (ctx.ctx_res_w == RES_MATCH) |
5404 | break; /* we are in case's "word | word)" */ | 5435 | break; /* we are in case's "word | word)" */ |
5405 | #endif | 5436 | #endif |
5437 | if (next == '\\') | ||
5438 | next = i_peek_and_eat_bkslash_nl(input); | ||
5406 | if (next == '|') { /* || */ | 5439 | if (next == '|') { /* || */ |
5407 | ch = i_getch(input); | 5440 | ch = i_getch(input); |
5408 | nommu_addchr(&ctx.as_string, ch); | 5441 | nommu_addchr(&ctx.as_string, ch); |
@@ -6123,7 +6156,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) | |||
6123 | } else | 6156 | } else |
6124 | /* If EXP_FLAG_SINGLEWORD, we handle assignment 'a=....$@.....' | 6157 | /* If EXP_FLAG_SINGLEWORD, we handle assignment 'a=....$@.....' |
6125 | * and in this case should treat it like '$*' - see 'else...' below */ | 6158 | * and in this case should treat it like '$*' - see 'else...' below */ |
6126 | if (first_ch == ('@'|0x80) /* quoted $@ */ | 6159 | if (first_ch == (char)('@'|0x80) /* quoted $@ */ |
6127 | && !(output->o_expflags & EXP_FLAG_SINGLEWORD) /* not v="$@" case */ | 6160 | && !(output->o_expflags & EXP_FLAG_SINGLEWORD) /* not v="$@" case */ |
6128 | ) { | 6161 | ) { |
6129 | while (1) { | 6162 | while (1) { |
@@ -6890,7 +6923,7 @@ static struct squirrel *add_squirrel(struct squirrel *sq, int fd, int avoid_fd) | |||
6890 | if (sq) for (; sq[i].orig_fd >= 0; i++) { | 6923 | if (sq) for (; sq[i].orig_fd >= 0; i++) { |
6891 | /* If we collide with an already moved fd... */ | 6924 | /* If we collide with an already moved fd... */ |
6892 | if (fd == sq[i].moved_to) { | 6925 | if (fd == sq[i].moved_to) { |
6893 | sq[i].moved_to = fcntl_F_DUPFD(sq[i].moved_to, avoid_fd); | 6926 | sq[i].moved_to = dup_CLOEXEC(sq[i].moved_to, avoid_fd); |
6894 | debug_printf_redir("redirect_fd %d: already busy, moving to %d\n", fd, sq[i].moved_to); | 6927 | debug_printf_redir("redirect_fd %d: already busy, moving to %d\n", fd, sq[i].moved_to); |
6895 | if (sq[i].moved_to < 0) /* what? */ | 6928 | if (sq[i].moved_to < 0) /* what? */ |
6896 | xfunc_die(); | 6929 | xfunc_die(); |
@@ -6904,7 +6937,7 @@ static struct squirrel *add_squirrel(struct squirrel *sq, int fd, int avoid_fd) | |||
6904 | } | 6937 | } |
6905 | 6938 | ||
6906 | /* If this fd is open, we move and remember it; if it's closed, moved_to = -1 */ | 6939 | /* If this fd is open, we move and remember it; if it's closed, moved_to = -1 */ |
6907 | moved_to = fcntl_F_DUPFD(fd, avoid_fd); | 6940 | moved_to = dup_CLOEXEC(fd, avoid_fd); |
6908 | debug_printf_redir("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, moved_to); | 6941 | debug_printf_redir("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, moved_to); |
6909 | if (moved_to < 0 && errno != EBADF) | 6942 | if (moved_to < 0 && errno != EBADF) |
6910 | xfunc_die(); | 6943 | xfunc_die(); |
@@ -7622,6 +7655,10 @@ static NOINLINE void pseudo_exec_argv(nommu_save_t *nommu_save, | |||
7622 | */ | 7655 | */ |
7623 | close_saved_fds_and_FILE_fds(); | 7656 | close_saved_fds_and_FILE_fds(); |
7624 | //FIXME: should also close saved redir fds | 7657 | //FIXME: should also close saved redir fds |
7658 | //This casuses test failures in | ||
7659 | //redir_children_should_not_see_saved_fd_2.tests | ||
7660 | //redir_children_should_not_see_saved_fd_3.tests | ||
7661 | //if you replace "busybox find" with just "find" in them | ||
7625 | /* Without this, "rm -i FILE" can't be ^C'ed: */ | 7662 | /* Without this, "rm -i FILE" can't be ^C'ed: */ |
7626 | switch_off_special_sigs(G.special_sig_mask); | 7663 | switch_off_special_sigs(G.special_sig_mask); |
7627 | debug_printf_exec("running applet '%s'\n", argv[0]); | 7664 | debug_printf_exec("running applet '%s'\n", argv[0]); |
@@ -8166,6 +8203,12 @@ static NOINLINE int run_pipe(struct pipe *pi) | |||
8166 | rcode = 1; /* exitcode if redir failed */ | 8203 | rcode = 1; /* exitcode if redir failed */ |
8167 | if (setup_redirects(command, &squirrel) == 0) { | 8204 | if (setup_redirects(command, &squirrel) == 0) { |
8168 | debug_printf_exec(": run_list\n"); | 8205 | debug_printf_exec(": run_list\n"); |
8206 | //FIXME: we need to pass squirrel down into run_list() | ||
8207 | //for SH_STANDALONE case, or else this construct: | ||
8208 | // { find /proc/self/fd; true; } >FILE; cmd2 | ||
8209 | //has no way of closing saved fd#1 for "find", | ||
8210 | //and in SH_STANDALONE mode, "find" is not execed, | ||
8211 | //therefore CLOEXEC on saved fd does not help. | ||
8169 | rcode = run_list(command->group) & 0xff; | 8212 | rcode = run_list(command->group) & 0xff; |
8170 | } | 8213 | } |
8171 | restore_redirects(squirrel); | 8214 | restore_redirects(squirrel); |
@@ -9347,7 +9390,7 @@ int hush_main(int argc, char **argv) | |||
9347 | G_saved_tty_pgrp = 0; | 9390 | G_saved_tty_pgrp = 0; |
9348 | 9391 | ||
9349 | /* try to dup stdin to high fd#, >= 255 */ | 9392 | /* try to dup stdin to high fd#, >= 255 */ |
9350 | G_interactive_fd = fcntl_F_DUPFD(STDIN_FILENO, 254); | 9393 | G_interactive_fd = dup_CLOEXEC(STDIN_FILENO, 254); |
9351 | if (G_interactive_fd < 0) { | 9394 | if (G_interactive_fd < 0) { |
9352 | /* try to dup to any fd */ | 9395 | /* try to dup to any fd */ |
9353 | G_interactive_fd = dup(STDIN_FILENO); | 9396 | G_interactive_fd = dup(STDIN_FILENO); |
@@ -9420,10 +9463,10 @@ int hush_main(int argc, char **argv) | |||
9420 | #elif ENABLE_HUSH_INTERACTIVE | 9463 | #elif ENABLE_HUSH_INTERACTIVE |
9421 | /* No job control compiled in, only prompt/line editing */ | 9464 | /* No job control compiled in, only prompt/line editing */ |
9422 | if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) { | 9465 | if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) { |
9423 | G_interactive_fd = fcntl_F_DUPFD(STDIN_FILENO, 254); | 9466 | G_interactive_fd = dup_CLOEXEC(STDIN_FILENO, 254); |
9424 | if (G_interactive_fd < 0) { | 9467 | if (G_interactive_fd < 0) { |
9425 | /* try to dup to any fd */ | 9468 | /* try to dup to any fd */ |
9426 | G_interactive_fd = dup(STDIN_FILENO); | 9469 | G_interactive_fd = dup_CLOEXEC(STDIN_FILENO); |
9427 | if (G_interactive_fd < 0) | 9470 | if (G_interactive_fd < 0) |
9428 | /* give up */ | 9471 | /* give up */ |
9429 | G_interactive_fd = 0; | 9472 | G_interactive_fd = 0; |
diff --git a/shell/hush_test/hush-heredoc/heredoc_bkslash_newline1.right b/shell/hush_test/hush-heredoc/heredoc_bkslash_newline1.right new file mode 100644 index 000000000..fdb7ebd03 --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredoc_bkslash_newline1.right | |||
@@ -0,0 +1,8 @@ | |||
1 | heredoc0 | ||
2 | Ok0:0 | ||
3 | heredoc1 | ||
4 | Ok1:0 | ||
5 | heredoc2 | ||
6 | Ok2:0 | ||
7 | heredoc3 | ||
8 | Ok4:0 | ||
diff --git a/shell/hush_test/hush-heredoc/heredoc_bkslash_newline1.tests b/shell/hush_test/hush-heredoc/heredoc_bkslash_newline1.tests new file mode 100755 index 000000000..584edd0e4 --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredoc_bkslash_newline1.tests | |||
@@ -0,0 +1,25 @@ | |||
1 | cat <\ | ||
2 | <\ | ||
3 | EOF | ||
4 | heredoc0 | ||
5 | EOF | ||
6 | echo Ok0:$? | ||
7 | |||
8 | cat <<\ | ||
9 | EOF | ||
10 | heredoc1 | ||
11 | EOF | ||
12 | echo Ok1:$? | ||
13 | |||
14 | cat <<\ | ||
15 | - EOF | ||
16 | heredoc2 | ||
17 | EOF | ||
18 | echo Ok2:$? | ||
19 | |||
20 | cat <\ | ||
21 | <\ | ||
22 | - EOF | ||
23 | heredoc3 | ||
24 | EOF | ||
25 | echo Ok4:$? | ||
diff --git a/shell/hush_test/hush-parsing/bkslash_newline1.right b/shell/hush_test/hush-parsing/bkslash_newline1.right new file mode 100644 index 000000000..97ea0c197 --- /dev/null +++ b/shell/hush_test/hush-parsing/bkslash_newline1.right | |||
@@ -0,0 +1,4 @@ | |||
1 | and1 | ||
2 | and2 | ||
3 | or1 | ||
4 | ok | ||
diff --git a/shell/hush_test/hush-parsing/bkslash_newline1.tests b/shell/hush_test/hush-parsing/bkslash_newline1.tests new file mode 100755 index 000000000..6e374c4fb --- /dev/null +++ b/shell/hush_test/hush-parsing/bkslash_newline1.tests | |||
@@ -0,0 +1,8 @@ | |||
1 | echo and1 &\ | ||
2 | & echo and2 | ||
3 | |||
4 | echo or1 |\ | ||
5 | | echo NOT SHOWN | ||
6 | |||
7 | case w in a) echo SKIP;\ | ||
8 | ; w) echo ok;; esac; | ||
diff --git a/shell/hush_test/hush-parsing/bkslash_newline2.right b/shell/hush_test/hush-parsing/bkslash_newline2.right new file mode 100644 index 000000000..c863c5453 --- /dev/null +++ b/shell/hush_test/hush-parsing/bkslash_newline2.right | |||
@@ -0,0 +1,4 @@ | |||
1 | Line with one backslash: | ||
2 | \ | ||
3 | |||
4 | Ok:0 | ||
diff --git a/shell/hush_test/hush-parsing/bkslash_newline2.tests b/shell/hush_test/hush-parsing/bkslash_newline2.tests new file mode 100755 index 000000000..47d63042d --- /dev/null +++ b/shell/hush_test/hush-parsing/bkslash_newline2.tests | |||
@@ -0,0 +1,4 @@ | |||
1 | echo Line with one backslash: | ||
2 | echo '\ | ||
3 | ' | ||
4 | echo Ok:$? | ||
diff --git a/shell/hush_test/hush-quoting/dollar_repl_slash_bash2.right b/shell/hush_test/hush-quoting/dollar_repl_slash_bash2.right new file mode 100644 index 000000000..2aead7129 --- /dev/null +++ b/shell/hush_test/hush-quoting/dollar_repl_slash_bash2.right | |||
@@ -0,0 +1 @@ | |||
\/a\/bc\/def\/file | |||
diff --git a/shell/hush_test/hush-quoting/dollar_repl_slash_bash2.tests b/shell/hush_test/hush-quoting/dollar_repl_slash_bash2.tests new file mode 100755 index 000000000..64ca0c170 --- /dev/null +++ b/shell/hush_test/hush-quoting/dollar_repl_slash_bash2.tests | |||
@@ -0,0 +1,2 @@ | |||
1 | var="/a/bc/def/file" | ||
2 | echo "${var//\//\\/}" | ||
diff --git a/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_1.right b/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_1.right new file mode 100644 index 000000000..46ab7f5d1 --- /dev/null +++ b/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_1.right | |||
@@ -0,0 +1,5 @@ | |||
1 | /proc/self/fd | ||
2 | /proc/self/fd/0 | ||
3 | /proc/self/fd/1 | ||
4 | /proc/self/fd/2 | ||
5 | /proc/self/fd/3 | ||
diff --git a/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_1.tests b/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_1.tests new file mode 100755 index 000000000..544c810e3 --- /dev/null +++ b/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_1.tests | |||
@@ -0,0 +1,6 @@ | |||
1 | # The "find" should not see "saved" (duplicated) fd #1 | ||
2 | # Explicitly use bbox find, since other implementations of "find" | ||
3 | # may open other descriptors as well. | ||
4 | busybox find /proc/self/fd >tmp_$$.out | ||
5 | cat tmp_$$.out | ||
6 | rm -f tmp_$$.out | ||
diff --git a/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_2.right b/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_2.right new file mode 100644 index 000000000..46ab7f5d1 --- /dev/null +++ b/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_2.right | |||
@@ -0,0 +1,5 @@ | |||
1 | /proc/self/fd | ||
2 | /proc/self/fd/0 | ||
3 | /proc/self/fd/1 | ||
4 | /proc/self/fd/2 | ||
5 | /proc/self/fd/3 | ||
diff --git a/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_2.tests b/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_2.tests new file mode 100755 index 000000000..43777cade --- /dev/null +++ b/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_2.tests | |||
@@ -0,0 +1,6 @@ | |||
1 | # The "find" should not see "saved" (duplicated) fd #1 | ||
2 | # Explicitly use bbox find, since other implementations of "find" | ||
3 | # may open other descriptors as well. | ||
4 | { busybox find /proc/self/fd; } >tmp_$$.out | ||
5 | cat tmp_$$.out | ||
6 | rm -f tmp_$$.out | ||
diff --git a/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_3.right b/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_3.right new file mode 100644 index 000000000..46ab7f5d1 --- /dev/null +++ b/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_3.right | |||
@@ -0,0 +1,5 @@ | |||
1 | /proc/self/fd | ||
2 | /proc/self/fd/0 | ||
3 | /proc/self/fd/1 | ||
4 | /proc/self/fd/2 | ||
5 | /proc/self/fd/3 | ||
diff --git a/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_3.tests b/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_3.tests new file mode 100755 index 000000000..0a21173bd --- /dev/null +++ b/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_3.tests | |||
@@ -0,0 +1,6 @@ | |||
1 | # The "find" should not see "saved" (duplicated) fd #1 | ||
2 | # Explicitly use bbox find, since other implementations of "find" | ||
3 | # may open other descriptors as well. | ||
4 | { busybox find /proc/self/fd; true; } >tmp_$$.out | ||
5 | cat tmp_$$.out | ||
6 | rm -f tmp_$$.out | ||
diff --git a/shell/hush_test/hush-vars/var_LINENO1.tests b/shell/hush_test/hush-vars/var_LINENO1.tests index 851b52cf5..775861e64 100755 --- a/shell/hush_test/hush-vars/var_LINENO1.tests +++ b/shell/hush_test/hush-vars/var_LINENO1.tests | |||
@@ -1,4 +1,4 @@ | |||
1 | env | grep LINENO | 1 | env | grep ^LINENO |
2 | echo 2:$LINENO | 2 | echo 2:$LINENO |
3 | echo 3:$LINENO >&2 \ | 3 | echo 3:$LINENO >&2 \ |
4 | | { sleep 0.1; echo 4:$LINENO; } | 4 | | { sleep 0.1; echo 4:$LINENO; } |
diff --git a/testsuite/grep.tests b/testsuite/grep.tests index ed4ba455e..d0b0d2767 100755 --- a/testsuite/grep.tests +++ b/testsuite/grep.tests | |||
@@ -165,6 +165,12 @@ testing "grep -w word doesn't match wordword" \ | |||
165 | "wordword\n" \ | 165 | "wordword\n" \ |
166 | "" | 166 | "" |
167 | 167 | ||
168 | testing "grep -F -w w doesn't match ww" \ | ||
169 | "grep -F -w w input" \ | ||
170 | "" \ | ||
171 | "ww\n" \ | ||
172 | "" | ||
173 | |||
168 | testing "grep -w word match second word" \ | 174 | testing "grep -w word match second word" \ |
169 | "grep -w word input" \ | 175 | "grep -w word input" \ |
170 | "bword,word\n""wordb,word\n""bwordb,word\n" \ | 176 | "bword,word\n""wordb,word\n""bwordb,word\n" \ |
diff --git a/util-linux/fstrim.c b/util-linux/fstrim.c index 205d1e42b..558a94a9e 100644 --- a/util-linux/fstrim.c +++ b/util-linux/fstrim.c | |||
@@ -70,7 +70,9 @@ int fstrim_main(int argc UNUSED_PARAM, char **argv) | |||
70 | ; | 70 | ; |
71 | #endif | 71 | #endif |
72 | 72 | ||
73 | opts = getopt32long(argv, "^" "o:l:m:v" "\0" "=1", fstrim_longopts, | 73 | opts = getopt32long(argv, "^" |
74 | "o:l:m:v" | ||
75 | "\0" "=1", fstrim_longopts, | ||
74 | &arg_o, &arg_l, &arg_m | 76 | &arg_o, &arg_l, &arg_m |
75 | ); | 77 | ); |
76 | 78 | ||
@@ -85,15 +87,21 @@ int fstrim_main(int argc UNUSED_PARAM, char **argv) | |||
85 | range.minlen = xatoull_sfx(arg_m, kmg_i_suffixes); | 87 | range.minlen = xatoull_sfx(arg_m, kmg_i_suffixes); |
86 | 88 | ||
87 | mp = argv[optind]; | 89 | mp = argv[optind]; |
88 | if (find_block_device(mp)) { | 90 | //Wwhy bother checking that it's a blockdev? |
91 | // if (find_block_device(mp)) { | ||
89 | fd = xopen_nonblocking(mp); | 92 | fd = xopen_nonblocking(mp); |
93 | |||
94 | /* On ENOTTY error, util-linux 2.31 says: | ||
95 | * "fstrim: FILE: the discard operation is not supported" | ||
96 | */ | ||
90 | xioctl(fd, FITRIM, &range); | 97 | xioctl(fd, FITRIM, &range); |
98 | |||
91 | if (ENABLE_FEATURE_CLEAN_UP) | 99 | if (ENABLE_FEATURE_CLEAN_UP) |
92 | close(fd); | 100 | close(fd); |
93 | 101 | ||
94 | if (opts & OPT_v) | 102 | if (opts & OPT_v) |
95 | printf("%s: %llu bytes trimmed\n", mp, (unsigned long long)range.len); | 103 | printf("%s: %llu bytes trimmed\n", mp, (unsigned long long)range.len); |
96 | return EXIT_SUCCESS; | 104 | return EXIT_SUCCESS; |
97 | } | 105 | // } |
98 | return EXIT_FAILURE; | 106 | return EXIT_FAILURE; |
99 | } | 107 | } |