aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--archival/Config.src2
-rw-r--r--archival/ar.c16
-rw-r--r--archival/bbunzip.c23
-rw-r--r--archival/gzip.c1
-rw-r--r--archival/libarchive/data_extract_all.c118
-rw-r--r--archival/libarchive/decompress_gunzip.c36
-rw-r--r--archival/libarchive/get_header_tar.c1
-rw-r--r--archival/lzop.c14
-rw-r--r--archival/tar.c89
-rw-r--r--configs/android2_defconfig1
-rw-r--r--configs/android_defconfig1
-rw-r--r--configs/android_ndk_defconfig1
-rw-r--r--configs/cygwin_defconfig1
-rw-r--r--coreutils/Config.src15
-rw-r--r--coreutils/ls.c2
-rw-r--r--coreutils/sort.c67
-rw-r--r--coreutils/stat.c81
-rw-r--r--coreutils/stty.c2
-rw-r--r--coreutils/tr.c23
-rw-r--r--examples/var_service/README8
-rwxr-xr-xexamples/var_service/dhcp_if/convert2ntpconf2
-rwxr-xr-xexamples/var_service/dhcp_if/dhcp_handler13
-rwxr-xr-xexamples/var_service/dhcp_if/finish17
-rwxr-xr-xexamples/var_service/dhcp_if/log/run2
-rwxr-xr-xexamples/var_service/dhcp_if_pinger/run4
-rwxr-xr-xexamples/var_service/ftpd/log/run2
-rwxr-xr-xexamples/var_service/fw/run2
-rwxr-xr-xexamples/var_service/httpd/log/run2
-rwxr-xr-xexamples/var_service/ifplugd_if/log/run2
-rwxr-xr-xexamples/var_service/ifplugd_if/run3
-rwxr-xr-xexamples/var_service/inetd/log/run2
-rwxr-xr-xexamples/var_service/ntpd/log/run2
-rwxr-xr-xexamples/var_service/ntpd/run2
-rwxr-xr-xexamples/var_service/tftpd/log/run2
-rw-r--r--examples/var_service/zcip_if/README5
-rwxr-xr-xexamples/var_service/zcip_if/convert2ipconf24
-rwxr-xr-xexamples/var_service/zcip_if/finish13
-rwxr-xr-xexamples/var_service/zcip_if/log/run21
-rwxr-xr-xexamples/var_service/zcip_if/p_log4
-rwxr-xr-xexamples/var_service/zcip_if/run20
-rwxr-xr-xexamples/var_service/zcip_if/w_log4
-rwxr-xr-xexamples/var_service/zcip_if/zcip_handler47
-rw-r--r--findutils/xargs.c3
-rw-r--r--include/applets.src.h3
-rw-r--r--include/bb_archive.h3
-rw-r--r--include/libbb.h6
-rw-r--r--libbb/Config.src10
-rw-r--r--libbb/appletlib.c10
-rw-r--r--libbb/kernel_version.c8
-rw-r--r--libbb/lineedit.c4
-rw-r--r--libbb/procps.c8
-rw-r--r--libbb/progress.c20
-rw-r--r--libbb/systemd_support.c62
-rw-r--r--libbb/xfuncs.c6
-rw-r--r--loginutils/login.c2
-rw-r--r--miscutils/Config.src16
-rw-r--r--miscutils/fbsplash.c2
-rw-r--r--modutils/Config.src3
-rw-r--r--modutils/modinfo.c114
-rw-r--r--modutils/modprobe.c7
-rw-r--r--modutils/modutils.c5
-rw-r--r--modutils/rmmod.c12
-rw-r--r--networking/Config.src2
-rw-r--r--networking/httpd.c25
-rw-r--r--networking/ifupdown.c7
-rw-r--r--networking/libiproute/ll_map.c25
-rw-r--r--networking/udhcp/dumpleases.c28
-rw-r--r--networking/udhcp/leases.c11
-rw-r--r--networking/wget.c47
-rw-r--r--networking/zcip.c8
-rw-r--r--procps/pmap.c4
-rw-r--r--procps/ps.c4
-rw-r--r--procps/pstree.c2
-rw-r--r--procps/watch.c2
-rw-r--r--qemu_multiarch_testing/README5
-rwxr-xr-xscripts/trylink59
-rw-r--r--shell/ash.c115
-rw-r--r--shell/ash_test/ash-heredoc/heredoc2.right2
-rwxr-xr-xshell/ash_test/ash-heredoc/heredoc2.tests7
-rw-r--r--shell/ash_test/ash-heredoc/heredoc3.right1
-rwxr-xr-xshell/ash_test/ash-heredoc/heredoc3.tests9
-rw-r--r--shell/ash_test/ash-misc/command.right1
-rwxr-xr-xshell/ash_test/ash-misc/command.tests1
-rw-r--r--shell/ash_test/ash-misc/command2.right2
-rwxr-xr-xshell/ash_test/ash-misc/command2.tests6
-rw-r--r--shell/ash_test/ash-misc/exec.right2
-rwxr-xr-xshell/ash_test/ash-misc/exec.tests3
-rw-r--r--shell/ash_test/ash-misc/for.right1
-rwxr-xr-xshell/ash_test/ash-misc/for.tests5
-rw-r--r--shell/ash_test/ash-misc/local2.right1
-rwxr-xr-xshell/ash_test/ash-misc/local2.tests1
-rwxr-xr-xshell/ash_test/run-all6
-rw-r--r--shell/hush_test/hush-misc/for.right1
-rwxr-xr-xshell/hush_test/hush-misc/for.tests5
-rw-r--r--sysklogd/syslogd.c5
-rwxr-xr-xtestsuite/sort.tests44
-rwxr-xr-xtestsuite/tar.tests53
-rwxr-xr-xtestsuite/unzip.tests24
-rw-r--r--util-linux/Config.src10
-rw-r--r--util-linux/Kbuild.src1
-rw-r--r--util-linux/setarch.c54
101 files changed, 1041 insertions, 549 deletions
diff --git a/archival/Config.src b/archival/Config.src
index 76635ba78..a9afaea5b 100644
--- a/archival/Config.src
+++ b/archival/Config.src
@@ -31,7 +31,7 @@ config FEATURE_SEAMLESS_GZ
31 31
32config FEATURE_SEAMLESS_Z 32config FEATURE_SEAMLESS_Z
33 bool "tar, rpm, modprobe etc understand .Z data" 33 bool "tar, rpm, modprobe etc understand .Z data"
34 default n 34 default n # it is ancient
35 help 35 help
36 Make tar, rpm, modprobe etc understand .Z data. 36 Make tar, rpm, modprobe etc understand .Z data.
37 37
diff --git a/archival/ar.c b/archival/ar.c
index 89e6a1207..a850868f6 100644
--- a/archival/ar.c
+++ b/archival/ar.c
@@ -22,23 +22,13 @@
22//config: default n # needs to be improved to be able to replace binutils ar 22//config: default n # needs to be improved to be able to replace binutils ar
23//config: help 23//config: help
24//config: ar is an archival utility program used to create, modify, and 24//config: ar is an archival utility program used to create, modify, and
25//config: extract contents from archives. An archive is a single file holding 25//config: extract contents from archives. In practice, it is used exclusively
26//config: a collection of other files in a structure that makes it possible to 26//config: for object module archives used by compilers.
27//config: retrieve the original individual files (called archive members).
28//config: The original files' contents, mode (permissions), timestamp, owner,
29//config: and group are preserved in the archive, and can be restored on
30//config: extraction.
31//config: 27//config:
32//config: The stored filename is limited to 15 characters. (for more information
33//config: see long filename support).
34//config: ar has 60 bytes of overheads for every stored file.
35//config:
36//config: This implementation of ar can extract archives, it cannot create or
37//config: modify them.
38//config: On an x86 system, the ar applet adds about 1K. 28//config: On an x86 system, the ar applet adds about 1K.
39//config: 29//config:
40//config: Unless you have a specific application which requires ar, you should 30//config: Unless you have a specific application which requires ar, you should
41//config: probably say N here. 31//config: probably say N here: most compilers come with their own ar utility.
42//config: 32//config:
43//config:config FEATURE_AR_LONG_FILENAMES 33//config:config FEATURE_AR_LONG_FILENAMES
44//config: bool "Support for long filenames (not needed for debs)" 34//config: bool "Support for long filenames (not needed for debs)"
diff --git a/archival/bbunzip.c b/archival/bbunzip.c
index a859ef201..aaaf67e03 100644
--- a/archival/bbunzip.c
+++ b/archival/bbunzip.c
@@ -222,7 +222,7 @@ char* FAST_FUNC make_new_name_generic(char *filename, const char *expected_ext)
222 222
223//config:config UNCOMPRESS 223//config:config UNCOMPRESS
224//config: bool "uncompress" 224//config: bool "uncompress"
225//config: default n 225//config: default n # ancient
226//config: help 226//config: help
227//config: uncompress is used to decompress archives created by compress. 227//config: uncompress is used to decompress archives created by compress.
228//config: Not much used anymore, replaced by gzip/gunzip. 228//config: Not much used anymore, replaced by gzip/gunzip.
@@ -292,6 +292,13 @@ int uncompress_main(int argc UNUSED_PARAM, char **argv)
292//config: gunzip is used to decompress archives created by gzip. 292//config: gunzip is used to decompress archives created by gzip.
293//config: You can use the `-t' option to test the integrity of 293//config: You can use the `-t' option to test the integrity of
294//config: an archive, without decompressing it. 294//config: an archive, without decompressing it.
295//config:
296//config:config FEATURE_GUNZIP_LONG_OPTIONS
297//config: bool "Enable long options"
298//config: default y
299//config: depends on GUNZIP && LONG_OPTS
300//config: help
301//config: Enable use of long options.
295 302
296//applet:IF_GUNZIP(APPLET(gunzip, BB_DIR_BIN, BB_SUID_DROP)) 303//applet:IF_GUNZIP(APPLET(gunzip, BB_DIR_BIN, BB_SUID_DROP))
297//applet:IF_GUNZIP(APPLET_ODDNAME(zcat, gunzip, BB_DIR_BIN, BB_SUID_DROP, zcat)) 304//applet:IF_GUNZIP(APPLET_ODDNAME(zcat, gunzip, BB_DIR_BIN, BB_SUID_DROP, zcat))
@@ -323,6 +330,17 @@ char* FAST_FUNC make_new_name_gunzip(char *filename, const char *expected_ext UN
323 } 330 }
324 return filename; 331 return filename;
325} 332}
333
334#if ENABLE_FEATURE_GUNZIP_LONG_OPTIONS
335static const char gunzip_longopts[] ALIGN1 =
336 "stdout\0" No_argument "c"
337 "to-stdout\0" No_argument "c"
338 "force\0" No_argument "f"
339 "test\0" No_argument "t"
340 "no-name\0" No_argument "n"
341 ;
342#endif
343
326/* 344/*
327 * Linux kernel build uses gzip -d -n. We accept and ignore it. 345 * Linux kernel build uses gzip -d -n. We accept and ignore it.
328 * Man page says: 346 * Man page says:
@@ -339,6 +357,9 @@ char* FAST_FUNC make_new_name_gunzip(char *filename, const char *expected_ext UN
339int gunzip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 357int gunzip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
340int gunzip_main(int argc UNUSED_PARAM, char **argv) 358int gunzip_main(int argc UNUSED_PARAM, char **argv)
341{ 359{
360#if ENABLE_FEATURE_GUNZIP_LONG_OPTIONS
361 applet_long_options = gunzip_longopts;
362#endif
342 getopt32(argv, "cfvqdtn"); 363 getopt32(argv, "cfvqdtn");
343 argv += optind; 364 argv += optind;
344 365
diff --git a/archival/gzip.c b/archival/gzip.c
index c9171304a..f9bb3c742 100644
--- a/archival/gzip.c
+++ b/archival/gzip.c
@@ -2160,6 +2160,7 @@ static const char gzip_longopts[] ALIGN1 =
2160 "quiet\0" No_argument "q" 2160 "quiet\0" No_argument "q"
2161 "fast\0" No_argument "1" 2161 "fast\0" No_argument "1"
2162 "best\0" No_argument "9" 2162 "best\0" No_argument "9"
2163 "no-name\0" No_argument "n"
2163 ; 2164 ;
2164#endif 2165#endif
2165 2166
diff --git a/archival/libarchive/data_extract_all.c b/archival/libarchive/data_extract_all.c
index 45776dcbe..bd034afdc 100644
--- a/archival/libarchive/data_extract_all.c
+++ b/archival/libarchive/data_extract_all.c
@@ -11,6 +11,12 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
11 file_header_t *file_header = archive_handle->file_header; 11 file_header_t *file_header = archive_handle->file_header;
12 int dst_fd; 12 int dst_fd;
13 int res; 13 int res;
14 char *hard_link;
15#if ENABLE_FEATURE_TAR_LONG_OPTIONS
16 char *dst_name;
17#else
18# define dst_name (file_header->name)
19#endif
14 20
15#if ENABLE_FEATURE_TAR_SELINUX 21#if ENABLE_FEATURE_TAR_SELINUX
16 char *sctx = archive_handle->tar__sctx[PAX_NEXT_FILE]; 22 char *sctx = archive_handle->tar__sctx[PAX_NEXT_FILE];
@@ -23,11 +29,49 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
23 } 29 }
24#endif 30#endif
25 31
32 /* Hard links are encoded as regular files of size 0
33 * with a nonempty link field */
34 hard_link = NULL;
35 if (S_ISREG(file_header->mode) && file_header->size == 0)
36 hard_link = file_header->link_target;
37
38#if ENABLE_FEATURE_TAR_LONG_OPTIONS
39 dst_name = file_header->name;
40 if (archive_handle->tar__strip_components) {
41 unsigned n = archive_handle->tar__strip_components;
42 do {
43 dst_name = strchr(dst_name, '/');
44 if (!dst_name || dst_name[1] == '\0') {
45 data_skip(archive_handle);
46 goto ret;
47 }
48 dst_name++;
49 /*
50 * Link target is shortened only for hardlinks:
51 * softlinks restored unchanged.
52 */
53 if (hard_link) {
54// GNU tar 1.26 does not check that we reached end of link name:
55// if "dir/hardlink" is hardlinked to "file",
56// tar xvf a.tar --strip-components=1 says:
57// tar: hardlink: Cannot hard link to '': No such file or directory
58// and continues processing. We silently skip such entries.
59 hard_link = strchr(hard_link, '/');
60 if (!hard_link || hard_link[1] == '\0') {
61 data_skip(archive_handle);
62 goto ret;
63 }
64 hard_link++;
65 }
66 } while (--n != 0);
67 }
68#endif
69
26 if (archive_handle->ah_flags & ARCHIVE_CREATE_LEADING_DIRS) { 70 if (archive_handle->ah_flags & ARCHIVE_CREATE_LEADING_DIRS) {
27 char *slash = strrchr(file_header->name, '/'); 71 char *slash = strrchr(dst_name, '/');
28 if (slash) { 72 if (slash) {
29 *slash = '\0'; 73 *slash = '\0';
30 bb_make_directory(file_header->name, -1, FILEUTILS_RECUR); 74 bb_make_directory(dst_name, -1, FILEUTILS_RECUR);
31 *slash = '/'; 75 *slash = '/';
32 } 76 }
33 } 77 }
@@ -35,12 +79,7 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
35 if (archive_handle->ah_flags & ARCHIVE_UNLINK_OLD) { 79 if (archive_handle->ah_flags & ARCHIVE_UNLINK_OLD) {
36 /* Remove the entry if it exists */ 80 /* Remove the entry if it exists */
37 if (!S_ISDIR(file_header->mode)) { 81 if (!S_ISDIR(file_header->mode)) {
38 /* Is it hardlink? 82 if (hard_link) {
39 * We encode hard links as regular files of size 0 with a symlink */
40 if (S_ISREG(file_header->mode)
41 && file_header->link_target
42 && file_header->size == 0
43 ) {
44 /* Ugly special case: 83 /* Ugly special case:
45 * tar cf t.tar hardlink1 hardlink2 hardlink1 84 * tar cf t.tar hardlink1 hardlink2 hardlink1
46 * results in this tarball structure: 85 * results in this tarball structure:
@@ -48,22 +87,22 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
48 * hardlink2 -> hardlink1 87 * hardlink2 -> hardlink1
49 * hardlink1 -> hardlink1 <== !!! 88 * hardlink1 -> hardlink1 <== !!!
50 */ 89 */
51 if (strcmp(file_header->link_target, file_header->name) == 0) 90 if (strcmp(hard_link, dst_name) == 0)
52 goto ret; 91 goto ret;
53 } 92 }
54 /* Proceed with deleting */ 93 /* Proceed with deleting */
55 if (unlink(file_header->name) == -1 94 if (unlink(dst_name) == -1
56 && errno != ENOENT 95 && errno != ENOENT
57 ) { 96 ) {
58 bb_perror_msg_and_die("can't remove old file %s", 97 bb_perror_msg_and_die("can't remove old file %s",
59 file_header->name); 98 dst_name);
60 } 99 }
61 } 100 }
62 } 101 }
63 else if (archive_handle->ah_flags & ARCHIVE_EXTRACT_NEWER) { 102 else if (archive_handle->ah_flags & ARCHIVE_EXTRACT_NEWER) {
64 /* Remove the existing entry if its older than the extracted entry */ 103 /* Remove the existing entry if its older than the extracted entry */
65 struct stat existing_sb; 104 struct stat existing_sb;
66 if (lstat(file_header->name, &existing_sb) == -1) { 105 if (lstat(dst_name, &existing_sb) == -1) {
67 if (errno != ENOENT) { 106 if (errno != ENOENT) {
68 bb_perror_msg_and_die("can't stat old file"); 107 bb_perror_msg_and_die("can't stat old file");
69 } 108 }
@@ -73,30 +112,25 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
73 && !S_ISDIR(file_header->mode) 112 && !S_ISDIR(file_header->mode)
74 ) { 113 ) {
75 bb_error_msg("%s not created: newer or " 114 bb_error_msg("%s not created: newer or "
76 "same age file exists", file_header->name); 115 "same age file exists", dst_name);
77 } 116 }
78 data_skip(archive_handle); 117 data_skip(archive_handle);
79 goto ret; 118 goto ret;
80 } 119 }
81 else if ((unlink(file_header->name) == -1) && (errno != EISDIR)) { 120 else if ((unlink(dst_name) == -1) && (errno != EISDIR)) {
82 bb_perror_msg_and_die("can't remove old file %s", 121 bb_perror_msg_and_die("can't remove old file %s",
83 file_header->name); 122 dst_name);
84 } 123 }
85 } 124 }
86 125
87 /* Handle hard links separately 126 /* Handle hard links separately */
88 * We encode hard links as regular files of size 0 with a symlink */ 127 if (hard_link) {
89 if (S_ISREG(file_header->mode) 128 res = link(hard_link, dst_name);
90 && file_header->link_target 129 if (res != 0 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) {
91 && file_header->size == 0
92 ) {
93 /* hard link */
94 res = link(file_header->link_target, file_header->name);
95 if ((res == -1) && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) {
96 bb_perror_msg("can't create %slink " 130 bb_perror_msg("can't create %slink "
97 "from %s to %s", "hard", 131 "from %s to %s", "hard",
98 file_header->name, 132 dst_name,
99 file_header->link_target); 133 hard_link);
100 } 134 }
101 /* Hardlinks have no separate mode/ownership, skip chown/chmod */ 135 /* Hardlinks have no separate mode/ownership, skip chown/chmod */
102 goto ret; 136 goto ret;
@@ -106,17 +140,17 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
106 switch (file_header->mode & S_IFMT) { 140 switch (file_header->mode & S_IFMT) {
107 case S_IFREG: { 141 case S_IFREG: {
108 /* Regular file */ 142 /* Regular file */
109 char *dst_name; 143 char *dst_nameN;
110 int flags = O_WRONLY | O_CREAT | O_EXCL; 144 int flags = O_WRONLY | O_CREAT | O_EXCL;
111 if (archive_handle->ah_flags & ARCHIVE_O_TRUNC) 145 if (archive_handle->ah_flags & ARCHIVE_O_TRUNC)
112 flags = O_WRONLY | O_CREAT | O_TRUNC; 146 flags = O_WRONLY | O_CREAT | O_TRUNC;
113 dst_name = file_header->name; 147 dst_nameN = dst_name;
114#ifdef ARCHIVE_REPLACE_VIA_RENAME 148#ifdef ARCHIVE_REPLACE_VIA_RENAME
115 if (archive_handle->ah_flags & ARCHIVE_REPLACE_VIA_RENAME) 149 if (archive_handle->ah_flags & ARCHIVE_REPLACE_VIA_RENAME)
116 /* rpm-style temp file name */ 150 /* rpm-style temp file name */
117 dst_name = xasprintf("%s;%x", dst_name, (int)getpid()); 151 dst_nameN = xasprintf("%s;%x", dst_name, (int)getpid());
118#endif 152#endif
119 dst_fd = xopen3(dst_name, 153 dst_fd = xopen3(dst_nameN,
120 flags, 154 flags,
121 file_header->mode 155 file_header->mode
122 ); 156 );
@@ -124,32 +158,32 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
124 close(dst_fd); 158 close(dst_fd);
125#ifdef ARCHIVE_REPLACE_VIA_RENAME 159#ifdef ARCHIVE_REPLACE_VIA_RENAME
126 if (archive_handle->ah_flags & ARCHIVE_REPLACE_VIA_RENAME) { 160 if (archive_handle->ah_flags & ARCHIVE_REPLACE_VIA_RENAME) {
127 xrename(dst_name, file_header->name); 161 xrename(dst_nameN, dst_name);
128 free(dst_name); 162 free(dst_nameN);
129 } 163 }
130#endif 164#endif
131 break; 165 break;
132 } 166 }
133 case S_IFDIR: 167 case S_IFDIR:
134 res = mkdir(file_header->name, file_header->mode); 168 res = mkdir(dst_name, file_header->mode);
135 if ((res == -1) 169 if ((res == -1)
136 && (errno != EISDIR) /* btw, Linux doesn't return this */ 170 && (errno != EISDIR) /* btw, Linux doesn't return this */
137 && (errno != EEXIST) 171 && (errno != EEXIST)
138 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) 172 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
139 ) { 173 ) {
140 bb_perror_msg("can't make dir %s", file_header->name); 174 bb_perror_msg("can't make dir %s", dst_name);
141 } 175 }
142 break; 176 break;
143 case S_IFLNK: 177 case S_IFLNK:
144 /* Symlink */ 178 /* Symlink */
145//TODO: what if file_header->link_target == NULL (say, corrupted tarball?) 179//TODO: what if file_header->link_target == NULL (say, corrupted tarball?)
146 res = symlink(file_header->link_target, file_header->name); 180 res = symlink(file_header->link_target, dst_name);
147 if ((res == -1) 181 if (res != 0
148 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) 182 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
149 ) { 183 ) {
150 bb_perror_msg("can't create %slink " 184 bb_perror_msg("can't create %slink "
151 "from %s to %s", "sym", 185 "from %s to %s", "sym",
152 file_header->name, 186 dst_name,
153 file_header->link_target); 187 file_header->link_target);
154 } 188 }
155 break; 189 break;
@@ -157,11 +191,11 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
157 case S_IFBLK: 191 case S_IFBLK:
158 case S_IFCHR: 192 case S_IFCHR:
159 case S_IFIFO: 193 case S_IFIFO:
160 res = mknod(file_header->name, file_header->mode, file_header->device); 194 res = mknod(dst_name, file_header->mode, file_header->device);
161 if ((res == -1) 195 if ((res == -1)
162 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) 196 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
163 ) { 197 ) {
164 bb_perror_msg("can't create node %s", file_header->name); 198 bb_perror_msg("can't create node %s", dst_name);
165 } 199 }
166 break; 200 break;
167 default: 201 default:
@@ -186,20 +220,20 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
186 } 220 }
187#endif 221#endif
188 /* GNU tar 1.15.1 uses chown, not lchown */ 222 /* GNU tar 1.15.1 uses chown, not lchown */
189 chown(file_header->name, uid, gid); 223 chown(dst_name, uid, gid);
190 } 224 }
191 /* uclibc has no lchmod, glibc is even stranger - 225 /* uclibc has no lchmod, glibc is even stranger -
192 * it has lchmod which seems to do nothing! 226 * it has lchmod which seems to do nothing!
193 * so we use chmod... */ 227 * so we use chmod... */
194 if (!(archive_handle->ah_flags & ARCHIVE_DONT_RESTORE_PERM)) { 228 if (!(archive_handle->ah_flags & ARCHIVE_DONT_RESTORE_PERM)) {
195 chmod(file_header->name, file_header->mode); 229 chmod(dst_name, file_header->mode);
196 } 230 }
197 if (archive_handle->ah_flags & ARCHIVE_RESTORE_DATE) { 231 if (archive_handle->ah_flags & ARCHIVE_RESTORE_DATE) {
198 struct timeval t[2]; 232 struct timeval t[2];
199 233
200 t[1].tv_sec = t[0].tv_sec = file_header->mtime; 234 t[1].tv_sec = t[0].tv_sec = file_header->mtime;
201 t[1].tv_usec = t[0].tv_usec = 0; 235 t[1].tv_usec = t[0].tv_usec = 0;
202 utimes(file_header->name, t); 236 utimes(dst_name, t);
203 } 237 }
204 } 238 }
205 239
diff --git a/archival/libarchive/decompress_gunzip.c b/archival/libarchive/decompress_gunzip.c
index b6ae7f738..eb64645ae 100644
--- a/archival/libarchive/decompress_gunzip.c
+++ b/archival/libarchive/decompress_gunzip.c
@@ -308,11 +308,11 @@ static int huft_build(const unsigned *b, const unsigned n,
308 unsigned i; /* counter, current code */ 308 unsigned i; /* counter, current code */
309 unsigned j; /* counter */ 309 unsigned j; /* counter */
310 int k; /* number of bits in current code */ 310 int k; /* number of bits in current code */
311 unsigned *p; /* pointer into c[], b[], or v[] */ 311 const unsigned *p; /* pointer into c[], b[], or v[] */
312 huft_t *q; /* points to current table */ 312 huft_t *q; /* points to current table */
313 huft_t r; /* table entry for structure assignment */ 313 huft_t r; /* table entry for structure assignment */
314 huft_t *u[BMAX]; /* table stack */ 314 huft_t *u[BMAX]; /* table stack */
315 unsigned v[N_MAX]; /* values in order of bit length */ 315 unsigned v[N_MAX + 1]; /* values in order of bit length. last v[] is never used */
316 int ws[BMAX + 1]; /* bits decoded stack */ 316 int ws[BMAX + 1]; /* bits decoded stack */
317 int w; /* bits decoded */ 317 int w; /* bits decoded */
318 unsigned x[BMAX + 1]; /* bit offsets, then code stack */ 318 unsigned x[BMAX + 1]; /* bit offsets, then code stack */
@@ -327,7 +327,7 @@ static int huft_build(const unsigned *b, const unsigned n,
327 327
328 /* Generate counts for each bit length */ 328 /* Generate counts for each bit length */
329 memset(c, 0, sizeof(c)); 329 memset(c, 0, sizeof(c));
330 p = (unsigned *) b; /* cast allows us to reuse p for pointing to b */ 330 p = b;
331 i = n; 331 i = n;
332 do { 332 do {
333 c[*p]++; /* assume all entries <= BMAX */ 333 c[*p]++; /* assume all entries <= BMAX */
@@ -367,8 +367,12 @@ static int huft_build(const unsigned *b, const unsigned n,
367 *xp++ = j; 367 *xp++ = j;
368 } 368 }
369 369
370 /* Make a table of values in order of bit lengths */ 370 /* Make a table of values in order of bit lengths.
371 p = (unsigned *) b; 371 * To detect bad input, unused v[i]'s are set to invalid value UINT_MAX.
372 * In particular, last v[i] is never filled and must not be accessed.
373 */
374 memset(v, 0xff, sizeof(v));
375 p = b;
372 i = 0; 376 i = 0;
373 do { 377 do {
374 j = *p++; 378 j = *p++;
@@ -435,7 +439,9 @@ static int huft_build(const unsigned *b, const unsigned n,
435 439
436 /* set up table entry in r */ 440 /* set up table entry in r */
437 r.b = (unsigned char) (k - w); 441 r.b = (unsigned char) (k - w);
438 if (p >= v + n) { 442 if (/*p >= v + n || -- redundant, caught by the second check: */
443 *p == UINT_MAX /* do we access uninited v[i]? (see memset(v))*/
444 ) {
439 r.e = 99; /* out of values--invalid code */ 445 r.e = 99; /* out of values--invalid code */
440 } else if (*p < s) { 446 } else if (*p < s) {
441 r.e = (unsigned char) (*p < 256 ? 16 : 15); /* 256 is EOB code */ 447 r.e = (unsigned char) (*p < 256 ? 16 : 15); /* 256 is EOB code */
@@ -520,8 +526,9 @@ static NOINLINE int inflate_codes(STATE_PARAM_ONLY)
520 e = t->e; 526 e = t->e;
521 if (e > 16) 527 if (e > 16)
522 do { 528 do {
523 if (e == 99) 529 if (e == 99) {
524 abort_unzip(PASS_STATE_ONLY);; 530 abort_unzip(PASS_STATE_ONLY);
531 }
525 bb >>= t->b; 532 bb >>= t->b;
526 k -= t->b; 533 k -= t->b;
527 e -= 16; 534 e -= 16;
@@ -557,8 +564,9 @@ static NOINLINE int inflate_codes(STATE_PARAM_ONLY)
557 e = t->e; 564 e = t->e;
558 if (e > 16) 565 if (e > 16)
559 do { 566 do {
560 if (e == 99) 567 if (e == 99) {
561 abort_unzip(PASS_STATE_ONLY); 568 abort_unzip(PASS_STATE_ONLY);
569 }
562 bb >>= t->b; 570 bb >>= t->b;
563 k -= t->b; 571 k -= t->b;
564 e -= 16; 572 e -= 16;
@@ -824,8 +832,9 @@ static int inflate_block(STATE_PARAM smallint *e)
824 832
825 b_dynamic >>= 4; 833 b_dynamic >>= 4;
826 k_dynamic -= 4; 834 k_dynamic -= 4;
827 if (nl > 286 || nd > 30) 835 if (nl > 286 || nd > 30) {
828 abort_unzip(PASS_STATE_ONLY); /* bad lengths */ 836 abort_unzip(PASS_STATE_ONLY); /* bad lengths */
837 }
829 838
830 /* read in bit-length-code lengths */ 839 /* read in bit-length-code lengths */
831 for (j = 0; j < nb; j++) { 840 for (j = 0; j < nb; j++) {
@@ -906,12 +915,14 @@ static int inflate_block(STATE_PARAM smallint *e)
906 bl = lbits; 915 bl = lbits;
907 916
908 i = huft_build(ll, nl, 257, cplens, cplext, &inflate_codes_tl, &bl); 917 i = huft_build(ll, nl, 257, cplens, cplext, &inflate_codes_tl, &bl);
909 if (i != 0) 918 if (i != 0) {
910 abort_unzip(PASS_STATE_ONLY); 919 abort_unzip(PASS_STATE_ONLY);
920 }
911 bd = dbits; 921 bd = dbits;
912 i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &inflate_codes_td, &bd); 922 i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &inflate_codes_td, &bd);
913 if (i != 0) 923 if (i != 0) {
914 abort_unzip(PASS_STATE_ONLY); 924 abort_unzip(PASS_STATE_ONLY);
925 }
915 926
916 /* set up data for inflate_codes() */ 927 /* set up data for inflate_codes() */
917 inflate_codes_setup(PASS_STATE bl, bd); 928 inflate_codes_setup(PASS_STATE bl, bd);
@@ -999,6 +1010,7 @@ inflate_unzip_internal(STATE_PARAM transformer_state_t *xstate)
999 error_msg = "corrupted data"; 1010 error_msg = "corrupted data";
1000 if (setjmp(error_jmp)) { 1011 if (setjmp(error_jmp)) {
1001 /* Error from deep inside zip machinery */ 1012 /* Error from deep inside zip machinery */
1013 bb_error_msg(error_msg);
1002 n = -1; 1014 n = -1;
1003 goto ret; 1015 goto ret;
1004 } 1016 }
diff --git a/archival/libarchive/get_header_tar.c b/archival/libarchive/get_header_tar.c
index fb68673b9..ac2be726f 100644
--- a/archival/libarchive/get_header_tar.c
+++ b/archival/libarchive/get_header_tar.c
@@ -418,6 +418,7 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
418 418
419 /* Everything up to and including last ".." component is stripped */ 419 /* Everything up to and including last ".." component is stripped */
420 overlapping_strcpy(file_header->name, strip_unsafe_prefix(file_header->name)); 420 overlapping_strcpy(file_header->name, strip_unsafe_prefix(file_header->name));
421//TODO: do the same for file_header->link_target?
421 422
422 /* Strip trailing '/' in directories */ 423 /* Strip trailing '/' in directories */
423 /* Must be done after mode is set as '/' is used to check if it's a directory */ 424 /* Must be done after mode is set as '/' is used to check if it's a directory */
diff --git a/archival/lzop.c b/archival/lzop.c
index 73d11a705..a5fc01941 100644
--- a/archival/lzop.c
+++ b/archival/lzop.c
@@ -640,7 +640,7 @@ static int lzo_get_method(header_t *h)
640/**********************************************************************/ 640/**********************************************************************/
641// compress a file 641// compress a file
642/**********************************************************************/ 642/**********************************************************************/
643static NOINLINE smallint lzo_compress(const header_t *h) 643static NOINLINE int lzo_compress(const header_t *h)
644{ 644{
645 unsigned block_size = LZO_BLOCK_SIZE; 645 unsigned block_size = LZO_BLOCK_SIZE;
646 int r = 0; /* LZO_E_OK */ 646 int r = 0; /* LZO_E_OK */
@@ -650,7 +650,6 @@ static NOINLINE smallint lzo_compress(const header_t *h)
650 uint32_t d_adler32 = ADLER32_INIT_VALUE; 650 uint32_t d_adler32 = ADLER32_INIT_VALUE;
651 uint32_t d_crc32 = CRC32_INIT_VALUE; 651 uint32_t d_crc32 = CRC32_INIT_VALUE;
652 int l; 652 int l;
653 smallint ok = 1;
654 uint8_t *wrk_mem = NULL; 653 uint8_t *wrk_mem = NULL;
655 654
656 if (h->method == M_LZO1X_1) 655 if (h->method == M_LZO1X_1)
@@ -732,7 +731,7 @@ static NOINLINE smallint lzo_compress(const header_t *h)
732 free(wrk_mem); 731 free(wrk_mem);
733 free(b1); 732 free(b1);
734 free(b2); 733 free(b2);
735 return ok; 734 return 1;
736} 735}
737 736
738static FAST_FUNC void lzo_check( 737static FAST_FUNC void lzo_check(
@@ -753,7 +752,7 @@ static FAST_FUNC void lzo_check(
753/**********************************************************************/ 752/**********************************************************************/
754// decompress a file 753// decompress a file
755/**********************************************************************/ 754/**********************************************************************/
756static NOINLINE smallint lzo_decompress(const header_t *h) 755static NOINLINE int lzo_decompress(const header_t *h)
757{ 756{
758 unsigned block_size = LZO_BLOCK_SIZE; 757 unsigned block_size = LZO_BLOCK_SIZE;
759 int r; 758 int r;
@@ -761,7 +760,6 @@ static NOINLINE smallint lzo_decompress(const header_t *h)
761 uint32_t c_adler32 = ADLER32_INIT_VALUE; 760 uint32_t c_adler32 = ADLER32_INIT_VALUE;
762 uint32_t d_adler32 = ADLER32_INIT_VALUE; 761 uint32_t d_adler32 = ADLER32_INIT_VALUE;
763 uint32_t c_crc32 = CRC32_INIT_VALUE, d_crc32 = CRC32_INIT_VALUE; 762 uint32_t c_crc32 = CRC32_INIT_VALUE, d_crc32 = CRC32_INIT_VALUE;
764 smallint ok = 1;
765 uint8_t *b1; 763 uint8_t *b1;
766 uint32_t mcs_block_size = MAX_COMPRESSED_SIZE(block_size); 764 uint32_t mcs_block_size = MAX_COMPRESSED_SIZE(block_size);
767 uint8_t *b2 = NULL; 765 uint8_t *b2 = NULL;
@@ -865,7 +863,7 @@ static NOINLINE smallint lzo_decompress(const header_t *h)
865 } 863 }
866 864
867 free(b2); 865 free(b2);
868 return ok; 866 return 1;
869} 867}
870 868
871/**********************************************************************/ 869/**********************************************************************/
@@ -1050,7 +1048,7 @@ static void lzo_set_method(header_t *h)
1050 h->level = level; 1048 h->level = level;
1051} 1049}
1052 1050
1053static smallint do_lzo_compress(void) 1051static int do_lzo_compress(void)
1054{ 1052{
1055 header_t header; 1053 header_t header;
1056 1054
@@ -1078,7 +1076,7 @@ static smallint do_lzo_compress(void)
1078/**********************************************************************/ 1076/**********************************************************************/
1079// decompress 1077// decompress
1080/**********************************************************************/ 1078/**********************************************************************/
1081static smallint do_lzo_decompress(void) 1079static int do_lzo_decompress(void)
1082{ 1080{
1083 header_t header; 1081 header_t header;
1084 1082
diff --git a/archival/tar.c b/archival/tar.c
index 0dd675f64..adb0b934f 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -152,9 +152,12 @@
152# define FNM_LEADING_DIR 0 152# define FNM_LEADING_DIR 0
153#endif 153#endif
154 154
155 155#if 0
156//#define DBG(fmt, ...) bb_error_msg("%s: " fmt, __func__, ## __VA_ARGS__) 156# define DBG(fmt, ...) bb_error_msg("%s: " fmt, __func__, ## __VA_ARGS__)
157#define DBG(...) ((void)0) 157#else
158# define DBG(...) ((void)0)
159#endif
160#define DBG_OPTION_PARSING 0
158 161
159 162
160#define block_buf bb_common_bufsiz1 163#define block_buf bb_common_bufsiz1
@@ -884,6 +887,7 @@ enum {
884 IF_FEATURE_SEAMLESS_Z( OPTBIT_COMPRESS ,) 887 IF_FEATURE_SEAMLESS_Z( OPTBIT_COMPRESS ,)
885 IF_FEATURE_TAR_NOPRESERVE_TIME(OPTBIT_NOPRESERVE_TIME,) 888 IF_FEATURE_TAR_NOPRESERVE_TIME(OPTBIT_NOPRESERVE_TIME,)
886#if ENABLE_FEATURE_TAR_LONG_OPTIONS 889#if ENABLE_FEATURE_TAR_LONG_OPTIONS
890 OPTBIT_STRIP_COMPONENTS,
887 OPTBIT_NORECURSION, 891 OPTBIT_NORECURSION,
888 IF_FEATURE_TAR_TO_COMMAND(OPTBIT_2COMMAND ,) 892 IF_FEATURE_TAR_TO_COMMAND(OPTBIT_2COMMAND ,)
889 OPTBIT_NUMERIC_OWNER, 893 OPTBIT_NUMERIC_OWNER,
@@ -908,12 +912,13 @@ enum {
908 OPT_GZIP = IF_FEATURE_SEAMLESS_GZ( (1 << OPTBIT_GZIP )) + 0, // z 912 OPT_GZIP = IF_FEATURE_SEAMLESS_GZ( (1 << OPTBIT_GZIP )) + 0, // z
909 OPT_XZ = IF_FEATURE_SEAMLESS_XZ( (1 << OPTBIT_XZ )) + 0, // J 913 OPT_XZ = IF_FEATURE_SEAMLESS_XZ( (1 << OPTBIT_XZ )) + 0, // J
910 OPT_COMPRESS = IF_FEATURE_SEAMLESS_Z( (1 << OPTBIT_COMPRESS )) + 0, // Z 914 OPT_COMPRESS = IF_FEATURE_SEAMLESS_Z( (1 << OPTBIT_COMPRESS )) + 0, // Z
911 OPT_NOPRESERVE_TIME = IF_FEATURE_TAR_NOPRESERVE_TIME((1 << OPTBIT_NOPRESERVE_TIME)) + 0, // m 915 OPT_NOPRESERVE_TIME = IF_FEATURE_TAR_NOPRESERVE_TIME((1 << OPTBIT_NOPRESERVE_TIME)) + 0, // m
912 OPT_NORECURSION = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NORECURSION )) + 0, // no-recursion 916 OPT_STRIP_COMPONENTS = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_STRIP_COMPONENTS)) + 0, // strip-components
913 OPT_2COMMAND = IF_FEATURE_TAR_TO_COMMAND( (1 << OPTBIT_2COMMAND )) + 0, // to-command 917 OPT_NORECURSION = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NORECURSION )) + 0, // no-recursion
914 OPT_NUMERIC_OWNER = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NUMERIC_OWNER )) + 0, // numeric-owner 918 OPT_2COMMAND = IF_FEATURE_TAR_TO_COMMAND( (1 << OPTBIT_2COMMAND )) + 0, // to-command
915 OPT_NOPRESERVE_PERM = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NOPRESERVE_PERM)) + 0, // no-same-permissions 919 OPT_NUMERIC_OWNER = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NUMERIC_OWNER )) + 0, // numeric-owner
916 OPT_OVERWRITE = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_OVERWRITE )) + 0, // overwrite 920 OPT_NOPRESERVE_PERM = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NOPRESERVE_PERM)) + 0, // no-same-permissions
921 OPT_OVERWRITE = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_OVERWRITE )) + 0, // overwrite
917 922
918 OPT_ANY_COMPRESS = (OPT_BZIP2 | OPT_LZMA | OPT_GZIP | OPT_XZ | OPT_COMPRESS), 923 OPT_ANY_COMPRESS = (OPT_BZIP2 | OPT_LZMA | OPT_GZIP | OPT_XZ | OPT_COMPRESS),
919}; 924};
@@ -957,6 +962,7 @@ static const char tar_longopts[] ALIGN1 =
957# if ENABLE_FEATURE_TAR_NOPRESERVE_TIME 962# if ENABLE_FEATURE_TAR_NOPRESERVE_TIME
958 "touch\0" No_argument "m" 963 "touch\0" No_argument "m"
959# endif 964# endif
965 "strip-components\0" Required_argument "\xf9"
960 "no-recursion\0" No_argument "\xfa" 966 "no-recursion\0" No_argument "\xfa"
961# if ENABLE_FEATURE_TAR_TO_COMMAND 967# if ENABLE_FEATURE_TAR_TO_COMMAND
962 "to-command\0" Required_argument "\xfb" 968 "to-command\0" Required_argument "\xfb"
@@ -1002,15 +1008,28 @@ int tar_main(int argc UNUSED_PARAM, char **argv)
1002 "tt:vv:" // count -t,-v 1008 "tt:vv:" // count -t,-v
1003 IF_FEATURE_TAR_FROM("X::T::") // cumulative lists 1009 IF_FEATURE_TAR_FROM("X::T::") // cumulative lists
1004#if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM 1010#if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM
1005 "\xff::" // cumulative lists for --exclude 1011 "\xff::" // --exclude=PATTERN is a list
1006#endif 1012#endif
1007 IF_FEATURE_TAR_CREATE("c:") "t:x:" // at least one of these is reqd 1013 IF_FEATURE_TAR_CREATE("c:") "t:x:" // at least one of these is reqd
1008 IF_FEATURE_TAR_CREATE("c--tx:t--cx:x--ct") // mutually exclusive 1014 IF_FEATURE_TAR_CREATE("c--tx:t--cx:x--ct") // mutually exclusive
1009 IF_NOT_FEATURE_TAR_CREATE("t--x:x--t"); // mutually exclusive 1015 IF_NOT_FEATURE_TAR_CREATE("t--x:x--t") // mutually exclusive
1016#if ENABLE_FEATURE_TAR_LONG_OPTIONS
1017 ":\xf9+" // --strip-components=NUM
1018#endif
1019 ;
1010#if ENABLE_FEATURE_TAR_LONG_OPTIONS 1020#if ENABLE_FEATURE_TAR_LONG_OPTIONS
1011 applet_long_options = tar_longopts; 1021 applet_long_options = tar_longopts;
1012#endif 1022#endif
1013#if ENABLE_DESKTOP 1023#if ENABLE_DESKTOP
1024 /* Lie to buildroot when it starts asking stupid questions. */
1025 if (argv[1] && strcmp(argv[1], "--version") == 0) {
1026 // Output of 'tar --version' examples:
1027 // tar (GNU tar) 1.15.1
1028 // tar (GNU tar) 1.25
1029 // bsdtar 2.8.3 - libarchive 2.8.3
1030 puts("tar (busybox) " BB_VER);
1031 return 0;
1032 }
1014 if (argv[1] && argv[1][0] != '-') { 1033 if (argv[1] && argv[1][0] != '-') {
1015 /* Compat: 1034 /* Compat:
1016 * 1st argument without dash handles options with parameters 1035 * 1st argument without dash handles options with parameters
@@ -1047,10 +1066,14 @@ int tar_main(int argc UNUSED_PARAM, char **argv)
1047 IF_FEATURE_SEAMLESS_XZ( "J" ) 1066 IF_FEATURE_SEAMLESS_XZ( "J" )
1048 IF_FEATURE_SEAMLESS_Z( "Z" ) 1067 IF_FEATURE_SEAMLESS_Z( "Z" )
1049 IF_FEATURE_TAR_NOPRESERVE_TIME("m") 1068 IF_FEATURE_TAR_NOPRESERVE_TIME("m")
1069 IF_FEATURE_TAR_LONG_OPTIONS("\xf9:") // --strip-components
1050 , &base_dir // -C dir 1070 , &base_dir // -C dir
1051 , &tar_filename // -f filename 1071 , &tar_filename // -f filename
1052 IF_FEATURE_TAR_FROM(, &(tar_handle->accept)) // T 1072 IF_FEATURE_TAR_FROM(, &(tar_handle->accept)) // T
1053 IF_FEATURE_TAR_FROM(, &(tar_handle->reject)) // X 1073 IF_FEATURE_TAR_FROM(, &(tar_handle->reject)) // X
1074#if ENABLE_FEATURE_TAR_LONG_OPTIONS
1075 , &tar_handle->tar__strip_components // --strip-components
1076#endif
1054 IF_FEATURE_TAR_TO_COMMAND(, &(tar_handle->tar__to_command)) // --to-command 1077 IF_FEATURE_TAR_TO_COMMAND(, &(tar_handle->tar__to_command)) // --to-command
1055#if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM 1078#if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM
1056 , &excludes // --exclude 1079 , &excludes // --exclude
@@ -1058,11 +1081,49 @@ int tar_main(int argc UNUSED_PARAM, char **argv)
1058 , &verboseFlag // combined count for -t and -v 1081 , &verboseFlag // combined count for -t and -v
1059 , &verboseFlag // combined count for -t and -v 1082 , &verboseFlag // combined count for -t and -v
1060 ); 1083 );
1061 //bb_error_msg("opt:%08x", opt); 1084#if DBG_OPTION_PARSING
1085 bb_error_msg("opt: 0x%08x", opt);
1086# define showopt(o) bb_error_msg("opt & %s(%x): %x", #o, o, opt & o);
1087 showopt(OPT_TEST );
1088 showopt(OPT_EXTRACT );
1089 showopt(OPT_BASEDIR );
1090 showopt(OPT_TARNAME );
1091 showopt(OPT_2STDOUT );
1092 showopt(OPT_NOPRESERVE_OWNER);
1093 showopt(OPT_P );
1094 showopt(OPT_VERBOSE );
1095 showopt(OPT_KEEP_OLD );
1096 showopt(OPT_CREATE );
1097 showopt(OPT_DEREFERENCE );
1098 showopt(OPT_BZIP2 );
1099 showopt(OPT_LZMA );
1100 showopt(OPT_INCLUDE_FROM );
1101 showopt(OPT_EXCLUDE_FROM );
1102 showopt(OPT_GZIP );
1103 showopt(OPT_XZ );
1104 showopt(OPT_COMPRESS );
1105 showopt(OPT_NOPRESERVE_TIME );
1106 showopt(OPT_STRIP_COMPONENTS);
1107 showopt(OPT_NORECURSION );
1108 showopt(OPT_2COMMAND );
1109 showopt(OPT_NUMERIC_OWNER );
1110 showopt(OPT_NOPRESERVE_PERM );
1111 showopt(OPT_OVERWRITE );
1112 showopt(OPT_ANY_COMPRESS );
1113 bb_error_msg("base_dir:'%s'", base_dir);
1114 bb_error_msg("tar_filename:'%s'", tar_filename);
1115 bb_error_msg("verboseFlag:%d", verboseFlag);
1116 bb_error_msg("tar_handle->tar__to_command:'%s'", tar_handle->tar__to_command);
1117 bb_error_msg("tar_handle->tar__strip_components:%u", tar_handle->tar__strip_components);
1118 return 0;
1119# undef showopt
1120#endif
1062 argv += optind; 1121 argv += optind;
1063 1122
1064 if (verboseFlag) tar_handle->action_header = header_verbose_list; 1123 if (verboseFlag)
1065 if (verboseFlag == 1) tar_handle->action_header = header_list; 1124 tar_handle->action_header = header_verbose_list;
1125 if (verboseFlag == 1)
1126 tar_handle->action_header = header_list;
1066 1127
1067 if (opt & OPT_EXTRACT) 1128 if (opt & OPT_EXTRACT)
1068 tar_handle->action_data = data_extract_all; 1129 tar_handle->action_data = data_extract_all;
diff --git a/configs/android2_defconfig b/configs/android2_defconfig
index 4dfbdb526..1095094fe 100644
--- a/configs/android2_defconfig
+++ b/configs/android2_defconfig
@@ -89,7 +89,6 @@ CONFIG_PREFIX="./_install"
89# 89#
90# Busybox Library Tuning 90# Busybox Library Tuning
91# 91#
92# CONFIG_FEATURE_SYSTEMD is not set
93# CONFIG_FEATURE_RTMINMAX is not set 92# CONFIG_FEATURE_RTMINMAX is not set
94CONFIG_PASSWORD_MINLEN=6 93CONFIG_PASSWORD_MINLEN=6
95CONFIG_MD5_SMALL=1 94CONFIG_MD5_SMALL=1
diff --git a/configs/android_defconfig b/configs/android_defconfig
index e35830e7f..082994b6c 100644
--- a/configs/android_defconfig
+++ b/configs/android_defconfig
@@ -107,7 +107,6 @@ CONFIG_PREFIX="./_install"
107# 107#
108# Busybox Library Tuning 108# Busybox Library Tuning
109# 109#
110# CONFIG_FEATURE_SYSTEMD is not set
111# CONFIG_FEATURE_RTMINMAX is not set 110# CONFIG_FEATURE_RTMINMAX is not set
112CONFIG_PASSWORD_MINLEN=6 111CONFIG_PASSWORD_MINLEN=6
113CONFIG_MD5_SMALL=1 112CONFIG_MD5_SMALL=1
diff --git a/configs/android_ndk_defconfig b/configs/android_ndk_defconfig
index 66c85268f..63fafb468 100644
--- a/configs/android_ndk_defconfig
+++ b/configs/android_ndk_defconfig
@@ -96,7 +96,6 @@ CONFIG_PREFIX="./_install"
96# 96#
97# Busybox Library Tuning 97# Busybox Library Tuning
98# 98#
99# CONFIG_FEATURE_SYSTEMD is not set
100# CONFIG_FEATURE_RTMINMAX is not set 99# CONFIG_FEATURE_RTMINMAX is not set
101CONFIG_PASSWORD_MINLEN=6 100CONFIG_PASSWORD_MINLEN=6
102CONFIG_MD5_SMALL=1 101CONFIG_MD5_SMALL=1
diff --git a/configs/cygwin_defconfig b/configs/cygwin_defconfig
index aa346e34c..2c02be743 100644
--- a/configs/cygwin_defconfig
+++ b/configs/cygwin_defconfig
@@ -89,7 +89,6 @@ CONFIG_PREFIX="./_install"
89# 89#
90# Busybox Library Tuning 90# Busybox Library Tuning
91# 91#
92# CONFIG_FEATURE_SYSTEMD is not set
93CONFIG_FEATURE_RTMINMAX=y 92CONFIG_FEATURE_RTMINMAX=y
94CONFIG_PASSWORD_MINLEN=6 93CONFIG_PASSWORD_MINLEN=6
95CONFIG_MD5_SMALL=1 94CONFIG_MD5_SMALL=1
diff --git a/coreutils/Config.src b/coreutils/Config.src
index 21b97d382..619c2efe8 100644
--- a/coreutils/Config.src
+++ b/coreutils/Config.src
@@ -543,21 +543,6 @@ config FEATURE_SPLIT_FANCY
543 Supports additional suffixes 'b' for 512 bytes, 543 Supports additional suffixes 'b' for 512 bytes,
544 'g' for 1GiB for the -b option. 544 'g' for 1GiB for the -b option.
545 545
546config STAT
547 bool "stat"
548 default y
549 help
550 display file or filesystem status.
551
552config FEATURE_STAT_FORMAT
553 bool "Enable custom formats (-c)"
554 default y
555 depends on STAT
556 help
557 Without this, stat will not support the '-c format' option where
558 users can pass a custom format string for output. This adds about
559 7k to a nonstatic build on amd64.
560
561config STTY 546config STTY
562 bool "stty" 547 bool "stty"
563 default y 548 default y
diff --git a/coreutils/ls.c b/coreutils/ls.c
index 14c8beaff..c48498858 100644
--- a/coreutils/ls.c
+++ b/coreutils/ls.c
@@ -1105,7 +1105,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1105 1105
1106#if ENABLE_FEATURE_AUTOWIDTH 1106#if ENABLE_FEATURE_AUTOWIDTH
1107 /* obtain the terminal width */ 1107 /* obtain the terminal width */
1108 get_terminal_width_height(STDIN_FILENO, &G_terminal_width, NULL); 1108 G_terminal_width = get_terminal_width(STDIN_FILENO);
1109 /* go one less... */ 1109 /* go one less... */
1110 G_terminal_width--; 1110 G_terminal_width--;
1111#endif 1111#endif
diff --git a/coreutils/sort.c b/coreutils/sort.c
index 36f02543b..07d903388 100644
--- a/coreutils/sort.c
+++ b/coreutils/sort.c
@@ -106,7 +106,9 @@ static struct sort_key {
106 106
107static char *get_key(char *str, struct sort_key *key, int flags) 107static char *get_key(char *str, struct sort_key *key, int flags)
108{ 108{
109 int start = 0, end = 0, len, j; 109 int start = start; /* for compiler */
110 int end;
111 int len, j;
110 unsigned i; 112 unsigned i;
111 113
112 /* Special case whole string, so we don't have to make a copy */ 114 /* Special case whole string, so we don't have to make a copy */
@@ -123,12 +125,15 @@ static char *get_key(char *str, struct sort_key *key, int flags)
123 end = len; 125 end = len;
124 /* Loop through fields */ 126 /* Loop through fields */
125 else { 127 else {
128 unsigned char ch = 0;
129
126 end = 0; 130 end = 0;
127 for (i = 1; i < key->range[2*j] + j; i++) { 131 for (i = 1; i < key->range[2*j] + j; i++) {
128 if (key_separator) { 132 if (key_separator) {
129 /* Skip body of key and separator */ 133 /* Skip body of key and separator */
130 while (str[end]) { 134 while ((ch = str[end]) != '\0') {
131 if (str[end++] == key_separator) 135 end++;
136 if (ch == key_separator)
132 break; 137 break;
133 } 138 }
134 } else { 139 } else {
@@ -136,7 +141,7 @@ static char *get_key(char *str, struct sort_key *key, int flags)
136 while (isspace(str[end])) 141 while (isspace(str[end]))
137 end++; 142 end++;
138 /* Skip body of key */ 143 /* Skip body of key */
139 while (str[end]) { 144 while (str[end] != '\0') {
140 if (isspace(str[end])) 145 if (isspace(str[end]))
141 break; 146 break;
142 end++; 147 end++;
@@ -144,23 +149,29 @@ static char *get_key(char *str, struct sort_key *key, int flags)
144 } 149 }
145 } 150 }
146 /* Remove last delim: "abc:def:" => "abc:def" */ 151 /* Remove last delim: "abc:def:" => "abc:def" */
147 if (key_separator && j && end != 0) 152 if (j && ch) {
153 //if (str[end-1] != key_separator)
154 // bb_error_msg(_and_die("BUG! "
155 // "str[start:%d,end:%d]:'%.*s'",
156 // start, end, (int)(end-start), &str[start]);
148 end--; 157 end--;
158 }
149 } 159 }
150 if (!j) start = end; 160 if (!j) start = end;
151 } 161 }
152 /* Strip leading whitespace if necessary */ 162 /* Strip leading whitespace if necessary */
153//XXX: skip_whitespace()
154 if (flags & FLAG_b) 163 if (flags & FLAG_b)
164 /* not using skip_whitespace() for speed */
155 while (isspace(str[start])) start++; 165 while (isspace(str[start])) start++;
156 /* Strip trailing whitespace if necessary */ 166 /* Strip trailing whitespace if necessary */
157 if (flags & FLAG_bb) 167 if (flags & FLAG_bb)
158 while (end > start && isspace(str[end-1])) end--; 168 while (end > start && isspace(str[end-1])) end--;
159 /* Handle offsets on start and end */ 169 /* -kSTART,N.ENDCHAR: honor ENDCHAR (1-based) */
160 if (key->range[3]) { 170 if (key->range[3]) {
161 end += key->range[3] - 1; 171 end = key->range[3];
162 if (end > len) end = len; 172 if (end > len) end = len;
163 } 173 }
174 /* -kN.STARTCHAR[,...]: honor STARTCHAR (1-based) */
164 if (key->range[1]) { 175 if (key->range[1]) {
165 start += key->range[1] - 1; 176 start += key->range[1] - 1;
166 if (start > len) start = len; 177 if (start > len) start = len;
@@ -281,7 +292,7 @@ static int compare_keys(const void *xarg, const void *yarg)
281 else if (!yy) 292 else if (!yy)
282 retval = 1; 293 retval = 1;
283 else 294 else
284 retval = (dx == thyme.tm_mon) ? 0 : dx - thyme.tm_mon; 295 retval = dx - thyme.tm_mon;
285 break; 296 break;
286 } 297 }
287 /* Full floating point version of -n */ 298 /* Full floating point version of -n */
@@ -307,8 +318,8 @@ static int compare_keys(const void *xarg, const void *yarg)
307 318
308 /* Perform fallback sort if necessary */ 319 /* Perform fallback sort if necessary */
309 if (!retval && !(option_mask32 & FLAG_s)) { 320 if (!retval && !(option_mask32 & FLAG_s)) {
310 retval = strcmp(*(char **)xarg, *(char **)yarg);
311 flags = option_mask32; 321 flags = option_mask32;
322 retval = strcmp(*(char **)xarg, *(char **)yarg);
312 } 323 }
313 324
314 if (flags & FLAG_r) 325 if (flags & FLAG_r)
@@ -336,7 +347,7 @@ int sort_main(int argc UNUSED_PARAM, char **argv)
336 char *line, **lines; 347 char *line, **lines;
337 char *str_ignored, *str_o, *str_t; 348 char *str_ignored, *str_o, *str_t;
338 llist_t *lst_k = NULL; 349 llist_t *lst_k = NULL;
339 int i, flag; 350 int i;
340 int linecount; 351 int linecount;
341 unsigned opts; 352 unsigned opts;
342 353
@@ -359,7 +370,7 @@ int sort_main(int argc UNUSED_PARAM, char **argv)
359 /* note: below this point we use option_mask32, not opts, 370 /* note: below this point we use option_mask32, not opts,
360 * since that reduces register pressure and makes code smaller */ 371 * since that reduces register pressure and makes code smaller */
361 372
362 /* parse sort key */ 373 /* Parse sort key */
363 while (lst_k) { 374 while (lst_k) {
364 enum { 375 enum {
365 FLAG_allowed_for_k = 376 FLAG_allowed_for_k =
@@ -386,17 +397,18 @@ int sort_main(int argc UNUSED_PARAM, char **argv)
386 key->range[2*i+1] = str2u(&str_k); 397 key->range[2*i+1] = str2u(&str_k);
387 } 398 }
388 while (*str_k) { 399 while (*str_k) {
389 const char *temp2; 400 int flag;
401 const char *idx;
390 402
391 if (*str_k == ',' && !i++) { 403 if (*str_k == ',' && !i++) {
392 str_k++; 404 str_k++;
393 break; 405 break;
394 } /* no else needed: fall through to syntax error 406 } /* no else needed: fall through to syntax error
395 because comma isn't in OPT_STR */ 407 because comma isn't in OPT_STR */
396 temp2 = strchr(OPT_STR, *str_k); 408 idx = strchr(OPT_STR, *str_k);
397 if (!temp2) 409 if (!idx)
398 bb_error_msg_and_die("unknown key option"); 410 bb_error_msg_and_die("unknown key option");
399 flag = 1 << (temp2 - OPT_STR); 411 flag = 1 << (idx - OPT_STR);
400 if (flag & ~FLAG_allowed_for_k) 412 if (flag & ~FLAG_allowed_for_k)
401 bb_error_msg_and_die("unknown sort type"); 413 bb_error_msg_and_die("unknown sort type");
402 /* b after ',' means strip _trailing_ space */ 414 /* b after ',' means strip _trailing_ space */
@@ -430,10 +442,10 @@ int sort_main(int argc UNUSED_PARAM, char **argv)
430 } while (*++argv); 442 } while (*++argv);
431 443
432#if ENABLE_FEATURE_SORT_BIG 444#if ENABLE_FEATURE_SORT_BIG
433 /* if no key, perform alphabetic sort */ 445 /* If no key, perform alphabetic sort */
434 if (!key_list) 446 if (!key_list)
435 add_key()->range[0] = 1; 447 add_key()->range[0] = 1;
436 /* handle -c */ 448 /* Handle -c */
437 if (option_mask32 & FLAG_c) { 449 if (option_mask32 & FLAG_c) {
438 int j = (option_mask32 & FLAG_u) ? -1 : 0; 450 int j = (option_mask32 & FLAG_u) ? -1 : 0;
439 for (i = 1; i < linecount; i++) { 451 for (i = 1; i < linecount; i++) {
@@ -447,20 +459,21 @@ int sort_main(int argc UNUSED_PARAM, char **argv)
447#endif 459#endif
448 /* Perform the actual sort */ 460 /* Perform the actual sort */
449 qsort(lines, linecount, sizeof(lines[0]), compare_keys); 461 qsort(lines, linecount, sizeof(lines[0]), compare_keys);
450 /* handle -u */ 462
463 /* Handle -u */
451 if (option_mask32 & FLAG_u) { 464 if (option_mask32 & FLAG_u) {
452 flag = 0; 465 int j = 0;
453 /* coreutils 6.3 drop lines for which only key is the same */ 466 /* coreutils 6.3 drop lines for which only key is the same */
454 /* -- disabling last-resort compare... */ 467 /* -- disabling last-resort compare... */
455 option_mask32 |= FLAG_s; 468 option_mask32 |= FLAG_s;
456 for (i = 1; i < linecount; i++) { 469 for (i = 1; i < linecount; i++) {
457 if (compare_keys(&lines[flag], &lines[i]) == 0) 470 if (compare_keys(&lines[j], &lines[i]) == 0)
458 free(lines[i]); 471 free(lines[i]);
459 else 472 else
460 lines[++flag] = lines[i]; 473 lines[++j] = lines[i];
461 } 474 }
462 if (linecount) 475 if (linecount)
463 linecount = flag+1; 476 linecount = j+1;
464 } 477 }
465 478
466 /* Print it */ 479 /* Print it */
@@ -469,9 +482,11 @@ int sort_main(int argc UNUSED_PARAM, char **argv)
469 if (option_mask32 & FLAG_o) 482 if (option_mask32 & FLAG_o)
470 xmove_fd(xopen(str_o, O_WRONLY|O_CREAT|O_TRUNC), STDOUT_FILENO); 483 xmove_fd(xopen(str_o, O_WRONLY|O_CREAT|O_TRUNC), STDOUT_FILENO);
471#endif 484#endif
472 flag = (option_mask32 & FLAG_z) ? '\0' : '\n'; 485 {
473 for (i = 0; i < linecount; i++) 486 int ch = (option_mask32 & FLAG_z) ? '\0' : '\n';
474 printf("%s%c", lines[i], flag); 487 for (i = 0; i < linecount; i++)
488 printf("%s%c", lines[i], ch);
489 }
475 490
476 fflush_stdout_and_exit(EXIT_SUCCESS); 491 fflush_stdout_and_exit(EXIT_SUCCESS);
477} 492}
diff --git a/coreutils/stat.c b/coreutils/stat.c
index f7fd227bb..1a490fef7 100644
--- a/coreutils/stat.c
+++ b/coreutils/stat.c
@@ -12,54 +12,83 @@
12 * 12 *
13 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 13 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
14 */ 14 */
15//config:config STAT
16//config: bool "stat"
17//config: default y
18//config: help
19//config: display file or filesystem status.
20//config:
21//config:config FEATURE_STAT_FORMAT
22//config: bool "Enable custom formats (-c)"
23//config: default y
24//config: depends on STAT
25//config: help
26//config: Without this, stat will not support the '-c format' option where
27//config: users can pass a custom format string for output. This adds about
28//config: 7k to a nonstatic build on amd64.
29//config:
30//config:config FEATURE_STAT_FILESYSTEM
31//config: bool "Enable display of filesystem status (-f)"
32//config: default y
33//config: depends on STAT
34//config: select PLATFORM_LINUX # statfs()
35//config: help
36//config: Without this, stat will not support the '-f' option to display
37//config: information about filesystem status.
38
15 39
16//usage:#define stat_trivial_usage 40//usage:#define stat_trivial_usage
17//usage: "[OPTIONS] FILE..." 41//usage: "[OPTIONS] FILE..."
18//usage:#define stat_full_usage "\n\n" 42//usage:#define stat_full_usage "\n\n"
19//usage: "Display file (default) or filesystem status\n" 43//usage: "Display file"
44//usage: IF_FEATURE_STAT_FILESYSTEM(" (default) or filesystem")
45//usage: " status\n"
20//usage: IF_FEATURE_STAT_FORMAT( 46//usage: IF_FEATURE_STAT_FORMAT(
21//usage: "\n -c fmt Use the specified format" 47//usage: "\n -c FMT Use the specified format"
22//usage: ) 48//usage: )
49//usage: IF_FEATURE_STAT_FILESYSTEM(
23//usage: "\n -f Display filesystem status" 50//usage: "\n -f Display filesystem status"
51//usage: )
24//usage: "\n -L Follow links" 52//usage: "\n -L Follow links"
25//usage: "\n -t Display info in terse form" 53//usage: "\n -t Terse display"
26//usage: IF_SELINUX( 54//usage: IF_SELINUX(
27//usage: "\n -Z Print security context" 55//usage: "\n -Z Print security context"
28//usage: ) 56//usage: )
29//usage: IF_FEATURE_STAT_FORMAT( 57//usage: IF_FEATURE_STAT_FORMAT(
30//usage: "\n\nValid format sequences for files:\n" 58//usage: "\n\nFMT sequences"IF_FEATURE_STAT_FILESYSTEM(" for files")":\n"
31//usage: " %a Access rights in octal\n" 59//usage: " %a Access rights in octal\n"
32//usage: " %A Access rights in human readable form\n" 60//usage: " %A Access rights in human readable form\n"
33//usage: " %b Number of blocks allocated (see %B)\n" 61//usage: " %b Number of blocks allocated (see %B)\n"
34//usage: " %B The size in bytes of each block reported by %b\n" 62//usage: " %B Size in bytes of each block reported by %b\n"
35//usage: " %d Device number in decimal\n" 63//usage: " %d Device number in decimal\n"
36//usage: " %D Device number in hex\n" 64//usage: " %D Device number in hex\n"
37//usage: " %f Raw mode in hex\n" 65//usage: " %f Raw mode in hex\n"
38//usage: " %F File type\n" 66//usage: " %F File type\n"
39//usage: " %g Group ID of owner\n" 67//usage: " %g Group ID\n"
40//usage: " %G Group name of owner\n" 68//usage: " %G Group name\n"
41//usage: " %h Number of hard links\n" 69//usage: " %h Number of hard links\n"
42//usage: " %i Inode number\n" 70//usage: " %i Inode number\n"
43//usage: " %n File name\n" 71//usage: " %n File name\n"
44//usage: " %N File name, with -> TARGET if symlink\n" 72//usage: " %N File name, with -> TARGET if symlink\n"
45//usage: " %o I/O block size\n" 73//usage: " %o I/O block size\n"
46//usage: " %s Total size, in bytes\n" 74//usage: " %s Total size in bytes\n"
47//usage: " %t Major device type in hex\n" 75//usage: " %t Major device type in hex\n"
48//usage: " %T Minor device type in hex\n" 76//usage: " %T Minor device type in hex\n"
49//usage: " %u User ID of owner\n" 77//usage: " %u User ID\n"
50//usage: " %U User name of owner\n" 78//usage: " %U User name\n"
51//usage: " %x Time of last access\n" 79//usage: " %x Time of last access\n"
52//usage: " %X Time of last access as seconds since Epoch\n" 80//usage: " %X Time of last access as seconds since Epoch\n"
53//usage: " %y Time of last modification\n" 81//usage: " %y Time of last modification\n"
54//usage: " %Y Time of last modification as seconds since Epoch\n" 82//usage: " %Y Time of last modification as seconds since Epoch\n"
55//usage: " %z Time of last change\n" 83//usage: " %z Time of last change\n"
56//usage: " %Z Time of last change as seconds since Epoch\n" 84//usage: " %Z Time of last change as seconds since Epoch\n"
57//usage: "\nValid format sequences for file systems:\n" 85//usage: IF_FEATURE_STAT_FILESYSTEM(
86//usage: "\nFMT sequences for file systems:\n"
58//usage: " %a Free blocks available to non-superuser\n" 87//usage: " %a Free blocks available to non-superuser\n"
59//usage: " %b Total data blocks in file system\n" 88//usage: " %b Total data blocks\n"
60//usage: " %c Total file nodes in file system\n" 89//usage: " %c Total file nodes\n"
61//usage: " %d Free file nodes in file system\n" 90//usage: " %d Free file nodes\n"
62//usage: " %f Free blocks in file system\n" 91//usage: " %f Free blocks\n"
63//usage: IF_SELINUX( 92//usage: IF_SELINUX(
64//usage: " %C Security context in selinux\n" 93//usage: " %C Security context in selinux\n"
65//usage: ) 94//usage: )
@@ -71,13 +100,16 @@
71//usage: " %t Type in hex\n" 100//usage: " %t Type in hex\n"
72//usage: " %T Type in human readable form" 101//usage: " %T Type in human readable form"
73//usage: ) 102//usage: )
103//usage: )
74 104
75#include "libbb.h" 105#include "libbb.h"
76 106
77#define OPT_FILESYS (1 << 0) 107enum {
78#define OPT_TERSE (1 << 1) 108 OPT_TERSE = (1 << 0),
79#define OPT_DEREFERENCE (1 << 2) 109 OPT_DEREFERENCE = (1 << 1),
80#define OPT_SELINUX (1 << 3) 110 OPT_FILESYS = (1 << 2) * ENABLE_FEATURE_STAT_FILESYSTEM,
111 OPT_SELINUX = (1 << (2+ENABLE_FEATURE_STAT_FILESYSTEM)) * ENABLE_SELINUX,
112};
81 113
82#if ENABLE_FEATURE_STAT_FORMAT 114#if ENABLE_FEATURE_STAT_FORMAT
83typedef bool (*statfunc_ptr)(const char *, const char *); 115typedef bool (*statfunc_ptr)(const char *, const char *);
@@ -132,6 +164,7 @@ static const char *human_time(time_t t)
132#undef buf 164#undef buf
133} 165}
134 166
167#if ENABLE_FEATURE_STAT_FILESYSTEM
135/* Return the type of the specified file system. 168/* Return the type of the specified file system.
136 * Some systems have statfvs.f_basetype[FSTYPSZ]. (AIX, HP-UX, and Solaris) 169 * Some systems have statfvs.f_basetype[FSTYPSZ]. (AIX, HP-UX, and Solaris)
137 * Others have statfs.f_fstypename[MFSNAMELEN]. (NetBSD 1.5.2) 170 * Others have statfs.f_fstypename[MFSNAMELEN]. (NetBSD 1.5.2)
@@ -202,6 +235,7 @@ static unsigned long long get_f_fsid(const struct statfs *statfsbuf)
202 while (--sz > 0); 235 while (--sz > 0);
203 return r; 236 return r;
204} 237}
238#endif /* FEATURE_STAT_FILESYSTEM */
205 239
206#if ENABLE_FEATURE_STAT_FORMAT 240#if ENABLE_FEATURE_STAT_FORMAT
207static void strcatc(char *str, char c) 241static void strcatc(char *str, char c)
@@ -217,6 +251,7 @@ static void printfs(char *pformat, const char *msg)
217 printf(pformat, msg); 251 printf(pformat, msg);
218} 252}
219 253
254#if ENABLE_FEATURE_STAT_FILESYSTEM
220/* print statfs info */ 255/* print statfs info */
221static void FAST_FUNC print_statfs(char *pformat, const char m, 256static void FAST_FUNC print_statfs(char *pformat, const char m,
222 const char *const filename, const void *data 257 const char *const filename, const void *data
@@ -263,6 +298,7 @@ static void FAST_FUNC print_statfs(char *pformat, const char m,
263 printf(pformat, m); 298 printf(pformat, m);
264 } 299 }
265} 300}
301#endif
266 302
267/* print stat info */ 303/* print stat info */
268static void FAST_FUNC print_stat(char *pformat, const char m, 304static void FAST_FUNC print_stat(char *pformat, const char m,
@@ -423,6 +459,7 @@ static void print_it(const char *masterformat,
423} 459}
424#endif /* FEATURE_STAT_FORMAT */ 460#endif /* FEATURE_STAT_FORMAT */
425 461
462#if ENABLE_FEATURE_STAT_FILESYSTEM
426/* Stat the file system and print what we find. */ 463/* Stat the file system and print what we find. */
427#if !ENABLE_FEATURE_STAT_FORMAT 464#if !ENABLE_FEATURE_STAT_FORMAT
428#define do_statfs(filename, format) do_statfs(filename) 465#define do_statfs(filename, format) do_statfs(filename)
@@ -538,6 +575,7 @@ static bool do_statfs(const char *filename, const char *format)
538#endif /* FEATURE_STAT_FORMAT */ 575#endif /* FEATURE_STAT_FORMAT */
539 return 1; 576 return 1;
540} 577}
578#endif /* FEATURE_STAT_FILESYSTEM */
541 579
542/* stat the file and print what we find */ 580/* stat the file and print what we find */
543#if !ENABLE_FEATURE_STAT_FORMAT 581#if !ENABLE_FEATURE_STAT_FORMAT
@@ -721,12 +759,15 @@ int stat_main(int argc UNUSED_PARAM, char **argv)
721 statfunc_ptr statfunc = do_stat; 759 statfunc_ptr statfunc = do_stat;
722 760
723 opt_complementary = "-1"; /* min one arg */ 761 opt_complementary = "-1"; /* min one arg */
724 opts = getopt32(argv, "ftL" 762 opts = getopt32(argv, "tL"
763 IF_FEATURE_STAT_FILESYSTEM("f")
725 IF_SELINUX("Z") 764 IF_SELINUX("Z")
726 IF_FEATURE_STAT_FORMAT("c:", &format) 765 IF_FEATURE_STAT_FORMAT("c:", &format)
727 ); 766 );
767#if ENABLE_FEATURE_STAT_FILESYSTEM
728 if (opts & OPT_FILESYS) /* -f */ 768 if (opts & OPT_FILESYS) /* -f */
729 statfunc = do_statfs; 769 statfunc = do_statfs;
770#endif
730#if ENABLE_SELINUX 771#if ENABLE_SELINUX
731 if (opts & OPT_SELINUX) { 772 if (opts & OPT_SELINUX) {
732 selinux_or_die(); 773 selinux_or_die();
diff --git a/coreutils/stty.c b/coreutils/stty.c
index 378a848e7..b63b0b91a 100644
--- a/coreutils/stty.c
+++ b/coreutils/stty.c
@@ -1403,7 +1403,7 @@ int stty_main(int argc UNUSED_PARAM, char **argv)
1403 perror_on_device_and_die("%s"); 1403 perror_on_device_and_die("%s");
1404 1404
1405 if (stty_state & (STTY_verbose_output | STTY_recoverable_output | STTY_noargs)) { 1405 if (stty_state & (STTY_verbose_output | STTY_recoverable_output | STTY_noargs)) {
1406 get_terminal_width_height(STDOUT_FILENO, &G.max_col, NULL); 1406 G.max_col = get_terminal_width(STDOUT_FILENO);
1407 output_func(&mode, display_all); 1407 output_func(&mode, display_all);
1408 return EXIT_SUCCESS; 1408 return EXIT_SUCCESS;
1409 } 1409 }
diff --git a/coreutils/tr.c b/coreutils/tr.c
index e67948a36..2f49d5a86 100644
--- a/coreutils/tr.c
+++ b/coreutils/tr.c
@@ -91,7 +91,6 @@ static void map(char *pvector,
91 * Character classes, e.g. [:upper:] ==> A...Z 91 * Character classes, e.g. [:upper:] ==> A...Z
92 * Equiv classess, e.g. [=A=] ==> A (hmmmmmmm?) 92 * Equiv classess, e.g. [=A=] ==> A (hmmmmmmm?)
93 * not supported: 93 * not supported:
94 * \ooo-\ooo - octal ranges
95 * [x*N] - repeat char x N times 94 * [x*N] - repeat char x N times
96 * [x*] - repeat char x until it fills STRING2: 95 * [x*] - repeat char x until it fills STRING2:
97 * # echo qwe123 | /usr/bin/tr 123456789 '[d]' 96 * # echo qwe123 | /usr/bin/tr 123456789 '[d]'
@@ -99,7 +98,7 @@ static void map(char *pvector,
99 * # echo qwe123 | /usr/bin/tr 123456789 '[d*]' 98 * # echo qwe123 | /usr/bin/tr 123456789 '[d*]'
100 * qweddd 99 * qweddd
101 */ 100 */
102static unsigned expand(const char *arg, char **buffer_p) 101static unsigned expand(char *arg, char **buffer_p)
103{ 102{
104 char *buffer = *buffer_p; 103 char *buffer = *buffer_p;
105 unsigned pos = 0; 104 unsigned pos = 0;
@@ -113,9 +112,17 @@ static unsigned expand(const char *arg, char **buffer_p)
113 *buffer_p = buffer = xrealloc(buffer, size); 112 *buffer_p = buffer = xrealloc(buffer, size);
114 } 113 }
115 if (*arg == '\\') { 114 if (*arg == '\\') {
115 const char *z;
116 arg++; 116 arg++;
117 buffer[pos++] = bb_process_escape_sequence(&arg); 117 z = arg;
118 continue; 118 ac = bb_process_escape_sequence(&z);
119 arg = (char *)z;
120 arg--;
121 *arg = ac;
122 /*
123 * fall through, there may be a range.
124 * If not, current char will be treated anyway.
125 */
119 } 126 }
120 if (arg[1] == '-') { /* "0-9..." */ 127 if (arg[1] == '-') { /* "0-9..." */
121 ac = arg[2]; 128 ac = arg[2];
@@ -124,9 +131,15 @@ static unsigned expand(const char *arg, char **buffer_p)
124 continue; /* next iter will copy '-' and stop */ 131 continue; /* next iter will copy '-' and stop */
125 } 132 }
126 i = (unsigned char) *arg; 133 i = (unsigned char) *arg;
134 arg += 3; /* skip 0-9 or 0-\ */
135 if (ac == '\\') {
136 const char *z;
137 z = arg;
138 ac = bb_process_escape_sequence(&z);
139 arg = (char *)z;
140 }
127 while (i <= ac) /* ok: i is unsigned _int_ */ 141 while (i <= ac) /* ok: i is unsigned _int_ */
128 buffer[pos++] = i++; 142 buffer[pos++] = i++;
129 arg += 3; /* skip 0-9 */
130 continue; 143 continue;
131 } 144 }
132 if ((ENABLE_FEATURE_TR_CLASSES || ENABLE_FEATURE_TR_EQUIV) 145 if ((ENABLE_FEATURE_TR_CLASSES || ENABLE_FEATURE_TR_EQUIV)
diff --git a/examples/var_service/README b/examples/var_service/README
index 9ad1b2581..d096ad0b9 100644
--- a/examples/var_service/README
+++ b/examples/var_service/README
@@ -36,10 +36,10 @@ service accordingly. In effect, it allows you to unplug/plug-to-different-networ
36and have your IP properly re-negotiated at once. 36and have your IP properly re-negotiated at once.
37 37
38var_service/dhcp_if_pinger - 38var_service/dhcp_if_pinger -
39Uses var_service/dhcp_if's data (/var/service/dhcp_if/dhcp_if.out file) 39Uses var_service/dhcp_if's data to determine router IP. Pings it.
40to determine router IP. Pings it. If ping fails, restarts /var/service/dhcp_if 40If ping fails, restarts /var/service/dhcp_if service.
41service. Basically, an example of watchdog service for networks 41Basically, an example of watchdog service for networks which are not reliable
42which are not reliable and need babysitting. 42and need babysitting.
43 43
44var_service/fw - 44var_service/fw -
45A *one-shot* service which reconfigures network based on current known state 45A *one-shot* service which reconfigures network based on current known state
diff --git a/examples/var_service/dhcp_if/convert2ntpconf b/examples/var_service/dhcp_if/convert2ntpconf
index debf1ebfe..e9d829308 100755
--- a/examples/var_service/dhcp_if/convert2ntpconf
+++ b/examples/var_service/dhcp_if/convert2ntpconf
@@ -29,6 +29,6 @@ test "$ip" || exit 1
29{ 29{
30for n in $ntpsrv; do 30for n in $ntpsrv; do
31 echo "let cfg=cfg+1" 31 echo "let cfg=cfg+1"
32 echo "ntpip[\$cfg]='$n'"; 32 echo "ntpip[\$cfg]='$n'"
33done 33done
34} >"$1" 34} >"$1"
diff --git a/examples/var_service/dhcp_if/dhcp_handler b/examples/var_service/dhcp_if/dhcp_handler
index 927e02a17..3d2a5cb79 100755
--- a/examples/var_service/dhcp_if/dhcp_handler
+++ b/examples/var_service/dhcp_if/dhcp_handler
@@ -36,7 +36,7 @@ service=${PWD##*/}
36file_ipconf="$service.ipconf" 36file_ipconf="$service.ipconf"
37file_ntpconf="$service.ntpconf" 37file_ntpconf="$service.ntpconf"
38dir_ipconf="/var/run/service/fw" 38dir_ipconf="/var/run/service/fw"
39dir_ntpconf="/var/run/service/ntp" 39dir_ntpconf="/var/run/service/ntpd"
40 40
41exec >/dev/null 41exec >/dev/null
42#exec >>"$0.out" #debug 42#exec >>"$0.out" #debug
@@ -47,7 +47,7 @@ echo "`date`: Params: $*"
47if test x"$1" != x"bound" && test x"$1" != x"renew" ; then 47if test x"$1" != x"bound" && test x"$1" != x"renew" ; then
48 # Reconfigure network with this interface disabled 48 # Reconfigure network with this interface disabled
49 echo "Deconfiguring" 49 echo "Deconfiguring"
50 rm "$service.out" 50 rm "env.out"
51 rm "$file_ipconf" 51 rm "$file_ipconf"
52 rm "$file_ntpconf" 52 rm "$file_ntpconf"
53 rm "$dir_ipconf/$file_ipconf" 53 rm "$dir_ipconf/$file_ipconf"
@@ -57,7 +57,8 @@ if test x"$1" != x"bound" && test x"$1" != x"renew" ; then
57fi 57fi
58 58
59# Bound: we've got the lease 59# Bound: we've got the lease
60#env >"$service.out" # debug 60# Record information for e.g. dhcp_$IF_pinger service
61env >"env.out"
61 62
62./convert2ipconf "$file_ipconf" 63./convert2ipconf "$file_ipconf"
63# Reconfigure routing and firewall if needed 64# Reconfigure routing and firewall if needed
@@ -69,7 +70,7 @@ if test $? != 0; then
69 sv u /var/service/fw 70 sv u /var/service/fw
70fi 71fi
71 72
72if test -d /var/service/ntp; then 73if test -d /var/service/ntpd; then
73 ./convert2ntpconf "$file_ntpconf" 74 ./convert2ntpconf "$file_ntpconf"
74 # Reconfigure ntp server addresses if needed 75 # Reconfigure ntp server addresses if needed
75 diff --brief "$file_ntpconf" "$dir_ntpconf/$file_ntpconf" >/dev/null 2>&1 76 diff --brief "$file_ntpconf" "$dir_ntpconf/$file_ntpconf" >/dev/null 2>&1
@@ -77,7 +78,7 @@ if test -d /var/service/ntp; then
77 echo "Reconfiguring ntp" 78 echo "Reconfiguring ntp"
78 mkdir -p "$dir_ntpconf" 2>/dev/null 79 mkdir -p "$dir_ntpconf" 2>/dev/null
79 cp "$file_ntpconf" "$dir_ntpconf/$file_ntpconf" 80 cp "$file_ntpconf" "$dir_ntpconf/$file_ntpconf"
80 sv t /var/service/ntp 81 sv t /var/service/ntpd
81 sv u /var/service/ntp 82 sv u /var/service/ntpd
82 fi 83 fi
83fi 84fi
diff --git a/examples/var_service/dhcp_if/finish b/examples/var_service/dhcp_if/finish
new file mode 100755
index 000000000..5e7667a2d
--- /dev/null
+++ b/examples/var_service/dhcp_if/finish
@@ -0,0 +1,17 @@
1#!/bin/sh
2# executed when service is taken down ("sv d .")
3
4service=${PWD##*/}
5file_ipconf="$service.ipconf"
6file_ntpconf="$service.ntpconf"
7dir_ipconf="/var/run/service/fw"
8dir_ntpconf="/var/run/service/ntpd"
9
10# Reconfigure network with this interface disabled
11echo "Finish: deconfiguring"
12rm "env.out"
13rm "$file_ipconf"
14rm "$file_ntpconf"
15rm "$dir_ipconf/$file_ipconf"
16rm "$dir_ntpconf/$file_ntpconf"
17sv u /var/service/fw
diff --git a/examples/var_service/dhcp_if/log/run b/examples/var_service/dhcp_if/log/run
index 560d1b19f..69d74b73f 100755
--- a/examples/var_service/dhcp_if/log/run
+++ b/examples/var_service/dhcp_if/log/run
@@ -6,7 +6,7 @@ logdir="/var/log/service/`(cd ..;basename $PWD)`"
6mkdir -p "$logdir" 2>/dev/null 6mkdir -p "$logdir" 2>/dev/null
7chown -R "$user": "$logdir" 7chown -R "$user": "$logdir"
8chmod -R go-rwxst,u+rwX "$logdir" 8chmod -R go-rwxst,u+rwX "$logdir"
9rm logdir 9rm -rf logdir
10ln -s "$logdir" logdir 10ln -s "$logdir" logdir
11 11
12# make this dir accessible to logger 12# make this dir accessible to logger
diff --git a/examples/var_service/dhcp_if_pinger/run b/examples/var_service/dhcp_if_pinger/run
index 1868510d1..e0e87a16a 100755
--- a/examples/var_service/dhcp_if_pinger/run
+++ b/examples/var_service/dhcp_if_pinger/run
@@ -21,9 +21,9 @@ if test -f "$0.log"; then
21 mv "$0.log.new" "$0.log" 21 mv "$0.log.new" "$0.log"
22fi 22fi
23 23
24test -f "/var/service/dhcp_$if/dhcp_$if.out" || exec env - sleep "$ping_time" 24test -f "/var/service/dhcp_$if/env.out" || exec env - sleep "$ping_time"
25 25
26. "/var/service/dhcp_$if/dhcp_$if.out" 26. "/var/service/dhcp_$if/env.out"
27test x"$router" != x"" || exec env - sleep "$ping_time" 27test x"$router" != x"" || exec env - sleep "$ping_time"
28 28
29#msg "Pinging $router" 29#msg "Pinging $router"
diff --git a/examples/var_service/ftpd/log/run b/examples/var_service/ftpd/log/run
index 560d1b19f..69d74b73f 100755
--- a/examples/var_service/ftpd/log/run
+++ b/examples/var_service/ftpd/log/run
@@ -6,7 +6,7 @@ logdir="/var/log/service/`(cd ..;basename $PWD)`"
6mkdir -p "$logdir" 2>/dev/null 6mkdir -p "$logdir" 2>/dev/null
7chown -R "$user": "$logdir" 7chown -R "$user": "$logdir"
8chmod -R go-rwxst,u+rwX "$logdir" 8chmod -R go-rwxst,u+rwX "$logdir"
9rm logdir 9rm -rf logdir
10ln -s "$logdir" logdir 10ln -s "$logdir" logdir
11 11
12# make this dir accessible to logger 12# make this dir accessible to logger
diff --git a/examples/var_service/fw/run b/examples/var_service/fw/run
index 396b678ab..81c7f2e7c 100755
--- a/examples/var_service/fw/run
+++ b/examples/var_service/fw/run
@@ -62,7 +62,7 @@ umask 077
62 62
63# Make sure rundir/ exists 63# Make sure rundir/ exists
64mkdir -p "$rundir" 2>/dev/null 64mkdir -p "$rundir" 2>/dev/null
65chown -R "$user:" "$rundir" 65chown -R "$user": "$rundir"
66chmod -R a=rX "$rundir" 66chmod -R a=rX "$rundir"
67rm -rf rundir 2>/dev/null 67rm -rf rundir 2>/dev/null
68ln -s "$rundir" rundir 68ln -s "$rundir" rundir
diff --git a/examples/var_service/httpd/log/run b/examples/var_service/httpd/log/run
index 560d1b19f..69d74b73f 100755
--- a/examples/var_service/httpd/log/run
+++ b/examples/var_service/httpd/log/run
@@ -6,7 +6,7 @@ logdir="/var/log/service/`(cd ..;basename $PWD)`"
6mkdir -p "$logdir" 2>/dev/null 6mkdir -p "$logdir" 2>/dev/null
7chown -R "$user": "$logdir" 7chown -R "$user": "$logdir"
8chmod -R go-rwxst,u+rwX "$logdir" 8chmod -R go-rwxst,u+rwX "$logdir"
9rm logdir 9rm -rf logdir
10ln -s "$logdir" logdir 10ln -s "$logdir" logdir
11 11
12# make this dir accessible to logger 12# make this dir accessible to logger
diff --git a/examples/var_service/ifplugd_if/log/run b/examples/var_service/ifplugd_if/log/run
index 560d1b19f..69d74b73f 100755
--- a/examples/var_service/ifplugd_if/log/run
+++ b/examples/var_service/ifplugd_if/log/run
@@ -6,7 +6,7 @@ logdir="/var/log/service/`(cd ..;basename $PWD)`"
6mkdir -p "$logdir" 2>/dev/null 6mkdir -p "$logdir" 2>/dev/null
7chown -R "$user": "$logdir" 7chown -R "$user": "$logdir"
8chmod -R go-rwxst,u+rwX "$logdir" 8chmod -R go-rwxst,u+rwX "$logdir"
9rm logdir 9rm -rf logdir
10ln -s "$logdir" logdir 10ln -s "$logdir" logdir
11 11
12# make this dir accessible to logger 12# make this dir accessible to logger
diff --git a/examples/var_service/ifplugd_if/run b/examples/var_service/ifplugd_if/run
index 2781cf9f9..c4f766e88 100755
--- a/examples/var_service/ifplugd_if/run
+++ b/examples/var_service/ifplugd_if/run
@@ -8,6 +8,9 @@ pwd="$PWD"
8 8
9if="${PWD##*/ifplugd_}" 9if="${PWD##*/ifplugd_}"
10 10
11echo "* Upping iface $if"
12ip link set dev "$if" up
13
11echo "* Starting ifplugd on $if [$$]" 14echo "* Starting ifplugd on $if [$$]"
12exec \ 15exec \
13env - PATH="$PATH" \ 16env - PATH="$PATH" \
diff --git a/examples/var_service/inetd/log/run b/examples/var_service/inetd/log/run
index 560d1b19f..69d74b73f 100755
--- a/examples/var_service/inetd/log/run
+++ b/examples/var_service/inetd/log/run
@@ -6,7 +6,7 @@ logdir="/var/log/service/`(cd ..;basename $PWD)`"
6mkdir -p "$logdir" 2>/dev/null 6mkdir -p "$logdir" 2>/dev/null
7chown -R "$user": "$logdir" 7chown -R "$user": "$logdir"
8chmod -R go-rwxst,u+rwX "$logdir" 8chmod -R go-rwxst,u+rwX "$logdir"
9rm logdir 9rm -rf logdir
10ln -s "$logdir" logdir 10ln -s "$logdir" logdir
11 11
12# make this dir accessible to logger 12# make this dir accessible to logger
diff --git a/examples/var_service/ntpd/log/run b/examples/var_service/ntpd/log/run
index 560d1b19f..69d74b73f 100755
--- a/examples/var_service/ntpd/log/run
+++ b/examples/var_service/ntpd/log/run
@@ -6,7 +6,7 @@ logdir="/var/log/service/`(cd ..;basename $PWD)`"
6mkdir -p "$logdir" 2>/dev/null 6mkdir -p "$logdir" 2>/dev/null
7chown -R "$user": "$logdir" 7chown -R "$user": "$logdir"
8chmod -R go-rwxst,u+rwX "$logdir" 8chmod -R go-rwxst,u+rwX "$logdir"
9rm logdir 9rm -rf logdir
10ln -s "$logdir" logdir 10ln -s "$logdir" logdir
11 11
12# make this dir accessible to logger 12# make this dir accessible to logger
diff --git a/examples/var_service/ntpd/run b/examples/var_service/ntpd/run
index 581d231a3..6f2a68188 100755
--- a/examples/var_service/ntpd/run
+++ b/examples/var_service/ntpd/run
@@ -15,7 +15,7 @@ default_p_opt="-p 0.$pool -p 1.$pool -p 2.$pool -p 3.$pool"
15 15
16# Make sure rundir/ exists 16# Make sure rundir/ exists
17mkdir -p "$rundir" 2>/dev/null 17mkdir -p "$rundir" 2>/dev/null
18chown -R "$user:" "$rundir" 18chown -R "$user": "$rundir"
19chmod -R a=rX "$rundir" 19chmod -R a=rX "$rundir"
20rm -rf rundir 2>/dev/null 20rm -rf rundir 2>/dev/null
21ln -s "$rundir" rundir 21ln -s "$rundir" rundir
diff --git a/examples/var_service/tftpd/log/run b/examples/var_service/tftpd/log/run
index 560d1b19f..69d74b73f 100755
--- a/examples/var_service/tftpd/log/run
+++ b/examples/var_service/tftpd/log/run
@@ -6,7 +6,7 @@ logdir="/var/log/service/`(cd ..;basename $PWD)`"
6mkdir -p "$logdir" 2>/dev/null 6mkdir -p "$logdir" 2>/dev/null
7chown -R "$user": "$logdir" 7chown -R "$user": "$logdir"
8chmod -R go-rwxst,u+rwX "$logdir" 8chmod -R go-rwxst,u+rwX "$logdir"
9rm logdir 9rm -rf logdir
10ln -s "$logdir" logdir 10ln -s "$logdir" logdir
11 11
12# make this dir accessible to logger 12# make this dir accessible to logger
diff --git a/examples/var_service/zcip_if/README b/examples/var_service/zcip_if/README
new file mode 100644
index 000000000..4ddccb22d
--- /dev/null
+++ b/examples/var_service/zcip_if/README
@@ -0,0 +1,5 @@
1The real README file is one directory up.
2
3This directory's run script can have useful comments.
4If it doesn't but you feel it should, please send a patch
5to busybox's mailing list.
diff --git a/examples/var_service/zcip_if/convert2ipconf b/examples/var_service/zcip_if/convert2ipconf
new file mode 100755
index 000000000..c858723fb
--- /dev/null
+++ b/examples/var_service/zcip_if/convert2ipconf
@@ -0,0 +1,24 @@
1#!/bin/sh
2# convert:
3
4#interface=eth1
5#ip=169.254.x.y
6
7# into:
8
9#let cfg=cfg+1
10#if[$cfg]=...; ip[$cfg]=...; ipmask[$cfg]=.../...; gw[$cfg]=...; net[$cfg]=... dns[$cfg]=...
11
12exec >/dev/null
13#exec >"$0.out" # debug
14exec 2>&1
15
16test "$interface" || exit 1
17test "$ip" || exit 1
18
19{
20echo "let cfg=cfg+1"
21test "$interface" && echo "if[\$cfg]='$interface'"
22test "$ip" && echo "ip[\$cfg]='$ip'"
23test "$ip" && echo "ipmask[\$cfg]='$ip/16'"
24} >"$1"
diff --git a/examples/var_service/zcip_if/finish b/examples/var_service/zcip_if/finish
new file mode 100755
index 000000000..95995cf5f
--- /dev/null
+++ b/examples/var_service/zcip_if/finish
@@ -0,0 +1,13 @@
1#!/bin/sh
2# executed when service is taken down ("sv d .")
3
4service=${PWD##*/}
5file_ipconf="$service.ipconf"
6dir_ipconf="/var/run/service/fw"
7
8# Reconfigure network with this interface disabled
9echo "Finish: deconfiguring"
10rm "env.out"
11rm "$file_ipconf"
12rm "$dir_ipconf/$file_ipconf"
13sv u /var/service/fw
diff --git a/examples/var_service/zcip_if/log/run b/examples/var_service/zcip_if/log/run
new file mode 100755
index 000000000..69d74b73f
--- /dev/null
+++ b/examples/var_service/zcip_if/log/run
@@ -0,0 +1,21 @@
1#!/bin/sh
2
3user=logger
4
5logdir="/var/log/service/`(cd ..;basename $PWD)`"
6mkdir -p "$logdir" 2>/dev/null
7chown -R "$user": "$logdir"
8chmod -R go-rwxst,u+rwX "$logdir"
9rm -rf logdir
10ln -s "$logdir" logdir
11
12# make this dir accessible to logger
13chmod a+rX .
14
15exec >/dev/null
16exec 2>&1
17exec \
18env - PATH="$PATH" \
19softlimit \
20setuidgid "$user" \
21svlogd -tt "$logdir"
diff --git a/examples/var_service/zcip_if/p_log b/examples/var_service/zcip_if/p_log
new file mode 100755
index 000000000..a2521be05
--- /dev/null
+++ b/examples/var_service/zcip_if/p_log
@@ -0,0 +1,4 @@
1#!/bin/sh
2
3cd log/logdir || exit 1
4cat @* current | $PAGER
diff --git a/examples/var_service/zcip_if/run b/examples/var_service/zcip_if/run
new file mode 100755
index 000000000..94a875465
--- /dev/null
+++ b/examples/var_service/zcip_if/run
@@ -0,0 +1,20 @@
1#!/bin/sh
2
3exec 2>&1
4exec </dev/null
5
6pwd="$PWD"
7
8if="${PWD##*/zcip_}"
9
10echo "* Upping iface $if"
11ip link set dev "$if" up
12
13echo "* Starting zcip"
14exec \
15env - PATH="$PATH" \
16softlimit \
17setuidgid root \
18zcip -fvv \
19 "$if" \
20 "$pwd/zcip_handler"
diff --git a/examples/var_service/zcip_if/w_log b/examples/var_service/zcip_if/w_log
new file mode 100755
index 000000000..aa36ef13b
--- /dev/null
+++ b/examples/var_service/zcip_if/w_log
@@ -0,0 +1,4 @@
1#!/bin/sh
2
3cd log/logdir || exit 1
4watch -n2 'w=`ttysize w`; h=`ttysize h`; tail -$((h-3)) current 2>&1 | cut -b1-$((w-2))'
diff --git a/examples/var_service/zcip_if/zcip_handler b/examples/var_service/zcip_if/zcip_handler
new file mode 100755
index 000000000..3c6ca788b
--- /dev/null
+++ b/examples/var_service/zcip_if/zcip_handler
@@ -0,0 +1,47 @@
1#!/bin/sh
2# executed by zcip
3# parameters: $1 and environment
4# $1 is:
5#
6# init: zcip starts. Environment:
7# interface=eth0
8#
9# config: Address is obtained.
10# interface=eth0
11# ip=169.254.a.b
12#
13# deconfig: Conflict or link went down.
14# interface=eth0
15
16service=${PWD##*/}
17file_ipconf="$service.ipconf"
18dir_ipconf="/var/run/service/fw"
19
20exec >/dev/null
21#exec >>"$0.out" #debug
22exec 2>&1
23
24echo "`date`: Params: $*"
25
26if test x"$1" != x"config"; then
27 # Reconfigure network with this interface disabled
28 echo "Deconfiguring"
29 rm "$file_ipconf"
30 rm "$dir_ipconf/$file_ipconf"
31 sv u /var/service/fw
32 exit
33fi
34
35# "config": we've got the address
36# Record information for e.g. dhcp_$IF_pinger service
37env >"env.out"
38
39./convert2ipconf "$file_ipconf"
40# Reconfigure routing and firewall if needed
41diff --brief "$file_ipconf" "$dir_ipconf/$file_ipconf" >/dev/null 2>&1
42if test $? != 0; then
43 echo "Reconfiguring fw"
44 mkdir -p "$dir_ipconf" 2>/dev/null
45 cp "$file_ipconf" "$dir_ipconf/$file_ipconf"
46 sv u /var/service/fw
47fi
diff --git a/findutils/xargs.c b/findutils/xargs.c
index dba74ea61..8b7ab7b6a 100644
--- a/findutils/xargs.c
+++ b/findutils/xargs.c
@@ -590,6 +590,9 @@ int xargs_main(int argc, char **argv)
590 G.argv = argv; 590 G.argv = argv;
591 argc = 0; 591 argc = 0;
592 read_args = process_stdin_with_replace; 592 read_args = process_stdin_with_replace;
593 /* Make -I imply -r. GNU findutils seems to do the same: */
594 /* (otherwise "echo -n | xargs -I% echo %" would SEGV) */
595 opt |= OPT_NO_EMPTY;
593 } else 596 } else
594#endif 597#endif
595 { 598 {
diff --git a/include/applets.src.h b/include/applets.src.h
index 5b597202e..6e1b02fc3 100644
--- a/include/applets.src.h
+++ b/include/applets.src.h
@@ -192,8 +192,6 @@ IF_KILLALL5(APPLET_ODDNAME(killall5, kill, BB_DIR_USR_SBIN, BB_SUID_DROP, killal
192IF_LAST(APPLET(last, BB_DIR_USR_BIN, BB_SUID_DROP)) 192IF_LAST(APPLET(last, BB_DIR_USR_BIN, BB_SUID_DROP))
193//IF_LENGTH(APPLET_NOFORK(length, length, BB_DIR_USR_BIN, BB_SUID_DROP, length)) 193//IF_LENGTH(APPLET_NOFORK(length, length, BB_DIR_USR_BIN, BB_SUID_DROP, length))
194IF_LESS(APPLET(less, BB_DIR_USR_BIN, BB_SUID_DROP)) 194IF_LESS(APPLET(less, BB_DIR_USR_BIN, BB_SUID_DROP))
195IF_SETARCH(APPLET_ODDNAME(linux32, setarch, BB_DIR_BIN, BB_SUID_DROP, linux32))
196IF_SETARCH(APPLET_ODDNAME(linux64, setarch, BB_DIR_BIN, BB_SUID_DROP, linux64))
197IF_LN(APPLET_NOEXEC(ln, ln, BB_DIR_BIN, BB_SUID_DROP, ln)) 195IF_LN(APPLET_NOEXEC(ln, ln, BB_DIR_BIN, BB_SUID_DROP, ln))
198IF_LOAD_POLICY(APPLET(load_policy, BB_DIR_USR_SBIN, BB_SUID_DROP)) 196IF_LOAD_POLICY(APPLET(load_policy, BB_DIR_USR_SBIN, BB_SUID_DROP))
199IF_LOADFONT(APPLET(loadfont, BB_DIR_USR_SBIN, BB_SUID_DROP)) 197IF_LOADFONT(APPLET(loadfont, BB_DIR_USR_SBIN, BB_SUID_DROP))
@@ -274,7 +272,6 @@ IF_SELINUXENABLED(APPLET(selinuxenabled, BB_DIR_USR_SBIN, BB_SUID_DROP))
274IF_SENDMAIL(APPLET(sendmail, BB_DIR_USR_SBIN, BB_SUID_DROP)) 272IF_SENDMAIL(APPLET(sendmail, BB_DIR_USR_SBIN, BB_SUID_DROP))
275IF_SEQ(APPLET_NOFORK(seq, seq, BB_DIR_USR_BIN, BB_SUID_DROP, seq)) 273IF_SEQ(APPLET_NOFORK(seq, seq, BB_DIR_USR_BIN, BB_SUID_DROP, seq))
276IF_SESTATUS(APPLET(sestatus, BB_DIR_USR_SBIN, BB_SUID_DROP)) 274IF_SESTATUS(APPLET(sestatus, BB_DIR_USR_SBIN, BB_SUID_DROP))
277IF_SETARCH(APPLET(setarch, BB_DIR_BIN, BB_SUID_DROP))
278IF_SETCONSOLE(APPLET(setconsole, BB_DIR_SBIN, BB_SUID_DROP)) 275IF_SETCONSOLE(APPLET(setconsole, BB_DIR_SBIN, BB_SUID_DROP))
279IF_SETENFORCE(APPLET(setenforce, BB_DIR_USR_SBIN, BB_SUID_DROP)) 276IF_SETENFORCE(APPLET(setenforce, BB_DIR_USR_SBIN, BB_SUID_DROP))
280IF_SETFILES(APPLET(setfiles, BB_DIR_SBIN, BB_SUID_DROP)) 277IF_SETFILES(APPLET(setfiles, BB_DIR_SBIN, BB_SUID_DROP))
diff --git a/include/bb_archive.h b/include/bb_archive.h
index e2c8aede4..03f174839 100644
--- a/include/bb_archive.h
+++ b/include/bb_archive.h
@@ -87,6 +87,9 @@ typedef struct archive_handle_t {
87 off_t offset; 87 off_t offset;
88 88
89 /* Archiver specific. Can make it a union if it ever gets big */ 89 /* Archiver specific. Can make it a union if it ever gets big */
90#if ENABLE_FEATURE_TAR_LONG_OPTIONS
91 unsigned tar__strip_components;
92#endif
90#define PAX_NEXT_FILE 0 93#define PAX_NEXT_FILE 0
91#define PAX_GLOBAL 1 94#define PAX_GLOBAL 1
92#if ENABLE_TAR || ENABLE_DPKG || ENABLE_DPKG_DEB 95#if ENABLE_TAR || ENABLE_DPKG || ENABLE_DPKG_DEB
diff --git a/include/libbb.h b/include/libbb.h
index de00abe7f..7959884e3 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -1347,11 +1347,6 @@ extern void selinux_preserve_fcontext(int fdesc) FAST_FUNC;
1347extern void selinux_or_die(void) FAST_FUNC; 1347extern void selinux_or_die(void) FAST_FUNC;
1348 1348
1349 1349
1350/* systemd support */
1351#define SD_LISTEN_FDS_START 3
1352int sd_listen_fds(void);
1353
1354
1355/* setup_environment: 1350/* setup_environment:
1356 * if chdir pw->pw_dir: ok: else if to_tmp == 1: goto /tmp else: goto / or die 1351 * if chdir pw->pw_dir: ok: else if to_tmp == 1: goto /tmp else: goto / or die
1357 * if clear_env = 1: cd(pw->pw_dir), clear environment, then set 1352 * if clear_env = 1: cd(pw->pw_dir), clear environment, then set
@@ -1418,6 +1413,7 @@ extern void print_login_prompt(void) FAST_FUNC;
1418char *xmalloc_ttyname(int fd) FAST_FUNC RETURNS_MALLOC; 1413char *xmalloc_ttyname(int fd) FAST_FUNC RETURNS_MALLOC;
1419/* NB: typically you want to pass fd 0, not 1. Think 'applet | grep something' */ 1414/* NB: typically you want to pass fd 0, not 1. Think 'applet | grep something' */
1420int get_terminal_width_height(int fd, unsigned *width, unsigned *height) FAST_FUNC; 1415int get_terminal_width_height(int fd, unsigned *width, unsigned *height) FAST_FUNC;
1416int get_terminal_width(int fd) FAST_FUNC;
1421 1417
1422int tcsetattr_stdin_TCSANOW(const struct termios *tp) FAST_FUNC; 1418int tcsetattr_stdin_TCSANOW(const struct termios *tp) FAST_FUNC;
1423 1419
diff --git a/libbb/Config.src b/libbb/Config.src
index 19021fed1..6ba256290 100644
--- a/libbb/Config.src
+++ b/libbb/Config.src
@@ -16,7 +16,7 @@ config PASSWORD_MINLEN
16 16
17config MD5_SMALL 17config MD5_SMALL
18 int "MD5: Trade bytes for speed (0:fast, 3:slow)" 18 int "MD5: Trade bytes for speed (0:fast, 3:slow)"
19 default 1 19 default 1 # all "fast or small" options default to small
20 range 0 3 20 range 0 3
21 help 21 help
22 Trade binary size versus speed for the md5sum algorithm. 22 Trade binary size versus speed for the md5sum algorithm.
@@ -30,7 +30,7 @@ config MD5_SMALL
30 30
31config SHA3_SMALL 31config SHA3_SMALL
32 int "SHA3: Trade bytes for speed (0:fast, 1:slow)" 32 int "SHA3: Trade bytes for speed (0:fast, 1:slow)"
33 default 1 33 default 1 # all "fast or small" options default to small
34 range 0 1 34 range 0 1
35 help 35 help
36 Trade binary size versus speed for the sha3sum algorithm. 36 Trade binary size versus speed for the sha3sum algorithm.
@@ -40,7 +40,7 @@ config SHA3_SMALL
40 40
41config FEATURE_FAST_TOP 41config FEATURE_FAST_TOP
42 bool "Faster /proc scanning code (+100 bytes)" 42 bool "Faster /proc scanning code (+100 bytes)"
43 default y 43 default n # all "fast or small" options default to small
44 help 44 help
45 This option makes top (and ps) ~20% faster (or 20% less CPU hungry), 45 This option makes top (and ps) ~20% faster (or 20% less CPU hungry),
46 but code size is slightly bigger. 46 but code size is slightly bigger.
@@ -114,7 +114,7 @@ config FEATURE_EDITING_SAVE_ON_EXIT
114config FEATURE_REVERSE_SEARCH 114config FEATURE_REVERSE_SEARCH
115 bool "Reverse history search" 115 bool "Reverse history search"
116 default y 116 default y
117 depends on FEATURE_EDITING_SAVEHISTORY 117 depends on FEATURE_EDITING
118 help 118 help
119 Enable readline-like Ctrl-R combination for reverse history search. 119 Enable readline-like Ctrl-R combination for reverse history search.
120 Increases code by about 0.5k. 120 Increases code by about 0.5k.
@@ -208,7 +208,7 @@ config FEATURE_SKIP_ROOTFS
208 208
209config MONOTONIC_SYSCALL 209config MONOTONIC_SYSCALL
210 bool "Use clock_gettime(CLOCK_MONOTONIC) syscall" 210 bool "Use clock_gettime(CLOCK_MONOTONIC) syscall"
211 default n 211 default y
212 select PLATFORM_LINUX 212 select PLATFORM_LINUX
213 help 213 help
214 Use clock_gettime(CLOCK_MONOTONIC) syscall for measuring 214 Use clock_gettime(CLOCK_MONOTONIC) syscall for measuring
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index 7da7cad1c..1d6a4b274 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -628,7 +628,7 @@ static int busybox_main(char **argv)
628 output_width = 80; 628 output_width = 80;
629 if (ENABLE_FEATURE_AUTOWIDTH) { 629 if (ENABLE_FEATURE_AUTOWIDTH) {
630 /* Obtain the terminal width */ 630 /* Obtain the terminal width */
631 get_terminal_width_height(0, &output_width, NULL); 631 output_width = get_terminal_width(2);
632 } 632 }
633 633
634 dup2(1, 2); 634 dup2(1, 2);
@@ -659,10 +659,10 @@ static int busybox_main(char **argv)
659 ) 659 )
660 IF_FEATURE_SH_STANDALONE( 660 IF_FEATURE_SH_STANDALONE(
661 "\tBusyBox is a multi-call binary that combines many common Unix\n" 661 "\tBusyBox is a multi-call binary that combines many common Unix\n"
662 "\tutilities into a single executable. The shell in this version\n" 662 "\tutilities into a single executable. The shell in this build\n"
663 "\thas been configured to prefer built-in utilities to external\n" 663 "\tis configured to run built-in utilities without $PATH search.\n"
664 "\tbinaries. This avoids having to install a link to busybox for\n" 664 "\tYou don't need to install a link to busybox for each utility.\n"
665 "\teach function to be invoked.\n" 665 "\tTo run external program, use full path (/sbin/ip instead of ip).\n"
666 ) 666 )
667 "\n" 667 "\n"
668#if ENABLE_GLOBBING 668#if ENABLE_GLOBBING
diff --git a/libbb/kernel_version.c b/libbb/kernel_version.c
index 738ed022b..9b6c62299 100644
--- a/libbb/kernel_version.c
+++ b/libbb/kernel_version.c
@@ -20,16 +20,16 @@
20int FAST_FUNC get_linux_version_code(void) 20int FAST_FUNC get_linux_version_code(void)
21{ 21{
22 struct utsname name; 22 struct utsname name;
23 char *s, *t; 23 char *t;
24 int i, r; 24 int i, r;
25 25
26 uname(&name); /* never fails */ 26 uname(&name); /* never fails */
27 s = name.release; 27 t = name.release;
28 r = 0; 28 r = 0;
29 for (i = 0; i < 3; i++) { 29 for (i = 0; i < 3; i++) {
30 t = strtok(s, "."); 30 t = strtok(t, ".");
31 r = r * 256 + (t ? atoi(t) : 0); 31 r = r * 256 + (t ? atoi(t) : 0);
32 s = NULL; 32 t = NULL;
33 } 33 }
34 return r; 34 return r;
35} 35}
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 5cb40a508..04361b509 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -829,10 +829,12 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type)
829 if (type == FIND_EXE_ONLY) { 829 if (type == FIND_EXE_ONLY) {
830 const char *p = applet_names; 830 const char *p = applet_names;
831 831
832 for (i=0; i < NUM_APPLETS; i++) { 832 i = 0;
833 while (i < NUM_APPLETS) {
833 if (strncmp(pfind, p, pf_len) == 0) 834 if (strncmp(pfind, p, pf_len) == 0)
834 add_match(xstrdup(p)); 835 add_match(xstrdup(p));
835 p += strlen(p) + 1; 836 p += strlen(p) + 1;
837 i++;
836 } 838 }
837 } 839 }
838#endif 840#endif
diff --git a/libbb/procps.c b/libbb/procps.c
index 5a4ea59d0..452b50b82 100644
--- a/libbb/procps.c
+++ b/libbb/procps.c
@@ -589,12 +589,14 @@ void FAST_FUNC read_cmdline(char *buf, int col, unsigned pid, const char *comm)
589 buf[sz] = ' '; 589 buf[sz] = ' ';
590 sz--; 590 sz--;
591 } 591 }
592 if (base[0] == '-') /* "-sh" (login shell)? */
593 base++;
592 594
593 /* If comm differs from argv0, prepend "{comm} ". 595 /* If comm differs from argv0, prepend "{comm} ".
594 * It allows to see thread names set by prctl(PR_SET_NAME). 596 * It allows to see thread names set by prctl(PR_SET_NAME).
595 */ 597 */
596 if (base[0] == '-') /* "-sh" (login shell)? */ 598 if (!comm)
597 base++; 599 return;
598 comm_len = strlen(comm); 600 comm_len = strlen(comm);
599 /* Why compare up to comm_len, not COMM_LEN-1? 601 /* Why compare up to comm_len, not COMM_LEN-1?
600 * Well, some processes rewrite argv, and use _spaces_ there 602 * Well, some processes rewrite argv, and use _spaces_ there
@@ -613,7 +615,7 @@ void FAST_FUNC read_cmdline(char *buf, int col, unsigned pid, const char *comm)
613 buf[col - 1] = '\0'; 615 buf[col - 1] = '\0';
614 } 616 }
615 } else { 617 } else {
616 snprintf(buf, col, "[%s]", comm); 618 snprintf(buf, col, "[%s]", comm ? comm : "?");
617 } 619 }
618} 620}
619 621
diff --git a/libbb/progress.c b/libbb/progress.c
index 372feb0c2..3c2f01667 100644
--- a/libbb/progress.c
+++ b/libbb/progress.c
@@ -45,13 +45,6 @@ enum {
45 STALLTIME = 5 45 STALLTIME = 5
46}; 46};
47 47
48static unsigned int get_tty2_width(void)
49{
50 unsigned width;
51 get_terminal_width_height(2, &width, NULL);
52 return width;
53}
54
55void FAST_FUNC bb_progress_init(bb_progress_t *p, const char *curfile) 48void FAST_FUNC bb_progress_init(bb_progress_t *p, const char *curfile)
56{ 49{
57#if ENABLE_UNICODE_SUPPORT 50#if ENABLE_UNICODE_SUPPORT
@@ -80,7 +73,7 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p,
80{ 73{
81 uoff_t beg_and_transferred; 74 uoff_t beg_and_transferred;
82 unsigned since_last_update, elapsed; 75 unsigned since_last_update, elapsed;
83 int barlength; 76 int notty;
84 int kiloscale; 77 int kiloscale;
85 78
86 //transferred = 1234; /* use for stall detection testing */ 79 //transferred = 1234; /* use for stall detection testing */
@@ -137,18 +130,21 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p,
137 } 130 }
138 } 131 }
139 132
133 notty = !isatty(STDERR_FILENO);
134
140 if (ENABLE_UNICODE_SUPPORT) 135 if (ENABLE_UNICODE_SUPPORT)
141 fprintf(stderr, "\r%s", p->curfile); 136 fprintf(stderr, "\r%s" + notty, p->curfile);
142 else 137 else
143 fprintf(stderr, "\r%-20.20s", p->curfile); 138 fprintf(stderr, "\r%-20.20s" + notty, p->curfile);
144 139
145 beg_and_transferred = beg_size + transferred; 140 beg_and_transferred = beg_size + transferred;
146 141
147 if (totalsize != 0) { 142 if (totalsize != 0) {
143 int barlength;
148 unsigned ratio = 100 * beg_and_transferred / totalsize; 144 unsigned ratio = 100 * beg_and_transferred / totalsize;
149 fprintf(stderr, "%4u%%", ratio); 145 fprintf(stderr, "%4u%%", ratio);
150 146
151 barlength = get_tty2_width() - 49; 147 barlength = get_terminal_width(2) - 49;
152 if (barlength > 0) { 148 if (barlength > 0) {
153 /* god bless gcc for variable arrays :) */ 149 /* god bless gcc for variable arrays :) */
154 char buf[barlength + 1]; 150 char buf[barlength + 1];
@@ -204,4 +200,6 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p,
204 hours = eta / 3600; 200 hours = eta / 3600;
205 fprintf(stderr, "%3u:%02u:%02u ETA", hours, secs / 60, secs % 60); 201 fprintf(stderr, "%3u:%02u:%02u ETA", hours, secs / 60, secs % 60);
206 } 202 }
203 if (notty)
204 fputc('\n', stderr);
207} 205}
diff --git a/libbb/systemd_support.c b/libbb/systemd_support.c
deleted file mode 100644
index 542a3efff..000000000
--- a/libbb/systemd_support.c
+++ /dev/null
@@ -1,62 +0,0 @@
1/*
2 * Copyright (C) 2011 Davide Cavalca <davide@geexbox.org>
3 *
4 * Based on http://cgit.freedesktop.org/systemd/tree/src/sd-daemon.c
5 * Copyright 2010 Lennart Poettering
6 *
7 * Permission is hereby granted, free of charge, to any person
8 * obtaining a copy of this software and associated documentation files
9 * (the "Software"), to deal in the Software without restriction,
10 * including without limitation the rights to use, copy, modify, merge,
11 * publish, distribute, sublicense, and/or sell copies of the Software,
12 * and to permit persons to whom the Software is furnished to do so,
13 * subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be
16 * included in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
22 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 */
27#include "libbb.h"
28
29//config:config FEATURE_SYSTEMD
30//config: bool "Enable systemd support"
31//config: default y
32//config: help
33//config: If you plan to use busybox daemons on a system where daemons
34//config: are controlled by systemd, enable this option.
35//config: If you don't use systemd, it is still safe to enable it,
36//config: but the downside is increased code size.
37
38//kbuild:lib-$(CONFIG_FEATURE_SYSTEMD) += systemd_support.o
39
40int sd_listen_fds(void)
41{
42 const char *e;
43 int n;
44 int fd;
45
46 e = getenv("LISTEN_PID");
47 if (!e)
48 return 0;
49 n = xatoi_positive(e);
50 /* Is this for us? */
51 if (getpid() != (pid_t) n)
52 return 0;
53
54 e = getenv("LISTEN_FDS");
55 if (!e)
56 return 0;
57 n = xatoi_positive(e);
58 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++)
59 close_on_exec_on(fd);
60
61 return n;
62}
diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c
index 0c9969640..206edb4a0 100644
--- a/libbb/xfuncs.c
+++ b/libbb/xfuncs.c
@@ -270,6 +270,12 @@ int FAST_FUNC get_terminal_width_height(int fd, unsigned *width, unsigned *heigh
270 *width = wh_helper(win.ws_col, 80, "COLUMNS", &err); 270 *width = wh_helper(win.ws_col, 80, "COLUMNS", &err);
271 return err; 271 return err;
272} 272}
273int FAST_FUNC get_terminal_width(int fd)
274{
275 unsigned width;
276 get_terminal_width_height(fd, &width, NULL);
277 return width;
278}
273 279
274int FAST_FUNC tcsetattr_stdin_TCSANOW(const struct termios *tp) 280int FAST_FUNC tcsetattr_stdin_TCSANOW(const struct termios *tp)
275{ 281{
diff --git a/loginutils/login.c b/loginutils/login.c
index f1f04da19..67fe82e86 100644
--- a/loginutils/login.c
+++ b/loginutils/login.c
@@ -58,7 +58,7 @@
58//usage:#define login_full_usage "\n\n" 58//usage:#define login_full_usage "\n\n"
59//usage: "Begin a new session on the system\n" 59//usage: "Begin a new session on the system\n"
60//usage: "\n -f Don't authenticate (user already authenticated)" 60//usage: "\n -f Don't authenticate (user already authenticated)"
61//usage: "\n -h Name of the remote host" 61//usage: "\n -h HOST Host user came from (for network logins)"
62//usage: "\n -p Preserve environment" 62//usage: "\n -p Preserve environment"
63 63
64#include "libbb.h" 64#include "libbb.h"
diff --git a/miscutils/Config.src b/miscutils/Config.src
index d69abf1a2..06f1c52ba 100644
--- a/miscutils/Config.src
+++ b/miscutils/Config.src
@@ -308,23 +308,13 @@ config LAST
308 help 308 help
309 'last' displays a list of the last users that logged into the system. 309 'last' displays a list of the last users that logged into the system.
310 310
311choice
312 prompt "Choose last implementation"
313 depends on LAST
314 default FEATURE_LAST_FANCY
315
316config FEATURE_LAST_SMALL
317 bool "small"
318 help
319 This is a small version of last with just the basic set of
320 features.
321
322config FEATURE_LAST_FANCY 311config FEATURE_LAST_FANCY
323 bool "huge" 312 bool "Turn on output of extra information"
313 default y
314 depends on LAST
324 help 315 help
325 'last' displays detailed information about the last users that 316 'last' displays detailed information about the last users that
326 logged into the system (mimics sysvinit last). +900 bytes. 317 logged into the system (mimics sysvinit last). +900 bytes.
327endchoice
328 318
329config HDPARM 319config HDPARM
330 bool "hdparm" 320 bool "hdparm"
diff --git a/miscutils/fbsplash.c b/miscutils/fbsplash.c
index 77033c258..9557c41db 100644
--- a/miscutils/fbsplash.c
+++ b/miscutils/fbsplash.c
@@ -150,7 +150,7 @@ static void fb_open(const char *strfb_device)
150 150
151 // map the device in memory 151 // map the device in memory
152 G.addr = mmap(NULL, 152 G.addr = mmap(NULL,
153 G.scr_var.yres * G.scr_fix.line_length, 153 (G.scr_var.yres_virtual ?: G.scr_var.yres) * G.scr_fix.line_length,
154 PROT_WRITE, MAP_SHARED, fbfd, 0); 154 PROT_WRITE, MAP_SHARED, fbfd, 0);
155 if (G.addr == MAP_FAILED) 155 if (G.addr == MAP_FAILED)
156 bb_perror_msg_and_die("mmap"); 156 bb_perror_msg_and_die("mmap");
diff --git a/modutils/Config.src b/modutils/Config.src
index 449ac65af..0b11832bc 100644
--- a/modutils/Config.src
+++ b/modutils/Config.src
@@ -38,9 +38,6 @@ config MODPROBE_SMALL
38 - rmmod is an alias to modprobe -r 38 - rmmod is an alias to modprobe -r
39 - depmod generates modules.dep.bb 39 - depmod generates modules.dep.bb
40 40
41 As of 2008-07, this code is experimental. It is 14kb smaller
42 than "non-small" modutils.
43
44config FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE 41config FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE
45 bool "Accept module options on modprobe command line" 42 bool "Accept module options on modprobe command line"
46 default y 43 default y
diff --git a/modutils/modinfo.c b/modutils/modinfo.c
index 8e74b6438..aa641ad54 100644
--- a/modutils/modinfo.c
+++ b/modutils/modinfo.c
@@ -5,11 +5,6 @@
5 * 5 *
6 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 6 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
7 */ 7 */
8
9//applet:IF_MODINFO(APPLET(modinfo, BB_DIR_SBIN, BB_SUID_DROP))
10
11//kbuild:lib-$(CONFIG_MODINFO) += modinfo.o modutils.o
12
13//config:config MODINFO 8//config:config MODINFO
14//config: bool "modinfo" 9//config: bool "modinfo"
15//config: default y 10//config: default y
@@ -17,26 +12,46 @@
17//config: help 12//config: help
18//config: Show information about a Linux Kernel module 13//config: Show information about a Linux Kernel module
19 14
15//applet:IF_MODINFO(APPLET(modinfo, BB_DIR_SBIN, BB_SUID_DROP))
16
17//kbuild:lib-$(CONFIG_MODINFO) += modinfo.o modutils.o
18
20#include <fnmatch.h> 19#include <fnmatch.h>
21#include <sys/utsname.h> /* uname() */ 20#include <sys/utsname.h> /* uname() */
22#include "libbb.h" 21#include "libbb.h"
23#include "modutils.h" 22#include "modutils.h"
24 23
25 24static const char *const shortcuts[] = {
26enum { 25 "filename", // -n
27 OPT_TAGS = (1 << 12) - 1, /* shortcut count */ 26 "author", // -a
28 OPT_F = (1 << 12), /* field name */ 27 "description", // -d
29 OPT_0 = (1 << 13), /* \0 as separator */ 28 "license", // -l
29 "parm", // -p
30 "version", // the rest has no shortcut options
31 "alias",
32 "srcversion",
33 "depends",
34 "uts_release",
35 "intree",
36 "vermagic",
37 "firmware",
30}; 38};
31 39
32struct modinfo_env { 40enum {
33 char *field; 41 OPT_0 = (1 << 0), /* \0 as separator */
34 int tags; 42 OPT_F = (1 << 1), /* field name */
43 /* first bits are for -nadlp options, the rest are for
44 * fields not selectable with "shortcut" options
45 */
46 OPT_n = (1 << 2),
47 OPT_TAGS = ((1 << ARRAY_SIZE(shortcuts)) - 1) << 2,
35}; 48};
36 49
37static void display(const char *data, const char *pattern, int flag) 50static void display(const char *data, const char *pattern)
38{ 51{
39 if (flag) { 52 int flag = option_mask32 >> 1; /* shift out -0 bit */
53 if (flag & (flag-1)) {
54 /* more than one field to show: print "FIELD:" pfx */
40 int n = printf("%s:", pattern); 55 int n = printf("%s:", pattern);
41 while (n++ < 16) 56 while (n++ < 16)
42 bb_putchar(' '); 57 bb_putchar(' ');
@@ -45,55 +60,45 @@ static void display(const char *data, const char *pattern, int flag)
45} 60}
46 61
47static void modinfo(const char *path, const char *version, 62static void modinfo(const char *path, const char *version,
48 const struct modinfo_env *env) 63 const char *field)
49{ 64{
50 static const char *const shortcuts[] = {
51 "filename",
52 "license",
53 "author",
54 "description",
55 "version",
56 "alias",
57 "srcversion",
58 "depends",
59 "uts_release",
60 "vermagic",
61 "parm",
62 "firmware",
63 };
64 size_t len; 65 size_t len;
65 int j; 66 int j;
66 char *ptr, *the_module; 67 char *ptr, *the_module;
67 const char *field = env->field; 68 char *allocated;
68 int tags = env->tags; 69 int tags = option_mask32;
69
70 if (tags & 1) { /* filename */
71 display(path, shortcuts[0], 1 != tags);
72 }
73 70
71 allocated = NULL;
74 len = MAXINT(ssize_t); 72 len = MAXINT(ssize_t);
75 the_module = xmalloc_open_zipped_read_close(path, &len); 73 the_module = xmalloc_open_zipped_read_close(path, &len);
76 if (!the_module) { 74 if (!the_module) {
77 if (path[0] == '/') 75 if (path[0] == '/')
78 return; 76 return;
79 /* Newer depmod puts relative paths in modules.dep */ 77 /* Newer depmod puts relative paths in modules.dep */
80 path = xasprintf("%s/%s/%s", CONFIG_DEFAULT_MODULES_DIR, version, path); 78 path = allocated = xasprintf("%s/%s/%s", CONFIG_DEFAULT_MODULES_DIR, version, path);
81 the_module = xmalloc_open_zipped_read_close(path, &len); 79 the_module = xmalloc_open_zipped_read_close(path, &len);
82 free((char*)path); 80 if (!the_module) {
83 if (!the_module) 81 bb_error_msg("module '%s' not found", path);
84 return; 82 goto ret;
83 }
85 } 84 }
86 85
87 if (field) 86 for (j = 1; (1<<j) & (OPT_TAGS|OPT_F); j++) {
88 tags |= OPT_F;
89 for (j = 1; (1<<j) & (OPT_TAGS + OPT_F); j++) {
90 const char *pattern; 87 const char *pattern;
91 88
92 if (!((1<<j) & tags)) 89 if (!((1<<j) & tags))
93 continue; 90 continue;
91
94 pattern = field; 92 pattern = field;
95 if ((1<<j) & OPT_TAGS) 93 if ((1<<j) & OPT_TAGS)
96 pattern = shortcuts[j]; 94 pattern = shortcuts[j-2];
95
96 if (strcmp(pattern, shortcuts[0]) == 0) {
97 /* "-n" or "-F filename" */
98 display(path, shortcuts[0]);
99 continue;
100 }
101
97 ptr = the_module; 102 ptr = the_module;
98 while (1) { 103 while (1) {
99 char *after_pattern; 104 char *after_pattern;
@@ -106,7 +111,7 @@ static void modinfo(const char *path, const char *version,
106 /* field prefixes are 0x80 or 0x00 */ 111 /* field prefixes are 0x80 or 0x00 */
107 if ((ptr[-1] & 0x7F) == 0x00) { 112 if ((ptr[-1] & 0x7F) == 0x00) {
108 ptr = after_pattern + 1; 113 ptr = after_pattern + 1;
109 display(ptr, pattern, (1<<j) != tags); 114 display(ptr, pattern);
110 ptr += strlen(ptr); 115 ptr += strlen(ptr);
111 } 116 }
112 } 117 }
@@ -114,15 +119,18 @@ static void modinfo(const char *path, const char *version,
114 } 119 }
115 } 120 }
116 free(the_module); 121 free(the_module);
122 ret:
123 free(allocated);
117} 124}
118 125
119//usage:#define modinfo_trivial_usage 126//usage:#define modinfo_trivial_usage
120//usage: "[-adlp0] [-F keyword] MODULE" 127//usage: "[-adlpn0] [-F keyword] MODULE"
121//usage:#define modinfo_full_usage "\n\n" 128//usage:#define modinfo_full_usage "\n\n"
122//usage: " -a Shortcut for '-F author'" 129//usage: " -a Shortcut for '-F author'"
123//usage: "\n -d Shortcut for '-F description'" 130//usage: "\n -d Shortcut for '-F description'"
124//usage: "\n -l Shortcut for '-F license'" 131//usage: "\n -l Shortcut for '-F license'"
125//usage: "\n -p Shortcut for '-F parm'" 132//usage: "\n -p Shortcut for '-F parm'"
133////usage: "\n -n Shortcut for '-F filename'"
126//usage: "\n -F keyword Keyword to look for" 134//usage: "\n -F keyword Keyword to look for"
127//usage: "\n -0 Separate output with NULs" 135//usage: "\n -0 Separate output with NULs"
128//usage:#define modinfo_example_usage 136//usage:#define modinfo_example_usage
@@ -131,7 +139,7 @@ static void modinfo(const char *path, const char *version,
131int modinfo_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 139int modinfo_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
132int modinfo_main(int argc UNUSED_PARAM, char **argv) 140int modinfo_main(int argc UNUSED_PARAM, char **argv)
133{ 141{
134 struct modinfo_env env; 142 const char *field;
135 char name[MODULE_NAME_LEN]; 143 char name[MODULE_NAME_LEN];
136 struct utsname uts; 144 struct utsname uts;
137 parser_t *parser; 145 parser_t *parser;
@@ -139,10 +147,12 @@ int modinfo_main(int argc UNUSED_PARAM, char **argv)
139 unsigned opts; 147 unsigned opts;
140 unsigned i; 148 unsigned i;
141 149
142 env.field = NULL; 150 field = NULL;
143 opt_complementary = "-1"; /* minimum one param */ 151 opt_complementary = "-1"; /* minimum one param */
144 opts = getopt32(argv, "nladvAsDumpF:0", &env.field); 152 opts = getopt32(argv, "0F:nadlp", &field);
145 env.tags = opts & OPT_TAGS ? opts & OPT_TAGS : OPT_TAGS; 153 /* If no field selected, show all */
154 if (!(opts & (OPT_TAGS|OPT_F)))
155 option_mask32 |= OPT_TAGS;
146 argv += optind; 156 argv += optind;
147 157
148 uname(&uts); 158 uname(&uts);
@@ -159,7 +169,7 @@ int modinfo_main(int argc UNUSED_PARAM, char **argv)
159 filename2modname(bb_basename(tokens[0]), name); 169 filename2modname(bb_basename(tokens[0]), name);
160 for (i = 0; argv[i]; i++) { 170 for (i = 0; argv[i]; i++) {
161 if (fnmatch(argv[i], name, 0) == 0) { 171 if (fnmatch(argv[i], name, 0) == 0) {
162 modinfo(tokens[0], uts.release, &env); 172 modinfo(tokens[0], uts.release, field);
163 argv[i] = (char *) ""; 173 argv[i] = (char *) "";
164 } 174 }
165 } 175 }
@@ -169,7 +179,7 @@ int modinfo_main(int argc UNUSED_PARAM, char **argv)
169 179
170 for (i = 0; argv[i]; i++) { 180 for (i = 0; argv[i]; i++) {
171 if (argv[i][0]) { 181 if (argv[i][0]) {
172 modinfo(argv[i], uts.release, &env); 182 modinfo(argv[i], uts.release, field);
173 } 183 }
174 } 184 }
175 185
diff --git a/modutils/modprobe.c b/modutils/modprobe.c
index 314a7a1cb..05bf02cf8 100644
--- a/modutils/modprobe.c
+++ b/modutils/modprobe.c
@@ -461,9 +461,8 @@ static int do_modprobe(struct module_entry *m)
461 rc = bb_delete_module(m2->modname, O_EXCL); 461 rc = bb_delete_module(m2->modname, O_EXCL);
462 if (rc) { 462 if (rc) {
463 if (first) { 463 if (first) {
464 bb_error_msg("can't unload module %s: %s", 464 bb_perror_msg("can't unload module '%s'",
465 humanly_readable_name(m2), 465 humanly_readable_name(m2));
466 moderror(rc));
467 break; 466 break;
468 } 467 }
469 } else { 468 } else {
@@ -622,7 +621,7 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
622 * autoclean will be removed". 621 * autoclean will be removed".
623 */ 622 */
624 if (bb_delete_module(NULL, O_NONBLOCK | O_EXCL) != 0) 623 if (bb_delete_module(NULL, O_NONBLOCK | O_EXCL) != 0)
625 bb_perror_msg_and_die("rmmod"); 624 bb_perror_nomsg_and_die();
626 } 625 }
627 return EXIT_SUCCESS; 626 return EXIT_SUCCESS;
628 } 627 }
diff --git a/modutils/modutils.c b/modutils/modutils.c
index 84300d931..ef4134af5 100644
--- a/modutils/modutils.c
+++ b/modutils/modutils.c
@@ -190,6 +190,11 @@ int FAST_FUNC bb_delete_module(const char *module, unsigned int flags)
190 return errno; 190 return errno;
191} 191}
192 192
193/* Note: not suitable for delete_module() errnos.
194 * For them, probably only EWOULDBLOCK needs explaining:
195 * "Other modules depend on us". So far we don't do such
196 * translation and don't use moderror() for removal errors.
197 */
193const char* FAST_FUNC moderror(int err) 198const char* FAST_FUNC moderror(int err)
194{ 199{
195 switch (err) { 200 switch (err) {
diff --git a/modutils/rmmod.c b/modutils/rmmod.c
index f13ff9eb6..5c353ef95 100644
--- a/modutils/rmmod.c
+++ b/modutils/rmmod.c
@@ -28,7 +28,7 @@
28int rmmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 28int rmmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
29int rmmod_main(int argc UNUSED_PARAM, char **argv) 29int rmmod_main(int argc UNUSED_PARAM, char **argv)
30{ 30{
31 int n; 31 int n, err;
32 unsigned flags = O_NONBLOCK | O_EXCL; 32 unsigned flags = O_NONBLOCK | O_EXCL;
33 33
34 /* Parse command line. */ 34 /* Parse command line. */
@@ -40,7 +40,8 @@ int rmmod_main(int argc UNUSED_PARAM, char **argv)
40 flags |= O_TRUNC; 40 flags |= O_TRUNC;
41 if (n & 4) { 41 if (n & 4) {
42 /* Unload _all_ unused modules via NULL delete_module() call */ 42 /* Unload _all_ unused modules via NULL delete_module() call */
43 if (bb_delete_module(NULL, flags) != 0 && errno != EFAULT) 43 err = bb_delete_module(NULL, flags);
44 if (err && err != EFAULT)
44 bb_perror_msg_and_die("rmmod"); 45 bb_perror_msg_and_die("rmmod");
45 return EXIT_SUCCESS; 46 return EXIT_SUCCESS;
46 } 47 }
@@ -58,9 +59,10 @@ int rmmod_main(int argc UNUSED_PARAM, char **argv)
58 safe_strncpy(modname, bname, MODULE_NAME_LEN); 59 safe_strncpy(modname, bname, MODULE_NAME_LEN);
59 else 60 else
60 filename2modname(bname, modname); 61 filename2modname(bname, modname);
61 if (bb_delete_module(modname, flags)) 62 err = bb_delete_module(modname, flags);
62 bb_error_msg_and_die("can't unload '%s': %s", 63 if (err)
63 modname, moderror(errno)); 64 bb_perror_msg_and_die("can't unload module '%s'",
65 modname);
64 } 66 }
65 67
66 return EXIT_SUCCESS; 68 return EXIT_SUCCESS;
diff --git a/networking/Config.src b/networking/Config.src
index 8c7417f86..27c604a31 100644
--- a/networking/Config.src
+++ b/networking/Config.src
@@ -497,7 +497,7 @@ config FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN
497 497
498config FEATURE_INETD_RPC 498config FEATURE_INETD_RPC
499 bool "Support RPC services" 499 bool "Support RPC services"
500 default y 500 default n # very rarely used, and needs Sun RPC support in libc
501 depends on INETD 501 depends on INETD
502 select FEATURE_HAVE_RPC 502 select FEATURE_HAVE_RPC
503 help 503 help
diff --git a/networking/httpd.c b/networking/httpd.c
index 00169c36d..ed15fd883 100644
--- a/networking/httpd.c
+++ b/networking/httpd.c
@@ -967,19 +967,30 @@ static void send_headers(int responseNum)
967 } 967 }
968#endif 968#endif
969 if (responseNum == HTTP_MOVED_TEMPORARILY) { 969 if (responseNum == HTTP_MOVED_TEMPORARILY) {
970 len += sprintf(iobuf + len, "Location: %s/%s%s\r\n", 970 /* Responding to "GET /dir" with
971 * "HTTP/1.0 302 Found" "Location: /dir/"
972 * - IOW, asking them to repeat with a slash.
973 * Here, overflow IS possible, can't use sprintf:
974 * mkdir test
975 * python -c 'print("get /test?" + ("x" * 8192))' | busybox httpd -i -h .
976 */
977 len += snprintf(iobuf + len, IOBUF_SIZE-3 - len,
978 "Location: %s/%s%s\r\n",
971 found_moved_temporarily, 979 found_moved_temporarily,
972 (g_query ? "?" : ""), 980 (g_query ? "?" : ""),
973 (g_query ? g_query : "")); 981 (g_query ? g_query : ""));
982 if (len > IOBUF_SIZE-3)
983 len = IOBUF_SIZE-3;
974 } 984 }
975 985
976#if ENABLE_FEATURE_HTTPD_ERROR_PAGES 986#if ENABLE_FEATURE_HTTPD_ERROR_PAGES
977 if (error_page && access(error_page, R_OK) == 0) { 987 if (error_page && access(error_page, R_OK) == 0) {
978 strcat(iobuf, "\r\n"); 988 iobuf[len++] = '\r';
979 len += 2; 989 iobuf[len++] = '\n';
980 990 if (DEBUG) {
981 if (DEBUG) 991 iobuf[len] = '\0';
982 fprintf(stderr, "headers: '%s'\n", iobuf); 992 fprintf(stderr, "headers: '%s'\n", iobuf);
993 }
983 full_write(STDOUT_FILENO, iobuf, len); 994 full_write(STDOUT_FILENO, iobuf, len);
984 if (DEBUG) 995 if (DEBUG)
985 fprintf(stderr, "writing error page: '%s'\n", error_page); 996 fprintf(stderr, "writing error page: '%s'\n", error_page);
@@ -1021,8 +1032,10 @@ static void send_headers(int responseNum)
1021 responseNum, responseString, 1032 responseNum, responseString,
1022 responseNum, responseString, infoString); 1033 responseNum, responseString, infoString);
1023 } 1034 }
1024 if (DEBUG) 1035 if (DEBUG) {
1036 iobuf[len] = '\0';
1025 fprintf(stderr, "headers: '%s'\n", iobuf); 1037 fprintf(stderr, "headers: '%s'\n", iobuf);
1038 }
1026 if (full_write(STDOUT_FILENO, iobuf, len) != len) { 1039 if (full_write(STDOUT_FILENO, iobuf, len) != len) {
1027 if (verbose > 1) 1040 if (verbose > 1)
1028 bb_perror_msg("error"); 1041 bb_perror_msg("error");
diff --git a/networking/ifupdown.c b/networking/ifupdown.c
index 7c45e8927..d477ff6d1 100644
--- a/networking/ifupdown.c
+++ b/networking/ifupdown.c
@@ -394,8 +394,8 @@ static int FAST_FUNC static_up6(struct interface_defn_t *ifd, execfn *exec)
394# if ENABLE_FEATURE_IFUPDOWN_IP 394# if ENABLE_FEATURE_IFUPDOWN_IP
395 result = execute("ip addr add %address%/%netmask% dev %iface%[[ label %label%]]", ifd, exec); 395 result = execute("ip addr add %address%/%netmask% dev %iface%[[ label %label%]]", ifd, exec);
396 result += execute("ip link set[[ mtu %mtu%]][[ addr %hwaddress%]] %iface% up", ifd, exec); 396 result += execute("ip link set[[ mtu %mtu%]][[ addr %hwaddress%]] %iface% up", ifd, exec);
397 /* Was: "[[ ip ....%gateway% ]]". Removed extra spaces w/o checking */ 397 /* Reportedly, IPv6 needs "dev %iface%", but IPv4 does not: */
398 result += execute("[[ip route add ::/0 via %gateway%]][[ metric %metric%]]", ifd, exec); 398 result += execute("[[ip route add ::/0 via %gateway% dev %iface%]][[ metric %metric%]]", ifd, exec);
399# else 399# else
400 result = execute("ifconfig %iface%[[ media %media%]][[ hw %hwaddress%]][[ mtu %mtu%]] up", ifd, exec); 400 result = execute("ifconfig %iface%[[ media %media%]][[ hw %hwaddress%]][[ mtu %mtu%]] up", ifd, exec);
401 result += execute("ifconfig %iface% add %address%/%netmask%", ifd, exec); 401 result += execute("ifconfig %iface% add %address%/%netmask%", ifd, exec);
@@ -421,7 +421,8 @@ static int FAST_FUNC v4tunnel_up(struct interface_defn_t *ifd, execfn *exec)
421 "%endpoint%[[ local %local%]][[ ttl %ttl%]]", ifd, exec); 421 "%endpoint%[[ local %local%]][[ ttl %ttl%]]", ifd, exec);
422 result += execute("ip link set %iface% up", ifd, exec); 422 result += execute("ip link set %iface% up", ifd, exec);
423 result += execute("ip addr add %address%/%netmask% dev %iface%", ifd, exec); 423 result += execute("ip addr add %address%/%netmask% dev %iface%", ifd, exec);
424 result += execute("[[ip route add ::/0 via %gateway%]]", ifd, exec); 424 /* Reportedly, IPv6 needs "dev %iface%", but IPv4 does not: */
425 result += execute("[[ip route add ::/0 via %gateway% dev %iface%]]", ifd, exec);
425 return ((result == 4) ? 4 : 0); 426 return ((result == 4) ? 4 : 0);
426} 427}
427 428
diff --git a/networking/libiproute/ll_map.c b/networking/libiproute/ll_map.c
index e2b85fc7b..af9eb46f7 100644
--- a/networking/libiproute/ll_map.c
+++ b/networking/libiproute/ll_map.c
@@ -136,7 +136,6 @@ unsigned FAST_FUNC ll_index_to_flags(int idx)
136int FAST_FUNC xll_name_to_index(const char *name) 136int FAST_FUNC xll_name_to_index(const char *name)
137{ 137{
138 int ret = 0; 138 int ret = 0;
139 int sock_fd;
140 139
141/* caching is not warranted - no users which repeatedly call it */ 140/* caching is not warranted - no users which repeatedly call it */
142#ifdef UNUSED 141#ifdef UNUSED
@@ -164,30 +163,8 @@ int FAST_FUNC xll_name_to_index(const char *name)
164 } 163 }
165 } 164 }
166 } 165 }
167 /* We have not found the interface in our cache, but the kernel
168 * may still know about it. One reason is that we may be using
169 * module on-demand loading, which means that the kernel will
170 * load the module and make the interface exist only when
171 * we explicitely request it (check for dev_load() in net/core/dev.c).
172 * I can think of other similar scenario, but they are less common...
173 * Jean II */
174#endif 166#endif
175 167 ret = if_nametoindex(name);
176 sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
177 if (sock_fd >= 0) {
178 struct ifreq ifr;
179 int tmp;
180
181 strncpy_IFNAMSIZ(ifr.ifr_name, name);
182 ifr.ifr_ifindex = -1;
183 tmp = ioctl(sock_fd, SIOCGIFINDEX, &ifr);
184 close(sock_fd);
185 if (tmp >= 0)
186 /* In theory, we should redump the interface list
187 * to update our cache, this is left as an exercise
188 * to the reader... Jean II */
189 ret = ifr.ifr_ifindex;
190 }
191/* out:*/ 168/* out:*/
192 if (ret <= 0) 169 if (ret <= 0)
193 bb_error_msg_and_die("can't find device '%s'", name); 170 bb_error_msg_and_die("can't find device '%s'", name);
diff --git a/networking/udhcp/dumpleases.c b/networking/udhcp/dumpleases.c
index 64cd73ec7..987cc9aff 100644
--- a/networking/udhcp/dumpleases.c
+++ b/networking/udhcp/dumpleases.c
@@ -4,18 +4,20 @@
4 */ 4 */
5 5
6//usage:#define dumpleases_trivial_usage 6//usage:#define dumpleases_trivial_usage
7//usage: "[-r|-a] [-f LEASEFILE]" 7//usage: "[-r|-a] [-d] [-f LEASEFILE]"
8//usage:#define dumpleases_full_usage "\n\n" 8//usage:#define dumpleases_full_usage "\n\n"
9//usage: "Display DHCP leases granted by udhcpd\n" 9//usage: "Display DHCP leases granted by udhcpd\n"
10//usage: IF_LONG_OPTS( 10//usage: IF_LONG_OPTS(
11//usage: "\n -f,--file=FILE Lease file" 11//usage: "\n -f,--file=FILE Lease file"
12//usage: "\n -r,--remaining Show remaining time" 12//usage: "\n -r,--remaining Show remaining time"
13//usage: "\n -a,--absolute Show expiration time" 13//usage: "\n -a,--absolute Show expiration time"
14//usage: "\n -d,--decimal Show time in seconds"
14//usage: ) 15//usage: )
15//usage: IF_NOT_LONG_OPTS( 16//usage: IF_NOT_LONG_OPTS(
16//usage: "\n -f FILE Lease file" 17//usage: "\n -f FILE Lease file"
17//usage: "\n -r Show remaining time" 18//usage: "\n -r Show remaining time"
18//usage: "\n -a Show expiration time" 19//usage: "\n -a Show expiration time"
20//usage: "\n -d Show time in seconds"
19//usage: ) 21//usage: )
20 22
21#include "common.h" 23#include "common.h"
@@ -28,21 +30,22 @@ int dumpleases_main(int argc UNUSED_PARAM, char **argv)
28 int fd; 30 int fd;
29 int i; 31 int i;
30 unsigned opt; 32 unsigned opt;
31 int64_t written_at, curr, expires_abs; 33 int64_t written_at, curr;
32 const char *file = LEASES_FILE; 34 const char *file = LEASES_FILE;
33 struct dyn_lease lease; 35 struct dyn_lease lease;
34 struct in_addr addr;
35 36
36 enum { 37 enum {
37 OPT_a = 0x1, // -a 38 OPT_a = 0x1, // -a
38 OPT_r = 0x2, // -r 39 OPT_r = 0x2, // -r
39 OPT_f = 0x4, // -f 40 OPT_f = 0x4, // -f
41 OPT_d = 0x8, // -d
40 }; 42 };
41#if ENABLE_LONG_OPTS 43#if ENABLE_LONG_OPTS
42 static const char dumpleases_longopts[] ALIGN1 = 44 static const char dumpleases_longopts[] ALIGN1 =
43 "absolute\0" No_argument "a" 45 "absolute\0" No_argument "a"
44 "remaining\0" No_argument "r" 46 "remaining\0" No_argument "r"
45 "file\0" Required_argument "f" 47 "file\0" Required_argument "f"
48 "decimal\0" No_argument "d"
46 ; 49 ;
47 50
48 applet_long_options = dumpleases_longopts; 51 applet_long_options = dumpleases_longopts;
@@ -50,13 +53,16 @@ int dumpleases_main(int argc UNUSED_PARAM, char **argv)
50 init_unicode(); 53 init_unicode();
51 54
52 opt_complementary = "=0:a--r:r--a"; 55 opt_complementary = "=0:a--r:r--a";
53 opt = getopt32(argv, "arf:", &file); 56 opt = getopt32(argv, "arf:d", &file);
54 57
55 fd = xopen(file, O_RDONLY); 58 fd = xopen(file, O_RDONLY);
56 59
57 printf("Mac Address IP Address Host Name Expires %s\n", (opt & OPT_a) ? "at" : "in");
58 /* "00:00:00:00:00:00 255.255.255.255 ABCDEFGHIJKLMNOPQRS Wed Jun 30 21:49:08 1993" */
59 /* "123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 */ 60 /* "123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 */
61 /* "00:00:00:00:00:00 255.255.255.255 ABCDEFGHIJKLMNOPQRS Wed Jun 30 21:49:08 1993" */
62 printf("Mac %-14s" "IP %-13s" "Host %-15s" "Expires %s\n",
63 "Address", "Address", "Name",
64 (opt & OPT_a) ? "at" : "in"
65 );
60 66
61 xread(fd, &written_at, sizeof(written_at)); 67 xread(fd, &written_at, sizeof(written_at));
62 written_at = SWAP_BE64(written_at); 68 written_at = SWAP_BE64(written_at);
@@ -65,6 +71,9 @@ int dumpleases_main(int argc UNUSED_PARAM, char **argv)
65 written_at = curr; /* lease file from future! :) */ 71 written_at = curr; /* lease file from future! :) */
66 72
67 while (full_read(fd, &lease, sizeof(lease)) == sizeof(lease)) { 73 while (full_read(fd, &lease, sizeof(lease)) == sizeof(lease)) {
74 struct in_addr addr;
75 int64_t expires_abs;
76
68 const char *fmt = ":%02x" + 1; 77 const char *fmt = ":%02x" + 1;
69 for (i = 0; i < 6; i++) { 78 for (i = 0; i < 6; i++) {
70 printf(fmt, lease.lease_mac[i]); 79 printf(fmt, lease.lease_mac[i]);
@@ -87,6 +96,13 @@ int dumpleases_main(int argc UNUSED_PARAM, char **argv)
87 puts("expired"); 96 puts("expired");
88 continue; 97 continue;
89 } 98 }
99 if (opt & OPT_d) {
100 /* -d: decimal time */
101 if (!(opt & OPT_a))
102 expires_abs -= curr;
103 printf("%llu\n", (unsigned long long) expires_abs);
104 continue;
105 }
90 if (!(opt & OPT_a)) { /* no -a */ 106 if (!(opt & OPT_a)) { /* no -a */
91 unsigned d, h, m; 107 unsigned d, h, m;
92 unsigned expires = expires_abs - curr; 108 unsigned expires = expires_abs - curr;
diff --git a/networking/udhcp/leases.c b/networking/udhcp/leases.c
index 745340ad3..844bb60b1 100644
--- a/networking/udhcp/leases.c
+++ b/networking/udhcp/leases.c
@@ -65,10 +65,15 @@ struct dyn_lease* FAST_FUNC add_lease(
65 if (hostname_len > sizeof(oldest->hostname)) 65 if (hostname_len > sizeof(oldest->hostname))
66 hostname_len = sizeof(oldest->hostname); 66 hostname_len = sizeof(oldest->hostname);
67 p = safe_strncpy(oldest->hostname, hostname, hostname_len); 67 p = safe_strncpy(oldest->hostname, hostname, hostname_len);
68 /* sanitization (s/non-ASCII/^/g) */ 68 /*
69 * Sanitization (s/bad_char/./g).
70 * The intent is not to allow only "DNS-valid" hostnames,
71 * but merely make dumpleases output safe for shells to use.
72 * We accept "0-9A-Za-z._-", all other chars turn to dots.
73 */
69 while (*p) { 74 while (*p) {
70 if (*p < ' ' || *p > 126) 75 if (!isalnum(*p) && *p != '-' && *p != '_')
71 *p = '^'; 76 *p = '.';
72 p++; 77 p++;
73 } 78 }
74 } 79 }
diff --git a/networking/wget.c b/networking/wget.c
index 0082ced39..edf8fd8af 100644
--- a/networking/wget.c
+++ b/networking/wget.c
@@ -102,7 +102,8 @@
102//usage: "[-c|--continue] [-s|--spider] [-q|--quiet] [-O|--output-document FILE]\n" 102//usage: "[-c|--continue] [-s|--spider] [-q|--quiet] [-O|--output-document FILE]\n"
103//usage: " [--header 'header: value'] [-Y|--proxy on/off] [-P DIR]\n" 103//usage: " [--header 'header: value'] [-Y|--proxy on/off] [-P DIR]\n"
104/* Since we ignore these opts, we don't show them in --help */ 104/* Since we ignore these opts, we don't show them in --help */
105/* //usage: " [--no-check-certificate] [--no-cache]" */ 105/* //usage: " [--no-check-certificate] [--no-cache] [--passive-ftp] [-t TRIES]" */
106/* //usage: " [-nv] [-nc] [-nH] [-np]" */
106//usage: " [-U|--user-agent AGENT]" IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..." 107//usage: " [-U|--user-agent AGENT]" IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..."
107//usage: ) 108//usage: )
108//usage: IF_NOT_FEATURE_WGET_LONG_OPTIONS( 109//usage: IF_NOT_FEATURE_WGET_LONG_OPTIONS(
@@ -1225,19 +1226,22 @@ int wget_main(int argc UNUSED_PARAM, char **argv)
1225 "directory-prefix\0" Required_argument "P" 1226 "directory-prefix\0" Required_argument "P"
1226 "proxy\0" Required_argument "Y" 1227 "proxy\0" Required_argument "Y"
1227 "user-agent\0" Required_argument "U" 1228 "user-agent\0" Required_argument "U"
1228#if ENABLE_FEATURE_WGET_TIMEOUT 1229IF_FEATURE_WGET_TIMEOUT(
1229 "timeout\0" Required_argument "T" 1230 "timeout\0" Required_argument "T")
1230#endif
1231 /* Ignored: */ 1231 /* Ignored: */
1232 // "tries\0" Required_argument "t" 1232IF_DESKTOP( "tries\0" Required_argument "t")
1233 "header\0" Required_argument "\xff"
1234 "post-data\0" Required_argument "\xfe"
1233 /* Ignored (we always use PASV): */ 1235 /* Ignored (we always use PASV): */
1234 "passive-ftp\0" No_argument "\xff" 1236IF_DESKTOP( "passive-ftp\0" No_argument "\xf0")
1235 "header\0" Required_argument "\xfe"
1236 "post-data\0" Required_argument "\xfd"
1237 /* Ignored (we don't do ssl) */ 1237 /* Ignored (we don't do ssl) */
1238 "no-check-certificate\0" No_argument "\xfc" 1238IF_DESKTOP( "no-check-certificate\0" No_argument "\xf0")
1239 /* Ignored (we don't support caching) */ 1239 /* Ignored (we don't support caching) */
1240 "no-cache\0" No_argument "\xfb" 1240IF_DESKTOP( "no-cache\0" No_argument "\xf0")
1241IF_DESKTOP( "no-verbose\0" No_argument "\xf0")
1242IF_DESKTOP( "no-clobber\0" No_argument "\xf0")
1243IF_DESKTOP( "no-host-directories\0" No_argument "\xf0")
1244IF_DESKTOP( "no-parent\0" No_argument "\xf0")
1241 ; 1245 ;
1242#endif 1246#endif
1243 1247
@@ -1257,14 +1261,25 @@ int wget_main(int argc UNUSED_PARAM, char **argv)
1257#if ENABLE_FEATURE_WGET_LONG_OPTIONS 1261#if ENABLE_FEATURE_WGET_LONG_OPTIONS
1258 applet_long_options = wget_longopts; 1262 applet_long_options = wget_longopts;
1259#endif 1263#endif
1260 opt_complementary = "-1" 1264 opt_complementary = "-1" /* at least one URL */
1261 IF_FEATURE_WGET_TIMEOUT(":T+") 1265 IF_FEATURE_WGET_TIMEOUT(":T+") /* -T NUM */
1262 IF_FEATURE_WGET_LONG_OPTIONS(":\xfe::"); 1266 IF_FEATURE_WGET_LONG_OPTIONS(":\xff::"); /* --header is a list */
1263 getopt32(argv, "csqO:P:Y:U:T:" /*ignored:*/ "t:", 1267 getopt32(argv, "csqO:P:Y:U:T:"
1264 &G.fname_out, &G.dir_prefix, 1268 /*ignored:*/ "t:"
1269 /*ignored:*/ "n::"
1270 /* wget has exactly four -n<letter> opts, all of which we can ignore:
1271 * -nv --no-verbose: be moderately quiet (-q is full quiet)
1272 * -nc --no-clobber: abort if exists, neither download to FILE.n nor overwrite FILE
1273 * -nH --no-host-directories: wget -r http://host/ won't create host/
1274 * -np --no-parent
1275 * "n::" above says that we accept -n[ARG].
1276 * Specifying "n:" would be a bug: "-n ARG" would eat ARG!
1277 */
1278 , &G.fname_out, &G.dir_prefix,
1265 &G.proxy_flag, &G.user_agent, 1279 &G.proxy_flag, &G.user_agent,
1266 IF_FEATURE_WGET_TIMEOUT(&G.timeout_seconds) IF_NOT_FEATURE_WGET_TIMEOUT(NULL), 1280 IF_FEATURE_WGET_TIMEOUT(&G.timeout_seconds) IF_NOT_FEATURE_WGET_TIMEOUT(NULL),
1267 NULL /* -t RETRIES */ 1281 NULL, /* -t RETRIES */
1282 NULL /* -n[ARG] */
1268 IF_FEATURE_WGET_LONG_OPTIONS(, &headers_llist) 1283 IF_FEATURE_WGET_LONG_OPTIONS(, &headers_llist)
1269 IF_FEATURE_WGET_LONG_OPTIONS(, &G.post_data) 1284 IF_FEATURE_WGET_LONG_OPTIONS(, &G.post_data)
1270 ); 1285 );
diff --git a/networking/zcip.c b/networking/zcip.c
index d15c67d55..1d6910555 100644
--- a/networking/zcip.c
+++ b/networking/zcip.c
@@ -345,7 +345,7 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
345 state = PROBE; 345 state = PROBE;
346 while (1) { 346 while (1) {
347 struct pollfd fds[1]; 347 struct pollfd fds[1];
348 unsigned deadline_us; 348 unsigned deadline_us = deadline_us;
349 struct arp_packet p; 349 struct arp_packet p;
350 int ip_conflict; 350 int ip_conflict;
351 int n; 351 int n;
@@ -361,8 +361,10 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
361 // make the kernel filter out all packets except 361 // make the kernel filter out all packets except
362 // ones we'd care about. 362 // ones we'd care about.
363 } 363 }
364 // Set deadline_us to the point in time when we timeout 364 if (timeout_ms >= 0) {
365 deadline_us = MONOTONIC_US() + timeout_ms * 1000; 365 // Set deadline_us to the point in time when we timeout
366 deadline_us = MONOTONIC_US() + timeout_ms * 1000;
367 }
366 368
367 VDBG("...wait %d %s nsent=%u\n", 369 VDBG("...wait %d %s nsent=%u\n",
368 timeout_ms, argv_intf, nsent); 370 timeout_ms, argv_intf, nsent);
diff --git a/procps/pmap.c b/procps/pmap.c
index fd995a54d..aa221cfb8 100644
--- a/procps/pmap.c
+++ b/procps/pmap.c
@@ -20,7 +20,7 @@
20//usage:#define pmap_trivial_usage 20//usage:#define pmap_trivial_usage
21//usage: "[-xq] PID" 21//usage: "[-xq] PID"
22//usage:#define pmap_full_usage "\n\n" 22//usage:#define pmap_full_usage "\n\n"
23//usage: "Display detailed process memory usage" 23//usage: "Display process memory usage"
24//usage: "\n" 24//usage: "\n"
25//usage: "\n -x Show details" 25//usage: "\n -x Show details"
26//usage: "\n -q Quiet" 26//usage: "\n -q Quiet"
@@ -66,7 +66,7 @@ static int procps_get_maps(pid_t pid, unsigned opt)
66 int ret; 66 int ret;
67 char buf[256]; 67 char buf[256];
68 68
69 read_cmdline(buf, sizeof(buf), pid, "no such process"); 69 read_cmdline(buf, sizeof(buf), pid, NULL);
70 printf("%u: %s\n", (int)pid, buf); 70 printf("%u: %s\n", (int)pid, buf);
71 71
72 if (!(opt & OPT_q) && (opt & OPT_x)) 72 if (!(opt & OPT_q) && (opt & OPT_x))
diff --git a/procps/ps.c b/procps/ps.c
index 07ff7568f..8c373376d 100644
--- a/procps/ps.c
+++ b/procps/ps.c
@@ -638,7 +638,7 @@ int ps_main(int argc UNUSED_PARAM, char **argv)
638 * and such large widths */ 638 * and such large widths */
639 terminal_width = MAX_WIDTH; 639 terminal_width = MAX_WIDTH;
640 if (isatty(1)) { 640 if (isatty(1)) {
641 get_terminal_width_height(0, &terminal_width, NULL); 641 terminal_width = get_terminal_width(0);
642 if (--terminal_width > MAX_WIDTH) 642 if (--terminal_width > MAX_WIDTH)
643 terminal_width = MAX_WIDTH; 643 terminal_width = MAX_WIDTH;
644 } 644 }
@@ -688,7 +688,7 @@ int ps_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
688 if (w_count) { 688 if (w_count) {
689 terminal_width = (w_count == 1) ? 132 : MAX_WIDTH; 689 terminal_width = (w_count == 1) ? 132 : MAX_WIDTH;
690 } else { 690 } else {
691 get_terminal_width_height(0, &terminal_width, NULL); 691 terminal_width = get_terminal_width(0);
692 /* Go one less... */ 692 /* Go one less... */
693 if (--terminal_width > MAX_WIDTH) 693 if (--terminal_width > MAX_WIDTH)
694 terminal_width = MAX_WIDTH; 694 terminal_width = MAX_WIDTH;
diff --git a/procps/pstree.c b/procps/pstree.c
index ed1a41289..c5fb83688 100644
--- a/procps/pstree.c
+++ b/procps/pstree.c
@@ -381,7 +381,7 @@ int pstree_main(int argc UNUSED_PARAM, char **argv)
381 381
382 INIT_G(); 382 INIT_G();
383 383
384 get_terminal_width_height(0, &G.output_width, NULL); 384 G.output_width = get_terminal_width(0);
385 385
386 opt_complementary = "?1"; 386 opt_complementary = "?1";
387 getopt32(argv, "p"); 387 getopt32(argv, "p");
diff --git a/procps/watch.c b/procps/watch.c
index 0397f21bf..97aa04767 100644
--- a/procps/watch.c
+++ b/procps/watch.c
@@ -72,7 +72,7 @@ int watch_main(int argc UNUSED_PARAM, char **argv)
72 72
73 // STDERR_FILENO is procps3 compat: 73 // STDERR_FILENO is procps3 compat:
74 // "watch ls 2>/dev/null" does not detect tty size 74 // "watch ls 2>/dev/null" does not detect tty size
75 get_terminal_width_height(STDERR_FILENO, &new_width, NULL); 75 new_width = get_terminal_width(STDERR_FILENO);
76 if (new_width != width) { 76 if (new_width != width) {
77 width = new_width; 77 width = new_width;
78 free(header); 78 free(header);
diff --git a/qemu_multiarch_testing/README b/qemu_multiarch_testing/README
index 9757ff0e4..ecb63f9ef 100644
--- a/qemu_multiarch_testing/README
+++ b/qemu_multiarch_testing/README
@@ -11,6 +11,11 @@ hdc.img, from hdc.dir/* data. This requires root for loop mount.
11one or more system-image-ARCH directories into this directory 11one or more system-image-ARCH directories into this directory
12(the one which contains this README). 12(the one which contains this README).
13 13
14* Install qemu-system-ARCH. The arch names may differ from
15system-image-ARCH: for example, all ARM flavors (armv4l...armv6l)
16are served by the same qemu - qemu-system-arm. On my machine,
17I needed to install qemu-system-{arm,mips,x86,ppc,sparc,m68k,sh4}.
18
14* Run: ./parallel-build-hdc-img.sh system-image-DIR1 system-image-DIR2... 19* Run: ./parallel-build-hdc-img.sh system-image-DIR1 system-image-DIR2...
15(background it if you don't want to see "Waiting to finish" thing). 20(background it if you don't want to see "Waiting to finish" thing).
16This runs build in several qemu virtual machines in parallel. 21This runs build in several qemu virtual machines in parallel.
diff --git a/scripts/trylink b/scripts/trylink
index 48c487bcd..6e1187ed0 100755
--- a/scripts/trylink
+++ b/scripts/trylink
@@ -47,18 +47,22 @@ try() {
47 47
48check_cc() { 48check_cc() {
49 local tempname="$(mktemp)" 49 local tempname="$(mktemp)"
50 local r
51 echo "int main(int argc,char**argv){return argv?argc:0;}" >"$tempname".c
50 # Can use "-o /dev/null", but older gcc tend to *unlink it* on failure! :( 52 # Can use "-o /dev/null", but older gcc tend to *unlink it* on failure! :(
51 # "-xc": C language. "/dev/null" is an empty source file. 53 # Was using "-xc /dev/null", but we need a valid C program.
52 if $CC $CPPFLAGS $CFLAGS $1 -shared -xc /dev/null -o "$tempname".o >/dev/null 2>&1; then 54 # "eval" may be needed if CFLAGS can contain
53 echo "$1"; 55 # '... -D"BB_VER=KBUILD_STR(1.N.M)" ...'
54 else 56 # and we need shell to process quotes!
55 echo "$2"; 57 $CC $CFLAGS $1 "$tempname".c -o "$tempname" >/dev/null 2>&1
56 fi 58 r=$?
57 rm -f "$tempname" "$tempname".o 59 rm -f "$tempname" "$tempname".c "$tempname".o
60 return $r
58} 61}
59 62
60check_libc_is_glibc() { 63check_libc_is_glibc() {
61 local tempname="$(mktemp)" 64 local tempname="$(mktemp)"
65 local r
62 echo "\ 66 echo "\
63 #include <stdlib.h> 67 #include <stdlib.h>
64 /* Apparently uclibc defines __GLIBC__ (compat trick?). Oh well. */ 68 /* Apparently uclibc defines __GLIBC__ (compat trick?). Oh well. */
@@ -66,12 +70,10 @@ check_libc_is_glibc() {
66 syntax error here 70 syntax error here
67 #endif 71 #endif
68 " >"$tempname".c 72 " >"$tempname".c
69 if $CC $CPPFLAGS $CFLAGS "$tempname".c -c -o "$tempname".o >/dev/null 2>&1; then 73 ! $CC $CFLAGS "$tempname".c -c -o "$tempname".o >/dev/null 2>&1
70 echo "$2"; 74 r=$?
71 else 75 rm -f "$tempname" "$tempname".c "$tempname".o
72 echo "$1"; 76 return $r
73 fi
74 rm -f "$tempname" "$tempname".[co]
75} 77}
76 78
77EXE="$1" 79EXE="$1"
@@ -83,32 +85,41 @@ A_FILES="$6"
83LDLIBS="$7" 85LDLIBS="$7"
84 86
85# The --sort-section option is not supported by older versions of ld 87# The --sort-section option is not supported by older versions of ld
86SORT_SECTION=`check_cc "-Wl,--sort-section,alignment" ""` 88SORT_SECTION="-Wl,--sort-section,alignment"
89if ! check_cc "-Wl,--sort-section,alignment"; then
90 echo "Your linker does not support --sort-section,alignment"
91 SORT_SECTION=""
92fi
87 93
88START_GROUP="-Wl,--start-group" 94START_GROUP="-Wl,--start-group"
89END_GROUP="-Wl,--end-group" 95END_GROUP="-Wl,--end-group"
90INFO_OPTS="-Wl,--warn-common -Wl,-Map,$EXE.map -Wl,--verbose" 96INFO_OPTS="-Wl,--warn-common -Wl,-Map,$EXE.map -Wl,--verbose"
91 97
92# gold may not support --sort-common (yet) 98# gold may not support --sort-common (yet)
93SORT_COMMON=`check_cc "-Wl,--sort-common" ""` 99SORT_COMMON="-Wl,--sort-common"
100if ! check_cc "-Wl,--sort-common"; then
101 echo "Your linker does not support --sort-common"
102 SORT_COMMON=""
103fi
94 104
95# Static linking against glibc produces buggy executables 105# Static linking against glibc produces buggy executables
96# (glibc does not cope well with ld --gc-sections). 106# (glibc does not cope well with ld --gc-sections).
97# See sources.redhat.com/bugzilla/show_bug.cgi?id=3400 107# See sources.redhat.com/bugzilla/show_bug.cgi?id=3400
98# Note that glibc is unsuitable for static linking anyway. 108# Note that glibc is unsuitable for static linking anyway.
99# We are removing -Wl,--gc-sections from link command line. 109# We are removing -Wl,--gc-sections from link command line.
100GC_SECTIONS=`( 110GC_SECTIONS="-Wl,--gc-sections"
101. ./.config 111if (. ./.config && test x"$CONFIG_STATIC" = x"y") then
102if test x"$CONFIG_STATIC" = x"y"; then 112 if check_libc_is_glibc; then
103 check_libc_is_glibc "" "-Wl,--gc-sections" 113 echo "Static linking against glibc, can't use --gc-sections"
104else 114 GC_SECTIONS=""
105 echo "-Wl,--gc-sections" 115 fi
106fi 116fi
107)`
108
109# The --gc-sections option is not supported by older versions of ld 117# The --gc-sections option is not supported by older versions of ld
110if test -n "$GC_SECTIONS"; then 118if test -n "$GC_SECTIONS"; then
111 GC_SECTIONS=`check_cc "$GC_SECTIONS" ""` 119 if ! check_cc "$GC_SECTIONS"; then
120 echo "Your linker does not support $GC_SECTIONS"
121 GC_SECTIONS=""
122 fi
112fi 123fi
113 124
114# Sanitize lib list (dups, extra spaces etc) 125# Sanitize lib list (dups, extra spaces etc)
diff --git a/shell/ash.c b/shell/ash.c
index 21fc05f01..08b6aa430 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -2747,7 +2747,7 @@ updatepwd(const char *dir)
2747 new = stack_putstr(p, new); 2747 new = stack_putstr(p, new);
2748 USTPUTC('/', new); 2748 USTPUTC('/', new);
2749 } 2749 }
2750 p = strtok(0, "/"); 2750 p = strtok(NULL, "/");
2751 } 2751 }
2752 if (new > lim) 2752 if (new > lim)
2753 STUNPUTC(new); 2753 STUNPUTC(new);
@@ -5731,7 +5731,7 @@ popredir(int drop, int restore)
5731 struct redirtab *rp; 5731 struct redirtab *rp;
5732 int i; 5732 int i;
5733 5733
5734 if (--g_nullredirs >= 0) 5734 if (--g_nullredirs >= 0 || redirlist == NULL)
5735 return; 5735 return;
5736 INT_OFF; 5736 INT_OFF;
5737 rp = redirlist; 5737 rp = redirlist;
@@ -8159,14 +8159,15 @@ findkwd(const char *s)
8159 * Locate and print what a word is... 8159 * Locate and print what a word is...
8160 */ 8160 */
8161static int 8161static int
8162describe_command(char *command, int describe_command_verbose) 8162describe_command(char *command, const char *path, int describe_command_verbose)
8163{ 8163{
8164 struct cmdentry entry; 8164 struct cmdentry entry;
8165 struct tblentry *cmdp; 8165 struct tblentry *cmdp;
8166#if ENABLE_ASH_ALIAS 8166#if ENABLE_ASH_ALIAS
8167 const struct alias *ap; 8167 const struct alias *ap;
8168#endif 8168#endif
8169 const char *path = pathval(); 8169
8170 path = path ? path : pathval();
8170 8171
8171 if (describe_command_verbose) { 8172 if (describe_command_verbose) {
8172 out1str(command); 8173 out1str(command);
@@ -8266,7 +8267,7 @@ typecmd(int argc UNUSED_PARAM, char **argv)
8266 verbose = 0; 8267 verbose = 0;
8267 } 8268 }
8268 while (argv[i]) { 8269 while (argv[i]) {
8269 err |= describe_command(argv[i++], verbose); 8270 err |= describe_command(argv[i++], NULL, verbose);
8270 } 8271 }
8271 return err; 8272 return err;
8272} 8273}
@@ -8280,6 +8281,7 @@ commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8280 VERIFY_BRIEF = 1, 8281 VERIFY_BRIEF = 1,
8281 VERIFY_VERBOSE = 2, 8282 VERIFY_VERBOSE = 2,
8282 } verify = 0; 8283 } verify = 0;
8284 const char *path = NULL;
8283 8285
8284 while ((c = nextopt("pvV")) != '\0') 8286 while ((c = nextopt("pvV")) != '\0')
8285 if (c == 'V') 8287 if (c == 'V')
@@ -8290,9 +8292,11 @@ commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8290 else if (c != 'p') 8292 else if (c != 'p')
8291 abort(); 8293 abort();
8292#endif 8294#endif
8295 else
8296 path = bb_default_path;
8293 /* Mimic bash: just "command -v" doesn't complain, it's a nop */ 8297 /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8294 if (verify && (*argptr != NULL)) { 8298 if (verify && (*argptr != NULL)) {
8295 return describe_command(*argptr, verify - VERIFY_BRIEF); 8299 return describe_command(*argptr, path, verify - VERIFY_BRIEF);
8296 } 8300 }
8297 8301
8298 return 0; 8302 return 0;
@@ -9296,14 +9300,15 @@ parse_command_args(char **argv, const char **path)
9296 for (;;) { 9300 for (;;) {
9297 cp = *++argv; 9301 cp = *++argv;
9298 if (!cp) 9302 if (!cp)
9299 return 0; 9303 return NULL;
9300 if (*cp++ != '-') 9304 if (*cp++ != '-')
9301 break; 9305 break;
9302 c = *cp++; 9306 c = *cp++;
9303 if (!c) 9307 if (!c)
9304 break; 9308 break;
9305 if (c == '-' && !*cp) { 9309 if (c == '-' && !*cp) {
9306 argv++; 9310 if (!*++argv)
9311 return NULL;
9307 break; 9312 break;
9308 } 9313 }
9309 do { 9314 do {
@@ -9313,7 +9318,7 @@ parse_command_args(char **argv, const char **path)
9313 break; 9318 break;
9314 default: 9319 default:
9315 /* run 'typecmd' for other options */ 9320 /* run 'typecmd' for other options */
9316 return 0; 9321 return NULL;
9317 } 9322 }
9318 c = *cp++; 9323 c = *cp++;
9319 } while (c); 9324 } while (c);
@@ -9400,6 +9405,9 @@ localcmd(int argc UNUSED_PARAM, char **argv)
9400{ 9405{
9401 char *name; 9406 char *name;
9402 9407
9408 if (!funcnest)
9409 ash_msg_and_raise_error("not in a function");
9410
9403 argv = argptr; 9411 argv = argptr;
9404 while ((name = *argv++) != NULL) { 9412 while ((name = *argv++) != NULL) {
9405 mklocal(name); 9413 mklocal(name);
@@ -9865,7 +9873,7 @@ evalcommand(union node *cmd, int flags)
9865 if (evalbltin(cmdentry.u.cmd, argc, argv)) { 9873 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
9866 int exit_status; 9874 int exit_status;
9867 int i = exception_type; 9875 int i = exception_type;
9868 if (i == EXEXIT) 9876 if (i == EXEXIT || i == EXEXEC)
9869 goto raise; 9877 goto raise;
9870 exit_status = 2; 9878 exit_status = 2;
9871 if (i == EXINT) 9879 if (i == EXINT)
@@ -10959,7 +10967,7 @@ static union node *andor(void);
10959static union node *pipeline(void); 10967static union node *pipeline(void);
10960static union node *parse_command(void); 10968static union node *parse_command(void);
10961static void parseheredoc(void); 10969static void parseheredoc(void);
10962static char nexttoken_ends_list(void); 10970static int peektoken(void);
10963static int readtoken(void); 10971static int readtoken(void);
10964 10972
10965static union node * 10973static union node *
@@ -10968,11 +10976,27 @@ list(int nlflag)
10968 union node *n1, *n2, *n3; 10976 union node *n1, *n2, *n3;
10969 int tok; 10977 int tok;
10970 10978
10971 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10972 if (nlflag == 2 && nexttoken_ends_list())
10973 return NULL;
10974 n1 = NULL; 10979 n1 = NULL;
10975 for (;;) { 10980 for (;;) {
10981 switch (peektoken()) {
10982 case TNL:
10983 if (!(nlflag & 1))
10984 break;
10985 parseheredoc();
10986 return n1;
10987
10988 case TEOF:
10989 if (!n1 && (nlflag & 1))
10990 n1 = NODE_EOF;
10991 parseheredoc();
10992 return n1;
10993 }
10994
10995 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10996 if (nlflag == 2 && tokname_array[peektoken()][0])
10997 return n1;
10998 nlflag |= 2;
10999
10976 n2 = andor(); 11000 n2 = andor();
10977 tok = readtoken(); 11001 tok = readtoken();
10978 if (tok == TBACKGND) { 11002 if (tok == TBACKGND) {
@@ -10998,37 +11022,15 @@ list(int nlflag)
10998 n1 = n3; 11022 n1 = n3;
10999 } 11023 }
11000 switch (tok) { 11024 switch (tok) {
11025 case TNL:
11026 case TEOF:
11027 tokpushback = 1;
11028 /* fall through */
11001 case TBACKGND: 11029 case TBACKGND:
11002 case TSEMI: 11030 case TSEMI:
11003 tok = readtoken();
11004 /* fall through */
11005 case TNL:
11006 if (tok == TNL) {
11007 parseheredoc();
11008 if (nlflag == 1)
11009 return n1;
11010 } else {
11011 tokpushback = 1;
11012 }
11013 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11014 if (nexttoken_ends_list()) {
11015 /* Testcase: "<<EOF; then <W".
11016 * It used to segfault w/o this check:
11017 */
11018 if (heredoclist) {
11019 raise_error_unexpected_syntax(-1);
11020 }
11021 return n1;
11022 }
11023 break; 11031 break;
11024 case TEOF:
11025 if (heredoclist)
11026 parseheredoc();
11027 else
11028 pungetc(); /* push back EOF on input */
11029 return n1;
11030 default: 11032 default:
11031 if (nlflag == 1) 11033 if ((nlflag & 1))
11032 raise_error_unexpected_syntax(-1); 11034 raise_error_unexpected_syntax(-1);
11033 tokpushback = 1; 11035 tokpushback = 1;
11034 return n1; 11036 return n1;
@@ -11356,7 +11358,7 @@ parse_command(void)
11356 n1 = stzalloc(sizeof(struct nfor)); 11358 n1 = stzalloc(sizeof(struct nfor));
11357 n1->type = NFOR; 11359 n1->type = NFOR;
11358 n1->nfor.var = wordtext; 11360 n1->nfor.var = wordtext;
11359 checkkwd = CHKKWD | CHKALIAS; 11361 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11360 if (readtoken() == TIN) { 11362 if (readtoken() == TIN) {
11361 app = &ap; 11363 app = &ap;
11362 while (readtoken() == TWORD) { 11364 while (readtoken() == TWORD) {
@@ -11383,7 +11385,7 @@ parse_command(void)
11383 * Newline or semicolon here is optional (but note 11385 * Newline or semicolon here is optional (but note
11384 * that the original Bourne shell only allowed NL). 11386 * that the original Bourne shell only allowed NL).
11385 */ 11387 */
11386 if (lasttoken != TNL && lasttoken != TSEMI) 11388 if (lasttoken != TSEMI)
11387 tokpushback = 1; 11389 tokpushback = 1;
11388 } 11390 }
11389 checkkwd = CHKNL | CHKKWD | CHKALIAS; 11391 checkkwd = CHKNL | CHKKWD | CHKALIAS;
@@ -11402,10 +11404,8 @@ parse_command(void)
11402 /*n2->narg.next = NULL; - stzalloc did it */ 11404 /*n2->narg.next = NULL; - stzalloc did it */
11403 n2->narg.text = wordtext; 11405 n2->narg.text = wordtext;
11404 n2->narg.backquote = backquotelist; 11406 n2->narg.backquote = backquotelist;
11405 do { 11407 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11406 checkkwd = CHKKWD | CHKALIAS; 11408 if (readtoken() != TIN)
11407 } while (readtoken() == TNL);
11408 if (lasttoken != TIN)
11409 raise_error_unexpected_syntax(TIN); 11409 raise_error_unexpected_syntax(TIN);
11410 cpp = &n1->ncase.cases; 11410 cpp = &n1->ncase.cases;
11411 next_case: 11411 next_case:
@@ -12336,6 +12336,7 @@ static int
12336readtoken(void) 12336readtoken(void)
12337{ 12337{
12338 int t; 12338 int t;
12339 int kwd = checkkwd;
12339#if DEBUG 12340#if DEBUG
12340 smallint alreadyseen = tokpushback; 12341 smallint alreadyseen = tokpushback;
12341#endif 12342#endif
@@ -12349,7 +12350,7 @@ readtoken(void)
12349 /* 12350 /*
12350 * eat newlines 12351 * eat newlines
12351 */ 12352 */
12352 if (checkkwd & CHKNL) { 12353 if (kwd & CHKNL) {
12353 while (t == TNL) { 12354 while (t == TNL) {
12354 parseheredoc(); 12355 parseheredoc();
12355 t = xxreadtoken(); 12356 t = xxreadtoken();
@@ -12363,7 +12364,7 @@ readtoken(void)
12363 /* 12364 /*
12364 * check for keywords 12365 * check for keywords
12365 */ 12366 */
12366 if (checkkwd & CHKKWD) { 12367 if (kwd & CHKKWD) {
12367 const char *const *pp; 12368 const char *const *pp;
12368 12369
12369 pp = findkwd(wordtext); 12370 pp = findkwd(wordtext);
@@ -12397,14 +12398,14 @@ readtoken(void)
12397 return t; 12398 return t;
12398} 12399}
12399 12400
12400static char 12401static int
12401nexttoken_ends_list(void) 12402peektoken(void)
12402{ 12403{
12403 int t; 12404 int t;
12404 12405
12405 t = readtoken(); 12406 t = readtoken();
12406 tokpushback = 1; 12407 tokpushback = 1;
12407 return tokname_array[t][0]; 12408 return t;
12408} 12409}
12409 12410
12410/* 12411/*
@@ -12414,18 +12415,12 @@ nexttoken_ends_list(void)
12414static union node * 12415static union node *
12415parsecmd(int interact) 12416parsecmd(int interact)
12416{ 12417{
12417 int t;
12418
12419 tokpushback = 0; 12418 tokpushback = 0;
12419 checkkwd = 0;
12420 heredoclist = 0;
12420 doprompt = interact; 12421 doprompt = interact;
12421 setprompt_if(doprompt, doprompt); 12422 setprompt_if(doprompt, doprompt);
12422 needprompt = 0; 12423 needprompt = 0;
12423 t = readtoken();
12424 if (t == TEOF)
12425 return NODE_EOF;
12426 if (t == TNL)
12427 return NULL;
12428 tokpushback = 1;
12429 return list(1); 12424 return list(1);
12430} 12425}
12431 12426
diff --git a/shell/ash_test/ash-heredoc/heredoc2.right b/shell/ash_test/ash-heredoc/heredoc2.right
new file mode 100644
index 000000000..a486f1ac4
--- /dev/null
+++ b/shell/ash_test/ash-heredoc/heredoc2.right
@@ -0,0 +1,2 @@
1bar
2bar
diff --git a/shell/ash_test/ash-heredoc/heredoc2.tests b/shell/ash_test/ash-heredoc/heredoc2.tests
new file mode 100755
index 000000000..6d9ccb6cc
--- /dev/null
+++ b/shell/ash_test/ash-heredoc/heredoc2.tests
@@ -0,0 +1,7 @@
1foo () {
2cat <<EOF && { echo "$1" ; }
3$1
4EOF
5}
6
7foo "bar"
diff --git a/shell/ash_test/ash-heredoc/heredoc3.right b/shell/ash_test/ash-heredoc/heredoc3.right
new file mode 100644
index 000000000..ce0136250
--- /dev/null
+++ b/shell/ash_test/ash-heredoc/heredoc3.right
@@ -0,0 +1 @@
hello
diff --git a/shell/ash_test/ash-heredoc/heredoc3.tests b/shell/ash_test/ash-heredoc/heredoc3.tests
new file mode 100755
index 000000000..96c227cc1
--- /dev/null
+++ b/shell/ash_test/ash-heredoc/heredoc3.tests
@@ -0,0 +1,9 @@
1echo hello >greeting
2cat <<EOF &&
3$(cat greeting)
4EOF
5{
6 echo $?
7 cat greeting
8} >/dev/null
9rm greeting
diff --git a/shell/ash_test/ash-misc/command.right b/shell/ash_test/ash-misc/command.right
new file mode 100644
index 000000000..7f746d9c4
--- /dev/null
+++ b/shell/ash_test/ash-misc/command.right
@@ -0,0 +1 @@
recho: not found
diff --git a/shell/ash_test/ash-misc/command.tests b/shell/ash_test/ash-misc/command.tests
new file mode 100755
index 000000000..5d445af51
--- /dev/null
+++ b/shell/ash_test/ash-misc/command.tests
@@ -0,0 +1 @@
command -p -V recho
diff --git a/shell/ash_test/ash-misc/command2.right b/shell/ash_test/ash-misc/command2.right
new file mode 100644
index 000000000..8d2165f69
--- /dev/null
+++ b/shell/ash_test/ash-misc/command2.right
@@ -0,0 +1,2 @@
1test1
2./command2.tests: ./test1.sh: line 1: ./test2.sh: Permission denied
diff --git a/shell/ash_test/ash-misc/command2.tests b/shell/ash_test/ash-misc/command2.tests
new file mode 100755
index 000000000..9d9de9a89
--- /dev/null
+++ b/shell/ash_test/ash-misc/command2.tests
@@ -0,0 +1,6 @@
1echo "echo test1; ./test2.sh" >test1.sh
2echo "echo test2" >test2.sh
3
4command . ./test1.sh
5
6rm -f test1.sh test2.sh
diff --git a/shell/ash_test/ash-misc/exec.right b/shell/ash_test/ash-misc/exec.right
new file mode 100644
index 000000000..1741a38dd
--- /dev/null
+++ b/shell/ash_test/ash-misc/exec.right
@@ -0,0 +1,2 @@
1./exec.tests: exec: line 2: ./test1.sh: not found
2127
diff --git a/shell/ash_test/ash-misc/exec.tests b/shell/ash_test/ash-misc/exec.tests
new file mode 100755
index 000000000..624915de1
--- /dev/null
+++ b/shell/ash_test/ash-misc/exec.tests
@@ -0,0 +1,3 @@
1rm -f test1.sh
2(exec ./test1.sh)
3echo $?
diff --git a/shell/ash_test/ash-misc/for.right b/shell/ash_test/ash-misc/for.right
new file mode 100644
index 000000000..d86bac9de
--- /dev/null
+++ b/shell/ash_test/ash-misc/for.right
@@ -0,0 +1 @@
OK
diff --git a/shell/ash_test/ash-misc/for.tests b/shell/ash_test/ash-misc/for.tests
new file mode 100755
index 000000000..4889a9f2d
--- /dev/null
+++ b/shell/ash_test/ash-misc/for.tests
@@ -0,0 +1,5 @@
1for i
2in OK
3do
4 echo $i
5done
diff --git a/shell/ash_test/ash-misc/local2.right b/shell/ash_test/ash-misc/local2.right
new file mode 100644
index 000000000..630ef7979
--- /dev/null
+++ b/shell/ash_test/ash-misc/local2.right
@@ -0,0 +1 @@
./local2.tests: local: line 1: not in a function
diff --git a/shell/ash_test/ash-misc/local2.tests b/shell/ash_test/ash-misc/local2.tests
new file mode 100755
index 000000000..8e14037c5
--- /dev/null
+++ b/shell/ash_test/ash-misc/local2.tests
@@ -0,0 +1 @@
local x=1
diff --git a/shell/ash_test/run-all b/shell/ash_test/run-all
index ad93e251d..354cc1fcf 100755
--- a/shell/ash_test/run-all
+++ b/shell/ash_test/run-all
@@ -31,8 +31,9 @@ do_test()
31 *.orig|*~) ;; 31 *.orig|*~) ;;
32 #*) echo $x ; sh $x ;; 32 #*) echo $x ; sh $x ;;
33 *) 33 *)
34 echo -n "$1/$x: "
34 sh "$x" >"$TOPDIR/$noslash-$x.fail" 2>&1 && \ 35 sh "$x" >"$TOPDIR/$noslash-$x.fail" 2>&1 && \
35 { echo "$1/$x: ok"; rm "$TOPDIR/$noslash-$x.fail"; } || echo "$1/$x: fail"; 36 { echo "ok"; rm "$TOPDIR/$noslash-$x.fail"; } || echo "fail";
36 ;; 37 ;;
37 esac 38 esac
38 done 39 done
@@ -42,11 +43,12 @@ do_test()
42 test -x "$x" || continue 43 test -x "$x" || continue
43 name="${x%%.tests}" 44 name="${x%%.tests}"
44 test -f "$name.right" || continue 45 test -f "$name.right" || continue
46 echo -n "$1/$x: "
45 { 47 {
46 "$THIS_SH" "./$x" >"$name.xx" 2>&1 48 "$THIS_SH" "./$x" >"$name.xx" 2>&1
47 diff -u "$name.xx" "$name.right" >"$TOPDIR/$noslash-$x.fail" \ 49 diff -u "$name.xx" "$name.right" >"$TOPDIR/$noslash-$x.fail" \
48 && rm -f "$name.xx" "$TOPDIR/$noslash-$x.fail" 50 && rm -f "$name.xx" "$TOPDIR/$noslash-$x.fail"
49 } && echo "$1/$x: ok" || echo "$1/$x: fail" 51 } && echo "ok" || echo "fail"
50 done 52 done
51 ) 53 )
52} 54}
diff --git a/shell/hush_test/hush-misc/for.right b/shell/hush_test/hush-misc/for.right
new file mode 100644
index 000000000..d86bac9de
--- /dev/null
+++ b/shell/hush_test/hush-misc/for.right
@@ -0,0 +1 @@
OK
diff --git a/shell/hush_test/hush-misc/for.tests b/shell/hush_test/hush-misc/for.tests
new file mode 100755
index 000000000..4889a9f2d
--- /dev/null
+++ b/shell/hush_test/hush-misc/for.tests
@@ -0,0 +1,5 @@
1for i
2in OK
3do
4 echo $i
5done
diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c
index 288b29cf7..0ea557a6c 100644
--- a/sysklogd/syslogd.c
+++ b/sysklogd/syslogd.c
@@ -936,11 +936,6 @@ static NOINLINE int create_socket(void)
936 int sock_fd; 936 int sock_fd;
937 char *dev_log_name; 937 char *dev_log_name;
938 938
939#if ENABLE_FEATURE_SYSTEMD
940 if (sd_listen_fds() == 1)
941 return SD_LISTEN_FDS_START;
942#endif
943
944 memset(&sunx, 0, sizeof(sunx)); 939 memset(&sunx, 0, sizeof(sunx));
945 sunx.sun_family = AF_UNIX; 940 sunx.sun_family = AF_UNIX;
946 941
diff --git a/testsuite/sort.tests b/testsuite/sort.tests
index c4b223464..c51a8e475 100755
--- a/testsuite/sort.tests
+++ b/testsuite/sort.tests
@@ -106,6 +106,50 @@ a/a:a
106a:b 106a:b
107" "" 107" ""
108 108
109testing "sort with ENDCHAR" "sort -t. -k1,1.1 -k2 input" "\
110ab.1
111aa.2
112" "\
113aa.2
114ab.1
115" ""
116
117testing "glibc build sort" "sort -t. -k 1,1 -k 2n,2n -k 3 input" "\
118GLIBC_2.1
119GLIBC_2.1.1
120GLIBC_2.2
121GLIBC_2.2.1
122GLIBC_2.10
123GLIBC_2.20
124GLIBC_2.21
125" "\
126GLIBC_2.21
127GLIBC_2.1.1
128GLIBC_2.2.1
129GLIBC_2.2
130GLIBC_2.20
131GLIBC_2.10
132GLIBC_2.1
133" ""
134
135testing "glibc build sort unique" "sort -u -t. -k 1,1 -k 2n,2n -k 3 input" "\
136GLIBC_2.1
137GLIBC_2.1.1
138GLIBC_2.2
139GLIBC_2.2.1
140GLIBC_2.10
141GLIBC_2.20
142GLIBC_2.21
143" "\
144GLIBC_2.10
145GLIBC_2.2.1
146GLIBC_2.1.1
147GLIBC_2.20
148GLIBC_2.2
149GLIBC_2.1
150GLIBC_2.21
151" ""
152
109testing "sort -u should consider field only when discarding" "sort -u -k2 input" "\ 153testing "sort -u should consider field only when discarding" "sort -u -k2 input" "\
110a c 154a c
111" "\ 155" "\
diff --git a/testsuite/tar.tests b/testsuite/tar.tests
index 4929f4e49..890a73dd5 100755
--- a/testsuite/tar.tests
+++ b/testsuite/tar.tests
@@ -53,6 +53,15 @@ dd if=/dev/zero bs=512 count=20 2>/dev/null | tar xvf - 2>&1; echo $?
53"" "" 53"" ""
54SKIP= 54SKIP=
55 55
56# "tar cf test.tar input input_dir/ input_hard1 input_hard2 input_hard1 input_dir/ input":
57# GNU tar 1.26 records as hardlinks:
58# input_hard2 -> input_hard1
59# input_hard1 -> input_hard1 (!!!)
60# input_dir/file -> input_dir/file
61# input -> input
62# As of 1.24.0, we don't record last two: for them, nlink==1
63# and we check for "hardlink"ness only files with nlink!=1
64# We also don't use "hrw-r--r--" notation for hardlinks in "tar tv" listing.
56optional FEATURE_TAR_CREATE FEATURE_LS_SORTFILES 65optional FEATURE_TAR_CREATE FEATURE_LS_SORTFILES
57testing "tar hardlinks and repeated files" '\ 66testing "tar hardlinks and repeated files" '\
58rm -rf input_* test.tar 2>/dev/null 67rm -rf input_* test.tar 2>/dev/null
@@ -64,6 +73,7 @@ chmod -R 644 *
64chmod 755 input_dir 73chmod 755 input_dir
65tar cf test.tar input input_dir/ input_hard1 input_hard2 input_hard1 input_dir/ input 74tar cf test.tar input input_dir/ input_hard1 input_hard2 input_hard1 input_dir/ input
66tar tvf test.tar | sed "s/.*[0-9] input/input/" 75tar tvf test.tar | sed "s/.*[0-9] input/input/"
76rm -rf input_dir
67tar xf test.tar 2>&1 77tar xf test.tar 2>&1
68echo Ok: $? 78echo Ok: $?
69ls -l . input_dir/* | grep input_ | sed "s/\\(^[^ ]*\\) .* input/\\1 input/" 79ls -l . input_dir/* | grep input_ | sed "s/\\(^[^ ]*\\) .* input/\\1 input/"
@@ -246,6 +256,49 @@ Ok
246"" "" 256"" ""
247SKIP= 257SKIP=
248 258
259# attack.tar.bz2 has symlink pointing to a system file
260# followed by a regular file with the same name
261# containing "root::0:0::/root:/bin/sh":
262# lrwxrwxrwx root/root passwd -> /tmp/passwd
263# -rw-r--r-- root/root passwd
264# naive tar implementation may end up creating the symlink
265# and then writing into it.
266# The correct implementation unlinks target before
267# creating the second file.
268# We test that /tmp/passwd remains empty:
269optional UUDECODE FEATURE_SEAMLESS_BZ2
270testing "tar does not extract into symlinks" "\
271>>/tmp/passwd && uudecode -o input && tar xf input 2>&1 && rm passwd; cat /tmp/passwd; echo \$?
272" "\
2730
274" \
275"" "\
276begin-base64 644 attack.tar.bz2
277QlpoOTFBWSZTWRVn/bIAAKt7hMqwAEBAAP2QAhB0Y96AAACACCAAlISgpqe0
278po0DIaDynqAkpDRP1ANAhiYNSPR8VchKhAz0AK59+DA6FcMKBggOARIJdVHL
279DGllrjs20ATUgR1HmccBX3EhoMnpMJaNyggmxgLDMz54lBnBTJO/1L1lbMS4
280l4/V8LDoe90yiWJhOJvIypgEfxdyRThQkBVn/bI=
281====
282"
283SKIP=
284# And same with -k
285optional UUDECODE FEATURE_SEAMLESS_BZ2
286testing "tar -k does not extract into symlinks" "\
287>>/tmp/passwd && uudecode -o input && tar xf input -k 2>&1 && rm passwd; cat /tmp/passwd; echo \$?
288" "\
289tar: can't open 'passwd': File exists
2900
291" \
292"" "\
293begin-base64 644 attack.tar.bz2
294QlpoOTFBWSZTWRVn/bIAAKt7hMqwAEBAAP2QAhB0Y96AAACACCAAlISgpqe0
295po0DIaDynqAkpDRP1ANAhiYNSPR8VchKhAz0AK59+DA6FcMKBggOARIJdVHL
296DGllrjs20ATUgR1HmccBX3EhoMnpMJaNyggmxgLDMz54lBnBTJO/1L1lbMS4
297l4/V8LDoe90yiWJhOJvIypgEfxdyRThQkBVn/bI=
298====
299"
300SKIP=
301
249 302
250cd .. && rm -rf tar.tempdir || exit 1 303cd .. && rm -rf tar.tempdir || exit 1
251 304
diff --git a/testsuite/unzip.tests b/testsuite/unzip.tests
index 8677a0306..d8738a3bd 100755
--- a/testsuite/unzip.tests
+++ b/testsuite/unzip.tests
@@ -7,7 +7,7 @@
7 7
8. ./testing.sh 8. ./testing.sh
9 9
10# testing "test name" "options" "expected result" "file input" "stdin" 10# testing "test name" "commands" "expected result" "file input" "stdin"
11# file input will be file called "input" 11# file input will be file called "input"
12# test can create a file "actual" instead of writing to stdout 12# test can create a file "actual" instead of writing to stdout
13 13
@@ -30,6 +30,28 @@ testing "unzip (subdir only)" "unzip -q foo.zip foo/ && test -d foo && test ! -f
30rmdir foo 30rmdir foo
31rm foo.zip 31rm foo.zip
32 32
33# File containing some damaged encrypted stream
34testing "unzip (bad archive)" "uudecode; unzip bad.zip 2>&1; echo \$?" \
35"Archive: bad.zip
36 inflating: ]3j½r«IK-%Ix
37unzip: corrupted data
38unzip: inflate error
391
40" \
41"" "\
42begin-base64 644 bad.zip
43UEsDBBQAAgkIAAAAIQA5AAAANwAAADwAAAAQAAcAXTNqwr1ywqtJGxJLLSVJ
44eCkBD0AdKBk8JzQsIj01JC0/ORJQSwMEFAECCAAAAAAhADoAAAAPAAAANgAA
45AAwAAQASw73Ct1DCokohPXQiNjoUNTUiHRwgLT4WHlBLAQIQABQAAggIAAAA
46oQA5AAAANwAAADwAAAAQQAcADAAAACwAMgCAAAAAAABdM2rCvXLCq0kbEkst
47JUl4KQEPQB0oGSY4Cz4QNgEnJSYIPVBLAQIAABQAAggAAAAAIQAqAAAADwAA
48BDYAAAAMAAEADQAAADIADQAAAEEAAAASw73Ct1DKokohPXQiNzA+FAI1HCcW
49NzITNFBLBQUKAC4JAA04Cw0EOhZQSwUGAQAABAIAAgCZAAAAeQAAAAIALhM=
50====
51"
52
53rm *
54
33# Clean up scratch directory. 55# Clean up scratch directory.
34 56
35cd .. 57cd ..
diff --git a/util-linux/Config.src b/util-linux/Config.src
index 854b3682e..922cabdb8 100644
--- a/util-linux/Config.src
+++ b/util-linux/Config.src
@@ -489,16 +489,6 @@ config SCRIPTREPLAY
489 This program replays a typescript, using timing information 489 This program replays a typescript, using timing information
490 given by script -t. 490 given by script -t.
491 491
492config SETARCH
493 bool "setarch"
494 default y
495 select PLATFORM_LINUX
496 help
497 The linux32 utility is used to create a 32bit environment for the
498 specified program (usually a shell). It only makes sense to have
499 this util on a system that supports both 64bit and 32bit userland
500 (like amd64/x86, ppc64/ppc, sparc64/sparc, etc...).
501
502config SWAPONOFF 492config SWAPONOFF
503 bool "swaponoff" 493 bool "swaponoff"
504 default y 494 default y
diff --git a/util-linux/Kbuild.src b/util-linux/Kbuild.src
index 468fc6bc1..0b87c52ac 100644
--- a/util-linux/Kbuild.src
+++ b/util-linux/Kbuild.src
@@ -40,7 +40,6 @@ lib-$(CONFIG_READPROFILE) += readprofile.o
40lib-$(CONFIG_RTCWAKE) += rtcwake.o 40lib-$(CONFIG_RTCWAKE) += rtcwake.o
41lib-$(CONFIG_SCRIPT) += script.o 41lib-$(CONFIG_SCRIPT) += script.o
42lib-$(CONFIG_SCRIPTREPLAY) += scriptreplay.o 42lib-$(CONFIG_SCRIPTREPLAY) += scriptreplay.o
43lib-$(CONFIG_SETARCH) += setarch.o
44lib-$(CONFIG_SWAPONOFF) += swaponoff.o 43lib-$(CONFIG_SWAPONOFF) += swaponoff.o
45lib-$(CONFIG_SWITCH_ROOT) += switch_root.o 44lib-$(CONFIG_SWITCH_ROOT) += switch_root.o
46lib-$(CONFIG_UMOUNT) += umount.o 45lib-$(CONFIG_UMOUNT) += umount.o
diff --git a/util-linux/setarch.c b/util-linux/setarch.c
index 7b9421af1..2e989ec2a 100644
--- a/util-linux/setarch.c
+++ b/util-linux/setarch.c
@@ -6,13 +6,30 @@
6 * 6 *
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config SETARCH
10//config: bool "setarch"
11//config: default y
12//config: select PLATFORM_LINUX
13//config: help
14//config: The linux32 utility is used to create a 32bit environment for the
15//config: specified program (usually a shell). It only makes sense to have
16//config: this util on a system that supports both 64bit and 32bit userland
17//config: (like amd64/x86, ppc64/ppc, sparc64/sparc, etc...).
18
19//applet:IF_SETARCH(APPLET(setarch, BB_DIR_BIN, BB_SUID_DROP))
20//applet:IF_SETARCH(APPLET_ODDNAME(linux32, setarch, BB_DIR_BIN, BB_SUID_DROP, linux32))
21//applet:IF_SETARCH(APPLET_ODDNAME(linux64, setarch, BB_DIR_BIN, BB_SUID_DROP, linux64))
22
23//kbuild:lib-$(CONFIG_SETARCH) += setarch.o
9 24
10//usage:#define setarch_trivial_usage 25//usage:#define setarch_trivial_usage
11//usage: "personality PROG ARGS" 26//usage: "PERSONALITY [-R] PROG ARGS"
12//usage:#define setarch_full_usage "\n\n" 27//usage:#define setarch_full_usage "\n\n"
13//usage: "Personality may be:\n" 28//usage: "PERSONALITY may be:"
14//usage: " linux32 Set 32bit uname emulation\n" 29//usage: "\n"" linux32 Set 32bit uname emulation"
15//usage: " linux64 Set 64bit uname emulation" 30//usage: "\n"" linux64 Set 64bit uname emulation"
31//usage: "\n"
32//usage: "\n"" -R Disable address space randomization"
16//usage: 33//usage:
17//usage:#define linux32_trivial_usage NOUSAGE_STR 34//usage:#define linux32_trivial_usage NOUSAGE_STR
18//usage:#define linux32_full_usage "" 35//usage:#define linux32_full_usage ""
@@ -20,14 +37,18 @@
20//usage:#define linux64_trivial_usage NOUSAGE_STR 37//usage:#define linux64_trivial_usage NOUSAGE_STR
21//usage:#define linux64_full_usage "" 38//usage:#define linux64_full_usage ""
22 39
40#include "libbb.h"
23#include <sys/personality.h> 41#include <sys/personality.h>
24 42
25#include "libbb.h" 43#ifndef ADDR_NO_RANDOMIZE
44# define ADDR_NO_RANDOMIZE 0x0040000
45#endif
26 46
27int setarch_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 47int setarch_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
28int setarch_main(int argc UNUSED_PARAM, char **argv) 48int setarch_main(int argc UNUSED_PARAM, char **argv)
29{ 49{
30 int pers; 50 unsigned opts;
51 unsigned long pers;
31 52
32 /* Figure out what personality we are supposed to switch to ... 53 /* Figure out what personality we are supposed to switch to ...
33 * we can be invoked as either: 54 * we can be invoked as either:
@@ -35,7 +56,7 @@ int setarch_main(int argc UNUSED_PARAM, char **argv)
35 * argv[0] == "personality" 56 * argv[0] == "personality"
36 */ 57 */
37 if (ENABLE_SETARCH && applet_name[0] == 's' 58 if (ENABLE_SETARCH && applet_name[0] == 's'
38 && argv[1] && strncpy(argv[1], "linux", 5) 59 && argv[1] && is_prefixed_with(argv[1], "linux")
39 ) { 60 ) {
40 applet_name = argv[1]; 61 applet_name = argv[1];
41 argv++; 62 argv++;
@@ -47,15 +68,18 @@ int setarch_main(int argc UNUSED_PARAM, char **argv)
47 else 68 else
48 bb_show_usage(); 69 bb_show_usage();
49 70
50 argv++; 71 opts = getopt32(argv, "+R"); /* '+': stop at first non-option */
51 if (argv[0] == NULL) 72 if (opts)
52 bb_show_usage(); 73 pers |= ADDR_NO_RANDOMIZE;
53 74
54 /* Try to set personality */ 75 /* Try to set personality */
55 if (personality(pers) >= 0) { 76 if (personality(pers) < 0)
56 /* Try to execute the program */ 77 bb_perror_msg_and_die("personality(0x%lx)", pers);
57 BB_EXECVP(argv[0], argv); 78
58 } 79 argv += optind;
80 if (!argv[0])
81 (--argv)[0] = (char*)"/bin/sh";
59 82
60 bb_simple_perror_msg_and_die(argv[0]); 83 /* Try to execute the program */
84 BB_EXECVP_or_die(argv);
61} 85}