diff options
author | Nguyễn Thái Ngọc Duy <pclouds@gmail.com> | 2010-09-14 11:41:16 +1000 |
---|---|---|
committer | Nguyễn Thái Ngọc Duy <pclouds@gmail.com> | 2010-09-14 11:41:16 +1000 |
commit | 743d85e7d1c2a721baf020b9d79f45f0df2420a9 (patch) | |
tree | 9e551b726ac2bf9fd8eafb2764e7237f352bb429 | |
parent | 87911f4fcd86f7abc0aefba8e9cbec2ac9d127e4 (diff) | |
parent | c7f95d23f6bc7e17a3b79decf83eb362b389e53a (diff) | |
download | busybox-w32-743d85e7d1c2a721baf020b9d79f45f0df2420a9.tar.gz busybox-w32-743d85e7d1c2a721baf020b9d79f45f0df2420a9.tar.bz2 busybox-w32-743d85e7d1c2a721baf020b9d79f45f0df2420a9.zip |
Merge branch 'origin/master' (early part)
129 files changed, 2290 insertions, 1245 deletions
@@ -237,6 +237,17 @@ config UNICODE_NEUTRAL_TABLE | |||
237 | With this option on, more extensive (and bigger) table | 237 | With this option on, more extensive (and bigger) table |
238 | of neutral chars will be used. | 238 | of neutral chars will be used. |
239 | 239 | ||
240 | config UNICODE_PRESERVE_BROKEN | ||
241 | bool "Make it possible to enter sequences of chars which are not Unicode" | ||
242 | default n | ||
243 | depends on UNICODE_SUPPORT | ||
244 | help | ||
245 | With this option on, invalid UTF-8 bytes are not substituted | ||
246 | with the selected substitution character. | ||
247 | For example, this means that entering 'l', 's', ' ', 0xff, [Enter] | ||
248 | at shell prompt will list file named 0xff (single char name | ||
249 | with char value 255), not file named '?'. | ||
250 | |||
240 | config LONG_OPTS | 251 | config LONG_OPTS |
241 | bool "Support for --long-options" | 252 | bool "Support for --long-options" |
242 | default y | 253 | default y |
@@ -378,6 +378,11 @@ ifneq ($(KBUILD_SRC),) | |||
378 | $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL) | 378 | $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL) |
379 | endif | 379 | endif |
380 | 380 | ||
381 | # This target generates Kbuild's and Config.in's from *.c files | ||
382 | PHONY += gen_build_files | ||
383 | gen_build_files: | ||
384 | $(Q)$(srctree)/scripts/gen_build_files.sh $(srctree) $(objtree) | ||
385 | |||
381 | # To make sure we do not include .config for any of the *config targets | 386 | # To make sure we do not include .config for any of the *config targets |
382 | # catch them early, and hand them over to scripts/kconfig/Makefile | 387 | # catch them early, and hand them over to scripts/kconfig/Makefile |
383 | # It is allowed to specify more targets when calling make, including | 388 | # It is allowed to specify more targets when calling make, including |
@@ -429,7 +434,7 @@ ifeq ($(config-targets),1) | |||
429 | -include $(srctree)/arch/$(ARCH)/Makefile | 434 | -include $(srctree)/arch/$(ARCH)/Makefile |
430 | export KBUILD_DEFCONFIG | 435 | export KBUILD_DEFCONFIG |
431 | 436 | ||
432 | config %config: scripts_basic outputmakefile FORCE | 437 | config %config: scripts_basic outputmakefile gen_build_files FORCE |
433 | $(Q)mkdir -p include | 438 | $(Q)mkdir -p include |
434 | $(Q)$(MAKE) $(build)=scripts/kconfig $@ | 439 | $(Q)$(MAKE) $(build)=scripts/kconfig $@ |
435 | $(Q)$(MAKE) -C $(srctree) KBUILD_SRC= .kernelrelease | 440 | $(Q)$(MAKE) -C $(srctree) KBUILD_SRC= .kernelrelease |
@@ -444,7 +449,7 @@ ifeq ($(KBUILD_EXTMOD),) | |||
444 | # Carefully list dependencies so we do not try to build scripts twice | 449 | # Carefully list dependencies so we do not try to build scripts twice |
445 | # in parrallel | 450 | # in parrallel |
446 | PHONY += scripts | 451 | PHONY += scripts |
447 | scripts: scripts_basic include/config/MARKER | 452 | scripts: gen_build_files scripts_basic include/config/MARKER |
448 | $(Q)$(MAKE) $(build)=$(@) | 453 | $(Q)$(MAKE) $(build)=$(@) |
449 | 454 | ||
450 | scripts_basic: include/autoconf.h | 455 | scripts_basic: include/autoconf.h |
@@ -998,6 +1003,8 @@ $(mrproper-dirs): | |||
998 | mrproper: clean archmrproper $(mrproper-dirs) | 1003 | mrproper: clean archmrproper $(mrproper-dirs) |
999 | $(call cmd,rmdirs) | 1004 | $(call cmd,rmdirs) |
1000 | $(call cmd,rmfiles) | 1005 | $(call cmd,rmfiles) |
1006 | @find -name Config.src | sed 's/.src$/.in/' | xargs -r rm -f | ||
1007 | @find -name Kbuild.src | sed 's/.src$//' | xargs -r rm -f | ||
1001 | 1008 | ||
1002 | # distclean | 1009 | # distclean |
1003 | # | 1010 | # |
diff --git a/archival/cpio.c b/archival/cpio.c index 858e59b30..e0ca7fa5c 100644 --- a/archival/cpio.c +++ b/archival/cpio.c | |||
@@ -311,6 +311,7 @@ int cpio_main(int argc UNUSED_PARAM, char **argv) | |||
311 | /* no parameters */ | 311 | /* no parameters */ |
312 | opt_complementary = "=0"; | 312 | opt_complementary = "=0"; |
313 | opt = getopt32(argv, OPTION_STR, &cpio_filename); | 313 | opt = getopt32(argv, OPTION_STR, &cpio_filename); |
314 | argv += optind; | ||
314 | if (opt & CPIO_OPT_FILE) { /* -F */ | 315 | if (opt & CPIO_OPT_FILE) { /* -F */ |
315 | xmove_fd(xopen(cpio_filename, O_RDONLY), STDIN_FILENO); | 316 | xmove_fd(xopen(cpio_filename, O_RDONLY), STDIN_FILENO); |
316 | } | 317 | } |
@@ -424,7 +425,7 @@ int cpio_main(int argc UNUSED_PARAM, char **argv) | |||
424 | if (archive_handle->cpio__blocks != (off_t)-1 | 425 | if (archive_handle->cpio__blocks != (off_t)-1 |
425 | && !(opt & CPIO_OPT_QUIET) | 426 | && !(opt & CPIO_OPT_QUIET) |
426 | ) { | 427 | ) { |
427 | printf("%"OFF_FMT"u blocks\n", archive_handle->cpio__blocks); | 428 | fprintf(stderr, "%"OFF_FMT"u blocks\n", archive_handle->cpio__blocks); |
428 | } | 429 | } |
429 | 430 | ||
430 | return EXIT_SUCCESS; | 431 | return EXIT_SUCCESS; |
diff --git a/archival/libunarchive/get_header_tar.c b/archival/libunarchive/get_header_tar.c index adb4c157b..fcddcb834 100644 --- a/archival/libunarchive/get_header_tar.c +++ b/archival/libunarchive/get_header_tar.c | |||
@@ -18,87 +18,45 @@ typedef uint32_t aliased_uint32_t FIX_ALIASING; | |||
18 | typedef off_t aliased_off_t FIX_ALIASING; | 18 | typedef off_t aliased_off_t FIX_ALIASING; |
19 | 19 | ||
20 | 20 | ||
21 | /* | ||
22 | * GNU tar uses "base-256 encoding" for very large numbers (>8 billion). | ||
23 | * Encoding is binary, with highest bit always set as a marker | ||
24 | * and sign in next-highest bit: | ||
25 | * 80 00 .. 00 - zero | ||
26 | * bf ff .. ff - largest positive number | ||
27 | * ff ff .. ff - minus 1 | ||
28 | * c0 00 .. 00 - smallest negative number | ||
29 | * | ||
30 | * We expect it only in size field, where negative numbers don't make sense. | ||
31 | */ | ||
32 | static off_t getBase256_len12(const char *str) | ||
33 | { | ||
34 | off_t value; | ||
35 | int len; | ||
36 | |||
37 | /* if (*str & 0x40) error; - caller prevents this */ | ||
38 | |||
39 | if (sizeof(off_t) >= 12) { | ||
40 | /* Probably 128-bit (16 byte) off_t. Can be optimized. */ | ||
41 | len = 12; | ||
42 | value = *str++ & 0x3f; | ||
43 | while (--len) | ||
44 | value = (value << 8) + (unsigned char) *str++; | ||
45 | return value; | ||
46 | } | ||
47 | |||
48 | #ifdef CHECK_FOR_OVERFLOW | ||
49 | /* Can be optimized to eat 32-bit chunks */ | ||
50 | char c = *str++ & 0x3f; | ||
51 | len = 12; | ||
52 | while (1) { | ||
53 | if (c) | ||
54 | bb_error_msg_and_die("overflow in base-256 encoded file size"); | ||
55 | if (--len == sizeof(off_t)) | ||
56 | break; | ||
57 | c = *str++; | ||
58 | } | ||
59 | #else | ||
60 | str += (12 - sizeof(off_t)); | ||
61 | #endif | ||
62 | |||
63 | /* Now str points to sizeof(off_t) least significant bytes. | ||
64 | * | ||
65 | * Example of tar file with 8914993153 (0x213600001) byte file. | ||
66 | * Field starts at offset 7c: | ||
67 | * 00070 30 30 30 00 30 30 30 30 30 30 30 00 80 00 00 00 |000.0000000.....| | ||
68 | * 00080 00 00 00 02 13 60 00 01 31 31 31 32 30 33 33 36 |.....`..11120336| | ||
69 | * | ||
70 | * str is at offset 80 or 84 now (64-bit or 32-bit off_t). | ||
71 | * We (ab)use the fact that value happens to be aligned, | ||
72 | * and fetch it in one go: | ||
73 | */ | ||
74 | if (sizeof(off_t) == 8) { | ||
75 | value = *(aliased_off_t*)str; | ||
76 | value = SWAP_BE64(value); | ||
77 | } else if (sizeof(off_t) == 4) { | ||
78 | value = *(aliased_off_t*)str; | ||
79 | value = SWAP_BE32(value); | ||
80 | } else { | ||
81 | value = 0; | ||
82 | len = sizeof(off_t); | ||
83 | while (--len) | ||
84 | value = (value << 8) + (unsigned char) *str++; | ||
85 | } | ||
86 | return value; | ||
87 | } | ||
88 | |||
89 | /* NB: _DESTROYS_ str[len] character! */ | 21 | /* NB: _DESTROYS_ str[len] character! */ |
90 | static unsigned long long getOctal(char *str, int len) | 22 | static unsigned long long getOctal(char *str, int len) |
91 | { | 23 | { |
92 | unsigned long long v; | 24 | unsigned long long v; |
25 | char *end; | ||
93 | /* NB: leading spaces are allowed. Using strtoull to handle that. | 26 | /* NB: leading spaces are allowed. Using strtoull to handle that. |
94 | * The downside is that we accept e.g. "-123" too :( | 27 | * The downside is that we accept e.g. "-123" too :( |
95 | */ | 28 | */ |
96 | str[len] = '\0'; | 29 | str[len] = '\0'; |
97 | v = strtoull(str, &str, 8); | 30 | v = strtoull(str, &end, 8); |
98 | /* std: "Each numeric field is terminated by one or more | 31 | /* std: "Each numeric field is terminated by one or more |
99 | * <space> or NUL characters". We must support ' '! */ | 32 | * <space> or NUL characters". We must support ' '! */ |
100 | if (*str != '\0' && *str != ' ') | 33 | if (*end != '\0' && *end != ' ') { |
101 | bb_error_msg_and_die("corrupted octal value in tar header"); | 34 | int8_t first = str[0]; |
35 | if (!(first & 0x80)) | ||
36 | bb_error_msg_and_die("corrupted octal value in tar header"); | ||
37 | /* | ||
38 | * GNU tar uses "base-256 encoding" for very large numbers. | ||
39 | * Encoding is binary, with highest bit always set as a marker | ||
40 | * and sign in next-highest bit: | ||
41 | * 80 00 .. 00 - zero | ||
42 | * bf ff .. ff - largest positive number | ||
43 | * ff ff .. ff - minus 1 | ||
44 | * c0 00 .. 00 - smallest negative number | ||
45 | * | ||
46 | * Example of tar file with 8914993153 (0x213600001) byte file. | ||
47 | * Field starts at offset 7c: | ||
48 | * 00070 30 30 30 00 30 30 30 30 30 30 30 00 80 00 00 00 |000.0000000.....| | ||
49 | * 00080 00 00 00 02 13 60 00 01 31 31 31 32 30 33 33 36 |.....`..11120336| | ||
50 | * | ||
51 | * NB: tarballs with NEGATIVE unix times encoded that way were seen! | ||
52 | */ | ||
53 | v = first; | ||
54 | /* Sign-extend using 6th bit: */ | ||
55 | v <<= sizeof(unsigned long long)*8 - 7; | ||
56 | v = (long long)v >> (sizeof(unsigned long long)*8 - 7); | ||
57 | while (--len != 0) | ||
58 | v = (v << 8) + (unsigned char) *str++; | ||
59 | } | ||
102 | return v; | 60 | return v; |
103 | } | 61 | } |
104 | #define GET_OCTAL(a) getOctal((a), sizeof(a)) | 62 | #define GET_OCTAL(a) getOctal((a), sizeof(a)) |
@@ -358,15 +316,8 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) | |||
358 | file_header->tar__uname = tar.uname[0] ? xstrndup(tar.uname, sizeof(tar.uname)) : NULL; | 316 | file_header->tar__uname = tar.uname[0] ? xstrndup(tar.uname, sizeof(tar.uname)) : NULL; |
359 | file_header->tar__gname = tar.gname[0] ? xstrndup(tar.gname, sizeof(tar.gname)) : NULL; | 317 | file_header->tar__gname = tar.gname[0] ? xstrndup(tar.gname, sizeof(tar.gname)) : NULL; |
360 | #endif | 318 | #endif |
361 | /* mtime: rudimentally handle GNU tar's "base256 encoding" | 319 | file_header->mtime = GET_OCTAL(tar.mtime); |
362 | * People report tarballs with NEGATIVE unix times encoded that way */ | 320 | file_header->size = GET_OCTAL(tar.size); |
363 | file_header->mtime = (tar.mtime[0] & 0x80) /* base256? */ | ||
364 | ? 0 /* bogus */ | ||
365 | : GET_OCTAL(tar.mtime); | ||
366 | /* size: handle GNU tar's "base256 encoding" */ | ||
367 | file_header->size = (tar.size[0] & 0xc0) == 0x80 /* positive base256? */ | ||
368 | ? getBase256_len12(tar.size) | ||
369 | : GET_OCTAL(tar.size); | ||
370 | file_header->gid = GET_OCTAL(tar.gid); | 321 | file_header->gid = GET_OCTAL(tar.gid); |
371 | file_header->uid = GET_OCTAL(tar.uid); | 322 | file_header->uid = GET_OCTAL(tar.uid); |
372 | /* Set bits 0-11 of the files mode */ | 323 | /* Set bits 0-11 of the files mode */ |
diff --git a/archival/rpm.c b/archival/rpm.c index 6c1e341cd..38ec20ef5 100644 --- a/archival/rpm.c +++ b/archival/rpm.c | |||
@@ -9,8 +9,8 @@ | |||
9 | 9 | ||
10 | #include "libbb.h" | 10 | #include "libbb.h" |
11 | #include "unarchive.h" | 11 | #include "unarchive.h" |
12 | #include "rpm.h" | ||
12 | 13 | ||
13 | #define RPM_HEADER_MAGIC "\216\255\350" | ||
14 | #define RPM_CHAR_TYPE 1 | 14 | #define RPM_CHAR_TYPE 1 |
15 | #define RPM_INT8_TYPE 2 | 15 | #define RPM_INT8_TYPE 2 |
16 | #define RPM_INT16_TYPE 3 | 16 | #define RPM_INT16_TYPE 3 |
@@ -46,6 +46,7 @@ | |||
46 | #define TAG_DIRINDEXES 1116 | 46 | #define TAG_DIRINDEXES 1116 |
47 | #define TAG_BASENAMES 1117 | 47 | #define TAG_BASENAMES 1117 |
48 | #define TAG_DIRNAMES 1118 | 48 | #define TAG_DIRNAMES 1118 |
49 | |||
49 | #define RPMFILE_CONFIG (1 << 0) | 50 | #define RPMFILE_CONFIG (1 << 0) |
50 | #define RPMFILE_DOC (1 << 1) | 51 | #define RPMFILE_DOC (1 << 1) |
51 | 52 | ||
@@ -70,7 +71,7 @@ static void *map; | |||
70 | static rpm_index **mytags; | 71 | static rpm_index **mytags; |
71 | static int tagcount; | 72 | static int tagcount; |
72 | 73 | ||
73 | static void extract_cpio_gz(int fd); | 74 | static void extract_cpio(int fd, const char *source_rpm); |
74 | static rpm_index **rpm_gettags(int fd, int *num_tags); | 75 | static rpm_index **rpm_gettags(int fd, int *num_tags); |
75 | static int bsearch_rpmtag(const void *key, const void *item); | 76 | static int bsearch_rpmtag(const void *key, const void *item); |
76 | static char *rpm_getstr(int tag, int itemindex); | 77 | static char *rpm_getstr(int tag, int itemindex); |
@@ -121,6 +122,8 @@ int rpm_main(int argc, char **argv) | |||
121 | } | 122 | } |
122 | 123 | ||
123 | while (*argv) { | 124 | while (*argv) { |
125 | const char *source_rpm; | ||
126 | |||
124 | rpm_fd = xopen(*argv++, O_RDONLY); | 127 | rpm_fd = xopen(*argv++, O_RDONLY); |
125 | mytags = rpm_gettags(rpm_fd, &tagcount); | 128 | mytags = rpm_gettags(rpm_fd, &tagcount); |
126 | if (!mytags) | 129 | if (!mytags) |
@@ -129,11 +132,13 @@ int rpm_main(int argc, char **argv) | |||
129 | /* Mimimum is one page */ | 132 | /* Mimimum is one page */ |
130 | map = mmap(0, offset > pagesize ? (offset + offset % pagesize) : pagesize, PROT_READ, MAP_PRIVATE, rpm_fd, 0); | 133 | map = mmap(0, offset > pagesize ? (offset + offset % pagesize) : pagesize, PROT_READ, MAP_PRIVATE, rpm_fd, 0); |
131 | 134 | ||
135 | source_rpm = rpm_getstr(TAG_SOURCERPM, 0); | ||
136 | |||
132 | if (func & rpm_install) { | 137 | if (func & rpm_install) { |
133 | /* Backup any config files */ | 138 | /* Backup any config files */ |
134 | loop_through_files(TAG_BASENAMES, fileaction_dobackup); | 139 | loop_through_files(TAG_BASENAMES, fileaction_dobackup); |
135 | /* Extact the archive */ | 140 | /* Extact the archive */ |
136 | extract_cpio_gz(rpm_fd); | 141 | extract_cpio(rpm_fd, source_rpm); |
137 | /* Set the correct file uid/gid's */ | 142 | /* Set the correct file uid/gid's */ |
138 | loop_through_files(TAG_BASENAMES, fileaction_setowngrp); | 143 | loop_through_files(TAG_BASENAMES, fileaction_setowngrp); |
139 | } | 144 | } |
@@ -147,14 +152,20 @@ int rpm_main(int argc, char **argv) | |||
147 | time_t bdate_time; | 152 | time_t bdate_time; |
148 | struct tm *bdate_ptm; | 153 | struct tm *bdate_ptm; |
149 | char bdatestring[50]; | 154 | char bdatestring[50]; |
150 | printf("Name : %-29sRelocations: %s\n", rpm_getstr(TAG_NAME, 0), rpm_getstr(TAG_PREFIXS, 0) ? rpm_getstr(TAG_PREFIXS, 0) : "(not relocateable)"); | 155 | const char *p; |
151 | printf("Version : %-34sVendor: %s\n", rpm_getstr(TAG_VERSION, 0), rpm_getstr(TAG_VENDOR, 0) ? rpm_getstr(TAG_VENDOR, 0) : "(none)"); | 156 | |
157 | p = rpm_getstr(TAG_PREFIXS, 0); | ||
158 | if (!p) p = "(not relocateable)"; | ||
159 | printf("Name : %-29sRelocations: %s\n", rpm_getstr(TAG_NAME, 0), p); | ||
160 | p = rpm_getstr(TAG_VENDOR, 0); | ||
161 | if (!p) p = "(none)"; | ||
162 | printf("Version : %-34sVendor: %s\n", rpm_getstr(TAG_VERSION, 0), p); | ||
152 | bdate_time = rpm_getint(TAG_BUILDTIME, 0); | 163 | bdate_time = rpm_getint(TAG_BUILDTIME, 0); |
153 | bdate_ptm = localtime(&bdate_time); | 164 | bdate_ptm = localtime(&bdate_time); |
154 | strftime(bdatestring, 50, "%a %d %b %Y %T %Z", bdate_ptm); | 165 | strftime(bdatestring, 50, "%a %d %b %Y %T %Z", bdate_ptm); |
155 | printf("Release : %-30sBuild Date: %s\n", rpm_getstr(TAG_RELEASE, 0), bdatestring); | 166 | printf("Release : %-30sBuild Date: %s\n", rpm_getstr(TAG_RELEASE, 0), bdatestring); |
156 | printf("Install date: %-30sBuild Host: %s\n", "(not installed)", rpm_getstr(TAG_BUILDHOST, 0)); | 167 | printf("Install date: %-30sBuild Host: %s\n", "(not installed)", rpm_getstr(TAG_BUILDHOST, 0)); |
157 | printf("Group : %-30sSource RPM: %s\n", rpm_getstr(TAG_GROUP, 0), rpm_getstr(TAG_SOURCERPM, 0)); | 168 | printf("Group : %-30sSource RPM: %s\n", rpm_getstr(TAG_GROUP, 0), source_rpm); |
158 | printf("Size : %-33dLicense: %s\n", rpm_getint(TAG_SIZE, 0), rpm_getstr(TAG_LICENSE, 0)); | 169 | printf("Size : %-33dLicense: %s\n", rpm_getint(TAG_SIZE, 0), rpm_getstr(TAG_LICENSE, 0)); |
159 | printf("URL : %s\n", rpm_getstr(TAG_URL, 0)); | 170 | printf("URL : %s\n", rpm_getstr(TAG_URL, 0)); |
160 | printf("Summary : %s\n", rpm_getstr(TAG_SUMMARY, 0)); | 171 | printf("Summary : %s\n", rpm_getstr(TAG_SUMMARY, 0)); |
@@ -187,23 +198,23 @@ int rpm_main(int argc, char **argv) | |||
187 | return 0; | 198 | return 0; |
188 | } | 199 | } |
189 | 200 | ||
190 | static void extract_cpio_gz(int fd) | 201 | static void extract_cpio(int fd, const char *source_rpm) |
191 | { | 202 | { |
192 | archive_handle_t *archive_handle; | 203 | archive_handle_t *archive_handle; |
193 | unsigned char magic[2]; | 204 | |
194 | #if BB_MMU | 205 | if (source_rpm != NULL) { |
195 | IF_DESKTOP(long long) int FAST_FUNC (*xformer)(int src_fd, int dst_fd); | 206 | /* Binary rpm (it was built from some SRPM), install to root */ |
196 | enum { xformer_prog = 0 }; | 207 | xchdir("/"); |
197 | #else | 208 | } /* else: SRPM, install to current dir */ |
198 | enum { xformer = 0 }; | ||
199 | const char *xformer_prog; | ||
200 | #endif | ||
201 | 209 | ||
202 | /* Initialize */ | 210 | /* Initialize */ |
203 | archive_handle = init_handle(); | 211 | archive_handle = init_handle(); |
204 | archive_handle->seek = seek_by_read; | 212 | archive_handle->seek = seek_by_read; |
205 | //archive_handle->action_header = header_list; | ||
206 | archive_handle->action_data = data_extract_all; | 213 | archive_handle->action_data = data_extract_all; |
214 | #if 0 /* For testing (rpm -i only lists the files in internal cpio): */ | ||
215 | archive_handle->action_header = header_list; | ||
216 | archive_handle->action_data = data_skip; | ||
217 | #endif | ||
207 | archive_handle->ah_flags = ARCHIVE_RESTORE_DATE | ARCHIVE_CREATE_LEADING_DIRS | 218 | archive_handle->ah_flags = ARCHIVE_RESTORE_DATE | ARCHIVE_CREATE_LEADING_DIRS |
208 | /* compat: overwrite existing files. | 219 | /* compat: overwrite existing files. |
209 | * try "rpm -i foo.src.rpm" few times in a row - | 220 | * try "rpm -i foo.src.rpm" few times in a row - |
@@ -213,46 +224,14 @@ static void extract_cpio_gz(int fd) | |||
213 | archive_handle->src_fd = fd; | 224 | archive_handle->src_fd = fd; |
214 | /*archive_handle->offset = 0; - init_handle() did it */ | 225 | /*archive_handle->offset = 0; - init_handle() did it */ |
215 | 226 | ||
216 | // TODO: open_zipped does the same | 227 | setup_unzip_on_fd(archive_handle->src_fd /*, fail_if_not_detected: 1*/); |
217 | |||
218 | xread(archive_handle->src_fd, &magic, 2); | ||
219 | #if BB_MMU | ||
220 | xformer = unpack_gz_stream; | ||
221 | #else | ||
222 | xformer_prog = "gunzip"; | ||
223 | #endif | ||
224 | if (magic[0] != 0x1f || magic[1] != 0x8b) { | ||
225 | if (!ENABLE_FEATURE_SEAMLESS_BZ2 | ||
226 | || magic[0] != 'B' || magic[1] != 'Z' | ||
227 | ) { | ||
228 | bb_error_msg_and_die("no gzip" | ||
229 | IF_FEATURE_SEAMLESS_BZ2("/bzip2") | ||
230 | " magic"); | ||
231 | } | ||
232 | #if BB_MMU | ||
233 | xformer = unpack_bz2_stream; | ||
234 | #else | ||
235 | xformer_prog = "bunzip2"; | ||
236 | #endif | ||
237 | } else { | ||
238 | #if !BB_MMU | ||
239 | /* NOMMU version of open_transformer execs an external unzipper that should | ||
240 | * have the file position at the start of the file */ | ||
241 | xlseek(archive_handle->src_fd, 0, SEEK_SET); | ||
242 | #endif | ||
243 | } | ||
244 | |||
245 | xchdir("/"); /* Install RPM's to root */ | ||
246 | open_transformer(archive_handle->src_fd, xformer, xformer_prog); | ||
247 | archive_handle->offset = 0; | ||
248 | while (get_header_cpio(archive_handle) == EXIT_SUCCESS) | 228 | while (get_header_cpio(archive_handle) == EXIT_SUCCESS) |
249 | continue; | 229 | continue; |
250 | } | 230 | } |
251 | 231 | ||
252 | |||
253 | static rpm_index **rpm_gettags(int fd, int *num_tags) | 232 | static rpm_index **rpm_gettags(int fd, int *num_tags) |
254 | { | 233 | { |
255 | /* We should never need mode than 200, and realloc later */ | 234 | /* We should never need more than 200 (shrink via realloc later) */ |
256 | rpm_index **tags = xzalloc(200 * sizeof(tags[0])); | 235 | rpm_index **tags = xzalloc(200 * sizeof(tags[0])); |
257 | int pass, tagindex = 0; | 236 | int pass, tagindex = 0; |
258 | 237 | ||
@@ -260,27 +239,16 @@ static rpm_index **rpm_gettags(int fd, int *num_tags) | |||
260 | 239 | ||
261 | /* 1st pass is the signature headers, 2nd is the main stuff */ | 240 | /* 1st pass is the signature headers, 2nd is the main stuff */ |
262 | for (pass = 0; pass < 2; pass++) { | 241 | for (pass = 0; pass < 2; pass++) { |
263 | struct { | 242 | struct rpm_header header; |
264 | char magic[3]; /* 3 byte magic: 0x8e 0xad 0xe8 */ | ||
265 | uint8_t version; /* 1 byte version number */ | ||
266 | uint32_t reserved; /* 4 bytes reserved */ | ||
267 | uint32_t entries; /* Number of entries in header (4 bytes) */ | ||
268 | uint32_t size; /* Size of store (4 bytes) */ | ||
269 | } header; | ||
270 | struct BUG_header { | ||
271 | char BUG_header[sizeof(header) == 16 ? 1 : -1]; | ||
272 | }; | ||
273 | rpm_index *tmpindex; | 243 | rpm_index *tmpindex; |
274 | int storepos; | 244 | int storepos; |
275 | 245 | ||
276 | xread(fd, &header, sizeof(header)); | 246 | xread(fd, &header, sizeof(header)); |
277 | if (strncmp((char *) &header.magic, RPM_HEADER_MAGIC, 3) != 0) | 247 | if (header.magic_and_ver != htonl(RPM_HEADER_MAGICnVER)) |
278 | return NULL; /* Invalid magic */ | 248 | return NULL; /* Invalid magic, or not version 1 */ |
279 | if (header.version != 1) | ||
280 | return NULL; /* This program only supports v1 headers */ | ||
281 | header.size = ntohl(header.size); | 249 | header.size = ntohl(header.size); |
282 | header.entries = ntohl(header.entries); | 250 | header.entries = ntohl(header.entries); |
283 | storepos = xlseek(fd,0,SEEK_CUR) + header.entries * 16; | 251 | storepos = xlseek(fd, 0, SEEK_CUR) + header.entries * 16; |
284 | 252 | ||
285 | while (header.entries--) { | 253 | while (header.entries--) { |
286 | tmpindex = tags[tagindex++] = xmalloc(sizeof(*tmpindex)); | 254 | tmpindex = tags[tagindex++] = xmalloc(sizeof(*tmpindex)); |
@@ -292,14 +260,16 @@ static rpm_index **rpm_gettags(int fd, int *num_tags) | |||
292 | if (pass == 0) | 260 | if (pass == 0) |
293 | tmpindex->tag -= 743; | 261 | tmpindex->tag -= 743; |
294 | } | 262 | } |
295 | xlseek(fd, header.size, SEEK_CUR); /* Seek past store */ | 263 | storepos = xlseek(fd, header.size, SEEK_CUR); /* Seek past store */ |
296 | /* Skip padding to 8 byte boundary after reading signature headers */ | 264 | /* Skip padding to 8 byte boundary after reading signature headers */ |
297 | if (pass == 0) | 265 | if (pass == 0) |
298 | xlseek(fd, (8 - (xlseek(fd,0,SEEK_CUR) % 8)) % 8, SEEK_CUR); | 266 | xlseek(fd, (-storepos) & 0x7, SEEK_CUR); |
299 | } | 267 | } |
300 | tags = xrealloc(tags, tagindex * sizeof(tags[0])); /* realloc tags to save space */ | 268 | /* realloc tags to save space */ |
269 | tags = xrealloc(tags, tagindex * sizeof(tags[0])); | ||
301 | *num_tags = tagindex; | 270 | *num_tags = tagindex; |
302 | return tags; /* All done, leave the file at the start of the gzipped cpio archive */ | 271 | /* All done, leave the file at the start of the gzipped cpio archive */ |
272 | return tags; | ||
303 | } | 273 | } |
304 | 274 | ||
305 | static int bsearch_rpmtag(const void *key, const void *item) | 275 | static int bsearch_rpmtag(const void *key, const void *item) |
@@ -324,10 +294,13 @@ static char *rpm_getstr(int tag, int itemindex) | |||
324 | found = bsearch(&tag, mytags, tagcount, sizeof(struct rpmtag *), bsearch_rpmtag); | 294 | found = bsearch(&tag, mytags, tagcount, sizeof(struct rpmtag *), bsearch_rpmtag); |
325 | if (!found || itemindex >= found[0]->count) | 295 | if (!found || itemindex >= found[0]->count) |
326 | return NULL; | 296 | return NULL; |
327 | if (found[0]->type == RPM_STRING_TYPE || found[0]->type == RPM_I18NSTRING_TYPE || found[0]->type == RPM_STRING_ARRAY_TYPE) { | 297 | if (found[0]->type == RPM_STRING_TYPE |
298 | || found[0]->type == RPM_I18NSTRING_TYPE | ||
299 | || found[0]->type == RPM_STRING_ARRAY_TYPE | ||
300 | ) { | ||
328 | int n; | 301 | int n; |
329 | char *tmpstr = (char *) map + found[0]->offset; | 302 | char *tmpstr = (char *) map + found[0]->offset; |
330 | for (n=0; n < itemindex; n++) | 303 | for (n = 0; n < itemindex; n++) |
331 | tmpstr = tmpstr + strlen(tmpstr) + 1; | 304 | tmpstr = tmpstr + strlen(tmpstr) + 1; |
332 | return tmpstr; | 305 | return tmpstr; |
333 | } | 306 | } |
diff --git a/archival/rpm.h b/archival/rpm.h new file mode 100644 index 000000000..f7c6fc2fa --- /dev/null +++ b/archival/rpm.h | |||
@@ -0,0 +1,38 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * RPM structs and consts | ||
4 | * | ||
5 | * Copyright (C) 2001 by Laurence Anderson | ||
6 | * | ||
7 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. | ||
8 | */ | ||
9 | |||
10 | /* RPM file starts with this struct: */ | ||
11 | struct rpm_lead { | ||
12 | uint32_t magic; | ||
13 | uint8_t major, minor; | ||
14 | uint16_t type; | ||
15 | uint16_t archnum; | ||
16 | char name[66]; | ||
17 | uint16_t osnum; | ||
18 | uint16_t signature_type; | ||
19 | char reserved[16]; | ||
20 | }; | ||
21 | struct BUG_rpm_lead { | ||
22 | char bug[sizeof(struct rpm_lead) == 96 ? 1 : -1]; | ||
23 | }; | ||
24 | #define RPM_LEAD_MAGIC 0xedabeedb | ||
25 | #define RPM_LEAD_MAGIC_STR "\355\253\356\333" | ||
26 | |||
27 | /* Then follows the header: */ | ||
28 | struct rpm_header { | ||
29 | uint32_t magic_and_ver; /* 3 byte magic: 0x8e 0xad 0xe8; 1 byte version: 0x01 */ | ||
30 | uint32_t reserved; /* 4 bytes reserved */ | ||
31 | uint32_t entries; /* Number of entries in header (4 bytes) */ | ||
32 | uint32_t size; /* Size of store (4 bytes) */ | ||
33 | }; | ||
34 | struct BUG_rpm_header { | ||
35 | char bug[sizeof(struct rpm_header) == 16 ? 1 : -1]; | ||
36 | }; | ||
37 | #define RPM_HEADER_MAGICnVER 0x8eade801 | ||
38 | #define RPM_HEADER_MAGIC_STR "\216\255\350" | ||
diff --git a/archival/rpm2cpio.c b/archival/rpm2cpio.c index 5403aee02..4ed5b023b 100644 --- a/archival/rpm2cpio.c +++ b/archival/rpm2cpio.c | |||
@@ -8,30 +8,7 @@ | |||
8 | */ | 8 | */ |
9 | #include "libbb.h" | 9 | #include "libbb.h" |
10 | #include "unarchive.h" | 10 | #include "unarchive.h" |
11 | 11 | #include "rpm.h" | |
12 | #define RPM_MAGIC 0xedabeedb | ||
13 | #define RPM_MAGIC_STR "\355\253\356\333" | ||
14 | |||
15 | struct rpm_lead { | ||
16 | uint32_t magic; | ||
17 | uint8_t major, minor; | ||
18 | uint16_t type; | ||
19 | uint16_t archnum; | ||
20 | char name[66]; | ||
21 | uint16_t osnum; | ||
22 | uint16_t signature_type; | ||
23 | char reserved[16]; | ||
24 | }; | ||
25 | |||
26 | #define RPM_HEADER_MAGICnVER 0x8eade801 | ||
27 | #define RPM_HEADER_MAGIC_STR "\216\255\350" | ||
28 | |||
29 | struct rpm_header { | ||
30 | uint32_t magic_and_ver; /* 3 byte magic: 0x8e 0xad 0xe8; 1 byte version */ | ||
31 | uint32_t reserved; /* 4 bytes reserved */ | ||
32 | uint32_t entries; /* Number of entries in header (4 bytes) */ | ||
33 | uint32_t size; /* Size of store (4 bytes) */ | ||
34 | }; | ||
35 | 12 | ||
36 | enum { rpm_fd = STDIN_FILENO }; | 13 | enum { rpm_fd = STDIN_FILENO }; |
37 | 14 | ||
@@ -65,8 +42,6 @@ int rpm2cpio_main(int argc UNUSED_PARAM, char **argv) | |||
65 | { | 42 | { |
66 | struct rpm_lead lead; | 43 | struct rpm_lead lead; |
67 | unsigned pos; | 44 | unsigned pos; |
68 | unsigned char magic[2]; | ||
69 | IF_DESKTOP(long long) int FAST_FUNC (*unpack)(int src_fd, int dst_fd); | ||
70 | 45 | ||
71 | if (argv[1]) { | 46 | if (argv[1]) { |
72 | xmove_fd(xopen(argv[1], O_RDONLY), rpm_fd); | 47 | xmove_fd(xopen(argv[1], O_RDONLY), rpm_fd); |
@@ -74,33 +49,45 @@ int rpm2cpio_main(int argc UNUSED_PARAM, char **argv) | |||
74 | xread(rpm_fd, &lead, sizeof(lead)); | 49 | xread(rpm_fd, &lead, sizeof(lead)); |
75 | 50 | ||
76 | /* Just check the magic, the rest is irrelevant */ | 51 | /* Just check the magic, the rest is irrelevant */ |
77 | if (lead.magic != htonl(RPM_MAGIC)) { | 52 | if (lead.magic != htonl(RPM_LEAD_MAGIC)) { |
78 | bb_error_msg_and_die("invalid RPM magic"); | 53 | bb_error_msg_and_die("invalid RPM magic"); |
79 | } | 54 | } |
80 | 55 | ||
81 | /* Skip the signature header, align to 8 bytes */ | 56 | /* Skip the signature header, align to 8 bytes */ |
82 | pos = skip_header(); | 57 | pos = skip_header(); |
83 | seek_by_jump(rpm_fd, (8 - pos) & 7); | 58 | seek_by_jump(rpm_fd, (-(int)pos) & 7); |
84 | 59 | ||
85 | /* Skip the main header */ | 60 | /* Skip the main header */ |
86 | skip_header(); | 61 | skip_header(); |
87 | 62 | ||
88 | xread(rpm_fd, &magic, 2); | 63 | #if 0 |
89 | unpack = unpack_gz_stream; | 64 | /* This works, but doesn't report uncompress errors (they happen in child) */ |
90 | if (magic[0] != 0x1f || magic[1] != 0x8b) { | 65 | setup_unzip_on_fd(rpm_fd /*fail_if_not_detected: 1*/); |
91 | if (!ENABLE_FEATURE_SEAMLESS_BZ2 | 66 | if (bb_copyfd_eof(rpm_fd, STDOUT_FILENO) < 0) |
92 | || magic[0] != 'B' || magic[1] != 'Z' | 67 | bb_error_msg_and_die("error unpacking"); |
93 | ) { | 68 | #else |
94 | bb_error_msg_and_die("invalid gzip" | 69 | /* BLOAT */ |
95 | IF_FEATURE_SEAMLESS_BZ2("/bzip2") | 70 | { |
96 | " magic"); | 71 | unsigned char magic[2]; |
72 | IF_DESKTOP(long long) int FAST_FUNC (*unpack)(int src_fd, int dst_fd); | ||
73 | |||
74 | xread(rpm_fd, &magic, 2); | ||
75 | unpack = unpack_gz_stream; | ||
76 | if (magic[0] != 0x1f || magic[1] != 0x8b) { | ||
77 | if (!ENABLE_FEATURE_SEAMLESS_BZ2 | ||
78 | || magic[0] != 'B' || magic[1] != 'Z' | ||
79 | ) { | ||
80 | bb_error_msg_and_die("invalid gzip" | ||
81 | IF_FEATURE_SEAMLESS_BZ2("/bzip2") | ||
82 | " magic"); | ||
83 | } | ||
84 | unpack = unpack_bz2_stream; | ||
97 | } | 85 | } |
98 | unpack = unpack_bz2_stream; | ||
99 | } | ||
100 | 86 | ||
101 | if (unpack(rpm_fd, STDOUT_FILENO) < 0) { | 87 | if (unpack(rpm_fd, STDOUT_FILENO) < 0) |
102 | bb_error_msg_and_die("error unpacking"); | 88 | bb_error_msg_and_die("error unpacking"); |
103 | } | 89 | } |
90 | #endif | ||
104 | 91 | ||
105 | if (ENABLE_FEATURE_CLEAN_UP) { | 92 | if (ENABLE_FEATURE_CLEAN_UP) { |
106 | close(rpm_fd); | 93 | close(rpm_fd); |
diff --git a/console-tools/clear.c b/console-tools/clear.c index 8b727b39b..b0c6d65d2 100644 --- a/console-tools/clear.c +++ b/console-tools/clear.c | |||
@@ -15,5 +15,6 @@ | |||
15 | int clear_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 15 | int clear_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
16 | int clear_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | 16 | int clear_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) |
17 | { | 17 | { |
18 | return printf("\033[H\033[J") != 6; | 18 | /* home; clear to the end of screen */ |
19 | return printf("\033[H""\033[J") != 6; | ||
19 | } | 20 | } |
diff --git a/console-tools/reset.c b/console-tools/reset.c index 6917eda42..f0ea5cb20 100644 --- a/console-tools/reset.c +++ b/console-tools/reset.c | |||
@@ -28,11 +28,11 @@ int reset_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
28 | 28 | ||
29 | if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) { | 29 | if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) { |
30 | /* See 'man 4 console_codes' for details: | 30 | /* See 'man 4 console_codes' for details: |
31 | * "ESC c" -- Reset | 31 | * "ESC c" -- Reset |
32 | * "ESC ( K" -- Select user mapping | 32 | * "ESC ( K" -- Select user mapping |
33 | * "ESC [ J" -- Erase display | 33 | * "ESC [ J" -- Erase to the end of screen |
34 | * "ESC [ 0 m" -- Reset all display attributes | 34 | * "ESC [ 0 m" -- Reset all display attributes |
35 | * "ESC [ ? 25 h" -- Make cursor visible. | 35 | * "ESC [ ? 25 h" -- Make cursor visible |
36 | */ | 36 | */ |
37 | printf("\033c\033(K\033[J\033[0m\033[?25h"); | 37 | printf("\033c\033(K\033[J\033[0m\033[?25h"); |
38 | /* http://bugs.busybox.net/view.php?id=1414: | 38 | /* http://bugs.busybox.net/view.php?id=1414: |
diff --git a/coreutils/Kbuild b/coreutils/Kbuild index 460d62d3f..ee22a3f7b 100644 --- a/coreutils/Kbuild +++ b/coreutils/Kbuild | |||
@@ -17,6 +17,7 @@ lib-$(CONFIG_CATV) += catv.o | |||
17 | lib-$(CONFIG_CHGRP) += chgrp.o chown.o | 17 | lib-$(CONFIG_CHGRP) += chgrp.o chown.o |
18 | lib-$(CONFIG_CHMOD) += chmod.o | 18 | lib-$(CONFIG_CHMOD) += chmod.o |
19 | lib-$(CONFIG_CHOWN) += chown.o | 19 | lib-$(CONFIG_CHOWN) += chown.o |
20 | lib-$(CONFIG_ADDUSER) += chown.o # used by adduser | ||
20 | lib-$(CONFIG_ADDGROUP) += chown.o # used by adduser | 21 | lib-$(CONFIG_ADDGROUP) += chown.o # used by adduser |
21 | lib-$(CONFIG_CHROOT) += chroot.o | 22 | lib-$(CONFIG_CHROOT) += chroot.o |
22 | lib-$(CONFIG_CKSUM) += cksum.o | 23 | lib-$(CONFIG_CKSUM) += cksum.o |
diff --git a/debianutils/run_parts.c b/debianutils/run_parts.c index 37e8487e1..ba05897f9 100644 --- a/debianutils/run_parts.c +++ b/debianutils/run_parts.c | |||
@@ -122,7 +122,6 @@ int run_parts_main(int argc UNUSED_PARAM, char **argv) | |||
122 | applet_long_options = runparts_longopts; | 122 | applet_long_options = runparts_longopts; |
123 | #endif | 123 | #endif |
124 | /* We require exactly one argument: the directory name */ | 124 | /* We require exactly one argument: the directory name */ |
125 | /* We require exactly one argument: the directory name */ | ||
126 | opt_complementary = "=1:a::"; | 125 | opt_complementary = "=1:a::"; |
127 | getopt32(argv, "ra:u:t"IF_FEATURE_RUN_PARTS_FANCY("l"), &arg_list, &umask_p); | 126 | getopt32(argv, "ra:u:t"IF_FEATURE_RUN_PARTS_FANCY("l"), &arg_list, &umask_p); |
128 | 127 | ||
diff --git a/e2fsprogs/Config.in b/e2fsprogs/Config.in index 9a0088ab5..964d08e4c 100644 --- a/e2fsprogs/Config.in +++ b/e2fsprogs/Config.in | |||
@@ -41,12 +41,12 @@ config LSATTR | |||
41 | ### mke2fs is used to create an ext2/ext3 filesystem. The normal compat | 41 | ### mke2fs is used to create an ext2/ext3 filesystem. The normal compat |
42 | ### symlinks 'mkfs.ext2' and 'mkfs.ext3' are also provided. | 42 | ### symlinks 'mkfs.ext2' and 'mkfs.ext3' are also provided. |
43 | 43 | ||
44 | ### config TUNE2FS | 44 | config TUNE2FS |
45 | ### bool "tune2fs" | 45 | bool "tune2fs" |
46 | ### default n | 46 | default n |
47 | ### help | 47 | help |
48 | ### tune2fs allows the system administrator to adjust various tunable | 48 | tune2fs allows the system administrator to adjust various tunable |
49 | ### filesystem parameters on Linux ext2/ext3 filesystems. | 49 | filesystem parameters on Linux ext2/ext3 filesystems. |
50 | 50 | ||
51 | ### config E2LABEL | 51 | ### config E2LABEL |
52 | ### bool "e2label" | 52 | ### bool "e2label" |
diff --git a/e2fsprogs/Kbuild b/e2fsprogs/Kbuild index 9f58ce092..0fdc9d215 100644 --- a/e2fsprogs/Kbuild +++ b/e2fsprogs/Kbuild | |||
@@ -9,4 +9,5 @@ lib-y:= | |||
9 | lib-$(CONFIG_CHATTR) += chattr.o e2fs_lib.o | 9 | lib-$(CONFIG_CHATTR) += chattr.o e2fs_lib.o |
10 | lib-$(CONFIG_LSATTR) += lsattr.o e2fs_lib.o | 10 | lib-$(CONFIG_LSATTR) += lsattr.o e2fs_lib.o |
11 | 11 | ||
12 | lib-$(CONFIG_FSCK) += fsck.o | 12 | lib-$(CONFIG_FSCK) += fsck.o |
13 | lib-$(CONFIG_TUNE2FS) += tune2fs.o | ||
diff --git a/util-linux/tune2fs.c b/e2fsprogs/tune2fs.c index 3b8f3d8ef..00ede4f1e 100644 --- a/util-linux/tune2fs.c +++ b/e2fsprogs/tune2fs.c | |||
@@ -9,16 +9,15 @@ | |||
9 | #include "libbb.h" | 9 | #include "libbb.h" |
10 | #include <linux/fs.h> | 10 | #include <linux/fs.h> |
11 | #include <linux/ext2_fs.h> | 11 | #include <linux/ext2_fs.h> |
12 | #include "volume_id/volume_id_internal.h" | ||
13 | 12 | ||
14 | // storage helpers | 13 | // storage helpers |
15 | char BUG_wrong_field_size(void); | 14 | char BUG_wrong_field_size(void); |
16 | #define STORE_LE(field, value) \ | 15 | #define STORE_LE(field, value) \ |
17 | do { \ | 16 | do { \ |
18 | if (sizeof(field) == 4) \ | 17 | if (sizeof(field) == 4) \ |
19 | field = cpu_to_le32(value); \ | 18 | field = SWAP_LE32(value); \ |
20 | else if (sizeof(field) == 2) \ | 19 | else if (sizeof(field) == 2) \ |
21 | field = cpu_to_le16(value); \ | 20 | field = SWAP_LE16(value); \ |
22 | else if (sizeof(field) == 1) \ | 21 | else if (sizeof(field) == 1) \ |
23 | field = (value); \ | 22 | field = (value); \ |
24 | else \ | 23 | else \ |
@@ -26,7 +25,7 @@ do { \ | |||
26 | } while (0) | 25 | } while (0) |
27 | 26 | ||
28 | #define FETCH_LE32(field) \ | 27 | #define FETCH_LE32(field) \ |
29 | (sizeof(field) == 4 ? cpu_to_le32(field) : BUG_wrong_field_size()) | 28 | (sizeof(field) == 4 ? SWAP_LE32(field) : BUG_wrong_field_size()) |
30 | 29 | ||
31 | enum { | 30 | enum { |
32 | OPT_L = 1 << 0, // label | 31 | OPT_L = 1 << 0, // label |
diff --git a/editors/Config.in b/editors/Config.in index e4fdd0f38..5f9566f0a 100644 --- a/editors/Config.in +++ b/editors/Config.in | |||
@@ -168,6 +168,18 @@ config FEATURE_VI_WIN_RESIZE | |||
168 | help | 168 | help |
169 | Make busybox vi behave nicely with terminals that get resized. | 169 | Make busybox vi behave nicely with terminals that get resized. |
170 | 170 | ||
171 | config FEATURE_VI_ASK_TERMINAL | ||
172 | bool "Use 'tell me cursor position' ESC sequence to measure window" | ||
173 | default n | ||
174 | depends on VI | ||
175 | help | ||
176 | If terminal size can't be retrieved and $LINES/$COLUMNS are not set, | ||
177 | this option makes vi perform a last-ditch effort to find it: | ||
178 | vi positions cursor to 999,999 and asks terminal to report real | ||
179 | cursor position using "ESC [ 6 n" escape sequence, then reads stdin. | ||
180 | |||
181 | This is not clean but helps a lot on serial lines and such. | ||
182 | |||
171 | config FEATURE_VI_OPTIMIZE_CURSOR | 183 | config FEATURE_VI_OPTIMIZE_CURSOR |
172 | bool "Optimize cursor movement" | 184 | bool "Optimize cursor movement" |
173 | default y | 185 | default y |
diff --git a/editors/cmp.c b/editors/cmp.c index 0cb80f21e..dbfa4be35 100644 --- a/editors/cmp.c +++ b/editors/cmp.c | |||
@@ -10,17 +10,6 @@ | |||
10 | /* BB_AUDIT SUSv3 (virtually) compliant -- uses nicer GNU format for -l. */ | 10 | /* BB_AUDIT SUSv3 (virtually) compliant -- uses nicer GNU format for -l. */ |
11 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/cmp.html */ | 11 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/cmp.html */ |
12 | 12 | ||
13 | /* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) | ||
14 | * | ||
15 | * Original version majorly reworked for SUSv3 compliance, bug fixes, and | ||
16 | * size optimizations. Changes include: | ||
17 | * 1) Now correctly distinguishes between errors and actual file differences. | ||
18 | * 2) Proper handling of '-' args. | ||
19 | * 3) Actual error checking of i/o. | ||
20 | * 4) Accept SUSv3 -l option. Note that we use the slightly nicer gnu format | ||
21 | * in the '-l' case. | ||
22 | */ | ||
23 | |||
24 | #include "libbb.h" | 13 | #include "libbb.h" |
25 | 14 | ||
26 | static const char fmt_eof[] ALIGN1 = "cmp: EOF on %s\n"; | 15 | static const char fmt_eof[] ALIGN1 = "cmp: EOF on %s\n"; |
@@ -37,8 +26,7 @@ int cmp_main(int argc UNUSED_PARAM, char **argv) | |||
37 | { | 26 | { |
38 | FILE *fp1, *fp2, *outfile = stdout; | 27 | FILE *fp1, *fp2, *outfile = stdout; |
39 | const char *filename1, *filename2 = "-"; | 28 | const char *filename1, *filename2 = "-"; |
40 | IF_DESKTOP(off_t skip1 = 0, skip2 = 0;) | 29 | off_t skip1 = 0, skip2 = 0, char_pos = 0; |
41 | off_t char_pos = 0; | ||
42 | int line_pos = 1; /* Hopefully won't overflow... */ | 30 | int line_pos = 1; /* Hopefully won't overflow... */ |
43 | const char *fmt; | 31 | const char *fmt; |
44 | int c1, c2; | 32 | int c1, c2; |
@@ -59,14 +47,12 @@ int cmp_main(int argc UNUSED_PARAM, char **argv) | |||
59 | 47 | ||
60 | if (*++argv) { | 48 | if (*++argv) { |
61 | filename2 = *argv; | 49 | filename2 = *argv; |
62 | #if ENABLE_DESKTOP | 50 | if (ENABLE_DESKTOP && *++argv) { |
63 | if (*++argv) { | ||
64 | skip1 = XATOOFF(*argv); | 51 | skip1 = XATOOFF(*argv); |
65 | if (*++argv) { | 52 | if (*++argv) { |
66 | skip2 = XATOOFF(*argv); | 53 | skip2 = XATOOFF(*argv); |
67 | } | 54 | } |
68 | } | 55 | } |
69 | #endif | ||
70 | } | 56 | } |
71 | 57 | ||
72 | fp2 = xfopen_stdin(filename2); | 58 | fp2 = xfopen_stdin(filename2); |
@@ -83,10 +69,10 @@ int cmp_main(int argc UNUSED_PARAM, char **argv) | |||
83 | else | 69 | else |
84 | fmt = fmt_differ; | 70 | fmt = fmt_differ; |
85 | 71 | ||
86 | #if ENABLE_DESKTOP | 72 | if (ENABLE_DESKTOP) { |
87 | while (skip1) { getc(fp1); skip1--; } | 73 | while (skip1) { getc(fp1); skip1--; } |
88 | while (skip2) { getc(fp2); skip2--; } | 74 | while (skip2) { getc(fp2); skip2--; } |
89 | #endif | 75 | } |
90 | do { | 76 | do { |
91 | c1 = getc(fp1); | 77 | c1 = getc(fp1); |
92 | c2 = getc(fp2); | 78 | c2 = getc(fp2); |
diff --git a/editors/sed.c b/editors/sed.c index e5e187725..4bd6e0168 100644 --- a/editors/sed.c +++ b/editors/sed.c | |||
@@ -487,7 +487,7 @@ static const char *parse_cmd_args(sed_cmd_t *sed_cmd, const char *cmdstr) | |||
487 | static void add_cmd(const char *cmdstr) | 487 | static void add_cmd(const char *cmdstr) |
488 | { | 488 | { |
489 | sed_cmd_t *sed_cmd; | 489 | sed_cmd_t *sed_cmd; |
490 | int temp; | 490 | unsigned len, n; |
491 | 491 | ||
492 | /* Append this line to any unfinished line from last time. */ | 492 | /* Append this line to any unfinished line from last time. */ |
493 | if (G.add_cmd_line) { | 493 | if (G.add_cmd_line) { |
@@ -496,12 +496,14 @@ static void add_cmd(const char *cmdstr) | |||
496 | cmdstr = G.add_cmd_line = tp; | 496 | cmdstr = G.add_cmd_line = tp; |
497 | } | 497 | } |
498 | 498 | ||
499 | /* If this line ends with backslash, request next line. */ | 499 | /* If this line ends with unescaped backslash, request next line. */ |
500 | temp = strlen(cmdstr); | 500 | n = len = strlen(cmdstr); |
501 | if (temp && cmdstr[--temp] == '\\') { | 501 | while (n && cmdstr[n-1] == '\\') |
502 | n--; | ||
503 | if ((len - n) & 1) { /* if odd number of trailing backslashes */ | ||
502 | if (!G.add_cmd_line) | 504 | if (!G.add_cmd_line) |
503 | G.add_cmd_line = xstrdup(cmdstr); | 505 | G.add_cmd_line = xstrdup(cmdstr); |
504 | G.add_cmd_line[temp] = '\0'; | 506 | G.add_cmd_line[len-1] = '\0'; |
505 | return; | 507 | return; |
506 | } | 508 | } |
507 | 509 | ||
@@ -560,7 +562,7 @@ static void add_cmd(const char *cmdstr) | |||
560 | /* last part (mandatory) will be a command */ | 562 | /* last part (mandatory) will be a command */ |
561 | if (!*cmdstr) | 563 | if (!*cmdstr) |
562 | bb_error_msg_and_die("missing command"); | 564 | bb_error_msg_and_die("missing command"); |
563 | sed_cmd->cmd = *(cmdstr++); | 565 | sed_cmd->cmd = *cmdstr++; |
564 | cmdstr = parse_cmd_args(sed_cmd, cmdstr); | 566 | cmdstr = parse_cmd_args(sed_cmd, cmdstr); |
565 | 567 | ||
566 | /* Add the command to the command array */ | 568 | /* Add the command to the command array */ |
@@ -936,7 +938,15 @@ static void process_files(void) | |||
936 | /* Skip blocks of commands we didn't match */ | 938 | /* Skip blocks of commands we didn't match */ |
937 | if (sed_cmd->cmd == '{') { | 939 | if (sed_cmd->cmd == '{') { |
938 | if (sed_cmd->invert ? matched : !matched) { | 940 | if (sed_cmd->invert ? matched : !matched) { |
939 | while (sed_cmd->cmd != '}') { | 941 | unsigned nest_cnt = 0; |
942 | while (1) { | ||
943 | if (sed_cmd->cmd == '{') | ||
944 | nest_cnt++; | ||
945 | if (sed_cmd->cmd == '}') { | ||
946 | nest_cnt--; | ||
947 | if (nest_cnt == 0) | ||
948 | break; | ||
949 | } | ||
940 | sed_cmd = sed_cmd->next; | 950 | sed_cmd = sed_cmd->next; |
941 | if (!sed_cmd) | 951 | if (!sed_cmd) |
942 | bb_error_msg_and_die("unterminated {"); | 952 | bb_error_msg_and_die("unterminated {"); |
@@ -1031,7 +1041,7 @@ static void process_files(void) | |||
1031 | case 'c': | 1041 | case 'c': |
1032 | /* Only triggers on last line of a matching range. */ | 1042 | /* Only triggers on last line of a matching range. */ |
1033 | if (!sed_cmd->in_match) | 1043 | if (!sed_cmd->in_match) |
1034 | sed_puts(sed_cmd->string, NO_EOL_CHAR); | 1044 | sed_puts(sed_cmd->string, '\n'); |
1035 | goto discard_line; | 1045 | goto discard_line; |
1036 | 1046 | ||
1037 | /* Read file, append contents to output */ | 1047 | /* Read file, append contents to output */ |
diff --git a/editors/vi.c b/editors/vi.c index 28612508f..d9124fd76 100644 --- a/editors/vi.c +++ b/editors/vi.c | |||
@@ -60,18 +60,18 @@ enum { | |||
60 | 60 | ||
61 | /* vt102 typical ESC sequence */ | 61 | /* vt102 typical ESC sequence */ |
62 | /* terminal standout start/normal ESC sequence */ | 62 | /* terminal standout start/normal ESC sequence */ |
63 | static const char SOs[] ALIGN1 = "\033[7m"; | 63 | #define SOs "\033[7m" |
64 | static const char SOn[] ALIGN1 = "\033[0m"; | 64 | #define SOn "\033[0m" |
65 | /* terminal bell sequence */ | 65 | /* terminal bell sequence */ |
66 | static const char bell[] ALIGN1 = "\007"; | 66 | #define bell "\007" |
67 | /* Clear-end-of-line and Clear-end-of-screen ESC sequence */ | 67 | /* Clear-end-of-line and Clear-end-of-screen ESC sequence */ |
68 | static const char Ceol[] ALIGN1 = "\033[0K"; | 68 | #define Ceol "\033[K" |
69 | static const char Ceos[] ALIGN1 = "\033[0J"; | 69 | #define Ceos "\033[J" |
70 | /* Cursor motion arbitrary destination ESC sequence */ | 70 | /* Cursor motion arbitrary destination ESC sequence */ |
71 | static const char CMrc[] ALIGN1 = "\033[%d;%dH"; | 71 | #define CMrc "\033[%u;%uH" |
72 | /* Cursor motion up and down ESC sequence */ | 72 | /* Cursor motion up and down ESC sequence */ |
73 | static const char CMup[] ALIGN1 = "\033[A"; | 73 | #define CMup "\033[A" |
74 | static const char CMdown[] ALIGN1 = "\n"; | 74 | #define CMdown "\n" |
75 | 75 | ||
76 | #if ENABLE_FEATURE_VI_DOT_CMD || ENABLE_FEATURE_VI_YANKMARK | 76 | #if ENABLE_FEATURE_VI_DOT_CMD || ENABLE_FEATURE_VI_YANKMARK |
77 | // cmds modifying text[] | 77 | // cmds modifying text[] |
@@ -138,6 +138,9 @@ struct globals { | |||
138 | int save_argc; // how many file names on cmd line | 138 | int save_argc; // how many file names on cmd line |
139 | int cmdcnt; // repetition count | 139 | int cmdcnt; // repetition count |
140 | unsigned rows, columns; // the terminal screen is this size | 140 | unsigned rows, columns; // the terminal screen is this size |
141 | #if ENABLE_FEATURE_VI_ASK_TERMINAL | ||
142 | int get_rowcol_error; | ||
143 | #endif | ||
141 | int crow, ccol; // cursor is on Crow x Ccol | 144 | int crow, ccol; // cursor is on Crow x Ccol |
142 | int offset; // chars scrolled off the screen to the left | 145 | int offset; // chars scrolled off the screen to the left |
143 | int have_status_msg; // is default edit status needed? | 146 | int have_status_msg; // is default edit status needed? |
@@ -503,7 +506,11 @@ static int init_text_buffer(char *fn) | |||
503 | #if ENABLE_FEATURE_VI_WIN_RESIZE | 506 | #if ENABLE_FEATURE_VI_WIN_RESIZE |
504 | static void query_screen_dimensions(void) | 507 | static void query_screen_dimensions(void) |
505 | { | 508 | { |
506 | get_terminal_width_height(STDIN_FILENO, &columns, &rows); | 509 | # if ENABLE_FEATURE_VI_ASK_TERMINAL |
510 | if (!G.get_rowcol_error) | ||
511 | G.get_rowcol_error = | ||
512 | # endif | ||
513 | get_terminal_width_height(STDIN_FILENO, &columns, &rows); | ||
507 | if (rows > MAX_SCR_ROWS) | 514 | if (rows > MAX_SCR_ROWS) |
508 | rows = MAX_SCR_ROWS; | 515 | rows = MAX_SCR_ROWS; |
509 | if (columns > MAX_SCR_COLS) | 516 | if (columns > MAX_SCR_COLS) |
@@ -530,6 +537,20 @@ static void edit_file(char *fn) | |||
530 | columns = 80; | 537 | columns = 80; |
531 | size = 0; | 538 | size = 0; |
532 | query_screen_dimensions(); | 539 | query_screen_dimensions(); |
540 | #if ENABLE_FEATURE_VI_ASK_TERMINAL | ||
541 | if (G.get_rowcol_error /* TODO? && no input on stdin */) { | ||
542 | uint64_t k; | ||
543 | write1("\033[999;999H" "\033[6n"); | ||
544 | fflush_all(); | ||
545 | k = read_key(STDIN_FILENO, readbuffer, /*timeout_ms:*/ 100); | ||
546 | if ((int32_t)k == KEYCODE_CURSOR_POS) { | ||
547 | uint32_t rc = (k >> 32); | ||
548 | columns = (rc & 0x7fff); | ||
549 | rows = ((rc >> 16) & 0x7fff); | ||
550 | } | ||
551 | query_screen_dimensions(); | ||
552 | } | ||
553 | #endif | ||
533 | new_screen(rows, columns); // get memory for virtual screen | 554 | new_screen(rows, columns); // get memory for virtual screen |
534 | init_text_buffer(fn); | 555 | init_text_buffer(fn); |
535 | 556 | ||
@@ -2306,7 +2327,7 @@ static int file_size(const char *fn) // what is the byte size of "fn" | |||
2306 | int cnt; | 2327 | int cnt; |
2307 | 2328 | ||
2308 | cnt = -1; | 2329 | cnt = -1; |
2309 | if (fn && fn[0] && stat(fn, &st_buf) == 0) // see if file exists | 2330 | if (fn && stat(fn, &st_buf) == 0) // see if file exists |
2310 | cnt = (int) st_buf.st_size; | 2331 | cnt = (int) st_buf.st_size; |
2311 | return cnt; | 2332 | return cnt; |
2312 | } | 2333 | } |
diff --git a/findutils/.gitignore b/findutils/.gitignore new file mode 100644 index 000000000..7a30caf5c --- /dev/null +++ b/findutils/.gitignore | |||
@@ -0,0 +1,3 @@ | |||
1 | # Config.in and Kbuild are auto-generated | ||
2 | Config.in | ||
3 | Kbuild | ||
diff --git a/findutils/Config.in b/findutils/Config.in deleted file mode 100644 index 8582d6446..000000000 --- a/findutils/Config.in +++ /dev/null | |||
@@ -1,253 +0,0 @@ | |||
1 | # | ||
2 | # For a description of the syntax of this configuration file, | ||
3 | # see scripts/kbuild/config-language.txt. | ||
4 | # | ||
5 | |||
6 | menu "Finding Utilities" | ||
7 | |||
8 | config FIND | ||
9 | bool "find" | ||
10 | default n | ||
11 | help | ||
12 | find is used to search your system to find specified files. | ||
13 | |||
14 | config FEATURE_FIND_PRINT0 | ||
15 | bool "Enable -print0: NUL-terminated output" | ||
16 | default y | ||
17 | depends on FIND | ||
18 | help | ||
19 | Causes output names to be separated by a NUL character | ||
20 | rather than a newline. This allows names that contain | ||
21 | newlines and other whitespace to be more easily | ||
22 | interpreted by other programs. | ||
23 | |||
24 | config FEATURE_FIND_MTIME | ||
25 | bool "Enable -mtime: modified time matching" | ||
26 | default y | ||
27 | depends on FIND | ||
28 | help | ||
29 | Allow searching based on the modification time of | ||
30 | files, in days. | ||
31 | |||
32 | config FEATURE_FIND_MMIN | ||
33 | bool "Enable -mmin: modified time matching by minutes" | ||
34 | default y | ||
35 | depends on FIND | ||
36 | help | ||
37 | Allow searching based on the modification time of | ||
38 | files, in minutes. | ||
39 | |||
40 | config FEATURE_FIND_PERM | ||
41 | bool "Enable -perm: permissions matching" | ||
42 | default y | ||
43 | depends on FIND | ||
44 | help | ||
45 | Enable searching based on file permissions. | ||
46 | |||
47 | config FEATURE_FIND_TYPE | ||
48 | bool "Enable -type: file type matching (file/dir/link/...)" | ||
49 | default y | ||
50 | depends on FIND | ||
51 | help | ||
52 | Enable searching based on file type (file, | ||
53 | directory, socket, device, etc.). | ||
54 | |||
55 | config FEATURE_FIND_XDEV | ||
56 | bool "Enable -xdev: 'stay in filesystem'" | ||
57 | default y | ||
58 | depends on FIND | ||
59 | help | ||
60 | This option allows find to restrict searches to a single filesystem. | ||
61 | |||
62 | config FEATURE_FIND_MAXDEPTH | ||
63 | bool "Enable -maxdepth N" | ||
64 | default y | ||
65 | depends on FIND | ||
66 | help | ||
67 | This option enables -maxdepth N option. | ||
68 | |||
69 | config FEATURE_FIND_NEWER | ||
70 | bool "Enable -newer: compare file modification times" | ||
71 | default y | ||
72 | depends on FIND | ||
73 | help | ||
74 | Support the 'find -newer' option for finding any files which have | ||
75 | a modified time that is more recent than the specified FILE. | ||
76 | |||
77 | config FEATURE_FIND_INUM | ||
78 | bool "Enable -inum: inode number matching" | ||
79 | default y | ||
80 | depends on FIND | ||
81 | help | ||
82 | Support the 'find -inum' option for searching by inode number. | ||
83 | |||
84 | config FEATURE_FIND_EXEC | ||
85 | bool "Enable -exec: execute commands" | ||
86 | default y | ||
87 | depends on FIND | ||
88 | help | ||
89 | Support the 'find -exec' option for executing commands based upon | ||
90 | the files matched. | ||
91 | |||
92 | config FEATURE_FIND_USER | ||
93 | bool "Enable -user: username/uid matching" | ||
94 | default y | ||
95 | depends on FIND | ||
96 | help | ||
97 | Support the 'find -user' option for searching by username or uid. | ||
98 | |||
99 | config FEATURE_FIND_GROUP | ||
100 | bool "Enable -group: group/gid matching" | ||
101 | default y | ||
102 | depends on FIND | ||
103 | help | ||
104 | Support the 'find -group' option for searching by group name or gid. | ||
105 | |||
106 | config FEATURE_FIND_NOT | ||
107 | bool "Enable the 'not' (!) operator" | ||
108 | default y | ||
109 | depends on FIND | ||
110 | help | ||
111 | Support the '!' operator to invert the test results. | ||
112 | If 'Enable full-blown desktop' is enabled, then will also support | ||
113 | the non-POSIX notation '-not'. | ||
114 | |||
115 | config FEATURE_FIND_DEPTH | ||
116 | bool "Enable -depth" | ||
117 | default y | ||
118 | depends on FIND | ||
119 | help | ||
120 | Process each directory's contents before the directory itself. | ||
121 | |||
122 | config FEATURE_FIND_PAREN | ||
123 | bool "Enable parens in options" | ||
124 | default y | ||
125 | depends on FIND | ||
126 | help | ||
127 | Enable usage of parens '(' to specify logical order of arguments. | ||
128 | |||
129 | config FEATURE_FIND_SIZE | ||
130 | bool "Enable -size: file size matching" | ||
131 | default y | ||
132 | depends on FIND | ||
133 | help | ||
134 | Support the 'find -size' option for searching by file size. | ||
135 | |||
136 | config FEATURE_FIND_PRUNE | ||
137 | bool "Enable -prune: exclude subdirectories" | ||
138 | default y | ||
139 | depends on FIND | ||
140 | help | ||
141 | If the file is a directory, dont descend into it. Useful for | ||
142 | exclusion .svn and CVS directories. | ||
143 | |||
144 | config FEATURE_FIND_DELETE | ||
145 | bool "Enable -delete: delete files/dirs" | ||
146 | default n | ||
147 | depends on FIND && FEATURE_FIND_DEPTH | ||
148 | help | ||
149 | Support the 'find -delete' option for deleting files and directories. | ||
150 | WARNING: This option can do much harm if used wrong. Busybox will not | ||
151 | try to protect the user from doing stupid things. Use with care. | ||
152 | |||
153 | config FEATURE_FIND_PATH | ||
154 | bool "Enable -path: match pathname with shell pattern" | ||
155 | default y | ||
156 | depends on FIND | ||
157 | help | ||
158 | The -path option matches whole pathname instead of just filename. | ||
159 | |||
160 | config FEATURE_FIND_REGEX | ||
161 | bool "Enable -regex: match pathname with regex" | ||
162 | default y | ||
163 | depends on FIND | ||
164 | help | ||
165 | The -regex option matches whole pathname against regular expression. | ||
166 | |||
167 | config FEATURE_FIND_CONTEXT | ||
168 | bool "Enable -context: security context matching" | ||
169 | default n | ||
170 | depends on FIND && SELINUX | ||
171 | help | ||
172 | Support the 'find -context' option for matching security context. | ||
173 | |||
174 | config FEATURE_FIND_LINKS | ||
175 | bool "Enable -links: link count matching" | ||
176 | default n | ||
177 | depends on FIND | ||
178 | help | ||
179 | Support the 'find -links' option for matching number of links. | ||
180 | |||
181 | config GREP | ||
182 | bool "grep" | ||
183 | default n | ||
184 | help | ||
185 | grep is used to search files for a specified pattern. | ||
186 | |||
187 | config FEATURE_GREP_EGREP_ALIAS | ||
188 | bool "Enable extended regular expressions (egrep & grep -E)" | ||
189 | default y | ||
190 | depends on GREP | ||
191 | help | ||
192 | Enabled support for extended regular expressions. Extended | ||
193 | regular expressions allow for alternation (foo|bar), grouping, | ||
194 | and various repetition operators. | ||
195 | |||
196 | config FEATURE_GREP_FGREP_ALIAS | ||
197 | bool "Alias fgrep to grep -F" | ||
198 | default y | ||
199 | depends on GREP | ||
200 | help | ||
201 | fgrep sees the search pattern as a normal string rather than | ||
202 | regular expressions. | ||
203 | grep -F always works, this just creates the fgrep alias. | ||
204 | |||
205 | config FEATURE_GREP_CONTEXT | ||
206 | bool "Enable before and after context flags (-A, -B and -C)" | ||
207 | default y | ||
208 | depends on GREP | ||
209 | help | ||
210 | Print the specified number of leading (-B) and/or trailing (-A) | ||
211 | context surrounding our matching lines. | ||
212 | Print the specified number of context lines (-C). | ||
213 | |||
214 | config XARGS | ||
215 | bool "xargs" | ||
216 | default n | ||
217 | help | ||
218 | xargs is used to execute a specified command for | ||
219 | every item from standard input. | ||
220 | |||
221 | config FEATURE_XARGS_SUPPORT_CONFIRMATION | ||
222 | bool "Enable -p: prompt and confirmation" | ||
223 | default n | ||
224 | depends on XARGS | ||
225 | help | ||
226 | Support -p: prompt the user whether to run each command | ||
227 | line and read a line from the terminal. | ||
228 | |||
229 | config FEATURE_XARGS_SUPPORT_QUOTES | ||
230 | bool "Enable single and double quotes and backslash" | ||
231 | default n | ||
232 | depends on XARGS | ||
233 | help | ||
234 | Support quoting in the input. | ||
235 | |||
236 | config FEATURE_XARGS_SUPPORT_TERMOPT | ||
237 | bool "Enable -x: exit if -s or -n is exceeded" | ||
238 | default n | ||
239 | depends on XARGS | ||
240 | help | ||
241 | Support -x: exit if the command size (see the -s or -n option) | ||
242 | is exceeded. | ||
243 | |||
244 | config FEATURE_XARGS_SUPPORT_ZERO_TERM | ||
245 | bool "Enable -0: NUL-terminated input" | ||
246 | default n | ||
247 | depends on XARGS | ||
248 | help | ||
249 | Support -0: input items are terminated by a NUL character | ||
250 | instead of whitespace, and the quotes and backslash | ||
251 | are not special. | ||
252 | |||
253 | endmenu | ||
diff --git a/findutils/Config.src b/findutils/Config.src new file mode 100644 index 000000000..9ee71a845 --- /dev/null +++ b/findutils/Config.src | |||
@@ -0,0 +1,10 @@ | |||
1 | # | ||
2 | # For a description of the syntax of this configuration file, | ||
3 | # see scripts/kbuild/config-language.txt. | ||
4 | # | ||
5 | |||
6 | menu "Finding Utilities" | ||
7 | |||
8 | INSERT | ||
9 | |||
10 | endmenu | ||
diff --git a/findutils/Kbuild b/findutils/Kbuild.src index 7b504bacf..771789ff5 100644 --- a/findutils/Kbuild +++ b/findutils/Kbuild.src | |||
@@ -5,6 +5,5 @@ | |||
5 | # Licensed under the GPL v2, see the file LICENSE in this tarball. | 5 | # Licensed under the GPL v2, see the file LICENSE in this tarball. |
6 | 6 | ||
7 | lib-y:= | 7 | lib-y:= |
8 | lib-$(CONFIG_FIND) += find.o | 8 | |
9 | lib-$(CONFIG_GREP) += grep.o | 9 | INSERT |
10 | lib-$(CONFIG_XARGS) += xargs.o | ||
diff --git a/findutils/find.c b/findutils/find.c index 0b06938da..9022867a2 100644 --- a/findutils/find.c +++ b/findutils/find.c | |||
@@ -53,6 +53,181 @@ | |||
53 | * diff -u /tmp/std_find /tmp/bb_find && echo Identical | 53 | * diff -u /tmp/std_find /tmp/bb_find && echo Identical |
54 | */ | 54 | */ |
55 | 55 | ||
56 | //kbuild:lib-$(CONFIG_FIND) += find.o | ||
57 | //config: | ||
58 | //config:config FIND | ||
59 | //config: bool "find" | ||
60 | //config: default n | ||
61 | //config: help | ||
62 | //config: find is used to search your system to find specified files. | ||
63 | //config: | ||
64 | //config:config FEATURE_FIND_PRINT0 | ||
65 | //config: bool "Enable -print0: NUL-terminated output" | ||
66 | //config: default y | ||
67 | //config: depends on FIND | ||
68 | //config: help | ||
69 | //config: Causes output names to be separated by a NUL character | ||
70 | //config: rather than a newline. This allows names that contain | ||
71 | //config: newlines and other whitespace to be more easily | ||
72 | //config: interpreted by other programs. | ||
73 | //config: | ||
74 | //config:config FEATURE_FIND_MTIME | ||
75 | //config: bool "Enable -mtime: modified time matching" | ||
76 | //config: default y | ||
77 | //config: depends on FIND | ||
78 | //config: help | ||
79 | //config: Allow searching based on the modification time of | ||
80 | //config: files, in days. | ||
81 | //config: | ||
82 | //config:config FEATURE_FIND_MMIN | ||
83 | //config: bool "Enable -mmin: modified time matching by minutes" | ||
84 | //config: default y | ||
85 | //config: depends on FIND | ||
86 | //config: help | ||
87 | //config: Allow searching based on the modification time of | ||
88 | //config: files, in minutes. | ||
89 | //config: | ||
90 | //config:config FEATURE_FIND_PERM | ||
91 | //config: bool "Enable -perm: permissions matching" | ||
92 | //config: default y | ||
93 | //config: depends on FIND | ||
94 | //config: help | ||
95 | //config: Enable searching based on file permissions. | ||
96 | //config: | ||
97 | //config:config FEATURE_FIND_TYPE | ||
98 | //config: bool "Enable -type: file type matching (file/dir/link/...)" | ||
99 | //config: default y | ||
100 | //config: depends on FIND | ||
101 | //config: help | ||
102 | //config: Enable searching based on file type (file, | ||
103 | //config: directory, socket, device, etc.). | ||
104 | //config: | ||
105 | //config:config FEATURE_FIND_XDEV | ||
106 | //config: bool "Enable -xdev: 'stay in filesystem'" | ||
107 | //config: default y | ||
108 | //config: depends on FIND | ||
109 | //config: help | ||
110 | //config: This option allows find to restrict searches to a single filesystem. | ||
111 | //config: | ||
112 | //config:config FEATURE_FIND_MAXDEPTH | ||
113 | //config: bool "Enable -maxdepth N" | ||
114 | //config: default y | ||
115 | //config: depends on FIND | ||
116 | //config: help | ||
117 | //config: This option enables -maxdepth N option. | ||
118 | //config: | ||
119 | //config:config FEATURE_FIND_NEWER | ||
120 | //config: bool "Enable -newer: compare file modification times" | ||
121 | //config: default y | ||
122 | //config: depends on FIND | ||
123 | //config: help | ||
124 | //config: Support the 'find -newer' option for finding any files which have | ||
125 | //config: a modified time that is more recent than the specified FILE. | ||
126 | //config: | ||
127 | //config:config FEATURE_FIND_INUM | ||
128 | //config: bool "Enable -inum: inode number matching" | ||
129 | //config: default y | ||
130 | //config: depends on FIND | ||
131 | //config: help | ||
132 | //config: Support the 'find -inum' option for searching by inode number. | ||
133 | //config: | ||
134 | //config:config FEATURE_FIND_EXEC | ||
135 | //config: bool "Enable -exec: execute commands" | ||
136 | //config: default y | ||
137 | //config: depends on FIND | ||
138 | //config: help | ||
139 | //config: Support the 'find -exec' option for executing commands based upon | ||
140 | //config: the files matched. | ||
141 | //config: | ||
142 | //config:config FEATURE_FIND_USER | ||
143 | //config: bool "Enable -user: username/uid matching" | ||
144 | //config: default y | ||
145 | //config: depends on FIND | ||
146 | //config: help | ||
147 | //config: Support the 'find -user' option for searching by username or uid. | ||
148 | //config: | ||
149 | //config:config FEATURE_FIND_GROUP | ||
150 | //config: bool "Enable -group: group/gid matching" | ||
151 | //config: default y | ||
152 | //config: depends on FIND | ||
153 | //config: help | ||
154 | //config: Support the 'find -group' option for searching by group name or gid. | ||
155 | //config: | ||
156 | //config:config FEATURE_FIND_NOT | ||
157 | //config: bool "Enable the 'not' (!) operator" | ||
158 | //config: default y | ||
159 | //config: depends on FIND | ||
160 | //config: help | ||
161 | //config: Support the '!' operator to invert the test results. | ||
162 | //config: If 'Enable full-blown desktop' is enabled, then will also support | ||
163 | //config: the non-POSIX notation '-not'. | ||
164 | //config: | ||
165 | //config:config FEATURE_FIND_DEPTH | ||
166 | //config: bool "Enable -depth" | ||
167 | //config: default y | ||
168 | //config: depends on FIND | ||
169 | //config: help | ||
170 | //config: Process each directory's contents before the directory itself. | ||
171 | //config: | ||
172 | //config:config FEATURE_FIND_PAREN | ||
173 | //config: bool "Enable parens in options" | ||
174 | //config: default y | ||
175 | //config: depends on FIND | ||
176 | //config: help | ||
177 | //config: Enable usage of parens '(' to specify logical order of arguments. | ||
178 | //config: | ||
179 | //config:config FEATURE_FIND_SIZE | ||
180 | //config: bool "Enable -size: file size matching" | ||
181 | //config: default y | ||
182 | //config: depends on FIND | ||
183 | //config: help | ||
184 | //config: Support the 'find -size' option for searching by file size. | ||
185 | //config: | ||
186 | //config:config FEATURE_FIND_PRUNE | ||
187 | //config: bool "Enable -prune: exclude subdirectories" | ||
188 | //config: default y | ||
189 | //config: depends on FIND | ||
190 | //config: help | ||
191 | //config: If the file is a directory, dont descend into it. Useful for | ||
192 | //config: exclusion .svn and CVS directories. | ||
193 | //config: | ||
194 | //config:config FEATURE_FIND_DELETE | ||
195 | //config: bool "Enable -delete: delete files/dirs" | ||
196 | //config: default n | ||
197 | //config: depends on FIND && FEATURE_FIND_DEPTH | ||
198 | //config: help | ||
199 | //config: Support the 'find -delete' option for deleting files and directories. | ||
200 | //config: WARNING: This option can do much harm if used wrong. Busybox will not | ||
201 | //config: try to protect the user from doing stupid things. Use with care. | ||
202 | //config: | ||
203 | //config:config FEATURE_FIND_PATH | ||
204 | //config: bool "Enable -path: match pathname with shell pattern" | ||
205 | //config: default y | ||
206 | //config: depends on FIND | ||
207 | //config: help | ||
208 | //config: The -path option matches whole pathname instead of just filename. | ||
209 | //config: | ||
210 | //config:config FEATURE_FIND_REGEX | ||
211 | //config: bool "Enable -regex: match pathname with regex" | ||
212 | //config: default y | ||
213 | //config: depends on FIND | ||
214 | //config: help | ||
215 | //config: The -regex option matches whole pathname against regular expression. | ||
216 | //config: | ||
217 | //config:config FEATURE_FIND_CONTEXT | ||
218 | //config: bool "Enable -context: security context matching" | ||
219 | //config: default n | ||
220 | //config: depends on FIND && SELINUX | ||
221 | //config: help | ||
222 | //config: Support the 'find -context' option for matching security context. | ||
223 | //config: | ||
224 | //config:config FEATURE_FIND_LINKS | ||
225 | //config: bool "Enable -links: link count matching" | ||
226 | //config: default n | ||
227 | //config: depends on FIND | ||
228 | //config: help | ||
229 | //config: Support the 'find -links' option for matching number of links. | ||
230 | |||
56 | #include <fnmatch.h> | 231 | #include <fnmatch.h> |
57 | #include "libbb.h" | 232 | #include "libbb.h" |
58 | #if ENABLE_FEATURE_FIND_REGEX | 233 | #if ENABLE_FEATURE_FIND_REGEX |
@@ -198,14 +373,19 @@ static int exec_actions(action ***appp, const char *fileName, const struct stat | |||
198 | ACTF(name) | 373 | ACTF(name) |
199 | { | 374 | { |
200 | const char *tmp = bb_basename(fileName); | 375 | const char *tmp = bb_basename(fileName); |
201 | if (tmp != fileName && !*tmp) { /* "foo/bar/". Oh no... go back to 'b' */ | 376 | if (tmp != fileName && *tmp == '\0') { |
377 | /* "foo/bar/". Oh no... go back to 'b' */ | ||
202 | tmp--; | 378 | tmp--; |
203 | while (tmp != fileName && *--tmp != '/') | 379 | while (tmp != fileName && *--tmp != '/') |
204 | continue; | 380 | continue; |
205 | if (*tmp == '/') | 381 | if (*tmp == '/') |
206 | tmp++; | 382 | tmp++; |
207 | } | 383 | } |
208 | return fnmatch(ap->pattern, tmp, FNM_PERIOD | (ap->iname ? FNM_CASEFOLD : 0)) == 0; | 384 | /* Was using FNM_PERIOD flag too, |
385 | * but somewhere between 4.1.20 and 4.4.0 GNU find stopped using it. | ||
386 | * find -name '*foo' should match .foo too: | ||
387 | */ | ||
388 | return fnmatch(ap->pattern, tmp, (ap->iname ? FNM_CASEFOLD : 0)) == 0; | ||
209 | } | 389 | } |
210 | 390 | ||
211 | #if ENABLE_FEATURE_FIND_PATH | 391 | #if ENABLE_FEATURE_FIND_PATH |
diff --git a/findutils/grep.c b/findutils/grep.c index 318fb4b2f..d5fe10320 100644 --- a/findutils/grep.c +++ b/findutils/grep.c | |||
@@ -19,15 +19,49 @@ | |||
19 | * (C) 2006 Jac Goudsmit added -o option | 19 | * (C) 2006 Jac Goudsmit added -o option |
20 | */ | 20 | */ |
21 | 21 | ||
22 | //kbuild:lib-$(CONFIG_GREP) += grep.o | ||
23 | //config: | ||
24 | //config:config GREP | ||
25 | //config: bool "grep" | ||
26 | //config: default n | ||
27 | //config: help | ||
28 | //config: grep is used to search files for a specified pattern. | ||
29 | //config: | ||
30 | //config:config FEATURE_GREP_EGREP_ALIAS | ||
31 | //config: bool "Enable extended regular expressions (egrep & grep -E)" | ||
32 | //config: default y | ||
33 | //config: depends on GREP | ||
34 | //config: help | ||
35 | //config: Enabled support for extended regular expressions. Extended | ||
36 | //config: regular expressions allow for alternation (foo|bar), grouping, | ||
37 | //config: and various repetition operators. | ||
38 | //config: | ||
39 | //config:config FEATURE_GREP_FGREP_ALIAS | ||
40 | //config: bool "Alias fgrep to grep -F" | ||
41 | //config: default y | ||
42 | //config: depends on GREP | ||
43 | //config: help | ||
44 | //config: fgrep sees the search pattern as a normal string rather than | ||
45 | //config: regular expressions. | ||
46 | //config: grep -F always works, this just creates the fgrep alias. | ||
47 | //config: | ||
48 | //config:config FEATURE_GREP_CONTEXT | ||
49 | //config: bool "Enable before and after context flags (-A, -B and -C)" | ||
50 | //config: default y | ||
51 | //config: depends on GREP | ||
52 | //config: help | ||
53 | //config: Print the specified number of leading (-B) and/or trailing (-A) | ||
54 | //config: context surrounding our matching lines. | ||
55 | //config: Print the specified number of context lines (-C). | ||
56 | |||
22 | #include "libbb.h" | 57 | #include "libbb.h" |
23 | #include "xregex.h" | 58 | #include "xregex.h" |
24 | 59 | ||
25 | /* options */ | 60 | /* options */ |
26 | #define OPTSTR_GREP \ | 61 | #define OPTSTR_GREP \ |
27 | "lnqvscFiHhe:f:Lorm:" \ | 62 | "lnqvscFiHhe:f:Lorm:w" \ |
28 | IF_FEATURE_GREP_CONTEXT("A:B:C:") \ | 63 | IF_FEATURE_GREP_CONTEXT("A:B:C:") \ |
29 | IF_FEATURE_GREP_EGREP_ALIAS("E") \ | 64 | IF_FEATURE_GREP_EGREP_ALIAS("E") \ |
30 | IF_DESKTOP("w") \ | ||
31 | IF_EXTRA_COMPAT("z") \ | 65 | IF_EXTRA_COMPAT("z") \ |
32 | "aI" | 66 | "aI" |
33 | 67 | ||
@@ -51,11 +85,11 @@ enum { | |||
51 | OPTBIT_o, /* show only matching parts of lines */ | 85 | OPTBIT_o, /* show only matching parts of lines */ |
52 | OPTBIT_r, /* recurse dirs */ | 86 | OPTBIT_r, /* recurse dirs */ |
53 | OPTBIT_m, /* -m MAX_MATCHES */ | 87 | OPTBIT_m, /* -m MAX_MATCHES */ |
88 | OPTBIT_w, /* -w whole word match */ | ||
54 | IF_FEATURE_GREP_CONTEXT( OPTBIT_A ,) /* -A NUM: after-match context */ | 89 | IF_FEATURE_GREP_CONTEXT( OPTBIT_A ,) /* -A NUM: after-match context */ |
55 | IF_FEATURE_GREP_CONTEXT( OPTBIT_B ,) /* -B NUM: before-match context */ | 90 | IF_FEATURE_GREP_CONTEXT( OPTBIT_B ,) /* -B NUM: before-match context */ |
56 | IF_FEATURE_GREP_CONTEXT( OPTBIT_C ,) /* -C NUM: -A and -B combined */ | 91 | IF_FEATURE_GREP_CONTEXT( OPTBIT_C ,) /* -C NUM: -A and -B combined */ |
57 | IF_FEATURE_GREP_EGREP_ALIAS(OPTBIT_E ,) /* extended regexp */ | 92 | IF_FEATURE_GREP_EGREP_ALIAS(OPTBIT_E ,) /* extended regexp */ |
58 | IF_DESKTOP( OPTBIT_w ,) /* whole word match */ | ||
59 | IF_EXTRA_COMPAT( OPTBIT_z ,) /* input is NUL terminated */ | 93 | IF_EXTRA_COMPAT( OPTBIT_z ,) /* input is NUL terminated */ |
60 | OPT_l = 1 << OPTBIT_l, | 94 | OPT_l = 1 << OPTBIT_l, |
61 | OPT_n = 1 << OPTBIT_n, | 95 | OPT_n = 1 << OPTBIT_n, |
@@ -73,11 +107,11 @@ enum { | |||
73 | OPT_o = 1 << OPTBIT_o, | 107 | OPT_o = 1 << OPTBIT_o, |
74 | OPT_r = 1 << OPTBIT_r, | 108 | OPT_r = 1 << OPTBIT_r, |
75 | OPT_m = 1 << OPTBIT_m, | 109 | OPT_m = 1 << OPTBIT_m, |
110 | OPT_w = 1 << OPTBIT_w, | ||
76 | OPT_A = IF_FEATURE_GREP_CONTEXT( (1 << OPTBIT_A)) + 0, | 111 | OPT_A = IF_FEATURE_GREP_CONTEXT( (1 << OPTBIT_A)) + 0, |
77 | OPT_B = IF_FEATURE_GREP_CONTEXT( (1 << OPTBIT_B)) + 0, | 112 | OPT_B = IF_FEATURE_GREP_CONTEXT( (1 << OPTBIT_B)) + 0, |
78 | OPT_C = IF_FEATURE_GREP_CONTEXT( (1 << OPTBIT_C)) + 0, | 113 | OPT_C = IF_FEATURE_GREP_CONTEXT( (1 << OPTBIT_C)) + 0, |
79 | OPT_E = IF_FEATURE_GREP_EGREP_ALIAS((1 << OPTBIT_E)) + 0, | 114 | OPT_E = IF_FEATURE_GREP_EGREP_ALIAS((1 << OPTBIT_E)) + 0, |
80 | OPT_w = IF_DESKTOP( (1 << OPTBIT_w)) + 0, | ||
81 | OPT_z = IF_EXTRA_COMPAT( (1 << OPTBIT_z)) + 0, | 115 | OPT_z = IF_EXTRA_COMPAT( (1 << OPTBIT_z)) + 0, |
82 | }; | 116 | }; |
83 | 117 | ||
@@ -263,7 +297,10 @@ static int grep_file(FILE *file) | |||
263 | while (pattern_ptr) { | 297 | while (pattern_ptr) { |
264 | gl = (grep_list_data_t *)pattern_ptr->data; | 298 | gl = (grep_list_data_t *)pattern_ptr->data; |
265 | if (FGREP_FLAG) { | 299 | if (FGREP_FLAG) { |
266 | found |= (strstr(line, gl->pattern) != NULL); | 300 | found |= (((option_mask32 & OPT_i) |
301 | ? strcasestr(line, gl->pattern) | ||
302 | : strstr(line, gl->pattern) | ||
303 | ) != NULL); | ||
267 | } else { | 304 | } else { |
268 | if (!(gl->flg_mem_alocated_compiled & COMPILED)) { | 305 | if (!(gl->flg_mem_alocated_compiled & COMPILED)) { |
269 | gl->flg_mem_alocated_compiled |= COMPILED; | 306 | gl->flg_mem_alocated_compiled |= COMPILED; |
diff --git a/findutils/xargs.c b/findutils/xargs.c index 3785f1ec0..c55ac5724 100644 --- a/findutils/xargs.c +++ b/findutils/xargs.c | |||
@@ -17,6 +17,47 @@ | |||
17 | * | 17 | * |
18 | */ | 18 | */ |
19 | 19 | ||
20 | //kbuild:lib-$(CONFIG_XARGS) += xargs.o | ||
21 | //config: | ||
22 | //config:config XARGS | ||
23 | //config: bool "xargs" | ||
24 | //config: default n | ||
25 | //config: help | ||
26 | //config: xargs is used to execute a specified command for | ||
27 | //config: every item from standard input. | ||
28 | //config: | ||
29 | //config:config FEATURE_XARGS_SUPPORT_CONFIRMATION | ||
30 | //config: bool "Enable -p: prompt and confirmation" | ||
31 | //config: default n | ||
32 | //config: depends on XARGS | ||
33 | //config: help | ||
34 | //config: Support -p: prompt the user whether to run each command | ||
35 | //config: line and read a line from the terminal. | ||
36 | //config: | ||
37 | //config:config FEATURE_XARGS_SUPPORT_QUOTES | ||
38 | //config: bool "Enable single and double quotes and backslash" | ||
39 | //config: default n | ||
40 | //config: depends on XARGS | ||
41 | //config: help | ||
42 | //config: Support quoting in the input. | ||
43 | //config: | ||
44 | //config:config FEATURE_XARGS_SUPPORT_TERMOPT | ||
45 | //config: bool "Enable -x: exit if -s or -n is exceeded" | ||
46 | //config: default n | ||
47 | //config: depends on XARGS | ||
48 | //config: help | ||
49 | //config: Support -x: exit if the command size (see the -s or -n option) | ||
50 | //config: is exceeded. | ||
51 | //config: | ||
52 | //config:config FEATURE_XARGS_SUPPORT_ZERO_TERM | ||
53 | //config: bool "Enable -0: NUL-terminated input" | ||
54 | //config: default n | ||
55 | //config: depends on XARGS | ||
56 | //config: help | ||
57 | //config: Support -0: input items are terminated by a NUL character | ||
58 | //config: instead of whitespace, and the quotes and backslash | ||
59 | //config: are not special. | ||
60 | |||
20 | #include "libbb.h" | 61 | #include "libbb.h" |
21 | 62 | ||
22 | /* This is a NOEXEC applet. Be very careful! */ | 63 | /* This is a NOEXEC applet. Be very careful! */ |
diff --git a/include/applets.h b/include/applets.h index 83c1792ac..36b24856a 100644 --- a/include/applets.h +++ b/include/applets.h | |||
@@ -83,6 +83,7 @@ IF_BBCONFIG(APPLET(bbconfig, _BB_DIR_BIN, _BB_SUID_DROP)) | |||
83 | //IF_BBSH(APPLET(bbsh, _BB_DIR_BIN, _BB_SUID_DROP)) | 83 | //IF_BBSH(APPLET(bbsh, _BB_DIR_BIN, _BB_SUID_DROP)) |
84 | IF_BEEP(APPLET(beep, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 84 | IF_BEEP(APPLET(beep, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
85 | IF_BLKID(APPLET(blkid, _BB_DIR_SBIN, _BB_SUID_DROP)) | 85 | IF_BLKID(APPLET(blkid, _BB_DIR_SBIN, _BB_SUID_DROP)) |
86 | IF_BOOTCHARTD(APPLET(bootchartd, _BB_DIR_SBIN, _BB_SUID_DROP)) | ||
86 | IF_BRCTL(APPLET(brctl, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) | 87 | IF_BRCTL(APPLET(brctl, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) |
87 | IF_BUNZIP2(APPLET(bunzip2, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 88 | IF_BUNZIP2(APPLET(bunzip2, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
88 | IF_BUNZIP2(APPLET_ODDNAME(bzcat, bunzip2, _BB_DIR_USR_BIN, _BB_SUID_DROP, bzcat)) | 89 | IF_BUNZIP2(APPLET_ODDNAME(bzcat, bunzip2, _BB_DIR_USR_BIN, _BB_SUID_DROP, bzcat)) |
@@ -247,8 +248,8 @@ IF_LS(APPLET_NOEXEC(ls, ls, _BB_DIR_BIN, _BB_SUID_DROP, ls)) | |||
247 | IF_LSATTR(APPLET(lsattr, _BB_DIR_BIN, _BB_SUID_DROP)) | 248 | IF_LSATTR(APPLET(lsattr, _BB_DIR_BIN, _BB_SUID_DROP)) |
248 | IF_LSMOD(APPLET(lsmod, _BB_DIR_SBIN, _BB_SUID_DROP)) | 249 | IF_LSMOD(APPLET(lsmod, _BB_DIR_SBIN, _BB_SUID_DROP)) |
249 | IF_MODPROBE_SMALL(APPLET_ODDNAME(lsmod, modprobe, _BB_DIR_SBIN, _BB_SUID_DROP, modprobe)) | 250 | IF_MODPROBE_SMALL(APPLET_ODDNAME(lsmod, modprobe, _BB_DIR_SBIN, _BB_SUID_DROP, modprobe)) |
250 | IF_LSPCI(APPLET(lspci, _BB_DIR_SBIN, _BB_SUID_DROP)) | 251 | IF_LSPCI(APPLET(lspci, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
251 | IF_LSUSB(APPLET(lsusb, _BB_DIR_SBIN, _BB_SUID_DROP)) | 252 | IF_LSUSB(APPLET(lsusb, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
252 | IF_UNLZMA(APPLET_ODDNAME(lzmacat, unlzma, _BB_DIR_USR_BIN, _BB_SUID_DROP, lzmacat)) | 253 | IF_UNLZMA(APPLET_ODDNAME(lzmacat, unlzma, _BB_DIR_USR_BIN, _BB_SUID_DROP, lzmacat)) |
253 | IF_LZOP(APPLET(lzop, _BB_DIR_BIN, _BB_SUID_DROP)) | 254 | IF_LZOP(APPLET(lzop, _BB_DIR_BIN, _BB_SUID_DROP)) |
254 | IF_LZOP(APPLET_ODDNAME(lzopcat, lzop, _BB_DIR_USR_BIN, _BB_SUID_DROP, lzopcat)) | 255 | IF_LZOP(APPLET_ODDNAME(lzopcat, lzop, _BB_DIR_USR_BIN, _BB_SUID_DROP, lzopcat)) |
@@ -321,6 +322,7 @@ IF_RENICE(APPLET(renice, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | |||
321 | IF_RESET(APPLET(reset, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 322 | IF_RESET(APPLET(reset, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
322 | IF_RESIZE(APPLET(resize, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 323 | IF_RESIZE(APPLET(resize, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
323 | IF_RESTORECON(APPLET_ODDNAME(restorecon, setfiles, _BB_DIR_SBIN, _BB_SUID_DROP, restorecon)) | 324 | IF_RESTORECON(APPLET_ODDNAME(restorecon, setfiles, _BB_DIR_SBIN, _BB_SUID_DROP, restorecon)) |
325 | IF_RFKILL(APPLET(rfkill, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) | ||
324 | IF_RM(APPLET_NOFORK(rm, rm, _BB_DIR_BIN, _BB_SUID_DROP, rm)) | 326 | IF_RM(APPLET_NOFORK(rm, rm, _BB_DIR_BIN, _BB_SUID_DROP, rm)) |
325 | IF_RMDIR(APPLET_NOFORK(rmdir, rmdir, _BB_DIR_BIN, _BB_SUID_DROP, rmdir)) | 327 | IF_RMDIR(APPLET_NOFORK(rmdir, rmdir, _BB_DIR_BIN, _BB_SUID_DROP, rmdir)) |
326 | IF_RMMOD(APPLET(rmmod, _BB_DIR_SBIN, _BB_SUID_DROP)) | 328 | IF_RMMOD(APPLET(rmmod, _BB_DIR_SBIN, _BB_SUID_DROP)) |
@@ -403,7 +405,7 @@ IF_TRUE(APPLET_NOFORK(true, true, _BB_DIR_BIN, _BB_SUID_DROP, true)) | |||
403 | IF_TTY(APPLET(tty, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 405 | IF_TTY(APPLET(tty, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
404 | IF_TTYSIZE(APPLET(ttysize, _BB_DIR_USR_BIN, _BB_SUID_DROP)) | 406 | IF_TTYSIZE(APPLET(ttysize, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
405 | IF_TUNCTL(APPLET(tunctl, _BB_DIR_SBIN, _BB_SUID_DROP)) | 407 | IF_TUNCTL(APPLET(tunctl, _BB_DIR_SBIN, _BB_SUID_DROP)) |
406 | IF_MKFS_EXT2(APPLET(tune2fs, _BB_DIR_SBIN, _BB_SUID_DROP)) | 408 | IF_TUNE2FS(APPLET(tune2fs, _BB_DIR_SBIN, _BB_SUID_DROP)) |
407 | IF_UDHCPC(APPLET(udhcpc, _BB_DIR_SBIN, _BB_SUID_DROP)) | 409 | IF_UDHCPC(APPLET(udhcpc, _BB_DIR_SBIN, _BB_SUID_DROP)) |
408 | IF_UDHCPD(APPLET(udhcpd, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) | 410 | IF_UDHCPD(APPLET(udhcpd, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) |
409 | IF_UDPSVD(APPLET_ODDNAME(udpsvd, tcpudpsvd, _BB_DIR_USR_BIN, _BB_SUID_DROP, udpsvd)) | 411 | IF_UDPSVD(APPLET_ODDNAME(udpsvd, tcpudpsvd, _BB_DIR_USR_BIN, _BB_SUID_DROP, udpsvd)) |
diff --git a/include/libbb.h b/include/libbb.h index 11d7f27d3..58a5968c5 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -664,6 +664,15 @@ extern char *xmalloc_reads(int fd, char *pfx, size_t *maxsz_p) FAST_FUNC; | |||
664 | extern void *xmalloc_read(int fd, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC; | 664 | extern void *xmalloc_read(int fd, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC; |
665 | /* Returns NULL if file can't be opened (default max size: INT_MAX - 4095) */ | 665 | /* Returns NULL if file can't be opened (default max size: INT_MAX - 4095) */ |
666 | extern void *xmalloc_open_read_close(const char *filename, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC; | 666 | extern void *xmalloc_open_read_close(const char *filename, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC; |
667 | /* Autodetects gzip/bzip2 formats. fd may be in the middle of the file! */ | ||
668 | #if ENABLE_FEATURE_SEAMLESS_LZMA \ | ||
669 | || ENABLE_FEATURE_SEAMLESS_BZ2 \ | ||
670 | || ENABLE_FEATURE_SEAMLESS_GZ \ | ||
671 | /* || ENABLE_FEATURE_SEAMLESS_Z */ | ||
672 | extern int setup_unzip_on_fd(int fd /*, int fail_if_not_detected*/) FAST_FUNC; | ||
673 | #else | ||
674 | # define setup_unzip_on_fd(...) ((void)0) | ||
675 | #endif | ||
667 | /* Autodetects .gz etc */ | 676 | /* Autodetects .gz etc */ |
668 | extern int open_zipped(const char *fname) FAST_FUNC; | 677 | extern int open_zipped(const char *fname) FAST_FUNC; |
669 | extern void *xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC; | 678 | extern void *xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC; |
diff --git a/include/unicode.h b/include/unicode.h index 4e2927297..eaf67c833 100644 --- a/include/unicode.h +++ b/include/unicode.h | |||
@@ -30,12 +30,21 @@ enum { | |||
30 | #else | 30 | #else |
31 | 31 | ||
32 | # if CONFIG_LAST_SUPPORTED_WCHAR < 126 || CONFIG_LAST_SUPPORTED_WCHAR >= 0x30000 | 32 | # if CONFIG_LAST_SUPPORTED_WCHAR < 126 || CONFIG_LAST_SUPPORTED_WCHAR >= 0x30000 |
33 | # define LAST_SUPPORTED_WCHAR 0x2ffff | 33 | # undef CONFIG_LAST_SUPPORTED_WCHAR |
34 | # else | 34 | # define CONFIG_LAST_SUPPORTED_WCHAR 0x2ffff |
35 | # define LAST_SUPPORTED_WCHAR CONFIG_LAST_SUPPORTED_WCHAR | 35 | # endif |
36 | |||
37 | # if CONFIG_LAST_SUPPORTED_WCHAR < 0x300 | ||
38 | # undef ENABLE_UNICODE_COMBINING_WCHARS | ||
39 | # define ENABLE_UNICODE_COMBINING_WCHARS 0 | ||
40 | # endif | ||
41 | |||
42 | # if CONFIG_LAST_SUPPORTED_WCHAR < 0x1100 | ||
43 | # undef ENABLE_UNICODE_WIDE_WCHARS | ||
44 | # define ENABLE_UNICODE_WIDE_WCHARS 0 | ||
36 | # endif | 45 | # endif |
37 | 46 | ||
38 | # if LAST_SUPPORTED_WCHAR < 0x590 | 47 | # if CONFIG_LAST_SUPPORTED_WCHAR < 0x590 |
39 | # undef ENABLE_UNICODE_BIDI_SUPPORT | 48 | # undef ENABLE_UNICODE_BIDI_SUPPORT |
40 | # define ENABLE_UNICODE_BIDI_SUPPORT 0 | 49 | # define ENABLE_UNICODE_BIDI_SUPPORT 0 |
41 | # endif | 50 | # endif |
@@ -92,6 +101,7 @@ size_t wcrtomb(char *s, wchar_t wc, mbstate_t *ps) FAST_FUNC; | |||
92 | int iswspace(wint_t wc) FAST_FUNC; | 101 | int iswspace(wint_t wc) FAST_FUNC; |
93 | int iswalnum(wint_t wc) FAST_FUNC; | 102 | int iswalnum(wint_t wc) FAST_FUNC; |
94 | int iswpunct(wint_t wc) FAST_FUNC; | 103 | int iswpunct(wint_t wc) FAST_FUNC; |
104 | int wcwidth(unsigned ucs) FAST_FUNC; | ||
95 | # if ENABLE_UNICODE_BIDI_SUPPORT | 105 | # if ENABLE_UNICODE_BIDI_SUPPORT |
96 | # undef unicode_bidi_isrtl | 106 | # undef unicode_bidi_isrtl |
97 | int unicode_bidi_isrtl(wint_t wc) FAST_FUNC; | 107 | int unicode_bidi_isrtl(wint_t wc) FAST_FUNC; |
diff --git a/include/usage.h b/include/usage.h index 4568fac9f..3fce939bb 100644 --- a/include/usage.h +++ b/include/usage.h | |||
@@ -154,18 +154,15 @@ | |||
154 | "\n -r Repetitions" \ | 154 | "\n -r Repetitions" \ |
155 | "\n -n Start new tone" \ | 155 | "\n -n Start new tone" \ |
156 | 156 | ||
157 | #define fbsplash_trivial_usage \ | 157 | #define bootchartd_trivial_usage \ |
158 | "-s IMGFILE [-c] [-d DEV] [-i INIFILE] [-f CMD]" | 158 | "start [PROG ARGS]|stop|init" |
159 | #define fbsplash_full_usage "\n\n" \ | 159 | #define bootchartd_full_usage "\n\n" \ |
160 | "Options:" \ | 160 | "Create /var/log/bootchart.tgz with boot chart data\n" \ |
161 | "\n -s Image" \ | 161 | "\nOptions:" \ |
162 | "\n -c Hide cursor" \ | 162 | "\nstart: start background logging; with PROG, run PROG, then kill logging with USR1" \ |
163 | "\n -d Framebuffer device (default /dev/fb0)" \ | 163 | "\nstop: send USR1 to all bootchartd processes" \ |
164 | "\n -i Config file (var=value):" \ | 164 | "\ninit: start background logging; stop when getty/xdm is seen (for init scripts)" \ |
165 | "\n BAR_LEFT,BAR_TOP,BAR_WIDTH,BAR_HEIGHT" \ | 165 | "\nUnder PID 1: as init, then exec $bootchart_init, /init, /sbin/init" \ |
166 | "\n BAR_R,BAR_G,BAR_B" \ | ||
167 | "\n -f Control pipe (else exit after drawing image)" \ | ||
168 | "\n commands: 'NN' (% for progress bar) or 'exit'" \ | ||
169 | 166 | ||
170 | #define brctl_trivial_usage \ | 167 | #define brctl_trivial_usage \ |
171 | "COMMAND [BRIDGE [INTERFACE]]" | 168 | "COMMAND [BRIDGE [INTERFACE]]" |
@@ -504,9 +501,9 @@ | |||
504 | "Clear screen" | 501 | "Clear screen" |
505 | 502 | ||
506 | #define cmp_trivial_usage \ | 503 | #define cmp_trivial_usage \ |
507 | "[-l] [-s] FILE1 [FILE2" IF_DESKTOP(" [SKIP1 [SKIP2]") "]]" | 504 | "[-l] [-s] FILE1 [FILE2" IF_DESKTOP(" [SKIP1 [SKIP2]]") "]" |
508 | #define cmp_full_usage "\n\n" \ | 505 | #define cmp_full_usage "\n\n" \ |
509 | "Compares FILE1 vs stdin if FILE2 is not specified\n" \ | 506 | "Compare FILE1 with FILE2 (or stdin)\n" \ |
510 | "\nOptions:" \ | 507 | "\nOptions:" \ |
511 | "\n -l Write the byte numbers (decimal) and values (octal)" \ | 508 | "\n -l Write the byte numbers (decimal) and values (octal)" \ |
512 | "\n for all differing bytes" \ | 509 | "\n for all differing bytes" \ |
@@ -515,7 +512,7 @@ | |||
515 | #define comm_trivial_usage \ | 512 | #define comm_trivial_usage \ |
516 | "[-123] FILE1 FILE2" | 513 | "[-123] FILE1 FILE2" |
517 | #define comm_full_usage "\n\n" \ | 514 | #define comm_full_usage "\n\n" \ |
518 | "Compare FILE1 to FILE2, or to stdin if - is specified\n" \ | 515 | "Compare FILE1 with FILE2\n" \ |
519 | "\nOptions:" \ | 516 | "\nOptions:" \ |
520 | "\n -1 Suppress lines unique to FILE1" \ | 517 | "\n -1 Suppress lines unique to FILE1" \ |
521 | "\n -2 Suppress lines unique to FILE2" \ | 518 | "\n -2 Suppress lines unique to FILE2" \ |
@@ -652,8 +649,16 @@ | |||
652 | "\n -S SALT" \ | 649 | "\n -S SALT" \ |
653 | ) \ | 650 | ) \ |
654 | 651 | ||
655 | #define cttyhack_trivial_usage NOUSAGE_STR | 652 | #define cttyhack_trivial_usage \ |
656 | #define cttyhack_full_usage "" | 653 | "PROG ARGS" |
654 | #define cttyhack_full_usage "\n\n" \ | ||
655 | "Give PROG a controlling tty if possible." \ | ||
656 | "\nExample for /etc/inittab (for busybox init):" \ | ||
657 | "\n ::respawn:/bin/cttyhack /bin/sh" \ | ||
658 | "\nGiving controlling tty to shell running with PID 1:" \ | ||
659 | "\n $ exec cttyhack sh" \ | ||
660 | "\nStarting interactive shell from boot shell script:" \ | ||
661 | "\n setsid cttyhack sh" \ | ||
657 | 662 | ||
658 | #define cut_trivial_usage \ | 663 | #define cut_trivial_usage \ |
659 | "[OPTIONS] [FILE]..." | 664 | "[OPTIONS] [FILE]..." |
@@ -1174,6 +1179,19 @@ | |||
1174 | "$ echo $?\n" \ | 1179 | "$ echo $?\n" \ |
1175 | "1\n" | 1180 | "1\n" |
1176 | 1181 | ||
1182 | #define fbsplash_trivial_usage \ | ||
1183 | "-s IMGFILE [-c] [-d DEV] [-i INIFILE] [-f CMD]" | ||
1184 | #define fbsplash_full_usage "\n\n" \ | ||
1185 | "Options:" \ | ||
1186 | "\n -s Image" \ | ||
1187 | "\n -c Hide cursor" \ | ||
1188 | "\n -d Framebuffer device (default /dev/fb0)" \ | ||
1189 | "\n -i Config file (var=value):" \ | ||
1190 | "\n BAR_LEFT,BAR_TOP,BAR_WIDTH,BAR_HEIGHT" \ | ||
1191 | "\n BAR_R,BAR_G,BAR_B" \ | ||
1192 | "\n -f Control pipe (else exit after drawing image)" \ | ||
1193 | "\n commands: 'NN' (% for progress bar) or 'exit'" \ | ||
1194 | |||
1177 | #define fbset_trivial_usage \ | 1195 | #define fbset_trivial_usage \ |
1178 | "[OPTIONS] [MODE]" | 1196 | "[OPTIONS] [MODE]" |
1179 | #define fbset_full_usage "\n\n" \ | 1197 | #define fbset_full_usage "\n\n" \ |
@@ -1531,8 +1549,7 @@ | |||
1531 | "\n -H HOST Log HOST into the utmp file as the hostname" \ | 1549 | "\n -H HOST Log HOST into the utmp file as the hostname" \ |
1532 | 1550 | ||
1533 | #define grep_trivial_usage \ | 1551 | #define grep_trivial_usage \ |
1534 | "[-HhnlLoqvsri" \ | 1552 | "[-HhnlLoqvsriw" \ |
1535 | IF_DESKTOP("w") \ | ||
1536 | "F" \ | 1553 | "F" \ |
1537 | IF_FEATURE_GREP_EGREP_ALIAS("E") \ | 1554 | IF_FEATURE_GREP_EGREP_ALIAS("E") \ |
1538 | IF_EXTRA_COMPAT("z") \ | 1555 | IF_EXTRA_COMPAT("z") \ |
@@ -1554,9 +1571,7 @@ | |||
1554 | "\n -s Suppress open and read errors" \ | 1571 | "\n -s Suppress open and read errors" \ |
1555 | "\n -r Recurse" \ | 1572 | "\n -r Recurse" \ |
1556 | "\n -i Ignore case" \ | 1573 | "\n -i Ignore case" \ |
1557 | IF_DESKTOP( \ | ||
1558 | "\n -w Match whole words only" \ | 1574 | "\n -w Match whole words only" \ |
1559 | ) \ | ||
1560 | "\n -F PATTERN is a literal (not regexp)" \ | 1575 | "\n -F PATTERN is a literal (not regexp)" \ |
1561 | IF_FEATURE_GREP_EGREP_ALIAS( \ | 1576 | IF_FEATURE_GREP_EGREP_ALIAS( \ |
1562 | "\n -E PATTERN is an extended regexp" \ | 1577 | "\n -E PATTERN is an extended regexp" \ |
@@ -3741,6 +3756,18 @@ | |||
3741 | "\n for customizable files, or the user section," \ | 3756 | "\n for customizable files, or the user section," \ |
3742 | "\n if it has changed" \ | 3757 | "\n if it has changed" \ |
3743 | 3758 | ||
3759 | #define rfkill_trivial_usage \ | ||
3760 | "COMMAND [INDEX|TYPE]" | ||
3761 | #define rfkill_full_usage "\n\n" \ | ||
3762 | "Enable/disable wireless devices\n" \ | ||
3763 | "\nCommands:" \ | ||
3764 | "\n list [INDEX|TYPE] List current state" \ | ||
3765 | "\n block INDEX|TYPE Disable device" \ | ||
3766 | "\n unblock INDEX|TYPE Enable device" \ | ||
3767 | "\n" \ | ||
3768 | "\n TYPE: all, wlan(wifi), bluetooth, uwb(ultrawideband)," \ | ||
3769 | "\n wimax, wwan, gps, fm" \ | ||
3770 | |||
3744 | #define rm_trivial_usage \ | 3771 | #define rm_trivial_usage \ |
3745 | "[OPTIONS] FILE..." | 3772 | "[OPTIONS] FILE..." |
3746 | #define rm_full_usage "\n\n" \ | 3773 | #define rm_full_usage "\n\n" \ |
@@ -3791,13 +3818,13 @@ | |||
3791 | "\n -A inet" IF_FEATURE_IPV6("{6}") " Select address family" \ | 3818 | "\n -A inet" IF_FEATURE_IPV6("{6}") " Select address family" \ |
3792 | 3819 | ||
3793 | #define rpm_trivial_usage \ | 3820 | #define rpm_trivial_usage \ |
3794 | "-i -q[ildc]p PACKAGE.rpm" | 3821 | "-i PACKAGE.rpm; rpm -qp[ildc] PACKAGE.rpm" |
3795 | #define rpm_full_usage "\n\n" \ | 3822 | #define rpm_full_usage "\n\n" \ |
3796 | "Manipulate RPM packages\n" \ | 3823 | "Manipulate RPM packages\n" \ |
3797 | "\nOptions:" \ | 3824 | "\nCommands:" \ |
3798 | "\n -i Install package" \ | 3825 | "\n -i Install package" \ |
3799 | "\n -q Query package" \ | 3826 | "\n -qp Query package" \ |
3800 | "\n -p Query uninstalled package" \ | 3827 | "\nOptions:" \ |
3801 | "\n -i Show information" \ | 3828 | "\n -i Show information" \ |
3802 | "\n -l List contents" \ | 3829 | "\n -l List contents" \ |
3803 | "\n -d List documents" \ | 3830 | "\n -d List documents" \ |
diff --git a/init/Config.in b/init/Config.in index 3d99d4792..76d509207 100644 --- a/init/Config.in +++ b/init/Config.in | |||
@@ -120,4 +120,18 @@ config MESG | |||
120 | Mesg controls access to your terminal by others. It is typically | 120 | Mesg controls access to your terminal by others. It is typically |
121 | used to allow or disallow other users to write to your terminal | 121 | used to allow or disallow other users to write to your terminal |
122 | 122 | ||
123 | config BOOTCHARTD | ||
124 | bool "bootchartd" | ||
125 | default n | ||
126 | help | ||
127 | bootchartd is commonly used to profile the boot process | ||
128 | for the purpose of speeding it up. In this case, it is started | ||
129 | by the kernel as the init process. This is configured by adding | ||
130 | the init=/sbin/bootchartd option to the kernel command line. | ||
131 | |||
132 | It can also be used to monitor the resource usage of a specific | ||
133 | application or the running system in general. In this case, | ||
134 | bootchartd is started interactively by running bootchartd start | ||
135 | and stopped using bootchartd stop. | ||
136 | |||
123 | endmenu | 137 | endmenu |
diff --git a/init/Kbuild b/init/Kbuild index c060f3af4..ce3f30256 100644 --- a/init/Kbuild +++ b/init/Kbuild | |||
@@ -5,6 +5,7 @@ | |||
5 | # Licensed under the GPL v2, see the file LICENSE in this tarball. | 5 | # Licensed under the GPL v2, see the file LICENSE in this tarball. |
6 | 6 | ||
7 | lib-y:= | 7 | lib-y:= |
8 | lib-$(CONFIG_HALT) += halt.o | 8 | lib-$(CONFIG_HALT) += halt.o |
9 | lib-$(CONFIG_INIT) += init.o | 9 | lib-$(CONFIG_INIT) += init.o |
10 | lib-$(CONFIG_MESG) += mesg.o | 10 | lib-$(CONFIG_MESG) += mesg.o |
11 | lib-$(CONFIG_BOOTCHARTD) += bootchartd.o | ||
diff --git a/init/bootchartd.c b/init/bootchartd.c new file mode 100644 index 000000000..d1f9ed30e --- /dev/null +++ b/init/bootchartd.c | |||
@@ -0,0 +1,356 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. | ||
4 | */ | ||
5 | #include "libbb.h" | ||
6 | #include <sys/mount.h> | ||
7 | #ifndef MS_SILENT | ||
8 | # define MS_SILENT (1 << 15) | ||
9 | #endif | ||
10 | #ifndef MNT_DETACH | ||
11 | # define MNT_DETACH 0x00000002 | ||
12 | #endif | ||
13 | |||
14 | #define BC_VERSION_STR "0.8" | ||
15 | |||
16 | /* For debugging, set to 0: | ||
17 | * strace won't work with DO_SIGNAL_SYNC set to 1. | ||
18 | */ | ||
19 | #define DO_SIGNAL_SYNC 1 | ||
20 | |||
21 | |||
22 | //Not supported: $PWD/bootchartd.conf and /etc/bootchartd.conf | ||
23 | |||
24 | //# tmpfs size | ||
25 | //# (32 MB should suffice for ~20 minutes worth of log data, but YMMV) | ||
26 | //TMPFS_SIZE=32m | ||
27 | // | ||
28 | //# Sampling period (in seconds) | ||
29 | //SAMPLE_PERIOD=0.2 | ||
30 | // | ||
31 | //# Whether to enable and store BSD process accounting information. The | ||
32 | //# kernel needs to be configured to enable v3 accounting | ||
33 | //# (CONFIG_BSD_PROCESS_ACCT_V3). accton from the GNU accounting utilities | ||
34 | //# is also required. | ||
35 | //PROCESS_ACCOUNTING="no" | ||
36 | // | ||
37 | //# Tarball for the various boot log files | ||
38 | //BOOTLOG_DEST=/var/log/bootchart.tgz | ||
39 | // | ||
40 | //# Whether to automatically stop logging as the boot process completes. | ||
41 | //# The logger will look for known processes that indicate bootup completion | ||
42 | //# at a specific runlevel (e.g. gdm-binary, mingetty, etc.). | ||
43 | //AUTO_STOP_LOGGER="yes" | ||
44 | // | ||
45 | //# Whether to automatically generate the boot chart once the boot logger | ||
46 | //# completes. The boot chart will be generated in $AUTO_RENDER_DIR. | ||
47 | //# Note that the bootchart package must be installed. | ||
48 | //AUTO_RENDER="no" | ||
49 | // | ||
50 | //# Image format to use for the auto-generated boot chart | ||
51 | //# (choose between png, svg and eps). | ||
52 | //AUTO_RENDER_FORMAT="png" | ||
53 | // | ||
54 | //# Output directory for auto-generated boot charts | ||
55 | //AUTO_RENDER_DIR="/var/log" | ||
56 | |||
57 | |||
58 | /* Globals */ | ||
59 | struct globals { | ||
60 | char jiffy_line[COMMON_BUFSIZE]; | ||
61 | } FIX_ALIASING; | ||
62 | #define G (*(struct globals*)&bb_common_bufsiz1) | ||
63 | #define INIT_G() do { } while (0) | ||
64 | |||
65 | static void dump_file(FILE *fp, const char *filename) | ||
66 | { | ||
67 | int fd = open(filename, O_RDONLY); | ||
68 | if (fd >= 0) { | ||
69 | fputs(G.jiffy_line, fp); | ||
70 | fflush(fp); | ||
71 | bb_copyfd_eof(fd, fileno(fp)); | ||
72 | close(fd); | ||
73 | fputc('\n', fp); | ||
74 | } | ||
75 | } | ||
76 | |||
77 | static int dump_procs(FILE *fp, int look_for_login_process) | ||
78 | { | ||
79 | struct dirent *entry; | ||
80 | DIR *dir = opendir("/proc"); | ||
81 | int found_login_process = 0; | ||
82 | |||
83 | fputs(G.jiffy_line, fp); | ||
84 | while ((entry = readdir(dir)) != NULL) { | ||
85 | char name[sizeof("/proc/%u/cmdline") + sizeof(int)*3]; | ||
86 | int stat_fd; | ||
87 | unsigned pid = bb_strtou(entry->d_name, NULL, 10); | ||
88 | if (errno) | ||
89 | continue; | ||
90 | |||
91 | /* Android's version reads /proc/PID/cmdline and extracts | ||
92 | * non-truncated process name. Do we want to do that? */ | ||
93 | |||
94 | sprintf(name, "/proc/%u/stat", pid); | ||
95 | stat_fd = open(name, O_RDONLY); | ||
96 | if (stat_fd >= 0) { | ||
97 | char *p; | ||
98 | char stat_line[4*1024]; | ||
99 | int rd = safe_read(stat_fd, stat_line, sizeof(stat_line)-2); | ||
100 | |||
101 | close(stat_fd); | ||
102 | if (rd < 0) | ||
103 | continue; | ||
104 | stat_line[rd] = '\0'; | ||
105 | p = strchrnul(stat_line, '\n'); | ||
106 | *p++ = '\n'; | ||
107 | *p = '\0'; | ||
108 | fputs(stat_line, fp); | ||
109 | if (!look_for_login_process) | ||
110 | continue; | ||
111 | p = strchr(stat_line, '('); | ||
112 | if (!p) | ||
113 | continue; | ||
114 | p++; | ||
115 | strchrnul(p, ')')[0] = '\0'; | ||
116 | /* If is gdm, kdm or a getty? */ | ||
117 | if (((p[0] == 'g' || p[0] == 'k' || p[0] == 'x') && p[1] == 'd' && p[2] == 'm') | ||
118 | || strstr(p, "getty") | ||
119 | ) { | ||
120 | found_login_process = 1; | ||
121 | } | ||
122 | } | ||
123 | } | ||
124 | closedir(dir); | ||
125 | fputc('\n', fp); | ||
126 | return found_login_process; | ||
127 | } | ||
128 | |||
129 | static char *make_tempdir(const char *prog) | ||
130 | { | ||
131 | char template[] = "/tmp/bootchart.XXXXXX"; | ||
132 | char *tempdir = xstrdup(mkdtemp(template)); | ||
133 | if (!tempdir) { | ||
134 | /* /tmp is not writable (happens when we are used as init). | ||
135 | * Try to mount a tmpfs, them cd and lazily unmount it. | ||
136 | * Since we unmount it at once, we can mount it anywhere. | ||
137 | * Try a few locations which are likely ti exist. | ||
138 | */ | ||
139 | static const char dirs[] = "/mnt\0""/tmp\0""/boot\0""/proc\0"; | ||
140 | const char *try_dir = dirs; | ||
141 | while (mount("none", try_dir, "tmpfs", MS_SILENT, "size=16m") != 0) { | ||
142 | try_dir += strlen(try_dir) + 1; | ||
143 | if (!try_dir[0]) | ||
144 | bb_perror_msg_and_die("can't %smount tmpfs", ""); | ||
145 | } | ||
146 | //bb_error_msg("mounted tmpfs on %s", try_dir); | ||
147 | xchdir(try_dir); | ||
148 | if (umount2(try_dir, MNT_DETACH) != 0) { | ||
149 | bb_perror_msg_and_die("can't %smount tmpfs", "un"); | ||
150 | } | ||
151 | } else { | ||
152 | xchdir(tempdir); | ||
153 | } | ||
154 | { | ||
155 | FILE *header_fp = xfopen("header", "w"); | ||
156 | if (prog) | ||
157 | fprintf(header_fp, "profile.process = %s\n", prog); | ||
158 | fputs("version = "BC_VERSION_STR"\n", header_fp); | ||
159 | fclose(header_fp); | ||
160 | } | ||
161 | |||
162 | return tempdir; | ||
163 | } | ||
164 | |||
165 | static void do_logging(void) | ||
166 | { | ||
167 | //# Enable process accounting if configured | ||
168 | //if [ "$PROCESS_ACCOUNTING" = "yes" ]; then | ||
169 | // [ -e kernel_pacct ] || : > kernel_pacct | ||
170 | // accton kernel_pacct | ||
171 | //fi | ||
172 | |||
173 | FILE *proc_stat = xfopen("proc_stat.log", "w"); | ||
174 | FILE *proc_diskstats = xfopen("proc_diskstats.log", "w"); | ||
175 | //FILE *proc_netdev = xfopen("proc_netdev.log", "w"); | ||
176 | FILE *proc_ps = xfopen("proc_ps.log", "w"); | ||
177 | int look_for_login_process = (getppid() == 1); | ||
178 | unsigned count = 60*1000*1000 / (200*1000); /* ~1 minute */ | ||
179 | |||
180 | while (--count && !bb_got_signal) { | ||
181 | char *p; | ||
182 | int len = open_read_close("/proc/uptime", G.jiffy_line, sizeof(G.jiffy_line)-2); | ||
183 | if (len < 0) | ||
184 | goto wait_more; | ||
185 | /* /proc/uptime has format "NNNNNN.MM NNNNNNN.MM" */ | ||
186 | /* we convert it to "NNNNNNMM\n" (using first value) */ | ||
187 | G.jiffy_line[len] = '\0'; | ||
188 | p = strchr(G.jiffy_line, '.'); | ||
189 | if (!p) | ||
190 | goto wait_more; | ||
191 | while (isdigit(*++p)) | ||
192 | p[-1] = *p; | ||
193 | p[-1] = '\n'; | ||
194 | p[0] = '\0'; | ||
195 | |||
196 | dump_file(proc_stat, "/proc/stat"); | ||
197 | dump_file(proc_diskstats, "/proc/diskstats"); | ||
198 | //dump_file(proc_netdev, "/proc/net/dev"); | ||
199 | if (dump_procs(proc_ps, look_for_login_process)) { | ||
200 | /* dump_procs saw a getty or {g,k,x}dm | ||
201 | * stop logging in 2 seconds: | ||
202 | */ | ||
203 | if (count > 2*1000*1000 / (200*1000)) | ||
204 | count = 2*1000*1000 / (200*1000); | ||
205 | } | ||
206 | fflush_all(); | ||
207 | wait_more: | ||
208 | usleep(200*1000); | ||
209 | } | ||
210 | |||
211 | // [ -e kernel_pacct ] && accton off | ||
212 | } | ||
213 | |||
214 | static void finalize(char *tempdir) | ||
215 | { | ||
216 | //# Stop process accounting if configured | ||
217 | //local pacct= | ||
218 | //[ -e kernel_pacct ] && pacct=kernel_pacct | ||
219 | |||
220 | //( | ||
221 | // echo "version = $VERSION" | ||
222 | // echo "title = Boot chart for $( hostname | sed q ) ($( date ))" | ||
223 | // echo "system.uname = $( uname -srvm | sed q )" | ||
224 | // echo "system.release = $( sed q /etc/SuSE-release )" | ||
225 | // echo "system.cpu = $( grep '^model name' /proc/cpuinfo | sed q ) ($cpucount)" | ||
226 | // echo "system.kernel.options = $( sed q /proc/cmdline )" | ||
227 | //) >> header | ||
228 | |||
229 | /* Package log files */ | ||
230 | system("tar -zcf /var/log/bootchart.tgz header *.log"); // + $pacct | ||
231 | /* Clean up (if we are not in detached tmpfs) */ | ||
232 | if (tempdir) { | ||
233 | unlink("header"); | ||
234 | unlink("proc_stat.log"); | ||
235 | unlink("proc_diskstats.log"); | ||
236 | //unlink("proc_netdev.log"); | ||
237 | unlink("proc_ps.log"); | ||
238 | rmdir(tempdir); | ||
239 | } | ||
240 | |||
241 | /* shell-based bootchartd tries to run /usr/bin/bootchart if $AUTO_RENDER=yes: | ||
242 | * /usr/bin/bootchart -o "$AUTO_RENDER_DIR" -f $AUTO_RENDER_FORMAT "$BOOTLOG_DEST" | ||
243 | */ | ||
244 | } | ||
245 | |||
246 | /* Usage: | ||
247 | * bootchartd start [PROG ARGS]: start logging in background, USR1 stops it. | ||
248 | * With PROG, runs PROG, then kills background logging. | ||
249 | * bootchartd stop: same as "killall -USR1 bootchartd" | ||
250 | * bootchartd init: start logging in background | ||
251 | * Stop when getty/gdm is seen (if AUTO_STOP_LOGGER = yes). | ||
252 | * Meant to be used from init scripts. | ||
253 | * bootchartd (pid==1): as init, but then execs $bootchart_init, /init, /sbin/init | ||
254 | * Meant to be used as kernel's init process. | ||
255 | */ | ||
256 | int bootchartd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | ||
257 | int bootchartd_main(int argc UNUSED_PARAM, char **argv) | ||
258 | { | ||
259 | pid_t parent_pid, logger_pid; | ||
260 | smallint cmd; | ||
261 | enum { | ||
262 | CMD_STOP = 0, | ||
263 | CMD_START, | ||
264 | CMD_INIT, | ||
265 | CMD_PID1, /* used to mark pid 1 case */ | ||
266 | }; | ||
267 | |||
268 | INIT_G(); | ||
269 | |||
270 | parent_pid = getpid(); | ||
271 | if (argv[1]) { | ||
272 | cmd = index_in_strings("stop\0""start\0""init\0", argv[1]); | ||
273 | if (cmd < 0) | ||
274 | bb_show_usage(); | ||
275 | if (cmd == CMD_STOP) { | ||
276 | pid_t *pidList = find_pid_by_name("bootchartd"); | ||
277 | while (*pidList != 0) { | ||
278 | if (*pidList != parent_pid) | ||
279 | kill(*pidList, SIGUSR1); | ||
280 | pidList++; | ||
281 | } | ||
282 | return EXIT_SUCCESS; | ||
283 | } | ||
284 | } else { | ||
285 | if (parent_pid != 1) | ||
286 | bb_show_usage(); | ||
287 | cmd = CMD_PID1; | ||
288 | } | ||
289 | |||
290 | /* Here we are in START or INIT state. Create logger child: */ | ||
291 | logger_pid = fork_or_rexec(argv); | ||
292 | |||
293 | if (logger_pid == 0) { /* child */ | ||
294 | char *tempdir; | ||
295 | |||
296 | bb_signals(0 | ||
297 | + (1 << SIGUSR1) | ||
298 | + (1 << SIGUSR2) | ||
299 | + (1 << SIGTERM) | ||
300 | + (1 << SIGQUIT) | ||
301 | + (1 << SIGINT) | ||
302 | + (1 << SIGHUP) | ||
303 | , record_signo); | ||
304 | |||
305 | if (DO_SIGNAL_SYNC) | ||
306 | /* Inform parent that we are ready */ | ||
307 | raise(SIGSTOP); | ||
308 | |||
309 | /* If we are started by kernel, PATH might be unset. | ||
310 | * In order to find "tar", let's set some sane PATH: | ||
311 | */ | ||
312 | if (cmd == CMD_PID1 && !getenv("PATH")) | ||
313 | putenv((char*)bb_PATH_root_path); | ||
314 | |||
315 | tempdir = make_tempdir(cmd == CMD_START ? argv[2] : NULL); | ||
316 | do_logging(); | ||
317 | finalize(tempdir); | ||
318 | return EXIT_SUCCESS; | ||
319 | } | ||
320 | |||
321 | /* parent */ | ||
322 | |||
323 | if (DO_SIGNAL_SYNC) { | ||
324 | /* Wait for logger child to set handlers, then unpause it. | ||
325 | * Otherwise with short-lived PROG (e.g. "bootchartd start true") | ||
326 | * we might send SIGUSR1 before logger sets its handler. | ||
327 | */ | ||
328 | waitpid(logger_pid, NULL, WUNTRACED); | ||
329 | kill(logger_pid, SIGCONT); | ||
330 | } | ||
331 | |||
332 | if (cmd == CMD_PID1) { | ||
333 | char *bootchart_init = getenv("bootchart_init"); | ||
334 | if (bootchart_init) | ||
335 | execl(bootchart_init, bootchart_init, NULL); | ||
336 | execl("/init", "init", NULL); | ||
337 | execl("/sbin/init", "init", NULL); | ||
338 | bb_perror_msg_and_die("can't exec '%s'", "/sbin/init"); | ||
339 | } | ||
340 | |||
341 | if (cmd == CMD_START && argv[2]) { /* "start PROG ARGS" */ | ||
342 | pid_t pid = vfork(); | ||
343 | if (pid < 0) | ||
344 | bb_perror_msg_and_die("vfork"); | ||
345 | if (pid == 0) { /* child */ | ||
346 | argv += 2; | ||
347 | execvp(argv[0], argv); | ||
348 | bb_perror_msg_and_die("can't exec '%s'", argv[0]); | ||
349 | } | ||
350 | /* parent */ | ||
351 | waitpid(pid, NULL, 0); | ||
352 | kill(logger_pid, SIGUSR1); | ||
353 | } | ||
354 | |||
355 | return EXIT_SUCCESS; | ||
356 | } | ||
diff --git a/libbb/appletlib.c b/libbb/appletlib.c index f287e4522..f6dc1f171 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c | |||
@@ -105,7 +105,9 @@ static const char *unpack_usage_messages(void) | |||
105 | 105 | ||
106 | static void full_write2_str(const char *str) | 106 | static void full_write2_str(const char *str) |
107 | { | 107 | { |
108 | xwrite_str(STDERR_FILENO, str); | 108 | // This uses stdio: |
109 | //xwrite_str(STDERR_FILENO, str); | ||
110 | write(STDERR_FILENO, str, strlen(str)); | ||
109 | } | 111 | } |
110 | 112 | ||
111 | void FAST_FUNC bb_show_usage(void) | 113 | void FAST_FUNC bb_show_usage(void) |
@@ -593,6 +595,17 @@ static void check_suid(int applet_no) | |||
593 | 595 | ||
594 | 596 | ||
595 | #if ENABLE_FEATURE_INSTALLER | 597 | #if ENABLE_FEATURE_INSTALLER |
598 | static const char usr_bin [] ALIGN1 = "/usr/bin/"; | ||
599 | static const char usr_sbin[] ALIGN1 = "/usr/sbin/"; | ||
600 | static const char *const install_dir[] = { | ||
601 | &usr_bin [8], /* "/" */ | ||
602 | &usr_bin [4], /* "/bin/" */ | ||
603 | &usr_sbin[4], /* "/sbin/" */ | ||
604 | usr_bin, | ||
605 | usr_sbin | ||
606 | }; | ||
607 | |||
608 | |||
596 | /* create (sym)links for each applet */ | 609 | /* create (sym)links for each applet */ |
597 | static void install_links(const char *busybox, int use_symbolic_links, | 610 | static void install_links(const char *busybox, int use_symbolic_links, |
598 | char *custom_install_dir) | 611 | char *custom_install_dir) |
@@ -600,16 +613,6 @@ static void install_links(const char *busybox, int use_symbolic_links, | |||
600 | /* directory table | 613 | /* directory table |
601 | * this should be consistent w/ the enum, | 614 | * this should be consistent w/ the enum, |
602 | * busybox.h::bb_install_loc_t, or else... */ | 615 | * busybox.h::bb_install_loc_t, or else... */ |
603 | static const char usr_bin [] ALIGN1 = "/usr/bin"; | ||
604 | static const char usr_sbin[] ALIGN1 = "/usr/sbin"; | ||
605 | static const char *const install_dir[] = { | ||
606 | &usr_bin [8], /* "", equivalent to "/" for concat_path_file() */ | ||
607 | &usr_bin [4], /* "/bin" */ | ||
608 | &usr_sbin[4], /* "/sbin" */ | ||
609 | usr_bin, | ||
610 | usr_sbin | ||
611 | }; | ||
612 | |||
613 | int (*lf)(const char *, const char *); | 616 | int (*lf)(const char *, const char *); |
614 | char *fpc; | 617 | char *fpc; |
615 | unsigned i; | 618 | unsigned i; |
@@ -633,8 +636,8 @@ static void install_links(const char *busybox, int use_symbolic_links, | |||
633 | } | 636 | } |
634 | } | 637 | } |
635 | #else | 638 | #else |
636 | #define install_links(x,y,z) ((void)0) | 639 | # define install_links(x,y,z) ((void)0) |
637 | #endif /* FEATURE_INSTALLER */ | 640 | #endif |
638 | 641 | ||
639 | /* If we were called as "busybox..." */ | 642 | /* If we were called as "busybox..." */ |
640 | static int busybox_main(char **argv) | 643 | static int busybox_main(char **argv) |
@@ -655,19 +658,20 @@ static int busybox_main(char **argv) | |||
655 | full_write2_str(bb_banner); /* reuse const string */ | 658 | full_write2_str(bb_banner); /* reuse const string */ |
656 | full_write2_str(" multi-call binary.\n"); /* reuse */ | 659 | full_write2_str(" multi-call binary.\n"); /* reuse */ |
657 | full_write2_str( | 660 | full_write2_str( |
658 | "Copyright (C) 1998-2009 Erik Andersen, Rob Landley, Denys Vlasenko\n" | 661 | "Copyright (C) 1998-2009 Erik Andersen, Rob Landley, Denys Vlasenko\n" |
659 | "and others. Licensed under GPLv2.\n" | 662 | "and others. Licensed under GPLv2.\n" |
660 | "See source distribution for full notice.\n" | 663 | "See source distribution for full notice.\n" |
661 | "\n" | 664 | "\n" |
662 | "Usage: busybox [function] [arguments]...\n" | 665 | "Usage: busybox [function] [arguments]...\n" |
663 | " or: function [arguments]...\n" | 666 | " or: function [arguments]...\n" |
664 | "\n" | 667 | "\n" |
665 | "\tBusyBox is a multi-call binary that combines many common Unix\n" | 668 | "\tBusyBox is a multi-call binary that combines many common Unix\n" |
666 | "\tutilities into a single executable. Most people will create a\n" | 669 | "\tutilities into a single executable. Most people will create a\n" |
667 | "\tlink to busybox for each function they wish to use and BusyBox\n" | 670 | "\tlink to busybox for each function they wish to use and BusyBox\n" |
668 | "\twill act like whatever it was invoked as.\n" | 671 | "\twill act like whatever it was invoked as.\n" |
669 | "\n" | 672 | "\n" |
670 | "Currently defined functions:\n"); | 673 | "Currently defined functions:\n" |
674 | ); | ||
671 | col = 0; | 675 | col = 0; |
672 | a = applet_names; | 676 | a = applet_names; |
673 | /* prevent last comma to be in the very last pos */ | 677 | /* prevent last comma to be in the very last pos */ |
@@ -692,6 +696,23 @@ static int busybox_main(char **argv) | |||
692 | return 0; | 696 | return 0; |
693 | } | 697 | } |
694 | 698 | ||
699 | if (strncmp(argv[1], "--list", 6) == 0) { | ||
700 | unsigned i = 0; | ||
701 | const char *a = applet_names; | ||
702 | dup2(1, 2); | ||
703 | while (*a) { | ||
704 | #if ENABLE_FEATURE_INSTALLER | ||
705 | if (argv[1][6]) /* --list-path? */ | ||
706 | full_write2_str(install_dir[APPLET_INSTALL_LOC(i)] + 1); | ||
707 | #endif | ||
708 | full_write2_str(a); | ||
709 | full_write2_str("\n"); | ||
710 | i++; | ||
711 | a += strlen(a) + 1; | ||
712 | } | ||
713 | return 0; | ||
714 | } | ||
715 | |||
695 | if (ENABLE_FEATURE_INSTALLER && strcmp(argv[1], "--install") == 0) { | 716 | if (ENABLE_FEATURE_INSTALLER && strcmp(argv[1], "--install") == 0) { |
696 | int use_symbolic_links; | 717 | int use_symbolic_links; |
697 | const char *busybox; | 718 | const char *busybox; |
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 9a04c38bf..f7faf4639 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c | |||
@@ -42,14 +42,10 @@ | |||
42 | #include "libbb.h" | 42 | #include "libbb.h" |
43 | #include "unicode.h" | 43 | #include "unicode.h" |
44 | 44 | ||
45 | /* FIXME: obsolete CONFIG item? */ | ||
46 | #define ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT 0 | ||
47 | |||
48 | #ifdef TEST | 45 | #ifdef TEST |
49 | # define ENABLE_FEATURE_EDITING 0 | 46 | # define ENABLE_FEATURE_EDITING 0 |
50 | # define ENABLE_FEATURE_TAB_COMPLETION 0 | 47 | # define ENABLE_FEATURE_TAB_COMPLETION 0 |
51 | # define ENABLE_FEATURE_USERNAME_COMPLETION 0 | 48 | # define ENABLE_FEATURE_USERNAME_COMPLETION 0 |
52 | # define ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT 0 | ||
53 | #endif | 49 | #endif |
54 | 50 | ||
55 | 51 | ||
@@ -66,9 +62,13 @@ | |||
66 | #endif | 62 | #endif |
67 | 63 | ||
68 | 64 | ||
65 | #define SEQ_CLEAR_TILL_END_OF_SCREEN "\033[J" | ||
66 | //#define SEQ_CLEAR_TILL_END_OF_LINE "\033[K" | ||
67 | |||
68 | |||
69 | #undef CHAR_T | 69 | #undef CHAR_T |
70 | #if ENABLE_UNICODE_SUPPORT | 70 | #if ENABLE_UNICODE_SUPPORT |
71 | # define BB_NUL L'\0' | 71 | # define BB_NUL ((wchar_t)0) |
72 | # define CHAR_T wchar_t | 72 | # define CHAR_T wchar_t |
73 | static bool BB_isspace(CHAR_T c) { return ((unsigned)c < 256 && isspace(c)); } | 73 | static bool BB_isspace(CHAR_T c) { return ((unsigned)c < 256 && isspace(c)); } |
74 | # if ENABLE_FEATURE_EDITING_VI | 74 | # if ENABLE_FEATURE_EDITING_VI |
@@ -92,6 +92,14 @@ static bool BB_ispunct(CHAR_T c) { return ((unsigned)c < 256 && ispunct(c)); } | |||
92 | #endif | 92 | #endif |
93 | 93 | ||
94 | 94 | ||
95 | # if ENABLE_UNICODE_PRESERVE_BROKEN | ||
96 | # define unicode_mark_raw_byte(wc) ((wc) | 0x20000000) | ||
97 | # define unicode_is_raw_byte(wc) ((wc) & 0x20000000) | ||
98 | # else | ||
99 | # define unicode_is_raw_byte(wc) 0 | ||
100 | # endif | ||
101 | |||
102 | |||
95 | enum { | 103 | enum { |
96 | /* We use int16_t for positions, need to limit line len */ | 104 | /* We use int16_t for positions, need to limit line len */ |
97 | MAX_LINELEN = CONFIG_FEATURE_EDITING_MAX_LEN < 0x7ff0 | 105 | MAX_LINELEN = CONFIG_FEATURE_EDITING_MAX_LEN < 0x7ff0 |
@@ -208,42 +216,107 @@ static size_t load_string(const char *src, int maxsize) | |||
208 | ssize_t len = mbstowcs(command_ps, src, maxsize - 1); | 216 | ssize_t len = mbstowcs(command_ps, src, maxsize - 1); |
209 | if (len < 0) | 217 | if (len < 0) |
210 | len = 0; | 218 | len = 0; |
211 | command_ps[len] = L'\0'; | 219 | command_ps[len] = 0; |
212 | return len; | 220 | return len; |
213 | } | 221 | } |
214 | static size_t save_string(char *dst, int maxsize) | 222 | static unsigned save_string(char *dst, unsigned maxsize) |
215 | { | 223 | { |
224 | # if !ENABLE_UNICODE_PRESERVE_BROKEN | ||
216 | ssize_t len = wcstombs(dst, command_ps, maxsize - 1); | 225 | ssize_t len = wcstombs(dst, command_ps, maxsize - 1); |
217 | if (len < 0) | 226 | if (len < 0) |
218 | len = 0; | 227 | len = 0; |
219 | dst[len] = '\0'; | 228 | dst[len] = '\0'; |
220 | return len; | 229 | return len; |
230 | # else | ||
231 | unsigned dstpos = 0; | ||
232 | unsigned srcpos = 0; | ||
233 | |||
234 | maxsize--; | ||
235 | while (dstpos < maxsize) { | ||
236 | wchar_t wc; | ||
237 | int n = srcpos; | ||
238 | while ((wc = command_ps[srcpos]) != 0 | ||
239 | && !unicode_is_raw_byte(wc) | ||
240 | ) { | ||
241 | srcpos++; | ||
242 | } | ||
243 | command_ps[srcpos] = 0; | ||
244 | n = wcstombs(dst + dstpos, command_ps + n, maxsize - dstpos); | ||
245 | if (n < 0) /* should not happen */ | ||
246 | break; | ||
247 | dstpos += n; | ||
248 | if (wc == 0) /* usually is */ | ||
249 | break; | ||
250 | /* We do have invalid byte here! */ | ||
251 | command_ps[srcpos] = wc; /* restore it */ | ||
252 | srcpos++; | ||
253 | if (dstpos == maxsize) | ||
254 | break; | ||
255 | dst[dstpos++] = (char) wc; | ||
256 | } | ||
257 | dst[dstpos] = '\0'; | ||
258 | return dstpos; | ||
259 | # endif | ||
221 | } | 260 | } |
222 | /* I thought just fputwc(c, stdout) would work. But no... */ | 261 | /* I thought just fputwc(c, stdout) would work. But no... */ |
223 | static void BB_PUTCHAR(wchar_t c) | 262 | static void BB_PUTCHAR(wchar_t c) |
224 | { | 263 | { |
225 | char buf[MB_CUR_MAX + 1]; | 264 | char buf[MB_CUR_MAX + 1]; |
226 | mbstate_t mbst = { 0 }; | 265 | mbstate_t mbst = { 0 }; |
227 | ssize_t len = wcrtomb(buf, c, &mbst); | 266 | ssize_t len; |
228 | 267 | ||
268 | len = wcrtomb(buf, c, &mbst); | ||
229 | if (len > 0) { | 269 | if (len > 0) { |
230 | buf[len] = '\0'; | 270 | buf[len] = '\0'; |
231 | fputs(buf, stdout); | 271 | fputs(buf, stdout); |
232 | } | 272 | } |
233 | } | 273 | } |
234 | #else | 274 | # if ENABLE_UNICODE_COMBINING_WCHARS || ENABLE_UNICODE_WIDE_WCHARS |
275 | static wchar_t adjust_width_and_validate_wc(unsigned *width_adj, wchar_t wc) | ||
276 | # else | ||
277 | static wchar_t adjust_width_and_validate_wc(wchar_t wc) | ||
278 | # define adjust_width_and_validate_wc(width_adj, wc) \ | ||
279 | ((*(width_adj))++, adjust_width_and_validate_wc(wc)) | ||
280 | # endif | ||
281 | { | ||
282 | int w = 1; | ||
283 | |||
284 | if (unicode_status == UNICODE_ON) { | ||
285 | if (wc > CONFIG_LAST_SUPPORTED_WCHAR) { | ||
286 | /* note: also true for unicode_is_raw_byte(wc) */ | ||
287 | goto subst; | ||
288 | } | ||
289 | w = wcwidth(wc); | ||
290 | if ((ENABLE_UNICODE_COMBINING_WCHARS && w < 0) | ||
291 | || (!ENABLE_UNICODE_COMBINING_WCHARS && w <= 0) | ||
292 | || (!ENABLE_UNICODE_WIDE_WCHARS && w > 1) | ||
293 | ) { | ||
294 | subst: | ||
295 | w = 1; | ||
296 | wc = CONFIG_SUBST_WCHAR; | ||
297 | } | ||
298 | } | ||
299 | |||
300 | # if ENABLE_UNICODE_COMBINING_WCHARS || ENABLE_UNICODE_WIDE_WCHARS | ||
301 | *width_adj += w; | ||
302 | #endif | ||
303 | return wc; | ||
304 | } | ||
305 | #else /* !UNICODE */ | ||
235 | static size_t load_string(const char *src, int maxsize) | 306 | static size_t load_string(const char *src, int maxsize) |
236 | { | 307 | { |
237 | safe_strncpy(command_ps, src, maxsize); | 308 | safe_strncpy(command_ps, src, maxsize); |
238 | return strlen(command_ps); | 309 | return strlen(command_ps); |
239 | } | 310 | } |
240 | # if ENABLE_FEATURE_TAB_COMPLETION | 311 | # if ENABLE_FEATURE_TAB_COMPLETION |
241 | static void save_string(char *dst, int maxsize) | 312 | static void save_string(char *dst, unsigned maxsize) |
242 | { | 313 | { |
243 | safe_strncpy(dst, command_ps, maxsize); | 314 | safe_strncpy(dst, command_ps, maxsize); |
244 | } | 315 | } |
245 | # endif | 316 | # endif |
246 | # define BB_PUTCHAR(c) bb_putchar(c) | 317 | # define BB_PUTCHAR(c) bb_putchar(c) |
318 | /* Should never be called: */ | ||
319 | int adjust_width_and_validate_wc(unsigned *width_adj, int wc); | ||
247 | #endif | 320 | #endif |
248 | 321 | ||
249 | 322 | ||
@@ -251,38 +324,35 @@ static void save_string(char *dst, int maxsize) | |||
251 | * Advance cursor on screen. If we reached right margin, scroll text up | 324 | * Advance cursor on screen. If we reached right margin, scroll text up |
252 | * and remove terminal margin effect by printing 'next_char' */ | 325 | * and remove terminal margin effect by printing 'next_char' */ |
253 | #define HACK_FOR_WRONG_WIDTH 1 | 326 | #define HACK_FOR_WRONG_WIDTH 1 |
254 | #if HACK_FOR_WRONG_WIDTH | 327 | static void put_cur_glyph_and_inc_cursor(void) |
255 | static void cmdedit_set_out_char(void) | ||
256 | #define cmdedit_set_out_char(next_char) cmdedit_set_out_char() | ||
257 | #else | ||
258 | static void cmdedit_set_out_char(int next_char) | ||
259 | #endif | ||
260 | { | 328 | { |
261 | CHAR_T c = command_ps[cursor]; | 329 | CHAR_T c = command_ps[cursor]; |
330 | unsigned width = 0; | ||
331 | int ofs_to_right; | ||
262 | 332 | ||
263 | if (c == BB_NUL) { | 333 | if (c == BB_NUL) { |
264 | /* erase character after end of input string */ | 334 | /* erase character after end of input string */ |
265 | c = ' '; | 335 | c = ' '; |
336 | } else { | ||
337 | /* advance cursor only if we aren't at the end yet */ | ||
338 | cursor++; | ||
339 | if (unicode_status == UNICODE_ON) { | ||
340 | IF_UNICODE_WIDE_WCHARS(width = cmdedit_x;) | ||
341 | c = adjust_width_and_validate_wc(&cmdedit_x, c); | ||
342 | IF_UNICODE_WIDE_WCHARS(width = cmdedit_x - width;) | ||
343 | } else { | ||
344 | cmdedit_x++; | ||
345 | } | ||
266 | } | 346 | } |
267 | #if ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT | 347 | |
268 | /* Display non-printable characters in reverse */ | 348 | ofs_to_right = cmdedit_x - cmdedit_termw; |
269 | if (!BB_isprint(c)) { | 349 | if (!ENABLE_UNICODE_WIDE_WCHARS || ofs_to_right <= 0) { |
270 | if (c >= 128) | 350 | /* c fits on this line */ |
271 | c -= 128; | ||
272 | if (c < ' ') | ||
273 | c += '@'; | ||
274 | if (c == 127) | ||
275 | c = '?'; | ||
276 | printf("\033[7m%c\033[0m", c); | ||
277 | } else | ||
278 | #endif | ||
279 | { | ||
280 | BB_PUTCHAR(c); | 351 | BB_PUTCHAR(c); |
281 | } | 352 | } |
282 | if (++cmdedit_x >= cmdedit_termw) { | 353 | |
283 | /* terminal is scrolled down */ | 354 | if (ofs_to_right >= 0) { |
284 | cmdedit_y++; | 355 | /* we go to the next line */ |
285 | cmdedit_x = 0; | ||
286 | #if HACK_FOR_WRONG_WIDTH | 356 | #if HACK_FOR_WRONG_WIDTH |
287 | /* This works better if our idea of term width is wrong | 357 | /* This works better if our idea of term width is wrong |
288 | * and it is actually wider (often happens on serial lines). | 358 | * and it is actually wider (often happens on serial lines). |
@@ -293,55 +363,83 @@ static void cmdedit_set_out_char(int next_char) | |||
293 | * this will break things: there will be one extra empty line */ | 363 | * this will break things: there will be one extra empty line */ |
294 | puts("\r"); /* + implicit '\n' */ | 364 | puts("\r"); /* + implicit '\n' */ |
295 | #else | 365 | #else |
296 | /* Works ok only if cmdedit_termw is correct */ | 366 | /* VT-10x terminals don't wrap cursor to next line when last char |
297 | /* destroy "(auto)margin" */ | 367 | * on the line is printed - cursor stays "over" this char. |
298 | bb_putchar(next_char); | 368 | * Need to print _next_ char too (first one to appear on next line) |
369 | * to make cursor move down to next line. | ||
370 | */ | ||
371 | /* Works ok only if cmdedit_termw is correct. */ | ||
372 | c = command_ps[cursor]; | ||
373 | if (c == BB_NUL) | ||
374 | c = ' '; | ||
375 | BB_PUTCHAR(c); | ||
299 | bb_putchar('\b'); | 376 | bb_putchar('\b'); |
300 | #endif | 377 | #endif |
378 | cmdedit_y++; | ||
379 | if (!ENABLE_UNICODE_WIDE_WCHARS || ofs_to_right == 0) { | ||
380 | width = 0; | ||
381 | } else { /* ofs_to_right > 0 */ | ||
382 | /* wide char c didn't fit on prev line */ | ||
383 | BB_PUTCHAR(c); | ||
384 | } | ||
385 | cmdedit_x = width; | ||
301 | } | 386 | } |
302 | // Huh? What if command_ps[cursor] == BB_NUL (we are at the end already?) | ||
303 | cursor++; | ||
304 | } | 387 | } |
305 | 388 | ||
306 | /* Move to end of line (by printing all chars till the end) */ | 389 | /* Move to end of line (by printing all chars till the end) */ |
307 | static void input_end(void) | 390 | static void put_till_end_and_adv_cursor(void) |
308 | { | 391 | { |
309 | while (cursor < command_len) | 392 | while (cursor < command_len) |
310 | cmdedit_set_out_char(' '); | 393 | put_cur_glyph_and_inc_cursor(); |
311 | } | 394 | } |
312 | 395 | ||
313 | /* Go to the next line */ | 396 | /* Go to the next line */ |
314 | static void goto_new_line(void) | 397 | static void goto_new_line(void) |
315 | { | 398 | { |
316 | input_end(); | 399 | put_till_end_and_adv_cursor(); |
317 | if (cmdedit_x) | 400 | if (cmdedit_x != 0) |
318 | bb_putchar('\n'); | 401 | bb_putchar('\n'); |
319 | } | 402 | } |
320 | 403 | ||
321 | 404 | static void beep(void) | |
322 | static void out1str(const char *s) | ||
323 | { | 405 | { |
324 | if (s) | 406 | bb_putchar('\007'); |
325 | fputs(s, stdout); | ||
326 | } | 407 | } |
327 | 408 | ||
328 | static void beep(void) | 409 | static void put_prompt(void) |
329 | { | 410 | { |
330 | bb_putchar('\007'); | 411 | unsigned w; |
412 | |||
413 | fputs(cmdedit_prompt, stdout); | ||
414 | fflush_all(); | ||
415 | cursor = 0; | ||
416 | w = cmdedit_termw; /* read volatile var once */ | ||
417 | cmdedit_y = cmdedit_prmt_len / w; /* new quasireal y */ | ||
418 | cmdedit_x = cmdedit_prmt_len % w; | ||
331 | } | 419 | } |
332 | 420 | ||
333 | /* Move back one character */ | 421 | /* Move back one character */ |
334 | /* (optimized for slow terminals) */ | 422 | /* (optimized for slow terminals) */ |
335 | static void input_backward(unsigned num) | 423 | static void input_backward(unsigned num) |
336 | { | 424 | { |
337 | int count_y; | ||
338 | |||
339 | if (num > cursor) | 425 | if (num > cursor) |
340 | num = cursor; | 426 | num = cursor; |
341 | if (!num) | 427 | if (num == 0) |
342 | return; | 428 | return; |
343 | cursor -= num; | 429 | cursor -= num; |
344 | 430 | ||
431 | if ((ENABLE_UNICODE_COMBINING_WCHARS || ENABLE_UNICODE_WIDE_WCHARS) | ||
432 | && unicode_status == UNICODE_ON | ||
433 | ) { | ||
434 | /* correct NUM to be equal to _screen_ width */ | ||
435 | int n = num; | ||
436 | num = 0; | ||
437 | while (--n >= 0) | ||
438 | adjust_width_and_validate_wc(&num, command_ps[cursor + n]); | ||
439 | if (num == 0) | ||
440 | return; | ||
441 | } | ||
442 | |||
345 | if (cmdedit_x >= num) { | 443 | if (cmdedit_x >= num) { |
346 | cmdedit_x -= num; | 444 | cmdedit_x -= num; |
347 | if (num <= 4) { | 445 | if (num <= 4) { |
@@ -361,38 +459,61 @@ static void input_backward(unsigned num) | |||
361 | } | 459 | } |
362 | 460 | ||
363 | /* Need to go one or more lines up */ | 461 | /* Need to go one or more lines up */ |
364 | num -= cmdedit_x; | 462 | if (ENABLE_UNICODE_WIDE_WCHARS) { |
365 | { | 463 | /* With wide chars, it is hard to "backtrack" |
366 | unsigned w = cmdedit_termw; /* volatile var */ | 464 | * and reliably figure out where to put cursor. |
367 | count_y = 1 + (num / w); | 465 | * Example (<> is a wide char; # is an ordinary char, _ cursor): |
368 | cmdedit_y -= count_y; | 466 | * |prompt: <><> | |
369 | cmdedit_x = w * count_y - num; | 467 | * |<><><><><><> | |
468 | * |_ | | ||
469 | * and user presses left arrow. num = 1, cmdedit_x = 0, | ||
470 | * We need to go up one line, and then - how do we know that | ||
471 | * we need to go *10* positions to the right? Because | ||
472 | * |prompt: <>#<>| | ||
473 | * |<><><>#<><><>| | ||
474 | * |_ | | ||
475 | * in this situation we need to go *11* positions to the right. | ||
476 | * | ||
477 | * A simpler thing to do is to redraw everything from the start | ||
478 | * up to new cursor position (which is already known): | ||
479 | */ | ||
480 | unsigned sv_cursor; | ||
481 | /* go to 1st column; go up to first line */ | ||
482 | printf("\r" "\033[%uA", cmdedit_y); | ||
483 | cmdedit_y = 0; | ||
484 | sv_cursor = cursor; | ||
485 | put_prompt(); /* sets cursor to 0 */ | ||
486 | while (cursor < sv_cursor) | ||
487 | put_cur_glyph_and_inc_cursor(); | ||
488 | } else { | ||
489 | int lines_up; | ||
490 | unsigned width; | ||
491 | /* num = chars to go back from the beginning of current line: */ | ||
492 | num -= cmdedit_x; | ||
493 | width = cmdedit_termw; /* read volatile var once */ | ||
494 | /* num=1...w: one line up, w+1...2w: two, etc: */ | ||
495 | lines_up = 1 + (num - 1) / width; | ||
496 | cmdedit_x = (width * cmdedit_y - num) % width; | ||
497 | cmdedit_y -= lines_up; | ||
498 | /* go to 1st column; go up */ | ||
499 | printf("\r" "\033[%uA", lines_up); | ||
500 | /* go to correct column. | ||
501 | * xterm, konsole, Linux VT interpret 0 as 1 below! wow. | ||
502 | * need to *make sure* we skip it if cmdedit_x == 0 */ | ||
503 | if (cmdedit_x) | ||
504 | printf("\033[%uC", cmdedit_x); | ||
370 | } | 505 | } |
371 | /* go to 1st column; go up; go to correct column */ | ||
372 | printf("\r" "\033[%dA" "\033[%dC", count_y, cmdedit_x); | ||
373 | } | ||
374 | |||
375 | static void put_prompt(void) | ||
376 | { | ||
377 | unsigned w; | ||
378 | |||
379 | out1str(cmdedit_prompt); | ||
380 | fflush_all(); | ||
381 | cursor = 0; | ||
382 | w = cmdedit_termw; /* read volatile var once */ | ||
383 | cmdedit_y = cmdedit_prmt_len / w; /* new quasireal y */ | ||
384 | cmdedit_x = cmdedit_prmt_len % w; | ||
385 | } | 506 | } |
386 | 507 | ||
387 | /* draw prompt, editor line, and clear tail */ | 508 | /* draw prompt, editor line, and clear tail */ |
388 | static void redraw(int y, int back_cursor) | 509 | static void redraw(int y, int back_cursor) |
389 | { | 510 | { |
390 | if (y > 0) /* up to start y */ | 511 | if (y > 0) /* up y lines */ |
391 | printf("\033[%uA", y); | 512 | printf("\033[%uA", y); |
392 | bb_putchar('\r'); | 513 | bb_putchar('\r'); |
393 | put_prompt(); | 514 | put_prompt(); |
394 | input_end(); /* rewrite */ | 515 | put_till_end_and_adv_cursor(); |
395 | printf("\033[J"); /* erase after cursor */ | 516 | printf(SEQ_CLEAR_TILL_END_OF_SCREEN); |
396 | input_backward(back_cursor); | 517 | input_backward(back_cursor); |
397 | } | 518 | } |
398 | 519 | ||
@@ -426,8 +547,9 @@ static void input_delete(int save) | |||
426 | * simplified into (command_len - j) */ | 547 | * simplified into (command_len - j) */ |
427 | (command_len - j) * sizeof(command_ps[0])); | 548 | (command_len - j) * sizeof(command_ps[0])); |
428 | command_len--; | 549 | command_len--; |
429 | input_end(); /* rewrite new line */ | 550 | put_till_end_and_adv_cursor(); |
430 | cmdedit_set_out_char(' '); /* erase char */ | 551 | /* Last char is still visible, erase it (and more) */ |
552 | printf(SEQ_CLEAR_TILL_END_OF_SCREEN); | ||
431 | input_backward(cursor - j); /* back to old pos cursor */ | 553 | input_backward(cursor - j); /* back to old pos cursor */ |
432 | } | 554 | } |
433 | 555 | ||
@@ -445,7 +567,7 @@ static void put(void) | |||
445 | (command_len - cursor + 1) * sizeof(command_ps[0])); | 567 | (command_len - cursor + 1) * sizeof(command_ps[0])); |
446 | memcpy(command_ps + cursor, delbuf, j * sizeof(command_ps[0])); | 568 | memcpy(command_ps + cursor, delbuf, j * sizeof(command_ps[0])); |
447 | command_len += j; | 569 | command_len += j; |
448 | input_end(); /* rewrite new line */ | 570 | put_till_end_and_adv_cursor(); |
449 | input_backward(cursor - ocursor - j + 1); /* at end of new text */ | 571 | input_backward(cursor - ocursor - j + 1); /* at end of new text */ |
450 | } | 572 | } |
451 | #endif | 573 | #endif |
@@ -463,7 +585,7 @@ static void input_backspace(void) | |||
463 | static void input_forward(void) | 585 | static void input_forward(void) |
464 | { | 586 | { |
465 | if (cursor < command_len) | 587 | if (cursor < command_len) |
466 | cmdedit_set_out_char(command_ps[cursor + 1]); | 588 | put_cur_glyph_and_inc_cursor(); |
467 | } | 589 | } |
468 | 590 | ||
469 | #if ENABLE_FEATURE_TAB_COMPLETION | 591 | #if ENABLE_FEATURE_TAB_COMPLETION |
@@ -721,21 +843,13 @@ static NOINLINE int find_match(char *matchBuf, int *len_with_quotes) | |||
721 | } | 843 | } |
722 | 844 | ||
723 | /* mask \+symbol and convert '\t' to ' ' */ | 845 | /* mask \+symbol and convert '\t' to ' ' */ |
724 | for (i = j = 0; matchBuf[i]; i++, j++) | 846 | for (i = j = 0; matchBuf[i]; i++, j++) { |
725 | if (matchBuf[i] == '\\') { | 847 | if (matchBuf[i] == '\\') { |
726 | collapse_pos(j, j + 1); | 848 | collapse_pos(j, j + 1); |
727 | int_buf[j] |= QUOT; | 849 | int_buf[j] |= QUOT; |
728 | i++; | 850 | i++; |
729 | #if ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT | ||
730 | if (matchBuf[i] == '\t') /* algorithm equivalent */ | ||
731 | int_buf[j] = ' ' | QUOT; | ||
732 | #endif | ||
733 | } | 851 | } |
734 | #if ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT | 852 | } |
735 | else if (matchBuf[i] == '\t') | ||
736 | int_buf[j] = ' '; | ||
737 | #endif | ||
738 | |||
739 | /* mask "symbols" or 'symbols' */ | 853 | /* mask "symbols" or 'symbols' */ |
740 | c2 = 0; | 854 | c2 = 0; |
741 | for (i = 0; int_buf[i]; i++) { | 855 | for (i = 0; int_buf[i]; i++) { |
@@ -1509,7 +1623,7 @@ static void ask_terminal(void) | |||
1509 | pfd.events = POLLIN; | 1623 | pfd.events = POLLIN; |
1510 | if (safe_poll(&pfd, 1, 0) == 0) { | 1624 | if (safe_poll(&pfd, 1, 0) == 0) { |
1511 | S.sent_ESC_br6n = 1; | 1625 | S.sent_ESC_br6n = 1; |
1512 | out1str("\033" "[6n"); | 1626 | fputs("\033" "[6n", stdout); |
1513 | fflush_all(); /* make terminal see it ASAP! */ | 1627 | fflush_all(); /* make terminal see it ASAP! */ |
1514 | } | 1628 | } |
1515 | } | 1629 | } |
@@ -1727,13 +1841,11 @@ static int lineedit_read_key(char *read_key_buffer) | |||
1727 | pushback: | 1841 | pushback: |
1728 | /* Invalid sequence. Save all "bad bytes" except first */ | 1842 | /* Invalid sequence. Save all "bad bytes" except first */ |
1729 | read_key_ungets(read_key_buffer, unicode_buf + 1, unicode_idx - 1); | 1843 | read_key_ungets(read_key_buffer, unicode_buf + 1, unicode_idx - 1); |
1730 | /* | 1844 | # if !ENABLE_UNICODE_PRESERVE_BROKEN |
1731 | * ic = unicode_buf[0] sounds even better, but currently | ||
1732 | * this does not work: wchar_t[] -> char[] conversion | ||
1733 | * when lineedit finishes mangles such "raw bytes" | ||
1734 | * (by misinterpreting them as unicode chars): | ||
1735 | */ | ||
1736 | ic = CONFIG_SUBST_WCHAR; | 1845 | ic = CONFIG_SUBST_WCHAR; |
1846 | # else | ||
1847 | ic = unicode_mark_raw_byte(unicode_buf[0]); | ||
1848 | # endif | ||
1737 | } else { | 1849 | } else { |
1738 | /* Valid unicode char, return its code */ | 1850 | /* Valid unicode char, return its code */ |
1739 | ic = wc; | 1851 | ic = wc; |
@@ -1925,7 +2037,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li | |||
1925 | case CTRL('E'): | 2037 | case CTRL('E'): |
1926 | vi_case('$'|VI_CMDMODE_BIT:) | 2038 | vi_case('$'|VI_CMDMODE_BIT:) |
1927 | /* Control-e -- End of line */ | 2039 | /* Control-e -- End of line */ |
1928 | input_end(); | 2040 | put_till_end_and_adv_cursor(); |
1929 | break; | 2041 | break; |
1930 | case CTRL('F'): | 2042 | case CTRL('F'): |
1931 | vi_case('l'|VI_CMDMODE_BIT:) | 2043 | vi_case('l'|VI_CMDMODE_BIT:) |
@@ -1954,12 +2066,12 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li | |||
1954 | /* Control-k -- clear to end of line */ | 2066 | /* Control-k -- clear to end of line */ |
1955 | command_ps[cursor] = BB_NUL; | 2067 | command_ps[cursor] = BB_NUL; |
1956 | command_len = cursor; | 2068 | command_len = cursor; |
1957 | printf("\033[J"); | 2069 | printf(SEQ_CLEAR_TILL_END_OF_SCREEN); |
1958 | break; | 2070 | break; |
1959 | case CTRL('L'): | 2071 | case CTRL('L'): |
1960 | vi_case(CTRL('L')|VI_CMDMODE_BIT:) | 2072 | vi_case(CTRL('L')|VI_CMDMODE_BIT:) |
1961 | /* Control-l -- clear screen */ | 2073 | /* Control-l -- clear screen */ |
1962 | printf("\033[H"); | 2074 | printf("\033[H"); /* cursor to top,left */ |
1963 | redraw(0, command_len - cursor); | 2075 | redraw(0, command_len - cursor); |
1964 | break; | 2076 | break; |
1965 | #if MAX_HISTORY > 0 | 2077 | #if MAX_HISTORY > 0 |
@@ -2010,7 +2122,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li | |||
2010 | vi_cmdmode = 0; | 2122 | vi_cmdmode = 0; |
2011 | break; | 2123 | break; |
2012 | case 'A'|VI_CMDMODE_BIT: | 2124 | case 'A'|VI_CMDMODE_BIT: |
2013 | input_end(); | 2125 | put_till_end_and_adv_cursor(); |
2014 | vi_cmdmode = 0; | 2126 | vi_cmdmode = 0; |
2015 | break; | 2127 | break; |
2016 | case 'x'|VI_CMDMODE_BIT: | 2128 | case 'x'|VI_CMDMODE_BIT: |
@@ -2170,7 +2282,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li | |||
2170 | input_backward(cursor); | 2282 | input_backward(cursor); |
2171 | break; | 2283 | break; |
2172 | case KEYCODE_END: | 2284 | case KEYCODE_END: |
2173 | input_end(); | 2285 | put_till_end_and_adv_cursor(); |
2174 | break; | 2286 | break; |
2175 | 2287 | ||
2176 | default: | 2288 | default: |
@@ -2230,7 +2342,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li | |||
2230 | /* We are at the end, append */ | 2342 | /* We are at the end, append */ |
2231 | command_ps[cursor] = ic; | 2343 | command_ps[cursor] = ic; |
2232 | command_ps[cursor + 1] = BB_NUL; | 2344 | command_ps[cursor + 1] = BB_NUL; |
2233 | cmdedit_set_out_char(' '); | 2345 | put_cur_glyph_and_inc_cursor(); |
2234 | if (unicode_bidi_isrtl(ic)) | 2346 | if (unicode_bidi_isrtl(ic)) |
2235 | input_backward(1); | 2347 | input_backward(1); |
2236 | } else { | 2348 | } else { |
@@ -2243,8 +2355,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li | |||
2243 | /* is right-to-left char, or neutral one (e.g. comma) was just added to rtl text? */ | 2355 | /* is right-to-left char, or neutral one (e.g. comma) was just added to rtl text? */ |
2244 | if (!isrtl_str()) | 2356 | if (!isrtl_str()) |
2245 | sc++; /* no */ | 2357 | sc++; /* no */ |
2246 | /* rewrite from cursor */ | 2358 | put_till_end_and_adv_cursor(); |
2247 | input_end(); | ||
2248 | /* to prev x pos + 1 */ | 2359 | /* to prev x pos + 1 */ |
2249 | input_backward(cursor - sc); | 2360 | input_backward(cursor - sc); |
2250 | } | 2361 | } |
@@ -2345,9 +2456,6 @@ int main(int argc, char **argv) | |||
2345 | "% "; | 2456 | "% "; |
2346 | #endif | 2457 | #endif |
2347 | 2458 | ||
2348 | #if ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT | ||
2349 | setlocale(LC_ALL, ""); | ||
2350 | #endif | ||
2351 | while (1) { | 2459 | while (1) { |
2352 | int l; | 2460 | int l; |
2353 | l = read_line_input(prompt, buff); | 2461 | l = read_line_input(prompt, buff); |
diff --git a/libbb/read.c b/libbb/read.c index 06ce29718..f3af144f0 100644 --- a/libbb/read.c +++ b/libbb/read.c | |||
@@ -6,7 +6,6 @@ | |||
6 | * | 6 | * |
7 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. | 7 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
8 | */ | 8 | */ |
9 | |||
10 | #include "libbb.h" | 9 | #include "libbb.h" |
11 | 10 | ||
12 | #define ZIPPED (ENABLE_FEATURE_SEAMLESS_LZMA \ | 11 | #define ZIPPED (ENABLE_FEATURE_SEAMLESS_LZMA \ |
@@ -16,7 +15,7 @@ | |||
16 | ) | 15 | ) |
17 | 16 | ||
18 | #if ZIPPED | 17 | #if ZIPPED |
19 | #include "unarchive.h" | 18 | # include "unarchive.h" |
20 | #endif | 19 | #endif |
21 | 20 | ||
22 | ssize_t FAST_FUNC safe_read(int fd, void *buf, size_t count) | 21 | ssize_t FAST_FUNC safe_read(int fd, void *buf, size_t count) |
@@ -306,14 +305,11 @@ void* FAST_FUNC xmalloc_xopen_read_close(const char *filename, size_t *maxsz_p) | |||
306 | return buf; | 305 | return buf; |
307 | } | 306 | } |
308 | 307 | ||
309 | int FAST_FUNC open_zipped(const char *fname) | 308 | #if ZIPPED |
309 | int FAST_FUNC setup_unzip_on_fd(int fd /*, int fail_if_not_detected*/) | ||
310 | { | 310 | { |
311 | #if !ZIPPED | 311 | const int fail_if_not_detected = 1; |
312 | return open(fname, O_RDONLY); | ||
313 | #else | ||
314 | unsigned char magic[2]; | 312 | unsigned char magic[2]; |
315 | char *sfx; | ||
316 | int fd; | ||
317 | #if BB_MMU | 313 | #if BB_MMU |
318 | IF_DESKTOP(long long) int FAST_FUNC (*xformer)(int src_fd, int dst_fd); | 314 | IF_DESKTOP(long long) int FAST_FUNC (*xformer)(int src_fd, int dst_fd); |
319 | enum { xformer_prog = 0 }; | 315 | enum { xformer_prog = 0 }; |
@@ -322,6 +318,62 @@ int FAST_FUNC open_zipped(const char *fname) | |||
322 | const char *xformer_prog; | 318 | const char *xformer_prog; |
323 | #endif | 319 | #endif |
324 | 320 | ||
321 | /* .gz and .bz2 both have 2-byte signature, and their | ||
322 | * unpack_XXX_stream wants this header skipped. */ | ||
323 | xread(fd, &magic, 2); | ||
324 | if (ENABLE_FEATURE_SEAMLESS_GZ | ||
325 | && magic[0] == 0x1f && magic[1] == 0x8b | ||
326 | ) { | ||
327 | # if BB_MMU | ||
328 | xformer = unpack_gz_stream; | ||
329 | # else | ||
330 | xformer_prog = "gunzip"; | ||
331 | # endif | ||
332 | goto found_magic; | ||
333 | } | ||
334 | if (ENABLE_FEATURE_SEAMLESS_BZ2 | ||
335 | && magic[0] == 'B' && magic[1] == 'Z' | ||
336 | ) { | ||
337 | # if BB_MMU | ||
338 | xformer = unpack_bz2_stream; | ||
339 | # else | ||
340 | xformer_prog = "bunzip2"; | ||
341 | # endif | ||
342 | goto found_magic; | ||
343 | } | ||
344 | // TODO: xz format support. rpm adopted it, "rpm -i FILE.rpm" badly needs this. | ||
345 | // Signature: 0xFD, '7', 'z', 'X', 'Z', 0x00 | ||
346 | // More info at: http://tukaani.org/xz/xz-file-format.txt | ||
347 | |||
348 | /* No known magic seen */ | ||
349 | if (fail_if_not_detected) | ||
350 | bb_error_msg_and_die("no gzip" | ||
351 | IF_FEATURE_SEAMLESS_BZ2("/bzip2") | ||
352 | " magic"); | ||
353 | xlseek(fd, -2, SEEK_CUR); | ||
354 | return fd; | ||
355 | |||
356 | found_magic: | ||
357 | # if !BB_MMU | ||
358 | /* NOMMU version of open_transformer execs | ||
359 | * an external unzipper that wants | ||
360 | * file position at the start of the file */ | ||
361 | xlseek(fd, -2, SEEK_CUR); | ||
362 | # endif | ||
363 | open_transformer(fd, xformer, xformer_prog); | ||
364 | |||
365 | return fd; | ||
366 | } | ||
367 | #endif /* ZIPPED */ | ||
368 | |||
369 | int FAST_FUNC open_zipped(const char *fname) | ||
370 | { | ||
371 | #if !ZIPPED | ||
372 | return open(fname, O_RDONLY); | ||
373 | #else | ||
374 | char *sfx; | ||
375 | int fd; | ||
376 | |||
325 | fd = open(fname, O_RDONLY); | 377 | fd = open(fname, O_RDONLY); |
326 | if (fd < 0) | 378 | if (fd < 0) |
327 | return fd; | 379 | return fd; |
@@ -335,40 +387,7 @@ int FAST_FUNC open_zipped(const char *fname) | |||
335 | if ((ENABLE_FEATURE_SEAMLESS_GZ && strcmp(sfx, ".gz") == 0) | 387 | if ((ENABLE_FEATURE_SEAMLESS_GZ && strcmp(sfx, ".gz") == 0) |
336 | || (ENABLE_FEATURE_SEAMLESS_BZ2 && strcmp(sfx, ".bz2") == 0) | 388 | || (ENABLE_FEATURE_SEAMLESS_BZ2 && strcmp(sfx, ".bz2") == 0) |
337 | ) { | 389 | ) { |
338 | /* .gz and .bz2 both have 2-byte signature, and their | 390 | setup_unzip_on_fd(fd /*, fail_if_not_detected: 1*/); |
339 | * unpack_XXX_stream wants this header skipped. */ | ||
340 | xread(fd, &magic, 2); | ||
341 | #if ENABLE_FEATURE_SEAMLESS_GZ | ||
342 | #if BB_MMU | ||
343 | xformer = unpack_gz_stream; | ||
344 | #else | ||
345 | xformer_prog = "gunzip"; | ||
346 | #endif | ||
347 | #endif | ||
348 | if (!ENABLE_FEATURE_SEAMLESS_GZ | ||
349 | || magic[0] != 0x1f || magic[1] != 0x8b | ||
350 | ) { | ||
351 | if (!ENABLE_FEATURE_SEAMLESS_BZ2 | ||
352 | || magic[0] != 'B' || magic[1] != 'Z' | ||
353 | ) { | ||
354 | bb_error_msg_and_die("no gzip" | ||
355 | IF_FEATURE_SEAMLESS_BZ2("/bzip2") | ||
356 | " magic"); | ||
357 | } | ||
358 | #if BB_MMU | ||
359 | xformer = unpack_bz2_stream; | ||
360 | #else | ||
361 | xformer_prog = "bunzip2"; | ||
362 | #endif | ||
363 | } else { | ||
364 | #if !BB_MMU | ||
365 | /* NOMMU version of open_transformer execs | ||
366 | * an external unzipper that wants | ||
367 | * file position at the start of the file */ | ||
368 | xlseek(fd, 0, SEEK_SET); | ||
369 | #endif | ||
370 | } | ||
371 | open_transformer(fd, xformer, xformer_prog); | ||
372 | } | 391 | } |
373 | } | 392 | } |
374 | 393 | ||
diff --git a/libbb/read_key.c b/libbb/read_key.c index 8422976c9..64557ab14 100644 --- a/libbb/read_key.c +++ b/libbb/read_key.c | |||
@@ -214,7 +214,7 @@ int64_t FAST_FUNC read_key(int fd, char *buffer, int timeout) | |||
214 | } | 214 | } |
215 | n++; | 215 | n++; |
216 | /* Try to decipher "ESC [ NNN ; NNN R" sequence */ | 216 | /* Try to decipher "ESC [ NNN ; NNN R" sequence */ |
217 | if (ENABLE_FEATURE_EDITING_ASK_TERMINAL | 217 | if ((ENABLE_FEATURE_EDITING_ASK_TERMINAL || ENABLE_FEATURE_VI_ASK_TERMINAL) |
218 | && n >= 5 | 218 | && n >= 5 |
219 | && buffer[0] == '[' | 219 | && buffer[0] == '[' |
220 | && buffer[n-1] == 'R' | 220 | && buffer[n-1] == 'R' |
diff --git a/libbb/time.c b/libbb/time.c index 5cd04268c..8d176e52e 100644 --- a/libbb/time.c +++ b/libbb/time.c | |||
@@ -68,6 +68,16 @@ void FAST_FUNC parse_datestr(const char *date_str, struct tm *ptm) | |||
68 | end = '\0'; | 68 | end = '\0'; |
69 | /* else end != NUL and we error out */ | 69 | /* else end != NUL and we error out */ |
70 | } | 70 | } |
71 | } else if (date_str[0] == '@') { | ||
72 | time_t t = bb_strtol(date_str + 1, NULL, 10); | ||
73 | if (!errno) { | ||
74 | struct tm *lt = localtime(&t); | ||
75 | if (lt) { | ||
76 | *ptm = *lt; | ||
77 | return; | ||
78 | } | ||
79 | } | ||
80 | end = '1'; | ||
71 | } else { | 81 | } else { |
72 | /* Googled the following on an old date manpage: | 82 | /* Googled the following on an old date manpage: |
73 | * | 83 | * |
diff --git a/libbb/unicode.c b/libbb/unicode.c index 83e70b412..b2c28239b 100644 --- a/libbb/unicode.c +++ b/libbb/unicode.c | |||
@@ -240,7 +240,7 @@ int FAST_FUNC iswpunct(wint_t wc) | |||
240 | } | 240 | } |
241 | 241 | ||
242 | 242 | ||
243 | # if LAST_SUPPORTED_WCHAR >= 0x300 | 243 | # if CONFIG_LAST_SUPPORTED_WCHAR >= 0x300 |
244 | struct interval { | 244 | struct interval { |
245 | uint16_t first; | 245 | uint16_t first; |
246 | uint16_t last; | 246 | uint16_t last; |
@@ -418,12 +418,11 @@ static int in_uint16_table(unsigned ucs, const uint16_t *table, unsigned max) | |||
418 | * This implementation assumes that wchar_t characters are encoded | 418 | * This implementation assumes that wchar_t characters are encoded |
419 | * in ISO 10646. | 419 | * in ISO 10646. |
420 | */ | 420 | */ |
421 | static int wcwidth(unsigned ucs) | 421 | int FAST_FUNC wcwidth(unsigned ucs) |
422 | { | 422 | { |
423 | # if LAST_SUPPORTED_WCHAR >= 0x300 | 423 | # if CONFIG_LAST_SUPPORTED_WCHAR >= 0x300 |
424 | /* sorted list of non-overlapping intervals of non-spacing characters */ | 424 | /* sorted list of non-overlapping intervals of non-spacing characters */ |
425 | /* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */ | 425 | /* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */ |
426 | static const struct interval combining[] = { | ||
427 | # define BIG_(a,b) { a, b }, | 426 | # define BIG_(a,b) { a, b }, |
428 | # define PAIR(a,b) | 427 | # define PAIR(a,b) |
429 | # define ARRAY /* PAIR if < 0x4000 and no more than 4 chars big */ \ | 428 | # define ARRAY /* PAIR if < 0x4000 and no more than 4 chars big */ \ |
@@ -557,10 +556,9 @@ static int wcwidth(unsigned ucs) | |||
557 | BIG_(0xFE20, 0xFE23) \ | 556 | BIG_(0xFE20, 0xFE23) \ |
558 | BIG_(0xFEFF, 0xFEFF) \ | 557 | BIG_(0xFEFF, 0xFEFF) \ |
559 | BIG_(0xFFF9, 0xFFFB) | 558 | BIG_(0xFFF9, 0xFFFB) |
560 | ARRAY | 559 | static const struct interval combining[] = { ARRAY }; |
561 | # undef BIG_ | 560 | # undef BIG_ |
562 | # undef PAIR | 561 | # undef PAIR |
563 | }; | ||
564 | # define BIG_(a,b) | 562 | # define BIG_(a,b) |
565 | # define PAIR(a,b) (a << 2) | (b-a), | 563 | # define PAIR(a,b) (a << 2) | (b-a), |
566 | static const uint16_t combining1[] = { ARRAY }; | 564 | static const uint16_t combining1[] = { ARRAY }; |
@@ -581,14 +579,14 @@ static int wcwidth(unsigned ucs) | |||
581 | if ((ucs & ~0x80) < 0x20 || ucs == 0x7f) | 579 | if ((ucs & ~0x80) < 0x20 || ucs == 0x7f) |
582 | return -1; | 580 | return -1; |
583 | /* Quick abort if it is an obviously invalid char */ | 581 | /* Quick abort if it is an obviously invalid char */ |
584 | if (ucs > LAST_SUPPORTED_WCHAR) | 582 | if (ucs > CONFIG_LAST_SUPPORTED_WCHAR) |
585 | return -1; | 583 | return -1; |
586 | 584 | ||
587 | /* Optimization: no combining chars below 0x300 */ | 585 | /* Optimization: no combining chars below 0x300 */ |
588 | if (LAST_SUPPORTED_WCHAR < 0x300 || ucs < 0x300) | 586 | if (CONFIG_LAST_SUPPORTED_WCHAR < 0x300 || ucs < 0x300) |
589 | return 1; | 587 | return 1; |
590 | 588 | ||
591 | # if LAST_SUPPORTED_WCHAR >= 0x300 | 589 | # if CONFIG_LAST_SUPPORTED_WCHAR >= 0x300 |
592 | /* Binary search in table of non-spacing characters */ | 590 | /* Binary search in table of non-spacing characters */ |
593 | if (in_interval_table(ucs, combining, ARRAY_SIZE(combining) - 1)) | 591 | if (in_interval_table(ucs, combining, ARRAY_SIZE(combining) - 1)) |
594 | return 0; | 592 | return 0; |
@@ -596,25 +594,25 @@ static int wcwidth(unsigned ucs) | |||
596 | return 0; | 594 | return 0; |
597 | 595 | ||
598 | /* Optimization: all chars below 0x1100 are not double-width */ | 596 | /* Optimization: all chars below 0x1100 are not double-width */ |
599 | if (LAST_SUPPORTED_WCHAR < 0x1100 || ucs < 0x1100) | 597 | if (CONFIG_LAST_SUPPORTED_WCHAR < 0x1100 || ucs < 0x1100) |
600 | return 1; | 598 | return 1; |
601 | 599 | ||
602 | # if LAST_SUPPORTED_WCHAR >= 0x1100 | 600 | # if CONFIG_LAST_SUPPORTED_WCHAR >= 0x1100 |
603 | /* Invalid code points: */ | 601 | /* Invalid code points: */ |
604 | /* High (d800..dbff) and low (dc00..dfff) surrogates (valid only in UTF16) */ | 602 | /* High (d800..dbff) and low (dc00..dfff) surrogates (valid only in UTF16) */ |
605 | /* Private Use Area (e000..f8ff) */ | 603 | /* Private Use Area (e000..f8ff) */ |
606 | /* Noncharacters fdd0..fdef */ | 604 | /* Noncharacters fdd0..fdef */ |
607 | if ((LAST_SUPPORTED_WCHAR >= 0xd800 && ucs >= 0xd800 && ucs <= 0xf8ff) | 605 | if ((CONFIG_LAST_SUPPORTED_WCHAR >= 0xd800 && ucs >= 0xd800 && ucs <= 0xf8ff) |
608 | || (LAST_SUPPORTED_WCHAR >= 0xfdd0 && ucs >= 0xfdd0 && ucs <= 0xfdef) | 606 | || (CONFIG_LAST_SUPPORTED_WCHAR >= 0xfdd0 && ucs >= 0xfdd0 && ucs <= 0xfdef) |
609 | ) { | 607 | ) { |
610 | return -1; | 608 | return -1; |
611 | } | 609 | } |
612 | /* 0xfffe and 0xffff in every plane are invalid */ | 610 | /* 0xfffe and 0xffff in every plane are invalid */ |
613 | if (LAST_SUPPORTED_WCHAR >= 0xfffe && ((ucs & 0xfffe) == 0xfffe)) { | 611 | if (CONFIG_LAST_SUPPORTED_WCHAR >= 0xfffe && ((ucs & 0xfffe) == 0xfffe)) { |
614 | return -1; | 612 | return -1; |
615 | } | 613 | } |
616 | 614 | ||
617 | # if LAST_SUPPORTED_WCHAR >= 0x10000 | 615 | # if CONFIG_LAST_SUPPORTED_WCHAR >= 0x10000 |
618 | if (ucs >= 0x10000) { | 616 | if (ucs >= 0x10000) { |
619 | /* Combining chars in Supplementary Multilingual Plane 0x1xxxx */ | 617 | /* Combining chars in Supplementary Multilingual Plane 0x1xxxx */ |
620 | static const struct interval combining0x10000[] = { | 618 | static const struct interval combining0x10000[] = { |
@@ -627,7 +625,7 @@ static int wcwidth(unsigned ucs) | |||
627 | if (in_interval_table(ucs ^ 0x10000, combining0x10000, ARRAY_SIZE(combining0x10000) - 1)) | 625 | if (in_interval_table(ucs ^ 0x10000, combining0x10000, ARRAY_SIZE(combining0x10000) - 1)) |
628 | return 0; | 626 | return 0; |
629 | /* Check a few non-spacing chars in Supplementary Special-purpose Plane 0xExxxx */ | 627 | /* Check a few non-spacing chars in Supplementary Special-purpose Plane 0xExxxx */ |
630 | if (LAST_SUPPORTED_WCHAR >= 0xE0001 | 628 | if (CONFIG_LAST_SUPPORTED_WCHAR >= 0xE0001 |
631 | && ( ucs == 0xE0001 | 629 | && ( ucs == 0xE0001 |
632 | || (ucs >= 0xE0020 && ucs <= 0xE007F) | 630 | || (ucs >= 0xE0020 && ucs <= 0xE007F) |
633 | || (ucs >= 0xE0100 && ucs <= 0xE01EF) | 631 | || (ucs >= 0xE0100 && ucs <= 0xE01EF) |
@@ -646,7 +644,7 @@ static int wcwidth(unsigned ucs) | |||
646 | || ucs == 0x2329 /* left-pointing angle bracket; also CJK punct. char */ | 644 | || ucs == 0x2329 /* left-pointing angle bracket; also CJK punct. char */ |
647 | || ucs == 0x232a /* right-pointing angle bracket; also CJK punct. char */ | 645 | || ucs == 0x232a /* right-pointing angle bracket; also CJK punct. char */ |
648 | || (ucs >= 0x2e80 && ucs <= 0xa4cf && ucs != 0x303f) /* CJK ... Yi */ | 646 | || (ucs >= 0x2e80 && ucs <= 0xa4cf && ucs != 0x303f) /* CJK ... Yi */ |
649 | # if LAST_SUPPORTED_WCHAR >= 0xac00 | 647 | # if CONFIG_LAST_SUPPORTED_WCHAR >= 0xac00 |
650 | || (ucs >= 0xac00 && ucs <= 0xd7a3) /* Hangul Syllables */ | 648 | || (ucs >= 0xac00 && ucs <= 0xd7a3) /* Hangul Syllables */ |
651 | || (ucs >= 0xf900 && ucs <= 0xfaff) /* CJK Compatibility Ideographs */ | 649 | || (ucs >= 0xf900 && ucs <= 0xfaff) /* CJK Compatibility Ideographs */ |
652 | || (ucs >= 0xfe10 && ucs <= 0xfe19) /* Vertical forms */ | 650 | || (ucs >= 0xfe10 && ucs <= 0xfe19) /* Vertical forms */ |
@@ -668,7 +666,6 @@ int FAST_FUNC unicode_bidi_isrtl(wint_t wc) | |||
668 | * http://www.unicode.org/Public/5.2.0/ucd/extracted/DerivedBidiClass.txt | 666 | * http://www.unicode.org/Public/5.2.0/ucd/extracted/DerivedBidiClass.txt |
669 | * Bidi_Class=Left_To_Right | Bidi_Class=Arabic_Letter | 667 | * Bidi_Class=Left_To_Right | Bidi_Class=Arabic_Letter |
670 | */ | 668 | */ |
671 | static const struct interval rtl_b[] = { | ||
672 | # define BIG_(a,b) { a, b }, | 669 | # define BIG_(a,b) { a, b }, |
673 | # define PAIR(a,b) | 670 | # define PAIR(a,b) |
674 | # define ARRAY \ | 671 | # define ARRAY \ |
@@ -723,10 +720,9 @@ int FAST_FUNC unicode_bidi_isrtl(wint_t wc) | |||
723 | {0x10E7F, 0x10FFF}, | 720 | {0x10E7F, 0x10FFF}, |
724 | {0x1E800, 0x1EFFF} | 721 | {0x1E800, 0x1EFFF} |
725 | */ | 722 | */ |
726 | ARRAY | 723 | static const struct interval rtl_b[] = { ARRAY }; |
727 | # undef BIG_ | 724 | # undef BIG_ |
728 | # undef PAIR | 725 | # undef PAIR |
729 | }; | ||
730 | # define BIG_(a,b) | 726 | # define BIG_(a,b) |
731 | # define PAIR(a,b) (a << 2) | (b-a), | 727 | # define PAIR(a,b) (a << 2) | (b-a), |
732 | static const uint16_t rtl_p[] = { ARRAY }; | 728 | static const uint16_t rtl_p[] = { ARRAY }; |
@@ -755,7 +751,6 @@ int FAST_FUNC unicode_bidi_is_neutral_wchar(wint_t wc) | |||
755 | * White_Space, Other_Neutral, European_Number, European_Separator, | 751 | * White_Space, Other_Neutral, European_Number, European_Separator, |
756 | * European_Terminator, Arabic_Number, Common_Separator | 752 | * European_Terminator, Arabic_Number, Common_Separator |
757 | */ | 753 | */ |
758 | static const struct interval neutral_b[] = { | ||
759 | # define BIG_(a,b) { a, b }, | 754 | # define BIG_(a,b) { a, b }, |
760 | # define PAIR(a,b) | 755 | # define PAIR(a,b) |
761 | # define ARRAY \ | 756 | # define ARRAY \ |
@@ -929,10 +924,9 @@ int FAST_FUNC unicode_bidi_is_neutral_wchar(wint_t wc) | |||
929 | {0x1F030, 0x1F093}, | 924 | {0x1F030, 0x1F093}, |
930 | {0x1F100, 0x1F10A} | 925 | {0x1F100, 0x1F10A} |
931 | */ | 926 | */ |
932 | ARRAY | 927 | static const struct interval neutral_b[] = { ARRAY }; |
933 | # undef BIG_ | 928 | # undef BIG_ |
934 | # undef PAIR | 929 | # undef PAIR |
935 | }; | ||
936 | # define BIG_(a,b) | 930 | # define BIG_(a,b) |
937 | # define PAIR(a,b) (a << 2) | (b-a), | 931 | # define PAIR(a,b) (a << 2) | (b-a), |
938 | static const uint16_t neutral_p[] = { ARRAY }; | 932 | static const uint16_t neutral_p[] = { ARRAY }; |
diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c index aec165f06..d93dd2af9 100644 --- a/libbb/xfuncs.c +++ b/libbb/xfuncs.c | |||
@@ -210,34 +210,40 @@ char* FAST_FUNC xmalloc_ttyname(int fd) | |||
210 | return buf; | 210 | return buf; |
211 | } | 211 | } |
212 | 212 | ||
213 | /* It is perfectly ok to pass in a NULL for either width or for | 213 | static int wh_helper(int value, int def_val, const char *env_name, int *err) |
214 | * height, in which case that value will not be set. */ | ||
215 | int FAST_FUNC get_terminal_width_height(int fd, unsigned *width, unsigned *height) | ||
216 | { | 214 | { |
217 | struct winsize win = { 0, 0, 0, 0 }; | 215 | if (value == 0) { |
218 | int ret = ioctl(fd, TIOCGWINSZ, &win); | 216 | char *s = getenv(env_name); |
219 | 217 | if (s) { | |
220 | if (height) { | 218 | value = atoi(s); |
221 | if (!win.ws_row) { | 219 | /* If LINES/COLUMNS are set, pretent that there is |
222 | char *s = getenv("LINES"); | 220 | * no error getting w/h, this prevents some ugly |
223 | if (s) win.ws_row = atoi(s); | 221 | * cursor tricks by our callers */ |
224 | } | 222 | *err = 0; |
225 | if (win.ws_row <= 1 || win.ws_row >= 30000) | ||
226 | win.ws_row = 24; | ||
227 | *height = (int) win.ws_row; | ||
228 | } | ||
229 | |||
230 | if (width) { | ||
231 | if (!win.ws_col) { | ||
232 | char *s = getenv("COLUMNS"); | ||
233 | if (s) win.ws_col = atoi(s); | ||
234 | } | 223 | } |
235 | if (win.ws_col <= 1 || win.ws_col >= 30000) | ||
236 | win.ws_col = 80; | ||
237 | *width = (int) win.ws_col; | ||
238 | } | 224 | } |
225 | if (value <= 1 || value >= 30000) | ||
226 | value = def_val; | ||
227 | return value; | ||
228 | } | ||
239 | 229 | ||
240 | return ret; | 230 | /* It is perfectly ok to pass in a NULL for either width or for |
231 | * height, in which case that value will not be set. */ | ||
232 | int FAST_FUNC get_terminal_width_height(int fd, unsigned *width, unsigned *height) | ||
233 | { | ||
234 | struct winsize win; | ||
235 | int err; | ||
236 | |||
237 | win.ws_row = 0; | ||
238 | win.ws_col = 0; | ||
239 | /* I've seen ioctl returning 0, but row/col is (still?) 0. | ||
240 | * We treat that as an error too. */ | ||
241 | err = ioctl(fd, TIOCGWINSZ, &win) != 0 || win.ws_row == 0; | ||
242 | if (height) | ||
243 | *height = wh_helper(win.ws_row, 24, "LINES", &err); | ||
244 | if (width) | ||
245 | *width = wh_helper(win.ws_col, 80, "COLUMNS", &err); | ||
246 | return err; | ||
241 | } | 247 | } |
242 | 248 | ||
243 | int FAST_FUNC tcsetattr_stdin_TCSANOW(const struct termios *tp) | 249 | int FAST_FUNC tcsetattr_stdin_TCSANOW(const struct termios *tp) |
diff --git a/miscutils/Config.in b/miscutils/Config.in index 0469b6399..7a69dd10f 100644 --- a/miscutils/Config.in +++ b/miscutils/Config.in | |||
@@ -545,6 +545,17 @@ config READAHEAD | |||
545 | As readahead(2) blocks until each file has been read, it is best to | 545 | As readahead(2) blocks until each file has been read, it is best to |
546 | run this applet as a background job. | 546 | run this applet as a background job. |
547 | 547 | ||
548 | config RFKILL | ||
549 | bool "rfkill" | ||
550 | default n | ||
551 | help | ||
552 | Enable/disable wireless devices. | ||
553 | |||
554 | rfkill list : list all wireless devices | ||
555 | rfkill list bluetooth : list all bluetooth devices | ||
556 | rfkill list 1 : list device corresponding to the given index | ||
557 | rfkill block|unblock wlan : block/unblock all wlan(wifi) devices | ||
558 | |||
548 | config RUNLEVEL | 559 | config RUNLEVEL |
549 | bool "runlevel" | 560 | bool "runlevel" |
550 | default n | 561 | default n |
diff --git a/miscutils/Kbuild b/miscutils/Kbuild index bbfa93dc7..3c8ce42ba 100644 --- a/miscutils/Kbuild +++ b/miscutils/Kbuild | |||
@@ -34,6 +34,7 @@ lib-$(CONFIG_MOUNTPOINT) += mountpoint.o | |||
34 | lib-$(CONFIG_MT) += mt.o | 34 | lib-$(CONFIG_MT) += mt.o |
35 | lib-$(CONFIG_RAIDAUTORUN) += raidautorun.o | 35 | lib-$(CONFIG_RAIDAUTORUN) += raidautorun.o |
36 | lib-$(CONFIG_READAHEAD) += readahead.o | 36 | lib-$(CONFIG_READAHEAD) += readahead.o |
37 | lib-$(CONFIG_RFKILL) += rfkill.o | ||
37 | lib-$(CONFIG_RUNLEVEL) += runlevel.o | 38 | lib-$(CONFIG_RUNLEVEL) += runlevel.o |
38 | lib-$(CONFIG_RX) += rx.o | 39 | lib-$(CONFIG_RX) += rx.o |
39 | lib-$(CONFIG_SETSID) += setsid.o | 40 | lib-$(CONFIG_SETSID) += setsid.o |
diff --git a/miscutils/fbsplash.c b/miscutils/fbsplash.c index 5974006bb..e370d207b 100644 --- a/miscutils/fbsplash.c +++ b/miscutils/fbsplash.c | |||
@@ -359,7 +359,7 @@ int fbsplash_main(int argc UNUSED_PARAM, char **argv) | |||
359 | 359 | ||
360 | if (fifo_filename && bCursorOff) { | 360 | if (fifo_filename && bCursorOff) { |
361 | // hide cursor (BEFORE any fb ops) | 361 | // hide cursor (BEFORE any fb ops) |
362 | full_write(STDOUT_FILENO, "\x1b" "[?25l", 6); | 362 | full_write(STDOUT_FILENO, "\033[?25l", 6); |
363 | } | 363 | } |
364 | 364 | ||
365 | fb_drawimage(); | 365 | fb_drawimage(); |
@@ -404,7 +404,7 @@ int fbsplash_main(int argc UNUSED_PARAM, char **argv) | |||
404 | } | 404 | } |
405 | 405 | ||
406 | if (bCursorOff) // restore cursor | 406 | if (bCursorOff) // restore cursor |
407 | full_write(STDOUT_FILENO, "\x1b" "[?25h", 6); | 407 | full_write(STDOUT_FILENO, "\033[?25h", 6); |
408 | 408 | ||
409 | return EXIT_SUCCESS; | 409 | return EXIT_SUCCESS; |
410 | } | 410 | } |
diff --git a/miscutils/less.c b/miscutils/less.c index e4f8ab979..848266212 100644 --- a/miscutils/less.c +++ b/miscutils/less.c | |||
@@ -29,11 +29,11 @@ | |||
29 | #endif | 29 | #endif |
30 | 30 | ||
31 | /* The escape codes for highlighted and normal text */ | 31 | /* The escape codes for highlighted and normal text */ |
32 | #define HIGHLIGHT "\033[7m" | 32 | #define HIGHLIGHT "\033[7m" |
33 | #define NORMAL "\033[0m" | 33 | #define NORMAL "\033[0m" |
34 | /* The escape code to clear the screen */ | 34 | /* The escape code to home and clear to the end of screen */ |
35 | #define CLEAR "\033[H\033[J" | 35 | #define CLEAR "\033[H\033[J" |
36 | /* The escape code to clear to end of line */ | 36 | /* The escape code to clear to the end of line */ |
37 | #define CLEAR_2_EOL "\033[K" | 37 | #define CLEAR_2_EOL "\033[K" |
38 | 38 | ||
39 | enum { | 39 | enum { |
diff --git a/miscutils/rfkill.c b/miscutils/rfkill.c new file mode 100644 index 000000000..0f5817b76 --- /dev/null +++ b/miscutils/rfkill.c | |||
@@ -0,0 +1,120 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * rfkill implementation for busybox | ||
4 | * | ||
5 | * Copyright (C) 2010 Malek Degachi <malek-degachi@laposte.net> | ||
6 | * | ||
7 | * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. | ||
8 | */ | ||
9 | #include "libbb.h" | ||
10 | #include <linux/rfkill.h> | ||
11 | |||
12 | enum { | ||
13 | OPT_b = (1 << 0), /* must be = 1 */ | ||
14 | OPT_u = (1 << 1), | ||
15 | OPT_l = (1 << 2), | ||
16 | }; | ||
17 | |||
18 | int rfkill_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | ||
19 | int rfkill_main(int argc UNUSED_PARAM, char **argv) | ||
20 | { | ||
21 | struct rfkill_event event; | ||
22 | const char *rf_name; | ||
23 | int rf_fd; | ||
24 | int mode; | ||
25 | int rf_type; | ||
26 | int rf_idx; | ||
27 | unsigned rf_opt = 0; | ||
28 | |||
29 | argv++; | ||
30 | /* Must have one or two params */ | ||
31 | if (!argv[0] || (argv[1] && argv[2])) | ||
32 | bb_show_usage(); | ||
33 | |||
34 | mode = O_RDWR | O_NONBLOCK; | ||
35 | rf_name = argv[1]; | ||
36 | if (strcmp(argv[0], "list") == 0) { | ||
37 | rf_opt |= OPT_l; | ||
38 | mode = O_RDONLY | O_NONBLOCK; | ||
39 | } else if (strcmp(argv[0], "block") == 0 && rf_name) { | ||
40 | rf_opt |= OPT_b; | ||
41 | } else if (strcmp(argv[0], "unblock") == 0 && rf_name) { | ||
42 | rf_opt |= OPT_u; | ||
43 | } else | ||
44 | bb_show_usage(); | ||
45 | |||
46 | rf_type = RFKILL_TYPE_ALL; | ||
47 | rf_idx = -1; | ||
48 | if (rf_name) { | ||
49 | static const char rfkill_types[] ALIGN1 = "all\0wlan\0bluetooth\0uwb\0wimax\0wwan\0gps\0fm\0"; | ||
50 | if (strcmp(rf_name, "wifi") == 0) | ||
51 | rf_name = "wlan"; | ||
52 | if (strcmp(rf_name, "ultrawideband") == 0) | ||
53 | rf_name = "uwb"; | ||
54 | rf_type = index_in_strings(rfkill_types, rf_name); | ||
55 | if (rf_type < 0) { | ||
56 | rf_idx = xatoi_u(rf_name); | ||
57 | } | ||
58 | } | ||
59 | |||
60 | rf_fd = device_open("/dev/rfkill", mode); | ||
61 | if (rf_fd < 0) | ||
62 | bb_perror_msg_and_die("/dev/rfkill"); | ||
63 | |||
64 | if (rf_opt & OPT_l) { | ||
65 | while (full_read(rf_fd, &event, sizeof(event)) == RFKILL_EVENT_SIZE_V1) { | ||
66 | parser_t *parser; | ||
67 | char *tokens[2]; | ||
68 | char rf_sysfs[sizeof("/sys/class/rfkill/rfkill%u/uevent") + sizeof(int)*3]; | ||
69 | char *name, *type; | ||
70 | |||
71 | if (rf_type && rf_type != event.type && rf_idx < 0) { | ||
72 | continue; | ||
73 | } | ||
74 | |||
75 | if (rf_idx >= 0 && event.idx != rf_idx) { | ||
76 | continue; | ||
77 | } | ||
78 | |||
79 | name = NULL; | ||
80 | type = NULL; | ||
81 | sprintf(rf_sysfs, "/sys/class/rfkill/rfkill%u/uevent", event.idx); | ||
82 | parser = config_open2(rf_sysfs, fopen_for_read); | ||
83 | while (config_read(parser, tokens, 2, 2, "\n=", PARSE_NORMAL)) { | ||
84 | if (strcmp(tokens[0], "RFKILL_NAME") == 0) { | ||
85 | name = xstrdup(tokens[1]); | ||
86 | continue; | ||
87 | } | ||
88 | if (strcmp(tokens[0], "RFKILL_TYPE") == 0) { | ||
89 | type = xstrdup(tokens[1]); | ||
90 | continue; | ||
91 | } | ||
92 | } | ||
93 | config_close(parser); | ||
94 | |||
95 | printf("%u: %s: %s\n", event.idx, name, type); | ||
96 | printf("\tSoft blocked: %s\n", event.soft ? "yes" : "no"); | ||
97 | printf("\tHard blocked: %s\n", event.hard ? "yes" : "no"); | ||
98 | free(name); | ||
99 | free(type); | ||
100 | } | ||
101 | } else { | ||
102 | memset(&event, 0, sizeof(event)); | ||
103 | if (rf_type >= 0) { | ||
104 | event.type = rf_type; | ||
105 | event.op = RFKILL_OP_CHANGE_ALL; | ||
106 | } | ||
107 | |||
108 | if (rf_idx >= 0) { | ||
109 | event.idx = rf_idx; | ||
110 | event.op = RFKILL_OP_CHANGE; | ||
111 | } | ||
112 | |||
113 | /* Note: OPT_b == 1 */ | ||
114 | event.soft = (rf_opt & OPT_b); | ||
115 | |||
116 | xwrite(rf_fd, &event, sizeof(event)); | ||
117 | } | ||
118 | |||
119 | return EXIT_SUCCESS; | ||
120 | } | ||
diff --git a/miscutils/setsid.c b/miscutils/setsid.c index d7de1f149..fd3283e30 100644 --- a/miscutils/setsid.c +++ b/miscutils/setsid.c | |||
@@ -25,11 +25,24 @@ int setsid_main(int argc UNUSED_PARAM, char **argv) | |||
25 | /* setsid() is allowed only when we are not a process group leader. | 25 | /* setsid() is allowed only when we are not a process group leader. |
26 | * Otherwise our PID serves as PGID of some existing process group | 26 | * Otherwise our PID serves as PGID of some existing process group |
27 | * and cannot be used as PGID of a new process group. */ | 27 | * and cannot be used as PGID of a new process group. */ |
28 | if (getpgrp() == getpid()) | 28 | if (setsid() < 0) { |
29 | if (fork_or_rexec(argv)) | 29 | pid_t pid = fork_or_rexec(argv); |
30 | exit(EXIT_SUCCESS); /* parent */ | 30 | if (pid != 0) { |
31 | /* parent */ | ||
32 | /* TODO: | ||
33 | * we can waitpid(pid, &status, 0) and then even | ||
34 | * emulate exitcode, making the behavior consistent | ||
35 | * in both forked and non forked cases. | ||
36 | * However, the code is larger and upstream | ||
37 | * does not do such trick. | ||
38 | */ | ||
39 | exit(EXIT_SUCCESS); | ||
40 | } | ||
31 | 41 | ||
32 | setsid(); /* no error possible */ | 42 | /* child */ |
43 | /* now there should be no error: */ | ||
44 | setsid(); | ||
45 | } | ||
33 | 46 | ||
34 | BB_EXECVP(argv[1], argv + 1); | 47 | BB_EXECVP(argv[1], argv + 1); |
35 | bb_simple_perror_msg_and_die(argv[1]); | 48 | bb_simple_perror_msg_and_die(argv[1]); |
diff --git a/networking/Config.in b/networking/Config.in index 61e59b244..ce7166f98 100644 --- a/networking/Config.in +++ b/networking/Config.in | |||
@@ -122,8 +122,8 @@ config FEATURE_FTPD_ACCEPT_BROKEN_LIST | |||
122 | default y | 122 | default y |
123 | depends on FTPD | 123 | depends on FTPD |
124 | help | 124 | help |
125 | Some ftp-clients (among them KDE's Konqueror) issue illegal | 125 | Some ftp clients (among them KDE's Konqueror) issue illegal |
126 | "LIST -la" requests. This option works around those problems. | 126 | "LIST -l" requests. This option works around such problems. |
127 | It might prevent you from listing files starting with "-" and | 127 | It might prevent you from listing files starting with "-" and |
128 | it increases the code size by ~40 bytes. | 128 | it increases the code size by ~40 bytes. |
129 | Most other ftp servers seem to behave similar to this. | 129 | Most other ftp servers seem to behave similar to this. |
diff --git a/networking/dnsd.c b/networking/dnsd.c index c76a54f9e..1a99040ac 100644 --- a/networking/dnsd.c +++ b/networking/dnsd.c | |||
@@ -44,10 +44,15 @@ struct dns_head { | |||
44 | uint16_t nauth; | 44 | uint16_t nauth; |
45 | uint16_t nadd; | 45 | uint16_t nadd; |
46 | }; | 46 | }; |
47 | /* Structure used to access type and class fields. | ||
48 | * They are totally unaligned, but gcc 4.3.4 thinks that pointer of type uint16_t* | ||
49 | * is 16-bit aligned and replaces 16-bit memcpy (in move_from_unaligned16 macro) | ||
50 | * with aligned halfword access on arm920t! | ||
51 | * Oh well. Slapping PACKED everywhere seems to help: */ | ||
47 | struct type_and_class { | 52 | struct type_and_class { |
48 | uint16_t type; | 53 | uint16_t type PACKED; |
49 | uint16_t class; | 54 | uint16_t class PACKED; |
50 | }; | 55 | } PACKED; |
51 | /* element of known name, ip address and reversed ip address */ | 56 | /* element of known name, ip address and reversed ip address */ |
52 | struct dns_entry { | 57 | struct dns_entry { |
53 | struct dns_entry *next; | 58 | struct dns_entry *next; |
diff --git a/networking/ftpd.c b/networking/ftpd.c index 9d43ea3a2..c63b9319e 100644 --- a/networking/ftpd.c +++ b/networking/ftpd.c | |||
@@ -618,10 +618,10 @@ popen_ls(const char *opt) | |||
618 | argv[4] = NULL; | 618 | argv[4] = NULL; |
619 | 619 | ||
620 | /* Improve compatibility with non-RFC conforming FTP clients | 620 | /* Improve compatibility with non-RFC conforming FTP clients |
621 | * which send e.g. "LIST -l", "LIST -la". | 621 | * which send e.g. "LIST -l", "LIST -la", "LIST -aL". |
622 | * See https://bugs.kde.org/show_bug.cgi?id=195578 */ | 622 | * See https://bugs.kde.org/show_bug.cgi?id=195578 */ |
623 | if (ENABLE_FEATURE_FTPD_ACCEPT_BROKEN_LIST | 623 | if (ENABLE_FEATURE_FTPD_ACCEPT_BROKEN_LIST |
624 | && G.ftp_arg && G.ftp_arg[0] == '-' && G.ftp_arg[1] == 'l' | 624 | && G.ftp_arg && G.ftp_arg[0] == '-' |
625 | ) { | 625 | ) { |
626 | const char *tmp = strchr(G.ftp_arg, ' '); | 626 | const char *tmp = strchr(G.ftp_arg, ' '); |
627 | if (tmp) /* skip the space */ | 627 | if (tmp) /* skip the space */ |
diff --git a/networking/ifplugd.c b/networking/ifplugd.c index 41b04c4ed..8cb07db5d 100644 --- a/networking/ifplugd.c +++ b/networking/ifplugd.c | |||
@@ -93,6 +93,7 @@ enum { // constant fds | |||
93 | 93 | ||
94 | struct globals { | 94 | struct globals { |
95 | smallint iface_last_status; | 95 | smallint iface_last_status; |
96 | smallint iface_prev_status; | ||
96 | smallint iface_exists; | 97 | smallint iface_exists; |
97 | 98 | ||
98 | /* Used in getopt32, must have sizeof == sizeof(int) */ | 99 | /* Used in getopt32, must have sizeof == sizeof(int) */ |
@@ -121,97 +122,42 @@ struct globals { | |||
121 | } while (0) | 122 | } while (0) |
122 | 123 | ||
123 | 124 | ||
125 | static const char *strstatus(int status) | ||
126 | { | ||
127 | if (status == IFSTATUS_ERR) | ||
128 | return "error"; | ||
129 | return "down\0up" + (status * 5); | ||
130 | } | ||
131 | |||
124 | static int run_script(const char *action) | 132 | static int run_script(const char *action) |
125 | { | 133 | { |
134 | char *env_PREVIOUS, *env_CURRENT; | ||
126 | char *argv[5]; | 135 | char *argv[5]; |
127 | int r; | 136 | int r; |
128 | 137 | ||
129 | bb_error_msg("executing '%s %s %s'", G.script_name, G.iface, action); | 138 | bb_error_msg("executing '%s %s %s'", G.script_name, G.iface, action); |
130 | 139 | ||
131 | #if 1 | ||
132 | |||
133 | argv[0] = (char*) G.script_name; | 140 | argv[0] = (char*) G.script_name; |
134 | argv[1] = (char*) G.iface; | 141 | argv[1] = (char*) G.iface; |
135 | argv[2] = (char*) action; | 142 | argv[2] = (char*) action; |
136 | argv[3] = (char*) G.extra_arg; | 143 | argv[3] = (char*) G.extra_arg; |
137 | argv[4] = NULL; | 144 | argv[4] = NULL; |
138 | 145 | ||
146 | env_PREVIOUS = xasprintf("%s=%s", IFPLUGD_ENV_PREVIOUS, strstatus(G.iface_prev_status)); | ||
147 | putenv(env_PREVIOUS); | ||
148 | env_CURRENT = xasprintf("%s=%s", IFPLUGD_ENV_CURRENT, strstatus(G.iface_last_status)); | ||
149 | putenv(env_CURRENT); | ||
150 | |||
139 | /* r < 0 - can't exec, 0 <= r < 0x180 - exited, >=0x180 - killed by sig (r-0x180) */ | 151 | /* r < 0 - can't exec, 0 <= r < 0x180 - exited, >=0x180 - killed by sig (r-0x180) */ |
140 | r = spawn_and_wait(argv); | 152 | r = spawn_and_wait(argv); |
141 | 153 | ||
154 | unsetenv(IFPLUGD_ENV_PREVIOUS); | ||
155 | unsetenv(IFPLUGD_ENV_CURRENT); | ||
156 | free(env_PREVIOUS); | ||
157 | free(env_CURRENT); | ||
158 | |||
142 | bb_error_msg("exit code: %d", r & 0xff); | 159 | bb_error_msg("exit code: %d", r & 0xff); |
143 | return (option_mask32 & FLAG_IGNORE_RETVAL) ? 0 : r; | 160 | return (option_mask32 & FLAG_IGNORE_RETVAL) ? 0 : r; |
144 | |||
145 | #else /* insanity */ | ||
146 | |||
147 | struct fd_pair pipe_pair; | ||
148 | char buf[256]; | ||
149 | int i = 0; | ||
150 | |||
151 | xpiped_pair(pipe_pair); | ||
152 | |||
153 | pid = vfork(); | ||
154 | if (pid < 0) { | ||
155 | bb_perror_msg("fork"); | ||
156 | return -1; | ||
157 | } | ||
158 | |||
159 | /* child */ | ||
160 | if (pid == 0) { | ||
161 | xmove_fd(pipe_pair.wr, 1); | ||
162 | xdup2(1, 2); | ||
163 | if (pipe_pair.rd > 2) | ||
164 | close(pipe_pair.rd); | ||
165 | |||
166 | // umask(0022); // Set up a sane umask | ||
167 | |||
168 | execlp(G.script_name, G.script_name, G.iface, action, G.extra_arg, NULL); | ||
169 | _exit(EXIT_FAILURE); | ||
170 | } | ||
171 | |||
172 | /* parent */ | ||
173 | close(pipe_pair.wr); | ||
174 | |||
175 | while (1) { | ||
176 | if (bb_got_signal && bb_got_signal != SIGCHLD) { | ||
177 | bb_error_msg("killing child"); | ||
178 | kill(pid, SIGTERM); | ||
179 | bb_got_signal = 0; | ||
180 | break; | ||
181 | } | ||
182 | |||
183 | r = read(pipe_pair.rd, &buf[i], 1); | ||
184 | |||
185 | if (buf[i] == '\n' || i == sizeof(buf)-2 || r != 1) { | ||
186 | if (r == 1 && buf[i] != '\n') | ||
187 | i++; | ||
188 | |||
189 | buf[i] = '\0'; | ||
190 | |||
191 | if (i > 0) | ||
192 | bb_error_msg("client: %s", buf); | ||
193 | |||
194 | i = 0; | ||
195 | } else { | ||
196 | i++; | ||
197 | } | ||
198 | |||
199 | if (r != 1) | ||
200 | break; | ||
201 | } | ||
202 | |||
203 | close(pipe_pair.rd); | ||
204 | |||
205 | wait(&r); | ||
206 | |||
207 | if (!WIFEXITED(r) || WEXITSTATUS(r) != 0) { | ||
208 | bb_error_msg("program execution failed, return value is %i", | ||
209 | WEXITSTATUS(r)); | ||
210 | return option_mask32 & FLAG_IGNORE_RETVAL ? 0 : WEXITSTATUS(r); | ||
211 | } | ||
212 | bb_error_msg("program executed successfully"); | ||
213 | return 0; | ||
214 | #endif | ||
215 | } | 161 | } |
216 | 162 | ||
217 | static int network_ioctl(int request, void* data, const char *errmsg) | 163 | static int network_ioctl(int request, void* data, const char *errmsg) |
@@ -228,13 +174,6 @@ static void set_ifreq_to_ifname(struct ifreq *ifreq) | |||
228 | strncpy_IFNAMSIZ(ifreq->ifr_name, G.iface); | 174 | strncpy_IFNAMSIZ(ifreq->ifr_name, G.iface); |
229 | } | 175 | } |
230 | 176 | ||
231 | static const char *strstatus(int status) | ||
232 | { | ||
233 | if (status == IFSTATUS_ERR) | ||
234 | return "error"; | ||
235 | return "down\0up" + (status * 5); | ||
236 | } | ||
237 | |||
238 | static void up_iface(void) | 177 | static void up_iface(void) |
239 | { | 178 | { |
240 | struct ifreq ifrequest; | 179 | struct ifreq ifrequest; |
@@ -474,9 +413,7 @@ static smallint detect_link(void) | |||
474 | } | 413 | } |
475 | 414 | ||
476 | if (status != G.iface_last_status) { | 415 | if (status != G.iface_last_status) { |
477 | //TODO: is it safe to repeatedly do this? | 416 | G.iface_prev_status = G.iface_last_status; |
478 | setenv(IFPLUGD_ENV_PREVIOUS, strstatus(G.iface_last_status), 1); | ||
479 | setenv(IFPLUGD_ENV_CURRENT, strstatus(status), 1); | ||
480 | G.iface_last_status = status; | 417 | G.iface_last_status = status; |
481 | } | 418 | } |
482 | 419 | ||
diff --git a/networking/ifupdown.c b/networking/ifupdown.c index bf88b1c19..2f3dd1d7b 100644 --- a/networking/ifupdown.c +++ b/networking/ifupdown.c | |||
@@ -573,8 +573,10 @@ static int FAST_FUNC dhcp_down(struct interface_defn_t *ifd, execfn *exec) | |||
573 | static int FAST_FUNC dhcp_down(struct interface_defn_t *ifd, execfn *exec) | 573 | static int FAST_FUNC dhcp_down(struct interface_defn_t *ifd, execfn *exec) |
574 | { | 574 | { |
575 | int result; | 575 | int result; |
576 | result = execute("kill " | 576 | result = execute( |
577 | "`cat /var/run/udhcpc.%iface%.pid` 2>/dev/null", ifd, exec); | 577 | "test -f /var/run/udhcpc.%iface%.pid && " |
578 | "kill `cat /var/run/udhcpc.%iface%.pid` 2>/dev/null", | ||
579 | ifd, exec); | ||
578 | /* Also bring the hardware interface down since | 580 | /* Also bring the hardware interface down since |
579 | killing the dhcp client alone doesn't do it. | 581 | killing the dhcp client alone doesn't do it. |
580 | This enables consecutive ifup->ifdown->ifup */ | 582 | This enables consecutive ifup->ifdown->ifup */ |
diff --git a/networking/route.c b/networking/route.c index 241be8e09..a3199621a 100644 --- a/networking/route.c +++ b/networking/route.c | |||
@@ -178,7 +178,7 @@ static NOINLINE void INET_setroute(int action, char **args) | |||
178 | int prefix_len; | 178 | int prefix_len; |
179 | 179 | ||
180 | prefix_len = xatoul_range(prefix+1, 0, 32); | 180 | prefix_len = xatoul_range(prefix+1, 0, 32); |
181 | mask_in_addr(rt) = htonl( ~ (0xffffffffUL >> prefix_len)); | 181 | mask_in_addr(rt) = htonl( ~(0xffffffffUL >> prefix_len)); |
182 | *prefix = '\0'; | 182 | *prefix = '\0'; |
183 | #if HAVE_NEW_ADDRT | 183 | #if HAVE_NEW_ADDRT |
184 | rt.rt_genmask.sa_family = AF_INET; | 184 | rt.rt_genmask.sa_family = AF_INET; |
diff --git a/networking/telnet.c b/networking/telnet.c index 09f75cc84..ec3db0c5e 100644 --- a/networking/telnet.c +++ b/networking/telnet.c | |||
@@ -299,7 +299,7 @@ static void put_iac_subopt(byte c, char *str) | |||
299 | static void put_iac_subopt_autologin(void) | 299 | static void put_iac_subopt_autologin(void) |
300 | { | 300 | { |
301 | int len = strlen(G.autologin) + 6; // (2 + 1 + 1 + strlen + 2) | 301 | int len = strlen(G.autologin) + 6; // (2 + 1 + 1 + strlen + 2) |
302 | const char *user = "USER"; | 302 | const char *p = "USER"; |
303 | 303 | ||
304 | if (G.iaclen + len > IACBUFSIZE) | 304 | if (G.iaclen + len > IACBUFSIZE) |
305 | iac_flush(); | 305 | iac_flush(); |
@@ -310,13 +310,14 @@ static void put_iac_subopt_autologin(void) | |||
310 | put_iac(TELQUAL_IS); | 310 | put_iac(TELQUAL_IS); |
311 | put_iac(NEW_ENV_VAR); | 311 | put_iac(NEW_ENV_VAR); |
312 | 312 | ||
313 | while (*user) | 313 | while (*p) |
314 | put_iac(*user++); | 314 | put_iac(*p++); |
315 | 315 | ||
316 | put_iac(NEW_ENV_VALUE); | 316 | put_iac(NEW_ENV_VALUE); |
317 | 317 | ||
318 | while (*G.autologin) | 318 | p = G.autologin; |
319 | put_iac(*G.autologin++); | 319 | while (*p) |
320 | put_iac(*p++); | ||
320 | 321 | ||
321 | put_iac(IAC); | 322 | put_iac(IAC); |
322 | put_iac(SE); | 323 | put_iac(SE); |
@@ -441,7 +442,6 @@ static void to_sga(void) | |||
441 | static void to_ttype(void) | 442 | static void to_ttype(void) |
442 | { | 443 | { |
443 | /* Tell server we will (or won't) do TTYPE */ | 444 | /* Tell server we will (or won't) do TTYPE */ |
444 | |||
445 | if (G.ttype) | 445 | if (G.ttype) |
446 | put_iac2(WILL, TELOPT_TTYPE); | 446 | put_iac2(WILL, TELOPT_TTYPE); |
447 | else | 447 | else |
@@ -453,7 +453,6 @@ static void to_ttype(void) | |||
453 | static void to_new_environ(void) | 453 | static void to_new_environ(void) |
454 | { | 454 | { |
455 | /* Tell server we will (or will not) do AUTOLOGIN */ | 455 | /* Tell server we will (or will not) do AUTOLOGIN */ |
456 | |||
457 | if (G.autologin) | 456 | if (G.autologin) |
458 | put_iac2(WILL, TELOPT_NEW_ENVIRON); | 457 | put_iac2(WILL, TELOPT_NEW_ENVIRON); |
459 | else | 458 | else |
@@ -505,12 +504,12 @@ static int subneg(byte c) | |||
505 | G.telstate = TS_SUB2; | 504 | G.telstate = TS_SUB2; |
506 | #if ENABLE_FEATURE_TELNET_TTYPE | 505 | #if ENABLE_FEATURE_TELNET_TTYPE |
507 | else | 506 | else |
508 | if (c == TELOPT_TTYPE) | 507 | if (c == TELOPT_TTYPE && G.ttype) |
509 | put_iac_subopt(TELOPT_TTYPE, G.ttype); | 508 | put_iac_subopt(TELOPT_TTYPE, G.ttype); |
510 | #endif | 509 | #endif |
511 | #if ENABLE_FEATURE_TELNET_AUTOLOGIN | 510 | #if ENABLE_FEATURE_TELNET_AUTOLOGIN |
512 | else | 511 | else |
513 | if (c == TELOPT_NEW_ENVIRON) | 512 | if (c == TELOPT_NEW_ENVIRON && G.autologin) |
514 | put_iac_subopt_autologin(); | 513 | put_iac_subopt_autologin(); |
515 | #endif | 514 | #endif |
516 | break; | 515 | break; |
diff --git a/networking/telnetd.c b/networking/telnetd.c index a8c86b62f..ea66a25c0 100644 --- a/networking/telnetd.c +++ b/networking/telnetd.c | |||
@@ -227,7 +227,7 @@ make_new_session( | |||
227 | IF_NOT_FEATURE_TELNETD_STANDALONE(void) | 227 | IF_NOT_FEATURE_TELNETD_STANDALONE(void) |
228 | ) { | 228 | ) { |
229 | #if !ENABLE_FEATURE_TELNETD_STANDALONE | 229 | #if !ENABLE_FEATURE_TELNETD_STANDALONE |
230 | enum { sock = 0 ); | 230 | enum { sock = 0 }; |
231 | #endif | 231 | #endif |
232 | const char *login_argv[2]; | 232 | const char *login_argv[2]; |
233 | struct termios termbuf; | 233 | struct termios termbuf; |
diff --git a/networking/udhcp/leases.c b/networking/udhcp/leases.c index 4999d8079..fad71ec6c 100644 --- a/networking/udhcp/leases.c +++ b/networking/udhcp/leases.c | |||
@@ -60,6 +60,8 @@ struct dyn_lease* FAST_FUNC add_lease( | |||
60 | memset(oldest, 0, sizeof(*oldest)); | 60 | memset(oldest, 0, sizeof(*oldest)); |
61 | if (hostname) { | 61 | if (hostname) { |
62 | char *p; | 62 | char *p; |
63 | |||
64 | hostname_len++; /* include NUL */ | ||
63 | if (hostname_len > sizeof(oldest->hostname)) | 65 | if (hostname_len > sizeof(oldest->hostname)) |
64 | hostname_len = sizeof(oldest->hostname); | 66 | hostname_len = sizeof(oldest->hostname); |
65 | p = safe_strncpy(oldest->hostname, hostname, hostname_len); | 67 | p = safe_strncpy(oldest->hostname, hostname, hostname_len); |
diff --git a/procps/ps.c b/procps/ps.c index b82c126d2..c3b200866 100644 --- a/procps/ps.c +++ b/procps/ps.c | |||
@@ -142,7 +142,7 @@ static unsigned get_kernel_HZ(void) | |||
142 | if (kernel_HZ == (unsigned)-1) | 142 | if (kernel_HZ == (unsigned)-1) |
143 | kernel_HZ = get_HZ_by_waiting(); | 143 | kernel_HZ = get_HZ_by_waiting(); |
144 | 144 | ||
145 | //if (open_read_close("/proc/uptime", buf, sizeof(buf) <= 0) | 145 | //if (open_read_close("/proc/uptime", buf, sizeof(buf)) <= 0) |
146 | // bb_perror_msg_and_die("can't read %s", "/proc/uptime"); | 146 | // bb_perror_msg_and_die("can't read %s", "/proc/uptime"); |
147 | //buf[sizeof(buf)-1] = '\0'; | 147 | //buf[sizeof(buf)-1] = '\0'; |
148 | ///sscanf(buf, "%llu", &seconds_since_boot); | 148 | ///sscanf(buf, "%llu", &seconds_since_boot); |
diff --git a/procps/top.c b/procps/top.c index f5c0a123f..e4afafc4c 100644 --- a/procps/top.c +++ b/procps/top.c | |||
@@ -478,8 +478,8 @@ static unsigned long display_header(int scr_width, int *lines_rem_p) | |||
478 | snprintf(scrbuf, scr_width, | 478 | snprintf(scrbuf, scr_width, |
479 | "Mem: %luK used, %luK free, %luK shrd, %luK buff, %luK cached", | 479 | "Mem: %luK used, %luK free, %luK shrd, %luK buff, %luK cached", |
480 | used, mfree, shared, buffers, cached); | 480 | used, mfree, shared, buffers, cached); |
481 | /* clear screen & go to top */ | 481 | /* go to top & clear to the end of screen */ |
482 | printf(OPT_BATCH_MODE ? "%s\n" : "\e[H\e[J%s\n", scrbuf); | 482 | printf(OPT_BATCH_MODE ? "%s\n" : "\033[H\033[J%s\n", scrbuf); |
483 | (*lines_rem_p)--; | 483 | (*lines_rem_p)--; |
484 | 484 | ||
485 | /* Display CPU time split as percentage of total time | 485 | /* Display CPU time split as percentage of total time |
@@ -518,7 +518,7 @@ static NOINLINE void display_process_list(int lines_rem, int scr_width) | |||
518 | #endif | 518 | #endif |
519 | 519 | ||
520 | /* what info of the processes is shown */ | 520 | /* what info of the processes is shown */ |
521 | printf(OPT_BATCH_MODE ? "%.*s" : "\e[7m%.*s\e[0m", scr_width, | 521 | printf(OPT_BATCH_MODE ? "%.*s" : "\033[7m%.*s\033[0m", scr_width, |
522 | " PID PPID USER STAT VSZ %MEM" | 522 | " PID PPID USER STAT VSZ %MEM" |
523 | IF_FEATURE_TOP_SMP_PROCESS(" CPU") | 523 | IF_FEATURE_TOP_SMP_PROCESS(" CPU") |
524 | IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE(" %CPU") | 524 | IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE(" %CPU") |
@@ -772,7 +772,7 @@ static void display_topmem_header(int scr_width, int *lines_rem_p) | |||
772 | snprintf(linebuf, sizeof(linebuf), | 772 | snprintf(linebuf, sizeof(linebuf), |
773 | "Mem total:%s anon:%s map:%s free:%s", | 773 | "Mem total:%s anon:%s map:%s free:%s", |
774 | S(total), S(anon), S(map), S(mfree)); | 774 | S(total), S(anon), S(map), S(mfree)); |
775 | printf(OPT_BATCH_MODE ? "%.*s\n" : "\e[H\e[J%.*s\n", scr_width, linebuf); | 775 | printf(OPT_BATCH_MODE ? "%.*s\n" : "\033[H\033[J%.*s\n", scr_width, linebuf); |
776 | 776 | ||
777 | snprintf(linebuf, sizeof(linebuf), | 777 | snprintf(linebuf, sizeof(linebuf), |
778 | " slab:%s buf:%s cache:%s dirty:%s write:%s", | 778 | " slab:%s buf:%s cache:%s dirty:%s write:%s", |
diff --git a/procps/watch.c b/procps/watch.c index 126945c40..a1cde9ea0 100644 --- a/procps/watch.c +++ b/procps/watch.c | |||
@@ -52,7 +52,8 @@ int watch_main(int argc UNUSED_PARAM, char **argv) | |||
52 | width = (unsigned)-1; // make sure first time new_width != width | 52 | width = (unsigned)-1; // make sure first time new_width != width |
53 | header = NULL; | 53 | header = NULL; |
54 | while (1) { | 54 | while (1) { |
55 | printf("\033[H\033[J"); | 55 | /* home; clear to the end of screen */ |
56 | printf("\033[H""\033[J"); | ||
56 | if (!(opt & 0x2)) { // no -t | 57 | if (!(opt & 0x2)) { // no -t |
57 | const unsigned time_len = sizeof("1234-67-90 23:56:89"); | 58 | const unsigned time_len = sizeof("1234-67-90 23:56:89"); |
58 | time_t t; | 59 | time_t t; |
diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean index cff33498f..03e397f42 100644 --- a/scripts/Makefile.clean +++ b/scripts/Makefile.clean | |||
@@ -14,7 +14,7 @@ clean := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.clean obj | |||
14 | 14 | ||
15 | # The filename Kbuild has precedence over Makefile | 15 | # The filename Kbuild has precedence over Makefile |
16 | kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src)) | 16 | kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src)) |
17 | include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile) | 17 | -include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile) |
18 | 18 | ||
19 | # Figure out what we need to build from the various variables | 19 | # Figure out what we need to build from the various variables |
20 | # ========================================================================== | 20 | # ========================================================================== |
diff --git a/scripts/gen_build_files.sh b/scripts/gen_build_files.sh new file mode 100755 index 000000000..d2db907f3 --- /dev/null +++ b/scripts/gen_build_files.sh | |||
@@ -0,0 +1,59 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | test $# -ge 2 || { echo "Syntax: $0 SRCTREE OBJTREE"; exit 1; } | ||
4 | |||
5 | # cd to objtree | ||
6 | cd -- "$2" || { echo "Syntax: $0 SRCTREE OBJTREE"; exit 1; } | ||
7 | |||
8 | srctree="$1" | ||
9 | |||
10 | find -type d | while read -r d; do | ||
11 | src="$srctree/$d/Kbuild.src" | ||
12 | dst="$d/Kbuild" | ||
13 | if test -f "$src"; then | ||
14 | echo " CHK $dst" | ||
15 | |||
16 | s=`sed -n 's@^//kbuild:@@p' -- "$srctree/$d"/*.c` | ||
17 | echo "# DO NOT EDIT. This file is generated from Kbuild.src" >"$dst.$$.tmp" | ||
18 | |||
19 | # Why "IFS='' read -r REPLY"?? | ||
20 | # This atrocity is needed to read lines without mangling. | ||
21 | # IFS='' prevents whitespace trimming, | ||
22 | # -r suppresses backslash handling. | ||
23 | while IFS='' read -r REPLY; do | ||
24 | test x"$REPLY" = x"INSERT" && REPLY="$s" | ||
25 | printf "%s\n" "$REPLY" | ||
26 | done <"$src" >>"$dst.$$.tmp" | ||
27 | |||
28 | if test -f "$dst" && cmp -s "$dst.$$.tmp" "$dst"; then | ||
29 | rm -- "$dst.$$.tmp" | ||
30 | else | ||
31 | echo " GEN $dst" | ||
32 | mv -- "$dst.$$.tmp" "$dst" | ||
33 | fi | ||
34 | fi | ||
35 | |||
36 | src="$srctree/$d/Config.src" | ||
37 | dst="$d/Config.in" | ||
38 | if test -f "$src"; then | ||
39 | echo " CHK $dst" | ||
40 | |||
41 | s=`sed -n 's@^//config:@@p' -- "$srctree/$d"/*.c` | ||
42 | echo "# DO NOT EDIT. This file is generated from Config.src" >"$dst.$$.tmp" | ||
43 | |||
44 | while IFS='' read -r REPLY; do | ||
45 | test x"$REPLY" = x"INSERT" && REPLY="$s" | ||
46 | printf "%s\n" "$REPLY" | ||
47 | done <"$src" >>"$dst.$$.tmp" | ||
48 | |||
49 | if test -f "$dst" && cmp -s "$dst.$$.tmp" "$dst"; then | ||
50 | rm -- "$dst.$$.tmp" | ||
51 | else | ||
52 | echo " GEN $dst" | ||
53 | mv -- "$dst.$$.tmp" "$dst" | ||
54 | fi | ||
55 | fi | ||
56 | done | ||
57 | |||
58 | # Last read failed. This is normal. Don't exit with its error code: | ||
59 | exit 0 | ||
diff --git a/scripts/randomtest b/scripts/randomtest index 6b7db9239..8d0d79e64 100755 --- a/scripts/randomtest +++ b/scripts/randomtest | |||
@@ -1,86 +1,88 @@ | |||
1 | #!/bin/sh | 1 | #!/bin/sh |
2 | 2 | ||
3 | # Select which libc to build against | 3 | # If not specified in environment... |
4 | libc="glibc" # assumed native | 4 | if ! test "$LIBC"; then |
5 | # static, cross-compilation | 5 | # Select which libc to build against |
6 | libc="uclibc" | 6 | LIBC="glibc" |
7 | LIBC="uclibc" | ||
8 | fi | ||
7 | # x86 32-bit: | 9 | # x86 32-bit: |
8 | uclibc_cross="i486-linux-uclibc-" | 10 | #CROSS_COMPILER_PREFIX="i486-linux-uclibc-" |
9 | # My system has strange prefix for x86 64-bit uclibc: | 11 | # My system has strange prefix for x86 64-bit uclibc: |
10 | #uclibc_cross="x86_64-pc-linux-gnu-" | 12 | #CROSS_COMPILER_PREFIX="x86_64-pc-linux-gnu-" |
11 | 13 | ||
12 | test -d tree || exit 1 | 14 | if test $# -lt 2 || ! test -d "$1" || test -e "$2"; then |
15 | echo "Usage: $0 SRC_DIR TMP_DIR" | ||
16 | echo | ||
17 | echo "SRC_DIR will be copied to TMP_DIR directory." | ||
18 | echo "Then a random build will be performed." | ||
19 | echo | ||
20 | echo "Useful variables:" | ||
21 | echo "\$LIBC, \$CROSS_COMPILER_PREFIX, \$MAKEOPTS" | ||
22 | exit 1 | ||
23 | fi | ||
13 | 24 | ||
14 | dir=test.$$ | 25 | cp -dpr -- "$1" "$2" || { echo "copy error"; exit 1; } |
15 | while test -e "$dir" -o -e failed."$dir"; do | 26 | cd -- "$2" || { echo "cd $dir error"; exit 1; } |
16 | dir=test."$RANDOM" | ||
17 | done | ||
18 | 27 | ||
19 | cp -dpr tree "$dir" || exit 1 | 28 | # Generate random config |
20 | cd "$dir" || exit 1 | 29 | make randconfig >/dev/null || { echo "randconfig error"; exit 1; } |
21 | |||
22 | echo "Running randconfig test in $dir..." >&2 | ||
23 | |||
24 | make randconfig >/dev/null || exit 1 | ||
25 | 30 | ||
31 | # Tweak resulting config | ||
26 | cat .config \ | 32 | cat .config \ |
27 | | grep -v ^CONFIG_DEBUG_PESSIMIZE= \ | 33 | | grep -v CONFIG_DEBUG_PESSIMIZE \ |
28 | | grep -v CONFIG_WERROR \ | 34 | | grep -v CONFIG_WERROR \ |
29 | | cat >.config.new | 35 | | grep -v CONFIG_CROSS_COMPILER_PREFIX \ |
30 | mv .config.new .config | ||
31 | #echo CONFIG_WERROR=y >>.config | ||
32 | echo '# CONFIG_WERROR is not set' >>.config | ||
33 | |||
34 | test "$libc" = glibc && { | ||
35 | cat .config \ | ||
36 | | grep -v CONFIG_STATIC \ | ||
37 | | grep -v CONFIG_SELINUX \ | 36 | | grep -v CONFIG_SELINUX \ |
38 | | grep -v CONFIG_EFENCE \ | 37 | | grep -v CONFIG_EFENCE \ |
39 | | grep -v CONFIG_DMALLOC \ | 38 | | grep -v CONFIG_DMALLOC \ |
40 | | cat >.config.new | 39 | \ |
40 | | grep -v CONFIG_RFKILL \ | ||
41 | >.config.new | ||
41 | mv .config.new .config | 42 | mv .config.new .config |
42 | echo '# CONFIG_STATIC is not set' >>.config | 43 | echo '# CONFIG_DEBUG_PESSIMIZE is not set' >>.config |
43 | } | 44 | echo '# CONFIG_WERROR is not set' >>.config |
45 | echo "CONFIG_CROSS_COMPILER_PREFIX=\"${CROSS_COMPILER_PREFIX}\"" >>.config | ||
44 | 46 | ||
45 | test "$libc" = uclibc && { | 47 | # If glibc, don't build static |
46 | cat .config \ | 48 | if test x"$LIBC" = x"glibc"; then |
47 | | grep -v ^CONFIG_SELINUX= \ | 49 | cat .config \ |
48 | | grep -v ^CONFIG_EFENCE= \ | 50 | | grep -v CONFIG_STATIC \ |
49 | | grep -v ^CONFIG_DMALLOC= \ | 51 | >.config.new |
50 | | grep -v ^CONFIG_BUILD_LIBBUSYBOX= \ | 52 | mv .config.new .config |
51 | | grep -v ^CONFIG_PAM= \ | 53 | echo '# CONFIG_STATIC is not set' >>.config |
52 | | grep -v ^CONFIG_TASKSET= \ | 54 | fi |
53 | | grep -v ^CONFIG_UNICODE_SUPPORT= \ | 55 | |
54 | | grep -v ^CONFIG_PIE= \ | 56 | # If glibc, build static, and remove some things |
55 | | grep -v CONFIG_STATIC \ | 57 | # likely to not work on uclibc. |
56 | | grep -v CONFIG_CROSS_COMPILER_PREFIX \ | 58 | if test x"$LIBC" = x"uclibc"; then |
57 | | cat >.config.new | 59 | cat .config \ |
58 | mv .config.new .config | 60 | | grep -v CONFIG_STATIC \ |
59 | echo 'CONFIG_CROSS_COMPILER_PREFIX="'"$uclibc_cross"'"' >>.config | 61 | | grep -v CONFIG_BUILD_LIBBUSYBOX \ |
60 | echo 'CONFIG_STATIC=y' >>.config | 62 | | grep -v CONFIG_TASKSET \ |
61 | } | 63 | | grep -v CONFIG_UNICODE_SUPPORT \ |
64 | | grep -v CONFIG_PIE \ | ||
65 | >.config.new | ||
66 | mv .config.new .config | ||
67 | echo 'CONFIG_STATIC=y' >>.config | ||
68 | fi | ||
62 | 69 | ||
63 | # If STATIC, remove some things | 70 | # If STATIC, remove some things. |
64 | # PAM with static linking is probably pointless | 71 | # PAM with static linking is probably pointless |
65 | # (but I need to try - now I don't have libpam.a on my system, only libpam.so) | 72 | # (but I need to try - now I don't have libpam.a on my system, only libpam.so) |
66 | grep -q ^CONFIG_STATIC= .config && { | 73 | if grep -q "^CONFIG_STATIC=y" .config; then |
67 | cat .config \ | 74 | cat .config \ |
68 | | grep -v ^CONFIG_PAM= \ | 75 | | grep -v CONFIG_PAM \ |
69 | | cat >.config.new | 76 | >.config.new |
70 | mv .config.new .config | 77 | mv .config.new .config |
71 | } | 78 | fi |
72 | 79 | ||
73 | # Regenerate .config with default answers for yanked-off options | 80 | # Regenerate .config with default answers for yanked-off options |
74 | { yes "" | make oldconfig >/dev/null; } || exit 1 | 81 | # (most of default answers are "no"). |
75 | 82 | { yes "" | make oldconfig >/dev/null; } || { echo "oldconfig error"; exit 1; } | |
76 | nice -n 10 make $MAKEOPTS 2>&1 | tee -a make.log | ||
77 | 83 | ||
78 | test -x busybox && { | 84 | # Build! |
79 | cd .. | 85 | nice -n 10 make $MAKEOPTS 2>&1 | tee make.log |
80 | rm -rf "$dir" | ||
81 | exit 0 | ||
82 | } | ||
83 | 86 | ||
84 | cd .. | 87 | # Return exitcode 1 if busybox executable does not exist |
85 | mv "$dir" "failed.$dir" | 88 | test -x busybox |
86 | exit 1 | ||
diff --git a/scripts/randomtest.loop b/scripts/randomtest.loop index 28edb6732..311536df8 100755 --- a/scripts/randomtest.loop +++ b/scripts/randomtest.loop | |||
@@ -1,10 +1,38 @@ | |||
1 | #!/bin/sh | 1 | #!/bin/sh |
2 | 2 | ||
3 | test -d "$1" || { echo "'$1' is not a directory"; exit 1; } | ||
4 | test -x "$1/scripts/randomtest" || { echo "No scripts/randomtest in '$1'"; exit 1; } | ||
5 | |||
6 | export LIBC="uclibc" | ||
7 | export CROSS_COMPILER_PREFIX="i486-linux-uclibc-" | ||
8 | export MAKEOPTS="-j9" | ||
9 | |||
3 | cnt=0 | 10 | cnt=0 |
4 | fail=0 | 11 | fail=0 |
5 | |||
6 | while sleep 1; do | 12 | while sleep 1; do |
7 | echo "Passes: $cnt Failures: $fail" | 13 | echo "Passes: $cnt Failures: $fail" |
8 | ./randomtest >/dev/null || exit #let fail++ | 14 | dir="test.$$" |
9 | let cnt++ | 15 | while test -e "$dir" -o -e "failed.$dir"; do |
16 | dir="test.$$.$RANDOM" | ||
17 | done | ||
18 | echo "Running randconfig test in $dir..." | ||
19 | if ! "$1/scripts/randomtest" "$1" "$dir" >/dev/null; then | ||
20 | mv -- "$dir" "failed.$dir" | ||
21 | echo "Failed build in: failed.$dir" | ||
22 | exit 1 # you may comment this out... | ||
23 | let fail++ | ||
24 | else | ||
25 | ( | ||
26 | cd -- "$dir/testsuite" || exit 1 | ||
27 | echo "Running testsuite in $dir..." | ||
28 | SKIP_KNOWN_BUGS=1 SKIP_INTERNET_TESTS=1 ./runtest -v >runtest.log 2>&1 | ||
29 | ) | ||
30 | if test $? != 0; then | ||
31 | echo "Failed runtest in $dir" | ||
32 | exit 1 | ||
33 | fi | ||
34 | tail -n10 -- "$dir/testsuite/runtest.log" | ||
35 | rm -rf -- "$dir" | ||
36 | fi | ||
37 | let cnt++ | ||
10 | done | 38 | done |
diff --git a/shell/Config.in b/shell/Config.in index 3b1650615..cf599dff4 100644 --- a/shell/Config.in +++ b/shell/Config.in | |||
@@ -354,9 +354,20 @@ config CTTYHACK | |||
354 | It analyzes stdin with various ioctls, trying to determine whether | 354 | It analyzes stdin with various ioctls, trying to determine whether |
355 | it is a /dev/ttyN or /dev/ttySN (virtual terminal or serial line). | 355 | it is a /dev/ttyN or /dev/ttySN (virtual terminal or serial line). |
356 | If it detects one, it closes stdin/out/err and reopens that device. | 356 | If it detects one, it closes stdin/out/err and reopens that device. |
357 | Then it executes given program. Usage example for /etc/inittab | 357 | Then it executes given program. Opening the device will make |
358 | (for busybox init): | 358 | that device a controlling tty. This may require cttyhack |
359 | to be a session leader. | ||
360 | |||
361 | Example for /etc/inittab (for busybox init): | ||
359 | 362 | ||
360 | ::respawn:/bin/cttyhack /bin/sh | 363 | ::respawn:/bin/cttyhack /bin/sh |
361 | 364 | ||
365 | Giving controlling tty to shell running with PID 1: | ||
366 | |||
367 | $ exec cttyhack sh | ||
368 | |||
369 | Starting an interactive shell from boot shell script: | ||
370 | |||
371 | setsid cttyhack sh | ||
372 | |||
362 | endmenu | 373 | endmenu |
diff --git a/shell/README b/shell/README index 59efe499f..550c712d3 100644 --- a/shell/README +++ b/shell/README | |||
@@ -1,108 +1,82 @@ | |||
1 | Various bits of what is known about busybox shells, in no particular order. | 1 | http://www.opengroup.org/onlinepubs/9699919799/ |
2 | 2 | Open Group Base Specifications Issue 7 | |
3 | 2008-02-14 | 3 | |
4 | ash: does not restore tty pgrp if killed by HUP. Symptom: Midnight Commander | 4 | |
5 | is backgrounded if you started ash under it, and then killed it with HUP. | 5 | http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap01.html |
6 | 6 | Shell & Utilities | |
7 | 2007-11-23 | 7 | |
8 | hush: fixed bogus glob handling; fixed exec <"$1"; added test and echo builtins | 8 | It says that any of the standard utilities may be implemented |
9 | 9 | as a regular shell built-in. It gives a list of utilities which | |
10 | 2007-06-13 | 10 | are usually implemented that way (and some of them can only |
11 | hush: exec <"$1" doesn't do parameter subst | 11 | be implemented as built-ins, like "alias"): |
12 | 12 | ||
13 | 2007-05-24 | 13 | alias |
14 | hush: environment-related memory leak plugged, with net code size | 14 | bg |
15 | decrease. | 15 | cd |
16 | 16 | command | |
17 | 2007-05-24 | 17 | false |
18 | hush: '( echo ${name )' will show syntax error message, but prompt | 18 | fc |
19 | doesn't return (need to press <enter>). Pressing Ctrl-C, <enter>, | 19 | fg |
20 | '( echo ${name )' again, Ctrl-C segfaults. | 20 | getopts |
21 | 21 | jobs | |
22 | 2007-05-21 | 22 | kill |
23 | hush: environment cannot be handled by libc routines as they are leaky | 23 | newgrp |
24 | (by API design and thus unfixable): hush will leak memory in this script, | 24 | pwd |
25 | bash does not: | 25 | read |
26 | pid=$$ | 26 | true |
27 | while true; do | 27 | umask |
28 | unset t; | 28 | unalias |
29 | t=111111111111111111111111111111111111111111111111111111111111111111111111 | 29 | wait |
30 | export t | 30 | |
31 | ps -o vsz,pid,comm | grep " $pid " | 31 | |
32 | done | 32 | http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html |
33 | The fix is to not use setenv/putenv/unsetenv but manipulate env ourself. TODO. | 33 | Shell Command Language |
34 | hush: meanwhile, first three command subst bugs mentioned below are fixed. :) | 34 | |
35 | 35 | It says that shell must implement special built-ins. Special built-ins | |
36 | 2007-05-06 | 36 | differ from regular ones by the fact that variable assignments |
37 | hush: more bugs spotted. Comparison with bash: | 37 | done on special builtin is *PRESERVED*. That is, |
38 | bash-3.2# echo "TEST`date;echo;echo`BEST" | 38 | |
39 | TESTSun May 6 09:21:05 CEST 2007BEST [we dont strip eols] | 39 | VAR=VAL special_builtin; echo $VAR |
40 | bash-3.2# echo "TEST`echo '$(echo ZZ)'`BEST" | 40 | |
41 | TEST$(echo ZZ)BEST [we execute inner echo] | 41 | should print VAL. |
42 | bash-3.2# echo "TEST`echo "'"`BEST" | 42 | |
43 | TEST'BEST [we totally mess up this one] | 43 | (Another distinction is that an error in special built-in should |
44 | bash-3.2# echo `sleep 5` | 44 | abort the shell, but this is not such a critical difference, |
45 | [Ctrl-C should work, Ctrl-Z should do nothing][we totally mess up this one] | 45 | and moreover, at least bash's "set" does not follow this rule, |
46 | bash-3.2# if true; then | 46 | which is even codified in autoconf now...). |
47 | > [Ctrl-C] | 47 | |
48 | bash-3.2# [we re-issue "> "] | 48 | List of special builtins: |
49 | bash-3.2# if echo `sleep 5`; then | 49 | |
50 | > true; fi [we execute sleep before "> "] | 50 | . file |
51 | 51 | : [argument...] | |
52 | 2007-05-04 | 52 | break [n] |
53 | hush: made ctrl-Z/C work correctly for "while true; do true; done" | 53 | continue [n] |
54 | (namely, it backgrounds/interrupts entire "while") | 54 | eval [argument...] |
55 | 55 | exec [command [argument...]] | |
56 | 2007-05-03 | 56 | exit [n] |
57 | hush: new bug spotted: Ctrl-C on "while true; do true; done" doesn't | 57 | export name[=word]... |
58 | work right: | 58 | export -p |
59 | # while true; do true; done | 59 | readonly name[=word]... |
60 | [1] 0 true <-- pressing Ctrl-C several times... | 60 | readonly -p |
61 | [2] 0 true | 61 | return [n] |
62 | [3] 0 true | 62 | set [-abCefhmnuvx] [-o option] [argument...] |
63 | Segmentation fault | 63 | set [+abCefhmnuvx] [+o option] [argument...] |
64 | 64 | set -- [argument...] | |
65 | 2007-05-03 | 65 | set -o |
66 | hush: update on "sleep 1 | exit 3; echo $?" bug. | 66 | set +o |
67 | parse_stream_outer() repeatedly calls parse_stream(). | 67 | shift [n] |
68 | parse_stream() is now fixed to stop on ';' in this example, | 68 | times |
69 | fixing it (parse_stream_outer() will call parse_stream() 1st time, | 69 | trap n [condition...] |
70 | execute the parse tree, call parse_stream() 2nd time and execute the tree). | 70 | trap [action condition...] |
71 | But it's not the end of story. | 71 | unset [-fv] name... |
72 | In more complex situations we _must_ parse way farther before executing. | 72 | |
73 | Example #2: "{ sleep 1 | exit 3; echo $?; ...few_lines... } >file". | 73 | In practice, no one uses this obscure feature - none of these builtins |
74 | Because of redirection, we cannot execute 1st pipe before we parse it all. | 74 | gives any special reasons to play such dirty tricks. |
75 | We probably need to learn to store $var expressions in parse tree. | 75 | |
76 | Debug printing of parse tree would be nice too. | 76 | However. This section says that *function invocation* should act |
77 | 77 | similar to special built-in. That is, variable assignments | |
78 | 2007-04-28 | 78 | done on function invocation should be preserved after function invocation. |
79 | hush: Ctrl-C and Ctrl-Z for single NOFORK commands are working. | 79 | |
80 | Memory and other resource leaks (opendir) are not addressed | 80 | This is significant: it is not unthinkable to want to run a function |
81 | (testcase is "rm -i" interrupted by ctrl-c). | 81 | with some variables set to special values. But because of the above, |
82 | 82 | it does not work: variable will "leak" out of the function. | |
83 | 2007-04-21 | ||
84 | hush: "sleep 5 | sleep 6" + Ctrl-Z + fg seems to work. | ||
85 | "rm -i" + Ctrl-C, "sleep 5" + Ctrl-Z still doesn't work | ||
86 | for SH_STANDALONE case :( | ||
87 | |||
88 | 2007-04-21 | ||
89 | hush: fixed non-backgrounding of "sleep 1 &" and totally broken | ||
90 | "sleep 1 | sleep 2 &". Noticed a bug where successive jobs | ||
91 | get numbers 1,2,3 even when job #1 has exited before job# 2 is started. | ||
92 | (bash reuses #1 in this case) | ||
93 | |||
94 | 2007-04-21 | ||
95 | hush: "sleep 1 | exit 3; echo $?" prints 0 because $? is substituted | ||
96 | _before_ pipe gets executed!! run_list_real() already has "pipe;echo" | ||
97 | parsed and handed to it for execution, so it sees "pipe"; "echo 0". | ||
98 | |||
99 | 2007-04-21 | ||
100 | hush: removed setsid() and made job control sort-of-sometimes-work. | ||
101 | Ctrl-C in "rm -i" works now except for SH_STANDALONE case. | ||
102 | "sleep 1 | exit 3" + "echo $?" works, "sleep 1 | exit 3; echo $?" | ||
103 | shows exitcode 0 (should be 3). "sleep 1 | sleep 2 &" fails horribly. | ||
104 | |||
105 | 2007-04-14 | ||
106 | lash, hush: both do setsid() and as a result don't have ctty! | ||
107 | Ctrl-C doesn't work for any child (try rm -i), etc... | ||
108 | lash: bare ">file" doesn't create a file (hush works) | ||
diff --git a/shell/ash.c b/shell/ash.c index 5d8415a79..16a331bb0 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -257,6 +257,7 @@ struct globals_misc { | |||
257 | 257 | ||
258 | /* indicates specified signal received */ | 258 | /* indicates specified signal received */ |
259 | uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */ | 259 | uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */ |
260 | uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */ | ||
260 | char *trap[NSIG]; | 261 | char *trap[NSIG]; |
261 | char **trap_ptr; /* used only by "trap hack" */ | 262 | char **trap_ptr; /* used only by "trap hack" */ |
262 | 263 | ||
@@ -285,6 +286,7 @@ extern struct globals_misc *const ash_ptr_to_globals_misc; | |||
285 | #define optlist (G_misc.optlist ) | 286 | #define optlist (G_misc.optlist ) |
286 | #define sigmode (G_misc.sigmode ) | 287 | #define sigmode (G_misc.sigmode ) |
287 | #define gotsig (G_misc.gotsig ) | 288 | #define gotsig (G_misc.gotsig ) |
289 | #define may_have_traps (G_misc.may_have_traps ) | ||
288 | #define trap (G_misc.trap ) | 290 | #define trap (G_misc.trap ) |
289 | #define trap_ptr (G_misc.trap_ptr ) | 291 | #define trap_ptr (G_misc.trap_ptr ) |
290 | #define random_gen (G_misc.random_gen ) | 292 | #define random_gen (G_misc.random_gen ) |
@@ -382,7 +384,7 @@ raise_interrupt(void) | |||
382 | /* Signal is not automatically unmasked after it is raised, | 384 | /* Signal is not automatically unmasked after it is raised, |
383 | * do it ourself - unmask all signals */ | 385 | * do it ourself - unmask all signals */ |
384 | sigprocmask_allsigs(SIG_UNBLOCK); | 386 | sigprocmask_allsigs(SIG_UNBLOCK); |
385 | /* pending_sig = 0; - now done in onsig() */ | 387 | /* pending_sig = 0; - now done in signal_handler() */ |
386 | 388 | ||
387 | ex_type = EXSIG; | 389 | ex_type = EXSIG; |
388 | if (gotsig[SIGINT - 1] && !trap[SIGINT]) { | 390 | if (gotsig[SIGINT - 1] && !trap[SIGINT]) { |
@@ -2743,9 +2745,7 @@ pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
2743 | /* ============ ... */ | 2745 | /* ============ ... */ |
2744 | 2746 | ||
2745 | 2747 | ||
2746 | #define IBUFSIZ COMMON_BUFSIZE | 2748 | #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024) |
2747 | /* buffer for top level input file */ | ||
2748 | #define basebuf bb_common_bufsiz1 | ||
2749 | 2749 | ||
2750 | /* Syntax classes */ | 2750 | /* Syntax classes */ |
2751 | #define CWORD 0 /* character is nothing special */ | 2751 | #define CWORD 0 /* character is nothing special */ |
@@ -3424,10 +3424,10 @@ ignoresig(int signo) | |||
3424 | } | 3424 | } |
3425 | 3425 | ||
3426 | /* | 3426 | /* |
3427 | * Signal handler. Only one usage site - in setsignal() | 3427 | * Only one usage site - in setsignal() |
3428 | */ | 3428 | */ |
3429 | static void | 3429 | static void |
3430 | onsig(int signo) | 3430 | signal_handler(int signo) |
3431 | { | 3431 | { |
3432 | gotsig[signo - 1] = 1; | 3432 | gotsig[signo - 1] = 1; |
3433 | 3433 | ||
@@ -3524,7 +3524,7 @@ setsignal(int signo) | |||
3524 | act.sa_handler = SIG_DFL; | 3524 | act.sa_handler = SIG_DFL; |
3525 | switch (new_act) { | 3525 | switch (new_act) { |
3526 | case S_CATCH: | 3526 | case S_CATCH: |
3527 | act.sa_handler = onsig; | 3527 | act.sa_handler = signal_handler; |
3528 | act.sa_flags = 0; /* matters only if !DFL and !IGN */ | 3528 | act.sa_flags = 0; /* matters only if !DFL and !IGN */ |
3529 | sigfillset(&act.sa_mask); /* ditto */ | 3529 | sigfillset(&act.sa_mask); /* ditto */ |
3530 | break; | 3530 | break; |
@@ -4083,9 +4083,9 @@ dowait(int wait_flags, struct job *job) | |||
4083 | } | 4083 | } |
4084 | 4084 | ||
4085 | static int | 4085 | static int |
4086 | blocking_wait_with_raise_on_sig(struct job *job) | 4086 | blocking_wait_with_raise_on_sig(void) |
4087 | { | 4087 | { |
4088 | pid_t pid = dowait(DOWAIT_BLOCK, job); | 4088 | pid_t pid = dowait(DOWAIT_BLOCK, NULL); |
4089 | if (pid <= 0 && pending_sig) | 4089 | if (pid <= 0 && pending_sig) |
4090 | raise_exception(EXSIG); | 4090 | raise_exception(EXSIG); |
4091 | return pid; | 4091 | return pid; |
@@ -4281,14 +4281,21 @@ waitcmd(int argc UNUSED_PARAM, char **argv) | |||
4281 | jp->waited = 1; | 4281 | jp->waited = 1; |
4282 | jp = jp->prev_job; | 4282 | jp = jp->prev_job; |
4283 | } | 4283 | } |
4284 | blocking_wait_with_raise_on_sig(); | ||
4284 | /* man bash: | 4285 | /* man bash: |
4285 | * "When bash is waiting for an asynchronous command via | 4286 | * "When bash is waiting for an asynchronous command via |
4286 | * the wait builtin, the reception of a signal for which a trap | 4287 | * the wait builtin, the reception of a signal for which a trap |
4287 | * has been set will cause the wait builtin to return immediately | 4288 | * has been set will cause the wait builtin to return immediately |
4288 | * with an exit status greater than 128, immediately after which | 4289 | * with an exit status greater than 128, immediately after which |
4289 | * the trap is executed." | 4290 | * the trap is executed." |
4290 | * Do we do it that way? */ | 4291 | * |
4291 | blocking_wait_with_raise_on_sig(NULL); | 4292 | * blocking_wait_with_raise_on_sig raises signal handlers |
4293 | * if it gets no pid (pid < 0). However, | ||
4294 | * if child sends us a signal *and immediately exits*, | ||
4295 | * blocking_wait_with_raise_on_sig gets pid > 0 | ||
4296 | * and does not handle pending_sig. Check this case: */ | ||
4297 | if (pending_sig) | ||
4298 | raise_exception(EXSIG); | ||
4292 | } | 4299 | } |
4293 | } | 4300 | } |
4294 | 4301 | ||
@@ -4308,7 +4315,7 @@ waitcmd(int argc UNUSED_PARAM, char **argv) | |||
4308 | job = getjob(*argv, 0); | 4315 | job = getjob(*argv, 0); |
4309 | /* loop until process terminated or stopped */ | 4316 | /* loop until process terminated or stopped */ |
4310 | while (job->state == JOBRUNNING) | 4317 | while (job->state == JOBRUNNING) |
4311 | blocking_wait_with_raise_on_sig(NULL); | 4318 | blocking_wait_with_raise_on_sig(); |
4312 | job->waited = 1; | 4319 | job->waited = 1; |
4313 | retval = getstatus(job); | 4320 | retval = getstatus(job); |
4314 | repeat: ; | 4321 | repeat: ; |
@@ -5715,7 +5722,11 @@ rmescapes(char *str, int flag) | |||
5715 | size_t fulllen = len + strlen(p) + 1; | 5722 | size_t fulllen = len + strlen(p) + 1; |
5716 | 5723 | ||
5717 | if (flag & RMESCAPE_GROW) { | 5724 | if (flag & RMESCAPE_GROW) { |
5725 | int strloc = str - (char *)stackblock(); | ||
5718 | r = makestrspace(fulllen, expdest); | 5726 | r = makestrspace(fulllen, expdest); |
5727 | /* p and str may be invalidated by makestrspace */ | ||
5728 | str = (char *)stackblock() + strloc; | ||
5729 | p = str + len; | ||
5719 | } else if (flag & RMESCAPE_HEAP) { | 5730 | } else if (flag & RMESCAPE_HEAP) { |
5720 | r = ckmalloc(fulllen); | 5731 | r = ckmalloc(fulllen); |
5721 | } else { | 5732 | } else { |
@@ -8819,7 +8830,7 @@ evalsubshell(union node *n, int flags) | |||
8819 | int status; | 8830 | int status; |
8820 | 8831 | ||
8821 | expredir(n->nredir.redirect); | 8832 | expredir(n->nredir.redirect); |
8822 | if (!backgnd && flags & EV_EXIT && !trap[0]) | 8833 | if (!backgnd && (flags & EV_EXIT) && !may_have_traps) |
8823 | goto nofork; | 8834 | goto nofork; |
8824 | INT_OFF; | 8835 | INT_OFF; |
8825 | jp = makejob(/*n,*/ 1); | 8836 | jp = makejob(/*n,*/ 1); |
@@ -8832,10 +8843,11 @@ evalsubshell(union node *n, int flags) | |||
8832 | ash_msg_and_raise_error("unable to spawn shell"); | 8843 | ash_msg_and_raise_error("unable to spawn shell"); |
8833 | #endif | 8844 | #endif |
8834 | if (forkshell(jp, n, backgnd) == 0) { | 8845 | if (forkshell(jp, n, backgnd) == 0) { |
8846 | /* child */ | ||
8835 | INT_ON; | 8847 | INT_ON; |
8836 | flags |= EV_EXIT; | 8848 | flags |= EV_EXIT; |
8837 | if (backgnd) | 8849 | if (backgnd) |
8838 | flags &=~ EV_TESTED; | 8850 | flags &= ~EV_TESTED; |
8839 | nofork: | 8851 | nofork: |
8840 | redirect(n->nredir.redirect, 0); | 8852 | redirect(n->nredir.redirect, 0); |
8841 | evaltreenr(n->nredir.n, flags); | 8853 | evaltreenr(n->nredir.n, flags); |
@@ -9365,7 +9377,9 @@ static const struct builtincmd builtintab[] = { | |||
9365 | { BUILTIN_SPEC_REG "return" , returncmd }, | 9377 | { BUILTIN_SPEC_REG "return" , returncmd }, |
9366 | { BUILTIN_SPEC_REG "set" , setcmd }, | 9378 | { BUILTIN_SPEC_REG "set" , setcmd }, |
9367 | { BUILTIN_SPEC_REG "shift" , shiftcmd }, | 9379 | { BUILTIN_SPEC_REG "shift" , shiftcmd }, |
9380 | #if ENABLE_ASH_BASH_COMPAT | ||
9368 | { BUILTIN_SPEC_REG "source" , dotcmd }, | 9381 | { BUILTIN_SPEC_REG "source" , dotcmd }, |
9382 | #endif | ||
9369 | #if ENABLE_ASH_BUILTIN_TEST | 9383 | #if ENABLE_ASH_BUILTIN_TEST |
9370 | { BUILTIN_REGULAR "test" , testcmd }, | 9384 | { BUILTIN_REGULAR "test" , testcmd }, |
9371 | #endif | 9385 | #endif |
@@ -9646,16 +9660,19 @@ evalcommand(union node *cmd, int flags) | |||
9646 | /* goes through to shellexec() */ | 9660 | /* goes through to shellexec() */ |
9647 | #endif | 9661 | #endif |
9648 | /* Fork off a child process if necessary. */ | 9662 | /* Fork off a child process if necessary. */ |
9649 | if (!(flags & EV_EXIT) || trap[0]) { | 9663 | if (!(flags & EV_EXIT) || may_have_traps) { |
9650 | INT_OFF; | 9664 | INT_OFF; |
9651 | jp = makejob(/*cmd,*/ 1); | 9665 | jp = makejob(/*cmd,*/ 1); |
9652 | if (forkshell(jp, cmd, FORK_FG) != 0) { | 9666 | if (forkshell(jp, cmd, FORK_FG) != 0) { |
9667 | /* parent */ | ||
9653 | exitstatus = waitforjob(jp); | 9668 | exitstatus = waitforjob(jp); |
9654 | INT_ON; | 9669 | INT_ON; |
9655 | TRACE(("forked child exited with %d\n", exitstatus)); | 9670 | TRACE(("forked child exited with %d\n", exitstatus)); |
9656 | break; | 9671 | break; |
9657 | } | 9672 | } |
9673 | /* child */ | ||
9658 | FORCE_INT_ON; | 9674 | FORCE_INT_ON; |
9675 | /* fall through to exec'ing external program */ | ||
9659 | } | 9676 | } |
9660 | listsetvar(varlist.list, VEXPORT|VSTACK); | 9677 | listsetvar(varlist.list, VEXPORT|VSTACK); |
9661 | shellexec(argv, path, cmdentry.u.index); | 9678 | shellexec(argv, path, cmdentry.u.index); |
@@ -9900,12 +9917,12 @@ preadfd(void) | |||
9900 | #if ENABLE_FEATURE_EDITING | 9917 | #if ENABLE_FEATURE_EDITING |
9901 | retry: | 9918 | retry: |
9902 | if (!iflag || g_parsefile->fd != STDIN_FILENO) | 9919 | if (!iflag || g_parsefile->fd != STDIN_FILENO) |
9903 | nr = nonblock_safe_read(g_parsefile->fd, buf, BUFSIZ - 1); | 9920 | nr = nonblock_safe_read(g_parsefile->fd, buf, IBUFSIZ - 1); |
9904 | else { | 9921 | else { |
9905 | #if ENABLE_FEATURE_TAB_COMPLETION | 9922 | #if ENABLE_FEATURE_TAB_COMPLETION |
9906 | line_input_state->path_lookup = pathval(); | 9923 | line_input_state->path_lookup = pathval(); |
9907 | #endif | 9924 | #endif |
9908 | nr = read_line_input(cmdedit_prompt, buf, BUFSIZ, line_input_state); | 9925 | nr = read_line_input(cmdedit_prompt, buf, IBUFSIZ, line_input_state); |
9909 | if (nr == 0) { | 9926 | if (nr == 0) { |
9910 | /* Ctrl+C pressed */ | 9927 | /* Ctrl+C pressed */ |
9911 | if (trap[SIGINT]) { | 9928 | if (trap[SIGINT]) { |
@@ -9922,7 +9939,7 @@ preadfd(void) | |||
9922 | } | 9939 | } |
9923 | } | 9940 | } |
9924 | #else | 9941 | #else |
9925 | nr = nonblock_safe_read(g_parsefile->fd, buf, BUFSIZ - 1); | 9942 | nr = nonblock_safe_read(g_parsefile->fd, buf, IBUFSIZ - 1); |
9926 | #endif | 9943 | #endif |
9927 | 9944 | ||
9928 | #if 0 | 9945 | #if 0 |
@@ -12484,36 +12501,43 @@ find_dot_file(char *name) | |||
12484 | static int FAST_FUNC | 12501 | static int FAST_FUNC |
12485 | dotcmd(int argc, char **argv) | 12502 | dotcmd(int argc, char **argv) |
12486 | { | 12503 | { |
12504 | char *fullname; | ||
12487 | struct strlist *sp; | 12505 | struct strlist *sp; |
12488 | volatile struct shparam saveparam; | 12506 | volatile struct shparam saveparam; |
12489 | int status = 0; | ||
12490 | 12507 | ||
12491 | for (sp = cmdenviron; sp; sp = sp->next) | 12508 | for (sp = cmdenviron; sp; sp = sp->next) |
12492 | setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED); | 12509 | setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED); |
12493 | 12510 | ||
12494 | if (argv[1]) { /* That's what SVR2 does */ | 12511 | if (!argv[1]) { |
12495 | char *fullname = find_dot_file(argv[1]); | 12512 | /* bash says: "bash: .: filename argument required" */ |
12496 | argv += 2; | 12513 | return 2; /* bash compat */ |
12497 | argc -= 2; | ||
12498 | if (argc) { /* argc > 0, argv[0] != NULL */ | ||
12499 | saveparam = shellparam; | ||
12500 | shellparam.malloced = 0; | ||
12501 | shellparam.nparam = argc; | ||
12502 | shellparam.p = argv; | ||
12503 | }; | ||
12504 | |||
12505 | setinputfile(fullname, INPUT_PUSH_FILE); | ||
12506 | commandname = fullname; | ||
12507 | cmdloop(0); | ||
12508 | popfile(); | ||
12509 | |||
12510 | if (argc) { | ||
12511 | freeparam(&shellparam); | ||
12512 | shellparam = saveparam; | ||
12513 | }; | ||
12514 | status = exitstatus; | ||
12515 | } | 12514 | } |
12516 | return status; | 12515 | |
12516 | /* "false; . empty_file; echo $?" should print 0, not 1: */ | ||
12517 | exitstatus = 0; | ||
12518 | |||
12519 | fullname = find_dot_file(argv[1]); | ||
12520 | |||
12521 | argv += 2; | ||
12522 | argc -= 2; | ||
12523 | if (argc) { /* argc > 0, argv[0] != NULL */ | ||
12524 | saveparam = shellparam; | ||
12525 | shellparam.malloced = 0; | ||
12526 | shellparam.nparam = argc; | ||
12527 | shellparam.p = argv; | ||
12528 | }; | ||
12529 | |||
12530 | setinputfile(fullname, INPUT_PUSH_FILE); | ||
12531 | commandname = fullname; | ||
12532 | cmdloop(0); | ||
12533 | popfile(); | ||
12534 | |||
12535 | if (argc) { | ||
12536 | freeparam(&shellparam); | ||
12537 | shellparam = saveparam; | ||
12538 | }; | ||
12539 | |||
12540 | return exitstatus; | ||
12517 | } | 12541 | } |
12518 | 12542 | ||
12519 | static int FAST_FUNC | 12543 | static int FAST_FUNC |
@@ -12824,6 +12848,8 @@ trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
12824 | action = ckstrdup(action); | 12848 | action = ckstrdup(action); |
12825 | } | 12849 | } |
12826 | free(trap[signo]); | 12850 | free(trap[signo]); |
12851 | if (action) | ||
12852 | may_have_traps = 1; | ||
12827 | trap[signo] = action; | 12853 | trap[signo] = action; |
12828 | if (signo != 0) | 12854 | if (signo != 0) |
12829 | setsignal(signo); | 12855 | setsignal(signo); |
@@ -13219,7 +13245,8 @@ static void | |||
13219 | init(void) | 13245 | init(void) |
13220 | { | 13246 | { |
13221 | /* from input.c: */ | 13247 | /* from input.c: */ |
13222 | basepf.next_to_pgetc = basepf.buf = basebuf; | 13248 | /* we will never free this */ |
13249 | basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ); | ||
13223 | 13250 | ||
13224 | /* from trap.c: */ | 13251 | /* from trap.c: */ |
13225 | signal(SIGCHLD, SIG_DFL); | 13252 | signal(SIGCHLD, SIG_DFL); |
diff --git a/shell/ash_test/ash-misc/source2.right b/shell/ash_test/ash-misc/source2.right new file mode 100644 index 000000000..ce7171c87 --- /dev/null +++ b/shell/ash_test/ash-misc/source2.right | |||
@@ -0,0 +1 @@ | |||
Done: 0 | |||
diff --git a/shell/ash_test/ash-misc/source2.tests b/shell/ash_test/ash-misc/source2.tests new file mode 100755 index 000000000..1870cdf7e --- /dev/null +++ b/shell/ash_test/ash-misc/source2.tests | |||
@@ -0,0 +1,3 @@ | |||
1 | false | ||
2 | . /dev/null | ||
3 | echo Done: $? | ||
diff --git a/shell/ash_test/ash-redir/redir3.tests b/shell/ash_test/ash-redir/redir3.tests index f50a7674c..e37d5e45a 100755 --- a/shell/ash_test/ash-redir/redir3.tests +++ b/shell/ash_test/ash-redir/redir3.tests | |||
@@ -1,4 +1,4 @@ | |||
1 | # redirects to closed descriptors should not leave these descriptors" | 1 | # redirects to closed descriptors should not leave these descriptors |
2 | # open afterwards | 2 | # open afterwards |
3 | echo TEST 9>/dev/null | 3 | echo TEST 9>/dev/null |
4 | echo MUST ERROR OUT >&9 | 4 | echo MUST ERROR OUT >&9 |
diff --git a/shell/ash_test/ash-redir/redir7.tests b/shell/ash_test/ash-redir/redir7.tests index 17d1040e0..ca3979a81 100755 --- a/shell/ash_test/ash-redir/redir7.tests +++ b/shell/ash_test/ash-redir/redir7.tests | |||
@@ -7,6 +7,6 @@ | |||
7 | echo -e 'echo Ok >uni\x81code' >>unicode.sh | 7 | echo -e 'echo Ok >uni\x81code' >>unicode.sh |
8 | echo -e 'cat uni\x81code' >>unicode.sh | 8 | echo -e 'cat uni\x81code' >>unicode.sh |
9 | echo -e 'cat uni?code' >>unicode.sh | 9 | echo -e 'cat uni?code' >>unicode.sh |
10 | . unicode.sh | 10 | . ./unicode.sh |
11 | rm uni*code* | 11 | rm uni*code* |
12 | echo Done | 12 | echo Done |
diff --git a/shell/ash_test/ash-redir/redir8.tests b/shell/ash_test/ash-redir/redir8.tests index 32ab607b8..8cb42c0d3 100755 --- a/shell/ash_test/ash-redir/redir8.tests +++ b/shell/ash_test/ash-redir/redir8.tests | |||
@@ -10,6 +10,6 @@ echo -e 'v=uni\x81code' >>unicode.sh | |||
10 | echo -e 'echo Ok >"$v"' >>unicode.sh | 10 | echo -e 'echo Ok >"$v"' >>unicode.sh |
11 | echo -e 'cat uni\x81code' >>unicode.sh | 11 | echo -e 'cat uni\x81code' >>unicode.sh |
12 | echo -e 'cat uni?code' >>unicode.sh | 12 | echo -e 'cat uni?code' >>unicode.sh |
13 | . unicode.sh | 13 | . ./unicode.sh |
14 | rm uni*code* | 14 | rm uni*code* |
15 | echo Done | 15 | echo Done |
diff --git a/shell/ash_test/ash-signals/signal5.right b/shell/ash_test/ash-signals/signal5.right new file mode 100644 index 000000000..162f56bbc --- /dev/null +++ b/shell/ash_test/ash-signals/signal5.right | |||
@@ -0,0 +1,12 @@ | |||
1 | sleeping for 3 sec | ||
2 | sleeping for 2 sec | ||
3 | Waiting | ||
4 | 2 sec passed, sending USR1 to parent | ||
5 | USR1 received | ||
6 | Wait exit code: 138 | ||
7 | Waiting | ||
8 | 3 sec passed, sending USR1 to parent | ||
9 | USR1 received | ||
10 | Wait exit code: 138 | ||
11 | Waiting | ||
12 | Wait returned 0 | ||
diff --git a/shell/ash_test/ash-signals/signal5.tests b/shell/ash_test/ash-signals/signal5.tests new file mode 100755 index 000000000..371120e95 --- /dev/null +++ b/shell/ash_test/ash-signals/signal5.tests | |||
@@ -0,0 +1,14 @@ | |||
1 | trap "echo USR1 received" USR1 | ||
2 | stub() { | ||
3 | echo "sleeping for $1 sec" | ||
4 | sleep $1 | ||
5 | echo "$1 sec passed, sending USR1 to parent" | ||
6 | kill -USR1 $$ | ||
7 | } | ||
8 | stub 3 & | ||
9 | stub 2 & | ||
10 | sleep 1 | ||
11 | until { echo "Waiting"; wait; } do | ||
12 | echo "Wait exit code: $?" | ||
13 | done | ||
14 | echo "Wait returned 0" | ||
diff --git a/shell/ash_test/ash-signals/signal6.right b/shell/ash_test/ash-signals/signal6.right new file mode 100644 index 000000000..df4d9306a --- /dev/null +++ b/shell/ash_test/ash-signals/signal6.right | |||
@@ -0,0 +1,2 @@ | |||
1 | got TERM | ||
2 | Done: 0 | ||
diff --git a/shell/ash_test/ash-signals/signal6.tests b/shell/ash_test/ash-signals/signal6.tests new file mode 100755 index 000000000..3ce151060 --- /dev/null +++ b/shell/ash_test/ash-signals/signal6.tests | |||
@@ -0,0 +1,2 @@ | |||
1 | { trap "echo got TERM" TERM; sleep 3; }& sleep 1; kill $!; wait | ||
2 | echo Done: $? | ||
diff --git a/shell/ash_test/ash-vars/var_leak.right b/shell/ash_test/ash-vars/var_leak.right index 45c5458dd..be78112c8 100644 --- a/shell/ash_test/ash-vars/var_leak.right +++ b/shell/ash_test/ash-vars/var_leak.right | |||
@@ -1,2 +1,3 @@ | |||
1 | should be empty: '' | 1 | should be empty: '' |
2 | should be empty: '' | 2 | should be not empty: 'val2' |
3 | should be not empty: 'val3' | ||
diff --git a/shell/ash_test/ash-vars/var_leak.tests b/shell/ash_test/ash-vars/var_leak.tests index 1b1123fb7..032059295 100755 --- a/shell/ash_test/ash-vars/var_leak.tests +++ b/shell/ash_test/ash-vars/var_leak.tests | |||
@@ -1,9 +1,18 @@ | |||
1 | # This currently fails with CONFIG_FEATURE_SH_NOFORK=y | 1 | # true is a regular builtin, varibale should not leak out of it |
2 | # this currently fails with CONFIG_FEATURE_SH_NOFORK=y | ||
2 | VAR='' | 3 | VAR='' |
3 | VAR=qwe true | 4 | VAR=val1 true |
4 | echo "should be empty: '$VAR'" | 5 | echo "should be empty: '$VAR'" |
5 | 6 | ||
6 | # This fails (always) | 7 | # ash follows the "special builtin leaks variables" rule here: |
8 | # exec is a special builtin. (bash does not do it) | ||
7 | VAR='' | 9 | VAR='' |
8 | VAR=qwe exec 2>&1 | 10 | VAR=val2 exec 2>&1 |
9 | echo "should be empty: '$VAR'" | 11 | echo "should be not empty: '$VAR'" |
12 | |||
13 | # ash follows the "function call is a special builtin" rule here | ||
14 | # (bash does not do it) | ||
15 | f() { true; } | ||
16 | VAR='' | ||
17 | VAR=val3 f | ||
18 | echo "should be not empty: '$VAR'" | ||
diff --git a/shell/cttyhack.c b/shell/cttyhack.c index 572a3af03..bde2acdc9 100644 --- a/shell/cttyhack.c +++ b/shell/cttyhack.c | |||
@@ -53,23 +53,32 @@ int cttyhack_main(int argc UNUSED_PARAM, char **argv) | |||
53 | } | 53 | } |
54 | 54 | ||
55 | strcpy(console, "/dev/tty"); | 55 | strcpy(console, "/dev/tty"); |
56 | if (ioctl(0, TIOCGSERIAL, &u.sr) == 0) { | 56 | fd = open(console, O_RDWR); |
57 | /* this is a serial console */ | 57 | if (fd >= 0) { |
58 | sprintf(console + 8, "S%d", u.sr.line); | 58 | /* We already have ctty, nothing to do */ |
59 | } else if (ioctl(0, VT_GETSTATE, &u.vt) == 0) { | 59 | close(fd); |
60 | /* this is linux virtual tty */ | 60 | } else { |
61 | sprintf(console + 8, "S%d" + 1, u.vt.v_active); | 61 | /* We don't have ctty (or don't have "/dev/tty" node...) */ |
62 | } | 62 | if (ioctl(0, TIOCGSERIAL, &u.sr) == 0) { |
63 | 63 | /* this is a serial console */ | |
64 | if (console[8]) { | 64 | sprintf(console + 8, "S%d", u.sr.line); |
65 | fd = xopen(console, O_RDWR); | 65 | } else if (ioctl(0, VT_GETSTATE, &u.vt) == 0) { |
66 | //bb_error_msg("switching to '%s'", console); | 66 | /* this is linux virtual tty */ |
67 | dup2(fd, 0); | 67 | sprintf(console + 8, "S%d" + 1, u.vt.v_active); |
68 | dup2(fd, 1); | 68 | } |
69 | dup2(fd, 2); | 69 | if (console[8]) { |
70 | while (fd > 2) close(fd--); | 70 | fd = xopen(console, O_RDWR); |
71 | /* Some other session may have it as ctty. Steal it from them */ | 71 | //bb_error_msg("switching to '%s'", console); |
72 | ioctl(0, TIOCSCTTY, 1); | 72 | dup2(fd, 0); |
73 | dup2(fd, 1); | ||
74 | dup2(fd, 2); | ||
75 | while (fd > 2) | ||
76 | close(fd--); | ||
77 | /* Some other session may have it as ctty, | ||
78 | * steal it from them: | ||
79 | */ | ||
80 | ioctl(0, TIOCSCTTY, 1); | ||
81 | } | ||
73 | } | 82 | } |
74 | 83 | ||
75 | BB_EXECVP(argv[0], argv); | 84 | BB_EXECVP(argv[0], argv); |
diff --git a/shell/hush.c b/shell/hush.c index 9b15efb30..8baccf246 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -39,25 +39,28 @@ | |||
39 | * | 39 | * |
40 | * POSIX syntax not implemented: | 40 | * POSIX syntax not implemented: |
41 | * aliases | 41 | * aliases |
42 | * <(list) and >(list) Process Substitution | ||
43 | * Tilde Expansion | 42 | * Tilde Expansion |
44 | * | 43 | * |
45 | * Bash stuff (optionally enabled): | 44 | * Bash compat TODO: |
46 | * &> and >& redirection of stdout+stderr | 45 | * redirection of stdout+stderr: &> and >& |
47 | * Brace Expansion | 46 | * brace expansion: one/{two,three,four} |
48 | * reserved words: [[ ]] function select | 47 | * reserved words: function select |
49 | * substrings ${var:1:5} | 48 | * advanced test: [[ ]] |
49 | * substrings: ${var:1:5} | ||
50 | * process substitution: <(list) and >(list) | ||
51 | * =~: regex operator | ||
50 | * let EXPR [EXPR...] | 52 | * let EXPR [EXPR...] |
51 | * Each EXPR is an arithmetic expression (ARITHMETIC EVALUATION) | 53 | * Each EXPR is an arithmetic expression (ARITHMETIC EVALUATION) |
52 | * If the last arg evaluates to 0, let returns 1; 0 otherwise. | 54 | * If the last arg evaluates to 0, let returns 1; 0 otherwise. |
53 | * NB: let `echo 'a=a + 1'` - error (IOW: multi-word expansion is used) | 55 | * NB: let `echo 'a=a + 1'` - error (IOW: multi-word expansion is used) |
54 | * ((EXPR)) | 56 | * ((EXPR)) |
55 | * The EXPR is evaluated according to ARITHMETIC EVALUATION. | 57 | * The EXPR is evaluated according to ARITHMETIC EVALUATION. |
56 | * This is exactly equivalent to let "expression". | 58 | * This is exactly equivalent to let "EXPR". |
59 | * $[EXPR]: synonym for $((EXPR)) | ||
57 | * | 60 | * |
58 | * TODOs: | 61 | * TODOs: |
59 | * grep for "TODO" and fix (some of them are easy) | 62 | * grep for "TODO" and fix (some of them are easy) |
60 | * special variables (done: PWD) | 63 | * special variables (done: PWD, PPID, RANDOM) |
61 | * follow IFS rules more precisely, including update semantics | 64 | * follow IFS rules more precisely, including update semantics |
62 | * export builtin should be special, its arguments are assignments | 65 | * export builtin should be special, its arguments are assignments |
63 | * and therefore expansion of them should be "one-word" expansion: | 66 | * and therefore expansion of them should be "one-word" expansion: |
@@ -673,6 +676,9 @@ static const struct built_in_command bltins1[] = { | |||
673 | #endif | 676 | #endif |
674 | BLTIN("set" , builtin_set , "Set/unset positional parameters"), | 677 | BLTIN("set" , builtin_set , "Set/unset positional parameters"), |
675 | BLTIN("shift" , builtin_shift , "Shift positional parameters"), | 678 | BLTIN("shift" , builtin_shift , "Shift positional parameters"), |
679 | #if ENABLE_HUSH_BASH_COMPAT | ||
680 | BLTIN("source" , builtin_source , "Run commands in a file"), | ||
681 | #endif | ||
676 | BLTIN("trap" , builtin_trap , "Trap signals"), | 682 | BLTIN("trap" , builtin_trap , "Trap signals"), |
677 | BLTIN("type" , builtin_type , "Show command type"), | 683 | BLTIN("type" , builtin_type , "Show command type"), |
678 | BLTIN("ulimit" , shell_builtin_ulimit , "Control resource limits"), | 684 | BLTIN("ulimit" , shell_builtin_ulimit , "Control resource limits"), |
@@ -6232,10 +6238,15 @@ static struct pipe *parse_stream(char **pstring, | |||
6232 | is_special = "{}<>;&|()#'" /* special outside of "str" */ | 6238 | is_special = "{}<>;&|()#'" /* special outside of "str" */ |
6233 | "\\$\"" IF_HUSH_TICK("`"); /* always special */ | 6239 | "\\$\"" IF_HUSH_TICK("`"); /* always special */ |
6234 | /* Are { and } special here? */ | 6240 | /* Are { and } special here? */ |
6235 | if (ctx.command->argv /* word [word]{... */ | 6241 | if (ctx.command->argv /* word [word]{... - non-special */ |
6236 | || dest.length /* word{... */ | 6242 | || dest.length /* word{... - non-special */ |
6237 | || dest.o_quoted /* ""{... */ | 6243 | || dest.o_quoted /* ""{... - non-special */ |
6238 | || (next != ';' && next != ')' && !strchr(G.ifs, next)) /* {word */ | 6244 | || (next != ';' /* }; - special */ |
6245 | && next != ')' /* }) - special */ | ||
6246 | && next != '&' /* }& and }&& ... - special */ | ||
6247 | && next != '|' /* }|| ... - special */ | ||
6248 | && !strchr(G.ifs, next) /* {word - non-special */ | ||
6249 | ) | ||
6239 | ) { | 6250 | ) { |
6240 | /* They are not special, skip "{}" */ | 6251 | /* They are not special, skip "{}" */ |
6241 | is_special += 2; | 6252 | is_special += 2; |
@@ -7859,21 +7870,26 @@ static int FAST_FUNC builtin_shift(char **argv) | |||
7859 | 7870 | ||
7860 | static int FAST_FUNC builtin_source(char **argv) | 7871 | static int FAST_FUNC builtin_source(char **argv) |
7861 | { | 7872 | { |
7862 | char *arg_path; | 7873 | char *arg_path, *filename; |
7863 | FILE *input; | 7874 | FILE *input; |
7864 | save_arg_t sv; | 7875 | save_arg_t sv; |
7865 | #if ENABLE_HUSH_FUNCTIONS | 7876 | #if ENABLE_HUSH_FUNCTIONS |
7866 | smallint sv_flg; | 7877 | smallint sv_flg; |
7867 | #endif | 7878 | #endif |
7868 | 7879 | ||
7869 | if (*++argv == NULL) | 7880 | arg_path = NULL; |
7870 | return EXIT_FAILURE; | 7881 | filename = *++argv; |
7871 | 7882 | if (!filename) { | |
7872 | if (strchr(*argv, '/') == NULL && (arg_path = find_in_path(*argv)) != NULL) { | 7883 | /* bash says: "bash: .: filename argument required" */ |
7873 | input = fopen_for_read(arg_path); | 7884 | return 2; /* bash compat */ |
7874 | free(arg_path); | 7885 | } |
7875 | } else | 7886 | if (!strchr(filename, '/')) { |
7876 | input = fopen_or_warn(*argv, "r"); | 7887 | arg_path = find_in_path(filename); |
7888 | if (arg_path) | ||
7889 | filename = arg_path; | ||
7890 | } | ||
7891 | input = fopen_or_warn(filename, "r"); | ||
7892 | free(arg_path); | ||
7877 | if (!input) { | 7893 | if (!input) { |
7878 | /* bb_perror_msg("%s", *argv); - done by fopen_or_warn */ | 7894 | /* bb_perror_msg("%s", *argv); - done by fopen_or_warn */ |
7879 | return EXIT_FAILURE; | 7895 | return EXIT_FAILURE; |
diff --git a/shell/hush_test/hush-parsing/group2.right b/shell/hush_test/hush-parsing/group2.right new file mode 100644 index 000000000..df4d9306a --- /dev/null +++ b/shell/hush_test/hush-parsing/group2.right | |||
@@ -0,0 +1,2 @@ | |||
1 | got TERM | ||
2 | Done: 0 | ||
diff --git a/shell/hush_test/hush-parsing/group2.tests b/shell/hush_test/hush-parsing/group2.tests new file mode 100755 index 000000000..d99178585 --- /dev/null +++ b/shell/hush_test/hush-parsing/group2.tests | |||
@@ -0,0 +1,3 @@ | |||
1 | # Bug was in handling of "}&" without space | ||
2 | { trap "echo got TERM" TERM; sleep 2; }& sleep 1; kill $!; wait | ||
3 | echo Done: $? | ||
diff --git a/testsuite/ar.tests b/testsuite/ar.tests index f112eb64a..4630d08a4 100755 --- a/testsuite/ar.tests +++ b/testsuite/ar.tests | |||
@@ -18,10 +18,10 @@ testing "ar creates archives" \ | |||
18 | rm test.a | 18 | rm test.a |
19 | 19 | ||
20 | testing "ar replaces things in archives" \ | 20 | testing "ar replaces things in archives" \ |
21 | "echo 'blah!' >file1 && echo 'blast!'> file2 && ar cr test.a README file1 file2 && mv file2 file1 && ar cr test.a file1 && ar p test.a file1" \ | 21 | "echo 'blah!' >file1 && echo 'blast!' >file2 && ar cr test.a README file1 file2 && mv file2 file1 && ar cr test.a file1 && ar p test.a file1" \ |
22 | "blast!\n" \ | 22 | "blast!\n" \ |
23 | "" \ | 23 | "" \ |
24 | "" | 24 | "" |
25 | rm test.a | 25 | rm test.a file1 file1 2>/dev/null |
26 | 26 | ||
27 | exit $FAILCOUNT | 27 | exit $FAILCOUNT |
diff --git a/testsuite/ash.tests b/testsuite/ash.tests index 6b2caf316..dd626e6d1 100755 --- a/testsuite/ash.tests +++ b/testsuite/ash.tests | |||
@@ -7,8 +7,34 @@ | |||
7 | 7 | ||
8 | . ./testing.sh | 8 | . ./testing.sh |
9 | 9 | ||
10 | test -f "$bindir/.config" && . "$bindir/.config" | ||
11 | |||
12 | test x"CONFIG_SCRIPT" = x"y" || exit 0 | ||
13 | test x"CONFIG_HEXDUMP" = x"y" || exit 0 | ||
14 | test x"CONFIG_FEATURE_DEVPTS" = x"y" || exit 0 | ||
15 | |||
10 | # testing "test name" "options" "expected result" "file input" "stdin" | 16 | # testing "test name" "options" "expected result" "file input" "stdin" |
11 | 17 | ||
18 | if test x"$CONFIG_UNICODE_PRESERVE_BROKEN" = x"y"; then | ||
19 | testing "One byte which is not valid unicode char followed by valid input" \ | ||
20 | "script -q -c 'ash' /dev/null >/dev/null; cat ash.output" \ | ||
21 | "\ | ||
22 | 00000000 ff 2d 0a |.-.| | ||
23 | 00000003 | ||
24 | " \ | ||
25 | "" \ | ||
26 | "echo \xff- | hexdump -C >ash.output; exit; exit; exit; exit\n" | ||
27 | |||
28 | testing "30 bytes which are not valid unicode chars followed by valid input" \ | ||
29 | "script -q -c 'ash' /dev/null >/dev/null; cat ash.output" \ | ||
30 | "\ | ||
31 | 00000000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| | ||
32 | 00000010 ff ff ff ff ff ff ff ff ff ff ff ff ff ff 2d 0a |..............-.| | ||
33 | 00000020 | ||
34 | " \ | ||
35 | "" \ | ||
36 | "echo \xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff- | hexdump -C >ash.output; exit; exit; exit; exit\n" | ||
37 | else | ||
12 | testing "One byte which is not valid unicode char followed by valid input" \ | 38 | testing "One byte which is not valid unicode char followed by valid input" \ |
13 | "script -q -c 'ash' /dev/null >/dev/null; cat ash.output" \ | 39 | "script -q -c 'ash' /dev/null >/dev/null; cat ash.output" \ |
14 | "\ | 40 | "\ |
@@ -27,6 +53,8 @@ testing "30 bytes which are not valid unicode chars followed by valid input" \ | |||
27 | " \ | 53 | " \ |
28 | "" \ | 54 | "" \ |
29 | "echo \xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff- | hexdump -C >ash.output; exit; exit; exit; exit\n" | 55 | "echo \xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff- | hexdump -C >ash.output; exit; exit; exit; exit\n" |
56 | fi | ||
57 | |||
30 | 58 | ||
31 | # Not sure this behavior is perfect: we lose all invalid input which precedes | 59 | # Not sure this behavior is perfect: we lose all invalid input which precedes |
32 | # arrow keys and such. In this example, \xff\xff are lost | 60 | # arrow keys and such. In this example, \xff\xff are lost |
@@ -43,7 +71,7 @@ testing "2 bytes which are not valid unicode chars followed by left arrow key" \ | |||
43 | # not checked by the test), then read and execute the rest: "echo A | ..." | 71 | # not checked by the test), then read and execute the rest: "echo A | ..." |
44 | # The bug was that ash was eating the beginning of "echo A" despite the pause. | 72 | # The bug was that ash was eating the beginning of "echo A" despite the pause. |
45 | testing "Invalid unicode chars followed by a pause do not eat next chars" \ | 73 | testing "Invalid unicode chars followed by a pause do not eat next chars" \ |
46 | "{ echo -ne 'echo \xff\n'; sleep 1; echo -ne 'echo A | hexdump -C >ash.output; exit; exit; exit; exit\n'; } \ | 74 | "{ $ECHO -ne 'echo \xff\n'; sleep 1; $ECHO -ne 'echo A | hexdump -C >ash.output; exit; exit; exit; exit\n'; } \ |
47 | | script -q -c 'ash' /dev/null >/dev/null; cat ash.output" \ | 75 | | script -q -c 'ash' /dev/null >/dev/null; cat ash.output" \ |
48 | "\ | 76 | "\ |
49 | 00000000 41 0a |A.| | 77 | 00000000 41 0a |A.| |
diff --git a/testsuite/awk.tests b/testsuite/awk.tests index 3a7c8f4d0..0691a7972 100755 --- a/testsuite/awk.tests +++ b/testsuite/awk.tests | |||
@@ -18,9 +18,11 @@ testing "awk -F case 7" "awk -F '[#]' '{ print NF }'" "5\n" "" "z##abc##zz\n" | |||
18 | 18 | ||
19 | # 4294967295 = 0xffffffff | 19 | # 4294967295 = 0xffffffff |
20 | testing "awk bitwise op" "awk '{ print or(4294967295,1) }'" "4.29497e+09\n" "" "\n" | 20 | testing "awk bitwise op" "awk '{ print or(4294967295,1) }'" "4.29497e+09\n" "" "\n" |
21 | optional DESKTOP | ||
21 | testing "awk hex const 1" "awk '{ print or(0xffffffff,1) }'" "4.29497e+09\n" "" "\n" | 22 | testing "awk hex const 1" "awk '{ print or(0xffffffff,1) }'" "4.29497e+09\n" "" "\n" |
22 | testing "awk hex const 2" "awk '{ print or(0x80000000,1) }'" "2.14748e+09\n" "" "\n" | 23 | testing "awk hex const 2" "awk '{ print or(0x80000000,1) }'" "2.14748e+09\n" "" "\n" |
23 | testing "awk oct const" "awk '{ print or(01234,1) }'" "669\n" "" "\n" | 24 | testing "awk oct const" "awk '{ print or(01234,1) }'" "669\n" "" "\n" |
25 | SKIP= | ||
24 | 26 | ||
25 | # long field seps requiring regex | 27 | # long field seps requiring regex |
26 | testing "awk long field sep" "awk -F-- '{ print NF, length(\$NF), \$NF }'" \ | 28 | testing "awk long field sep" "awk -F-- '{ print NF, length(\$NF), \$NF }'" \ |
@@ -33,12 +35,14 @@ testing "awk long field sep" "awk -F-- '{ print NF, length(\$NF), \$NF }'" \ | |||
33 | testing "awk gsub falls back to non-extended-regex" \ | 35 | testing "awk gsub falls back to non-extended-regex" \ |
34 | "awk 'gsub(\"@(samp|code|file)\{\",\"\");'; echo \$?" "0\n" "" "Hi\n" | 36 | "awk 'gsub(\"@(samp|code|file)\{\",\"\");'; echo \$?" "0\n" "" "Hi\n" |
35 | 37 | ||
36 | tar xjf awk_t1.tar.bz2 | 38 | optional TAR BUNZIP2 FEATURE_SEAMLESS_BZ2 |
39 | test x"$SKIP" != x"1" && tar xjf awk_t1.tar.bz2 | ||
37 | testing "awk 'gcc build bug'" \ | 40 | testing "awk 'gcc build bug'" \ |
38 | "awk -f awk_t1_opt-functions.awk -f awk_t1_opth-gen.awk <awk_t1_input | md5sum" \ | 41 | "awk -f awk_t1_opt-functions.awk -f awk_t1_opth-gen.awk <awk_t1_input | md5sum" \ |
39 | "f842e256461a5ab1ec60b58d16f1114f -\n" \ | 42 | "f842e256461a5ab1ec60b58d16f1114f -\n" \ |
40 | "" "" | 43 | "" "" |
41 | rm -rf awk_t1_* | 44 | rm -rf awk_t1_* 2>/dev/null |
45 | SKIP= | ||
42 | 46 | ||
43 | Q='":"' | 47 | Q='":"' |
44 | 48 | ||
diff --git a/testsuite/busybox.tests b/testsuite/busybox.tests index 6eeb3251d..0c740530d 100755 --- a/testsuite/busybox.tests +++ b/testsuite/busybox.tests | |||
@@ -10,8 +10,9 @@ HELPDUMP=`true | busybox 2>&1 | cat` | |||
10 | 10 | ||
11 | # We need to test under calling the binary under other names. | 11 | # We need to test under calling the binary under other names. |
12 | 12 | ||
13 | 13 | optional FEATURE_VERBOSE_USAGE | |
14 | testing "busybox --help busybox" "true | busybox --help busybox 2>&1 | cat" "$HELPDUMP\n\n" "" "" | 14 | testing "busybox --help busybox" "true | busybox --help busybox 2>&1 | cat" "$HELPDUMP\n\n" "" "" |
15 | SKIP= | ||
15 | 16 | ||
16 | ln -s `which busybox` busybox-suffix | 17 | ln -s `which busybox` busybox-suffix |
17 | for i in busybox ./busybox-suffix | 18 | for i in busybox ./busybox-suffix |
@@ -26,11 +27,11 @@ do | |||
26 | 27 | ||
27 | testing "$i --help" "$i --help 2>&1" "$HELPDUMP\n\n" "" "" | 28 | testing "$i --help" "$i --help 2>&1" "$HELPDUMP\n\n" "" "" |
28 | 29 | ||
29 | optional CAT | 30 | optional FEATURE_VERBOSE_USAGE CAT |
30 | testing "" "$i cat" "moo" "" "moo" | 31 | testing "" "$i cat" "moo" "" "moo" |
31 | testing "$i --help cat" "$i --help cat 2>&1 | grep print" \ | 32 | testing "$i --help cat" "$i --help cat 2>&1 | grep print" \ |
32 | "Concatenate FILEs and print them to stdout\n" "" "" | 33 | "Concatenate FILEs and print them to stdout\n" "" "" |
33 | optional "" | 34 | SKIP= |
34 | 35 | ||
35 | testing "$i --help unknown" "$i --help unknown 2>&1" \ | 36 | testing "$i --help unknown" "$i --help unknown 2>&1" \ |
36 | "unknown: applet not found\n" "" "" | 37 | "unknown: applet not found\n" "" "" |
diff --git a/testsuite/cpio.tests b/testsuite/cpio.tests index e53ade925..725e70eab 100755 --- a/testsuite/cpio.tests +++ b/testsuite/cpio.tests | |||
@@ -31,8 +31,9 @@ rm -rf cpio.testdir cpio.testdir2 2>/dev/null | |||
31 | 31 | ||
32 | # testing "test name" "command" "expected result" "file input" "stdin" | 32 | # testing "test name" "command" "expected result" "file input" "stdin" |
33 | 33 | ||
34 | optional FEATURE_LS_SORTFILES FEATURE_LS_TIMESTAMPS | ||
34 | testing "cpio extracts zero-sized hardlinks" \ | 35 | testing "cpio extracts zero-sized hardlinks" \ |
35 | "$ECHO -ne '$hexdump' | bzcat | cpio -i; echo \$?; | 36 | "$ECHO -ne '$hexdump' | bzcat | cpio -i 2>&1; echo \$?; |
36 | ls -ln cpio.testdir | $FILTER_LS" \ | 37 | ls -ln cpio.testdir | $FILTER_LS" \ |
37 | "\ | 38 | "\ |
38 | 1 blocks | 39 | 1 blocks |
@@ -41,11 +42,12 @@ ls -ln cpio.testdir | $FILTER_LS" \ | |||
41 | -rw-r--r-- 2 $user $group 0 y | 42 | -rw-r--r-- 2 $user $group 0 y |
42 | " \ | 43 | " \ |
43 | "" "" | 44 | "" "" |
45 | SKIP= | ||
44 | 46 | ||
45 | 47 | ||
46 | test x"$SKIP_KNOWN_BUGS" = x"" && { | 48 | test x"$SKIP_KNOWN_BUGS" = x"" && { |
47 | # Currently fails. Numerous buglets: "1 blocks" versus "1 block", | 49 | # Currently fails. Numerous buglets: "1 blocks" versus "1 block", |
48 | # "1 block" must go to stderr, does not list cpio.testdir/x and cpio.testdir/y | 50 | # does not list cpio.testdir/x and cpio.testdir/y |
49 | testing "cpio lists hardlinks" \ | 51 | testing "cpio lists hardlinks" \ |
50 | "$ECHO -ne '$hexdump' | bzcat | cpio -t 2>&1; echo \$?" \ | 52 | "$ECHO -ne '$hexdump' | bzcat | cpio -t 2>&1; echo \$?" \ |
51 | "\ | 53 | "\ |
@@ -69,8 +71,9 @@ ln cpio.testdir/empty cpio.testdir/empty1 | |||
69 | ln cpio.testdir/nonempty cpio.testdir/nonempty1 | 71 | ln cpio.testdir/nonempty cpio.testdir/nonempty1 |
70 | mkdir cpio.testdir2 | 72 | mkdir cpio.testdir2 |
71 | 73 | ||
74 | optional FEATURE_CPIO_O LONG_OPTS FEATURE_LS_SORTFILES FEATURE_LS_TIMESTAMPS | ||
72 | testing "cpio extracts zero-sized hardlinks 2" \ | 75 | testing "cpio extracts zero-sized hardlinks 2" \ |
73 | "find cpio.testdir | cpio -H newc --create | (cd cpio.testdir2 && cpio -i); echo \$?; | 76 | "find cpio.testdir | cpio -H newc --create | (cd cpio.testdir2 && cpio -i 2>&1); echo \$?; |
74 | ls -ln cpio.testdir2/cpio.testdir | $FILTER_LS" \ | 77 | ls -ln cpio.testdir2/cpio.testdir | $FILTER_LS" \ |
75 | "\ | 78 | "\ |
76 | 2 blocks | 79 | 2 blocks |
@@ -82,12 +85,14 @@ ls -ln cpio.testdir2/cpio.testdir | $FILTER_LS" \ | |||
82 | -rw-r--r-- 1 $user $group 0 solo | 85 | -rw-r--r-- 1 $user $group 0 solo |
83 | " \ | 86 | " \ |
84 | "" "" | 87 | "" "" |
88 | SKIP= | ||
85 | 89 | ||
86 | 90 | ||
87 | # Was trying to create "/usr/bin", correct is "usr/bin". | 91 | # Was trying to create "/usr/bin", correct is "usr/bin". |
88 | rm -rf cpio.testdir | 92 | rm -rf cpio.testdir |
93 | optional FEATURE_CPIO_P | ||
89 | testing "cpio -p with absolute paths" \ | 94 | testing "cpio -p with absolute paths" \ |
90 | "echo /usr/bin | cpio -dp cpio.testdir; echo \$?; | 95 | "echo /usr/bin | cpio -dp cpio.testdir 2>&1; echo \$?; |
91 | ls cpio.testdir" \ | 96 | ls cpio.testdir" \ |
92 | "\ | 97 | "\ |
93 | 1 blocks | 98 | 1 blocks |
@@ -95,6 +100,7 @@ ls cpio.testdir" \ | |||
95 | usr | 100 | usr |
96 | " \ | 101 | " \ |
97 | "" "" | 102 | "" "" |
103 | SKIP= | ||
98 | 104 | ||
99 | 105 | ||
100 | # Clean up | 106 | # Clean up |
diff --git a/testsuite/cut/cut-cuts-a-field b/testsuite/cut/cut-cuts-a-field index 4c7f44007..e200b6b78 100644 --- a/testsuite/cut/cut-cuts-a-field +++ b/testsuite/cut/cut-cuts-a-field | |||
@@ -1 +1 @@ | |||
test $(echo -e "f1\tf2\tf3" | busybox cut -f 2) = f2 | test $($ECHO -e "f1\tf2\tf3" | busybox cut -f 2) = f2 | ||
diff --git a/testsuite/date/date-R-works b/testsuite/date/date-R-works index 34cd735e5..d05634456 100644 --- a/testsuite/date/date-R-works +++ b/testsuite/date/date-R-works | |||
@@ -1 +1,8 @@ | |||
1 | test x"`date -R`" = x"`busybox date -R`" | 1 | dt1="`date -R`" |
2 | # Wait for the start of next second | ||
3 | dt="$dt1" | ||
4 | while test x"$dt" = x"$dt1"; do | ||
5 | dt="`date -R`" | ||
6 | done | ||
7 | |||
8 | test x"$dt" = x"`busybox date -R`" | ||
diff --git a/testsuite/diff.tests b/testsuite/diff.tests index 72ebb6c4c..06d5a4fd7 100755 --- a/testsuite/diff.tests +++ b/testsuite/diff.tests | |||
@@ -106,6 +106,7 @@ rm -rf diff1 diff2 | |||
106 | mkdir diff1 diff2 diff2/subdir | 106 | mkdir diff1 diff2 diff2/subdir |
107 | echo qwe >diff1/- | 107 | echo qwe >diff1/- |
108 | echo asd >diff2/subdir/- | 108 | echo asd >diff2/subdir/- |
109 | optional FEATURE_DIFF_DIR | ||
109 | testing "diff diff1 diff2/subdir" \ | 110 | testing "diff diff1 diff2/subdir" \ |
110 | "diff -ur diff1 diff2/subdir | $TRIM_TAB" \ | 111 | "diff -ur diff1 diff2/subdir | $TRIM_TAB" \ |
111 | "\ | 112 | "\ |
@@ -116,8 +117,10 @@ testing "diff diff1 diff2/subdir" \ | |||
116 | +asd | 117 | +asd |
117 | " \ | 118 | " \ |
118 | "" "" | 119 | "" "" |
120 | SKIP= | ||
119 | 121 | ||
120 | # using directory structure from prev test... | 122 | # using directory structure from prev test... |
123 | optional FEATURE_DIFF_DIR | ||
121 | testing "diff dir dir2/file/-" \ | 124 | testing "diff dir dir2/file/-" \ |
122 | "diff -ur diff1 diff2/subdir/- | $TRIM_TAB" \ | 125 | "diff -ur diff1 diff2/subdir/- | $TRIM_TAB" \ |
123 | "\ | 126 | "\ |
@@ -128,10 +131,12 @@ testing "diff dir dir2/file/-" \ | |||
128 | +asd | 131 | +asd |
129 | " \ | 132 | " \ |
130 | "" "" | 133 | "" "" |
134 | SKIP= | ||
131 | 135 | ||
132 | # using directory structure from prev test... | 136 | # using directory structure from prev test... |
133 | mkdir diff1/test | 137 | mkdir diff1/test |
134 | mkfifo diff2/subdir/test | 138 | mkfifo diff2/subdir/test |
139 | optional FEATURE_DIFF_DIR | ||
135 | testing "diff of dir and fifo" \ | 140 | testing "diff of dir and fifo" \ |
136 | "diff -ur diff1 diff2/subdir | $TRIM_TAB" \ | 141 | "diff -ur diff1 diff2/subdir | $TRIM_TAB" \ |
137 | "\ | 142 | "\ |
@@ -143,10 +148,12 @@ testing "diff of dir and fifo" \ | |||
143 | Only in diff2/subdir: test | 148 | Only in diff2/subdir: test |
144 | " \ | 149 | " \ |
145 | "" "" | 150 | "" "" |
151 | SKIP= | ||
146 | 152 | ||
147 | # using directory structure from prev test... | 153 | # using directory structure from prev test... |
148 | rmdir diff1/test | 154 | rmdir diff1/test |
149 | echo >diff1/test | 155 | echo >diff1/test |
156 | optional FEATURE_DIFF_DIR | ||
150 | testing "diff of file and fifo" \ | 157 | testing "diff of file and fifo" \ |
151 | "diff -ur diff1 diff2/subdir | $TRIM_TAB" \ | 158 | "diff -ur diff1 diff2/subdir | $TRIM_TAB" \ |
152 | "\ | 159 | "\ |
@@ -158,9 +165,11 @@ testing "diff of file and fifo" \ | |||
158 | File diff2/subdir/test is not a regular file or directory and was skipped | 165 | File diff2/subdir/test is not a regular file or directory and was skipped |
159 | " \ | 166 | " \ |
160 | "" "" | 167 | "" "" |
168 | SKIP= | ||
161 | 169 | ||
162 | # using directory structure from prev test... | 170 | # using directory structure from prev test... |
163 | mkfifo diff1/test2 | 171 | mkfifo diff1/test2 |
172 | optional FEATURE_DIFF_DIR | ||
164 | testing "diff -rN does not read non-regular files" \ | 173 | testing "diff -rN does not read non-regular files" \ |
165 | "diff -urN diff1 diff2/subdir | $TRIM_TAB" \ | 174 | "diff -urN diff1 diff2/subdir | $TRIM_TAB" \ |
166 | "\ | 175 | "\ |
@@ -173,6 +182,7 @@ File diff2/subdir/test is not a regular file or directory and was skipped | |||
173 | File diff1/test2 is not a regular file or directory and was skipped | 182 | File diff1/test2 is not a regular file or directory and was skipped |
174 | " \ | 183 | " \ |
175 | "" "" | 184 | "" "" |
185 | SKIP= | ||
176 | 186 | ||
177 | # clean up | 187 | # clean up |
178 | rm -rf diff1 diff2 | 188 | rm -rf diff1 diff2 |
diff --git a/testsuite/du/du-h-works b/testsuite/du/du-h-works index 3f8ff3d0b..c18433c29 100644 --- a/testsuite/du/du-h-works +++ b/testsuite/du/du-h-works | |||
@@ -1,4 +1,4 @@ | |||
1 | d=/bin | 1 | # FEATURE: CONFIG_FEATURE_HUMAN_READABLE |
2 | du -h "$d" > logfile.gnu | 2 | |
3 | busybox du -h "$d" > logfile.bb | 3 | dd if=/dev/zero of=file bs=1M count=1 2>/dev/null |
4 | cmp logfile.gnu logfile.bb | 4 | test x"`busybox du -h .`" = x"1.0M ." |
diff --git a/testsuite/du/du-k-works b/testsuite/du/du-k-works index 6c2c5d073..a52264945 100644 --- a/testsuite/du/du-k-works +++ b/testsuite/du/du-k-works | |||
@@ -1,4 +1,4 @@ | |||
1 | d=/bin | 1 | dd if=/dev/zero of=file1 bs=1k count=64 2>/dev/null |
2 | du -k "$d" > logfile.gnu | 2 | dd if=/dev/zero of=file2 bs=1k count=16 2>/dev/null |
3 | busybox du -k "$d" > logfile.bb | 3 | test x"`busybox du -k .`" = x"80 ." \ |
4 | cmp logfile.gnu logfile.bb | 4 | -o x"`busybox du -k .`" = x"88 ." \ |
diff --git a/testsuite/du/du-l-works b/testsuite/du/du-l-works index c3d2ec0c1..6b150e0dd 100644 --- a/testsuite/du/du-l-works +++ b/testsuite/du/du-l-works | |||
@@ -1,4 +1,8 @@ | |||
1 | d=/bin | 1 | # FEATURE: CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K |
2 | du -l "$d" > logfile.gnu | 2 | |
3 | busybox du -l "$d" > logfile.bb | 3 | dd if=/dev/zero of=file1 bs=1k count=64 2>/dev/null |
4 | cmp logfile.gnu logfile.bb | 4 | ln file1 file1.1 |
5 | dd if=/dev/zero of=file2 bs=1k count=16 2>/dev/null | ||
6 | test x"`busybox du -l .`" = x"144 ." \ | ||
7 | -o x"`busybox du -l .`" = x"148 ." \ | ||
8 | -o x"`busybox du -l .`" = x"152 ." \ | ||
diff --git a/testsuite/du/du-m-works b/testsuite/du/du-m-works index bf0a90e1b..9fa7437ac 100644 --- a/testsuite/du/du-m-works +++ b/testsuite/du/du-m-works | |||
@@ -1,4 +1,4 @@ | |||
1 | d=/bin | 1 | # FEATURE: CONFIG_FEATURE_HUMAN_READABLE |
2 | du -m "$d" > logfile.gnu | 2 | |
3 | busybox du -m "$d" > logfile.bb | 3 | dd if=/dev/zero of=file bs=1M count=1 2>/dev/null |
4 | cmp logfile.gnu logfile.bb | 4 | test x"`busybox du -m .`" = x"1 ." |
diff --git a/testsuite/du/du-s-works b/testsuite/du/du-s-works index ae970772a..534432cb0 100644 --- a/testsuite/du/du-s-works +++ b/testsuite/du/du-s-works | |||
@@ -1,4 +1,8 @@ | |||
1 | # FEATURE: CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K | ||
2 | |||
1 | d=/bin | 3 | d=/bin |
2 | du -s "$d" > logfile.gnu | 4 | du -s "$d" > logfile.gnu |
3 | busybox du -s "$d" > logfile.bb | 5 | busybox du -s "$d" > logfile.bb |
4 | cmp logfile.gnu logfile.bb | 6 | cmp logfile.gnu logfile.bb && exit 0 |
7 | diff -u logfile.gnu logfile.bb | ||
8 | exit 1 | ||
diff --git a/testsuite/du/du-works b/testsuite/du/du-works index 46a336dc3..e320f1dd0 100644 --- a/testsuite/du/du-works +++ b/testsuite/du/du-works | |||
@@ -1,4 +1,8 @@ | |||
1 | # FEATURE: CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K | ||
2 | |||
1 | d=/bin | 3 | d=/bin |
2 | du "$d" > logfile.gnu | 4 | du "$d" > logfile.gnu |
3 | busybox du "$d" > logfile.bb | 5 | busybox du "$d" > logfile.bb |
4 | cmp logfile.gnu logfile.bb | 6 | cmp logfile.gnu logfile.bb && exit 0 |
7 | diff -u logfile.gnu logfile.bb | ||
8 | exit 1 | ||
diff --git a/testsuite/echo/echo-does-not-print-newline b/testsuite/echo/echo-does-not-print-newline index 2ed03caf5..2857c0d13 100644 --- a/testsuite/echo/echo-does-not-print-newline +++ b/testsuite/echo/echo-does-not-print-newline | |||
@@ -1 +1,3 @@ | |||
1 | # FEATURE: CONFIG_FEATURE_FANCY_ECHO | ||
2 | |||
1 | test `busybox echo -n word | wc -c` -eq 4 | 3 | test `busybox echo -n word | wc -c` -eq 4 |
diff --git a/testsuite/echo/echo-prints-slash-zero b/testsuite/echo/echo-prints-slash-zero index d2466326f..d97ed8e66 100644 --- a/testsuite/echo/echo-prints-slash-zero +++ b/testsuite/echo/echo-prints-slash-zero | |||
@@ -1 +1,3 @@ | |||
1 | # FEATURE: CONFIG_FEATURE_FANCY_ECHO | ||
2 | |||
1 | test "`busybox echo -e -n 'msg\n\0' | od -t x1 | head -n 1`" = "0000000 6d 73 67 0a 00" | 3 | test "`busybox echo -e -n 'msg\n\0' | od -t x1 | head -n 1`" = "0000000 6d 73 67 0a 00" |
diff --git a/testsuite/expand.tests b/testsuite/expand.tests index 996631450..357a9ad6b 100755 --- a/testsuite/expand.tests +++ b/testsuite/expand.tests | |||
@@ -10,12 +10,15 @@ testing "expand" \ | |||
10 | "expand" \ | 10 | "expand" \ |
11 | " 12345678 12345678\n" \ | 11 | " 12345678 12345678\n" \ |
12 | "" \ | 12 | "" \ |
13 | "\t12345678\t12345678\n" \ | 13 | "\t12345678\t12345678\n" |
14 | 14 | ||
15 | optional UNICODE_SUPPORT | ||
15 | testing "expand with unicode characher 0x394" \ | 16 | testing "expand with unicode characher 0x394" \ |
16 | "expand" \ | 17 | "expand" \ |
17 | "Δ 12345ΔΔΔ 12345678\n" \ | 18 | "Δ 12345ΔΔΔ 12345678\n" \ |
18 | "" \ | 19 | "" \ |
19 | "Δ\t12345ΔΔΔ\t12345678\n" \ | 20 | "Δ\t12345ΔΔΔ\t12345678\n" |
21 | SKIP= | ||
22 | |||
20 | 23 | ||
21 | exit $FAILCOUNT | 24 | exit $FAILCOUNT |
diff --git a/testsuite/expand/expand-works-like-GNU b/testsuite/expand/expand-works-like-GNU index ee8c793ed..b0278d88d 100644 --- a/testsuite/expand/expand-works-like-GNU +++ b/testsuite/expand/expand-works-like-GNU | |||
@@ -1,6 +1,8 @@ | |||
1 | # FEATURE: CONFIG_UNEXPAND | ||
2 | |||
1 | rm -f foo bar | 3 | rm -f foo bar |
2 | echo -e "\ty" | expand -t 3 ../../busybox > foo | 4 | $ECHO -e "\ty" | expand -t 3 ../../busybox > foo |
3 | echo -e "\ty" | busybox unexpand -t 3 ../../busybox > bar | 5 | $ECHO -e "\ty" | busybox unexpand -t 3 ../../busybox > bar |
4 | set +e | 6 | set +e |
5 | test ! -f foo -a -f bar | 7 | test ! -f foo -a -f bar |
6 | if [ $? = 0 ] ; then | 8 | if [ $? = 0 ] ; then |
@@ -8,8 +10,8 @@ if [ $? = 0 ] ; then | |||
8 | diff -q foo bar | 10 | diff -q foo bar |
9 | fi | 11 | fi |
10 | rm -f foo bar | 12 | rm -f foo bar |
11 | echo -e "\ty\tx" | expand -it 3 ../../busybox > foo | 13 | $ECHO -e "\ty\tx" | expand -it 3 ../../busybox > foo |
12 | echo -e "\ty\tx" | busybox unexpand -it 3 ../../busybox > bar | 14 | $ECHO -e "\ty\tx" | busybox unexpand -it 3 ../../busybox > bar |
13 | set +e | 15 | set +e |
14 | test ! -f foo -a -f bar | 16 | test ! -f foo -a -f bar |
15 | if [ $? = 0 ] ; then | 17 | if [ $? = 0 ] ; then |
diff --git a/testsuite/find/find-supports-minus-xdev b/testsuite/find/find-supports-minus-xdev index 4c559a1f4..c807fc8f2 100644 --- a/testsuite/find/find-supports-minus-xdev +++ b/testsuite/find/find-supports-minus-xdev | |||
@@ -1 +1,3 @@ | |||
1 | # FEATURE: CONFIG_FEATURE_FIND_XDEV | ||
2 | |||
1 | busybox find . -xdev >/dev/null 2>&1 | 3 | busybox find . -xdev >/dev/null 2>&1 |
diff --git a/testsuite/fold.tests b/testsuite/fold.tests index 17721a180..0197d024d 100755 --- a/testsuite/fold.tests +++ b/testsuite/fold.tests | |||
@@ -28,6 +28,7 @@ be preserved | |||
28 | is here:>\0< - they must be preserved | 28 | is here:>\0< - they must be preserved |
29 | " \ | 29 | " \ |
30 | 30 | ||
31 | optional UNICODE_SUPPORT | ||
31 | # The text was taken from English and Ukrainian wikipedia pages | 32 | # The text was taken from English and Ukrainian wikipedia pages |
32 | testing "fold -sw66 with unicode input" "fold -sw66" \ | 33 | testing "fold -sw66 with unicode input" "fold -sw66" \ |
33 | "\ | 34 | "\ |
@@ -54,6 +55,7 @@ Way. | |||
54 | каталогом Мессьє та NGC224 за Новим загальним каталогом) — \ | 55 | каталогом Мессьє та NGC224 за Новим загальним каталогом) — \ |
55 | спіральна галактика, що знаходиться на відстані приблизно у 2,5 \ | 56 | спіральна галактика, що знаходиться на відстані приблизно у 2,5 \ |
56 | мільйони світлових років від нашої планети у сузір'ї Андромеди. \ | 57 | мільйони світлових років від нашої планети у сузір'ї Андромеди. \ |
57 | На початку ХХІ ст. в центрі галактики виявлено чорну дірку." \ | 58 | На початку ХХІ ст. в центрі галактики виявлено чорну дірку." |
59 | SKIP= | ||
58 | 60 | ||
59 | exit $FAILCOUNT | 61 | exit $FAILCOUNT |
diff --git a/testsuite/grep.tests b/testsuite/grep.tests index 8692307dd..d4bf80d83 100755 --- a/testsuite/grep.tests +++ b/testsuite/grep.tests | |||
@@ -75,6 +75,8 @@ testing "grep handles multiple regexps" "grep -e one -e two input ; echo \$?" \ | |||
75 | "one\ntwo\n0\n" "one\ntwo\n" "" | 75 | "one\ntwo\n0\n" "one\ntwo\n" "" |
76 | testing "grep -F handles multiple expessions" "grep -F -e one -e two input ; echo \$?" \ | 76 | testing "grep -F handles multiple expessions" "grep -F -e one -e two input ; echo \$?" \ |
77 | "one\ntwo\n0\n" "one\ntwo\n" "" | 77 | "one\ntwo\n0\n" "one\ntwo\n" "" |
78 | testing "grep -F handles -i" "grep -F -i foo input ; echo \$?" \ | ||
79 | "FOO\n0\n" "FOO\n" "" | ||
78 | 80 | ||
79 | # -f file/- | 81 | # -f file/- |
80 | testing "grep can read regexps from stdin" "grep -f - input ; echo \$?" \ | 82 | testing "grep can read regexps from stdin" "grep -f - input ; echo \$?" \ |
diff --git a/testsuite/hostid/hostid-works b/testsuite/hostid/hostid-works index e85698e66..bcfd717af 100644 --- a/testsuite/hostid/hostid-works +++ b/testsuite/hostid/hostid-works | |||
@@ -1,2 +1,8 @@ | |||
1 | test x$(hostid) = x$(busybox hostid) | 1 | h=x$(busybox hostid) |
2 | 2 | # Is $h a sequence of hex numbers? | |
3 | x="${h//[0123456789abcdef]/x}" | ||
4 | x="${x//xxx/x}" | ||
5 | x="${x//xxx/x}" | ||
6 | x="${x//xxx/x}" | ||
7 | x="${x//xx/x}" | ||
8 | test x"$x" = x"x" | ||
diff --git a/testsuite/hostname/hostname-d-works b/testsuite/hostname/hostname-d-works index a9aeb92cb..e062242bb 100644 --- a/testsuite/hostname/hostname-d-works +++ b/testsuite/hostname/hostname-d-works | |||
@@ -1,2 +1,3 @@ | |||
1 | test x$(hostname -d) = x$(busybox hostname -d) | 1 | f=$(busybox hostname -f) |
2 | 2 | d=$(busybox hostname -d) | |
3 | test x"${f#*.}" = x"$d" | ||
diff --git a/testsuite/ls/ls-1-works b/testsuite/ls/ls-1-works index 885694920..71ab9a66b 100644 --- a/testsuite/ls/ls-1-works +++ b/testsuite/ls/ls-1-works | |||
@@ -1,3 +1,5 @@ | |||
1 | # FEATURE: CONFIG_FEATURE_LS_SORTFILES | ||
2 | |||
1 | [ -n "$d" ] || d=.. | 3 | [ -n "$d" ] || d=.. |
2 | LC_ALL=C ls -1 "$d" > logfile.gnu | 4 | LC_ALL=C ls -1 "$d" > logfile.gnu |
3 | LC_ALL=C busybox ls -1 "$d" > logfile.bb | 5 | LC_ALL=C busybox ls -1 "$d" > logfile.bb |
diff --git a/testsuite/ls/ls-h-works b/testsuite/ls/ls-h-works index 0c83f7cc5..60016bac1 100644 --- a/testsuite/ls/ls-h-works +++ b/testsuite/ls/ls-h-works | |||
@@ -1,3 +1,5 @@ | |||
1 | # FEATURE: CONFIG_FEATURE_LS_SORTFILES CONFIG_FEATURE_HUMAN_READABLE | ||
2 | |||
1 | [ -n "$d" ] || d=.. | 3 | [ -n "$d" ] || d=.. |
2 | LC_ALL=C ls -h "$d" > logfile.gnu | 4 | LC_ALL=C ls -h "$d" > logfile.gnu |
3 | LC_ALL=C busybox ls -h "$d" > logfile.bb | 5 | LC_ALL=C busybox ls -h "$d" > logfile.bb |
diff --git a/testsuite/makedevs.tests b/testsuite/makedevs.tests index b41614f13..f69b4a6b1 100755 --- a/testsuite/makedevs.tests +++ b/testsuite/makedevs.tests | |||
@@ -16,6 +16,7 @@ FILTER_LS2="sed -e 's/, */,/g' -e 's/ */ /g' | cut -d' ' -f 1-4,9-" | |||
16 | rm -rf makedevs.testdir | 16 | rm -rf makedevs.testdir |
17 | mkdir makedevs.testdir | 17 | mkdir makedevs.testdir |
18 | 18 | ||
19 | optional FEATURE_MAKEDEVS_TABLE FEATURE_FIND_NOT FEATURE_FIND_TYPE FEATURE_LS_RECURSIVE FEATURE_LS_SORTFILES | ||
19 | testing "makedevs -d ../makedevs.device_table.txt ." \ | 20 | testing "makedevs -d ../makedevs.device_table.txt ." \ |
20 | "(cd makedevs.testdir && makedevs -d ../makedevs.device_table.txt . 2>&1); | 21 | "(cd makedevs.testdir && makedevs -d ../makedevs.device_table.txt . 2>&1); |
21 | find makedevs.testdir ! -type d | sort | xargs ls -lnR | $FILTER_LS" \ | 22 | find makedevs.testdir ! -type d | sort | xargs ls -lnR | $FILTER_LS" \ |
@@ -132,6 +133,7 @@ crw-rw-rw- 1 0 0 1,9 makedevs.testdir/dev/urandom | |||
132 | crw-rw-rw- 1 0 0 1,5 makedevs.testdir/dev/zero | 133 | crw-rw-rw- 1 0 0 1,5 makedevs.testdir/dev/zero |
133 | " \ | 134 | " \ |
134 | "" "" | 135 | "" "" |
136 | SKIP= | ||
135 | 137 | ||
136 | # clean up | 138 | # clean up |
137 | rm -rf makedevs.testdir | 139 | rm -rf makedevs.testdir |
diff --git a/testsuite/md5sum/md5sum-verifies-non-binary-file b/testsuite/md5sum/md5sum-verifies-non-binary-file index 8566a234d..1df818eb5 100644 --- a/testsuite/md5sum/md5sum-verifies-non-binary-file +++ b/testsuite/md5sum/md5sum-verifies-non-binary-file | |||
@@ -1,3 +1,5 @@ | |||
1 | # FEATURE: CONFIG_FEATURE_MD5_SHA1_SUM_CHECK | ||
2 | |||
1 | touch foo | 3 | touch foo |
2 | md5sum foo > bar | 4 | md5sum foo > bar |
3 | busybox md5sum -c bar | 5 | busybox md5sum -c bar |
diff --git a/testsuite/mdev.tests b/testsuite/mdev.tests index 036738e52..c375fc774 100755 --- a/testsuite/mdev.tests +++ b/testsuite/mdev.tests | |||
@@ -27,6 +27,7 @@ echo "8:0" >mdev.testdir/sys/block/sda/dev | |||
27 | 27 | ||
28 | # env - PATH=$PATH: on some systems chroot binary won't otherwise be found | 28 | # env - PATH=$PATH: on some systems chroot binary won't otherwise be found |
29 | 29 | ||
30 | optional STATIC FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME | ||
30 | testing "mdev add /block/sda" \ | 31 | testing "mdev add /block/sda" \ |
31 | "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; | 32 | "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; |
32 | ls -ln mdev.testdir/dev | $FILTER_LS" \ | 33 | ls -ln mdev.testdir/dev | $FILTER_LS" \ |
@@ -34,11 +35,13 @@ testing "mdev add /block/sda" \ | |||
34 | brw-rw---- 1 0 0 8,0 sda | 35 | brw-rw---- 1 0 0 8,0 sda |
35 | " \ | 36 | " \ |
36 | "" "" | 37 | "" "" |
38 | SKIP= | ||
37 | 39 | ||
38 | # continuing to use directory structure from prev test | 40 | # continuing to use directory structure from prev test |
39 | rm -rf mdev.testdir/dev/* | 41 | rm -rf mdev.testdir/dev/* |
40 | echo ".* 1:1 666" >mdev.testdir/etc/mdev.conf | 42 | echo ".* 1:1 666" >mdev.testdir/etc/mdev.conf |
41 | echo "sda 2:2 444" >>mdev.testdir/etc/mdev.conf | 43 | echo "sda 2:2 444" >>mdev.testdir/etc/mdev.conf |
44 | optional STATIC FEATURE_MDEV_CONF FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME | ||
42 | testing "mdev stops on first rule" \ | 45 | testing "mdev stops on first rule" \ |
43 | "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; | 46 | "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; |
44 | ls -ln mdev.testdir/dev | $FILTER_LS" \ | 47 | ls -ln mdev.testdir/dev | $FILTER_LS" \ |
@@ -46,11 +49,13 @@ testing "mdev stops on first rule" \ | |||
46 | brw-rw-rw- 1 1 1 8,0 sda | 49 | brw-rw-rw- 1 1 1 8,0 sda |
47 | " \ | 50 | " \ |
48 | "" "" | 51 | "" "" |
52 | SKIP= | ||
49 | 53 | ||
50 | # continuing to use directory structure from prev test | 54 | # continuing to use directory structure from prev test |
51 | rm -rf mdev.testdir/dev/* | 55 | rm -rf mdev.testdir/dev/* |
52 | echo "-.* 1:1 666" >mdev.testdir/etc/mdev.conf | 56 | echo "-.* 1:1 666" >mdev.testdir/etc/mdev.conf |
53 | echo "sda 2:2 444" >>mdev.testdir/etc/mdev.conf | 57 | echo "sda 2:2 444" >>mdev.testdir/etc/mdev.conf |
58 | optional STATIC FEATURE_MDEV_CONF FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME | ||
54 | testing "mdev does not stop on dash-rule" \ | 59 | testing "mdev does not stop on dash-rule" \ |
55 | "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; | 60 | "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; |
56 | ls -ln mdev.testdir/dev | $FILTER_LS" \ | 61 | ls -ln mdev.testdir/dev | $FILTER_LS" \ |
@@ -58,12 +63,14 @@ testing "mdev does not stop on dash-rule" \ | |||
58 | br--r--r-- 1 2 2 8,0 sda | 63 | br--r--r-- 1 2 2 8,0 sda |
59 | " \ | 64 | " \ |
60 | "" "" | 65 | "" "" |
66 | SKIP= | ||
61 | 67 | ||
62 | # continuing to use directory structure from prev test | 68 | # continuing to use directory structure from prev test |
63 | rm -rf mdev.testdir/dev/* | 69 | rm -rf mdev.testdir/dev/* |
64 | echo "\$MODALIAS=qw 1:1 666" >mdev.testdir/etc/mdev.conf | 70 | echo "\$MODALIAS=qw 1:1 666" >mdev.testdir/etc/mdev.conf |
65 | echo "\$MODALIAS=qw. 2:2 444" >>mdev.testdir/etc/mdev.conf | 71 | echo "\$MODALIAS=qw. 2:2 444" >>mdev.testdir/etc/mdev.conf |
66 | echo "\$MODALIAS=qw. 3:3 400" >>mdev.testdir/etc/mdev.conf | 72 | echo "\$MODALIAS=qw. 3:3 400" >>mdev.testdir/etc/mdev.conf |
73 | optional STATIC FEATURE_MDEV_CONF FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME | ||
67 | testing "mdev \$ENVVAR=regex match" \ | 74 | testing "mdev \$ENVVAR=regex match" \ |
68 | "env - PATH=$PATH ACTION=add DEVPATH=/block/sda MODALIAS=qwe chroot mdev.testdir /mdev 2>&1; | 75 | "env - PATH=$PATH ACTION=add DEVPATH=/block/sda MODALIAS=qwe chroot mdev.testdir /mdev 2>&1; |
69 | ls -ln mdev.testdir/dev | $FILTER_LS" \ | 76 | ls -ln mdev.testdir/dev | $FILTER_LS" \ |
@@ -71,10 +78,12 @@ testing "mdev \$ENVVAR=regex match" \ | |||
71 | br--r--r-- 1 2 2 8,0 sda | 78 | br--r--r-- 1 2 2 8,0 sda |
72 | " \ | 79 | " \ |
73 | "" "" | 80 | "" "" |
81 | SKIP= | ||
74 | 82 | ||
75 | # continuing to use directory structure from prev test | 83 | # continuing to use directory structure from prev test |
76 | rm -rf mdev.testdir/dev/* | 84 | rm -rf mdev.testdir/dev/* |
77 | echo "sda 0:0 444 >disk/scsiA" >mdev.testdir/etc/mdev.conf | 85 | echo "sda 0:0 444 >disk/scsiA" >mdev.testdir/etc/mdev.conf |
86 | optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME | ||
78 | testing "mdev move/symlink rule '>bar/baz'" \ | 87 | testing "mdev move/symlink rule '>bar/baz'" \ |
79 | "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; | 88 | "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; |
80 | ls -lnR mdev.testdir/dev | $FILTER_LS2" \ | 89 | ls -lnR mdev.testdir/dev | $FILTER_LS2" \ |
@@ -87,10 +96,12 @@ mdev.testdir/dev/disk: | |||
87 | br--r--r-- 1 0 0 scsiA | 96 | br--r--r-- 1 0 0 scsiA |
88 | " \ | 97 | " \ |
89 | "" "" | 98 | "" "" |
99 | SKIP= | ||
90 | 100 | ||
91 | # continuing to use directory structure from prev test | 101 | # continuing to use directory structure from prev test |
92 | rm -rf mdev.testdir/dev/* | 102 | rm -rf mdev.testdir/dev/* |
93 | echo "sda 0:0 444 >disk/" >mdev.testdir/etc/mdev.conf | 103 | echo "sda 0:0 444 >disk/" >mdev.testdir/etc/mdev.conf |
104 | optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME | ||
94 | testing "mdev move/symlink rule '>bar/'" \ | 105 | testing "mdev move/symlink rule '>bar/'" \ |
95 | "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; | 106 | "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; |
96 | ls -lnR mdev.testdir/dev | $FILTER_LS2" \ | 107 | ls -lnR mdev.testdir/dev | $FILTER_LS2" \ |
@@ -103,11 +114,13 @@ mdev.testdir/dev/disk: | |||
103 | br--r--r-- 1 0 0 sda | 114 | br--r--r-- 1 0 0 sda |
104 | " \ | 115 | " \ |
105 | "" "" | 116 | "" "" |
117 | SKIP= | ||
106 | 118 | ||
107 | # continuing to use directory structure from prev test | 119 | # continuing to use directory structure from prev test |
108 | rm -rf mdev.testdir/dev/* | 120 | rm -rf mdev.testdir/dev/* |
109 | # here we complicate things by having non-matching group 1 and using %0 | 121 | # here we complicate things by having non-matching group 1 and using %0 |
110 | echo "s([0-9])*d([a-z]+) 0:0 644 >sd/%2_%0" >mdev.testdir/etc/mdev.conf | 122 | echo "s([0-9])*d([a-z]+) 0:0 644 >sd/%2_%0" >mdev.testdir/etc/mdev.conf |
123 | optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_MDEV_RENAME_REGEXP FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME FEATURE_LS_SORTFILES | ||
111 | testing "mdev regexp substring match + replace" \ | 124 | testing "mdev regexp substring match + replace" \ |
112 | "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; | 125 | "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; |
113 | ls -lnR mdev.testdir/dev | $FILTER_LS2" \ | 126 | ls -lnR mdev.testdir/dev | $FILTER_LS2" \ |
@@ -120,10 +133,12 @@ mdev.testdir/dev/sd: | |||
120 | brw-r--r-- 1 0 0 a_sda | 133 | brw-r--r-- 1 0 0 a_sda |
121 | " \ | 134 | " \ |
122 | "" "" | 135 | "" "" |
136 | SKIP= | ||
123 | 137 | ||
124 | # continuing to use directory structure from prev test | 138 | # continuing to use directory structure from prev test |
125 | rm -rf mdev.testdir/dev/* | 139 | rm -rf mdev.testdir/dev/* |
126 | echo "sda 0:0 644 @echo @echo TEST" >mdev.testdir/etc/mdev.conf | 140 | echo "sda 0:0 644 @echo @echo TEST" >mdev.testdir/etc/mdev.conf |
141 | optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_EXEC FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME FEATURE_SH_IS_ASH | ||
127 | testing "mdev command" \ | 142 | testing "mdev command" \ |
128 | "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; | 143 | "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; |
129 | ls -lnR mdev.testdir/dev | $FILTER_LS" \ | 144 | ls -lnR mdev.testdir/dev | $FILTER_LS" \ |
@@ -133,10 +148,12 @@ mdev.testdir/dev: | |||
133 | brw-r--r-- 1 0 0 8,0 sda | 148 | brw-r--r-- 1 0 0 8,0 sda |
134 | " \ | 149 | " \ |
135 | "" "" | 150 | "" "" |
151 | SKIP= | ||
136 | 152 | ||
137 | # continuing to use directory structure from prev test | 153 | # continuing to use directory structure from prev test |
138 | rm -rf mdev.testdir/dev/* | 154 | rm -rf mdev.testdir/dev/* |
139 | echo "sda 0:0 644 =block/ @echo @echo TEST:\$MDEV" >mdev.testdir/etc/mdev.conf | 155 | echo "sda 0:0 644 =block/ @echo @echo TEST:\$MDEV" >mdev.testdir/etc/mdev.conf |
156 | optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_MDEV_EXEC FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME FEATURE_SH_IS_ASH | ||
140 | testing "mdev move and command" \ | 157 | testing "mdev move and command" \ |
141 | "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; | 158 | "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; |
142 | ls -lnR mdev.testdir/dev | $FILTER_LS2" \ | 159 | ls -lnR mdev.testdir/dev | $FILTER_LS2" \ |
@@ -149,10 +166,12 @@ mdev.testdir/dev/block: | |||
149 | brw-r--r-- 1 0 0 sda | 166 | brw-r--r-- 1 0 0 sda |
150 | " \ | 167 | " \ |
151 | "" "" | 168 | "" "" |
169 | SKIP= | ||
152 | 170 | ||
153 | # continuing to use directory structure from prev test | 171 | # continuing to use directory structure from prev test |
154 | rm -rf mdev.testdir/dev/* | 172 | rm -rf mdev.testdir/dev/* |
155 | echo "@8,0 0:1 644" >mdev.testdir/etc/mdev.conf | 173 | echo "@8,0 0:1 644" >mdev.testdir/etc/mdev.conf |
174 | optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_MDEV_RENAME_REGEXP FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME | ||
156 | testing "mdev #maj,min and no explicit uid" \ | 175 | testing "mdev #maj,min and no explicit uid" \ |
157 | "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; | 176 | "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; |
158 | ls -lnR mdev.testdir/dev | $FILTER_LS" \ | 177 | ls -lnR mdev.testdir/dev | $FILTER_LS" \ |
@@ -161,6 +180,7 @@ mdev.testdir/dev: | |||
161 | brw-r--r-- 1 0 1 8,0 sda | 180 | brw-r--r-- 1 0 1 8,0 sda |
162 | " \ | 181 | " \ |
163 | "" "" | 182 | "" "" |
183 | SKIP= | ||
164 | 184 | ||
165 | # continuing to use directory structure from prev test | 185 | # continuing to use directory structure from prev test |
166 | rm -rf mdev.testdir/dev/* | 186 | rm -rf mdev.testdir/dev/* |
@@ -174,6 +194,7 @@ echo "capi 0:0 0660 =capi20" >mdev.testdir/etc/mdev.conf | |||
174 | echo "capi([0-9]) 0:0 0660 =capi20.0%1" >>mdev.testdir/etc/mdev.conf | 194 | echo "capi([0-9]) 0:0 0660 =capi20.0%1" >>mdev.testdir/etc/mdev.conf |
175 | echo "capi([0-9]*) 0:0 0660 =capi20.%1" >>mdev.testdir/etc/mdev.conf | 195 | echo "capi([0-9]*) 0:0 0660 =capi20.%1" >>mdev.testdir/etc/mdev.conf |
176 | # mdev invocation with DEVPATH=/class/tty/capi20 was deleting /dev/capi20 | 196 | # mdev invocation with DEVPATH=/class/tty/capi20 was deleting /dev/capi20 |
197 | optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_RENAME FEATURE_MDEV_RENAME_REGEXP FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME FEATURE_LS_SORTFILES | ||
177 | testing "move rule does not delete node with name == device_name" \ | 198 | testing "move rule does not delete node with name == device_name" \ |
178 | "\ | 199 | "\ |
179 | env - PATH=$PATH ACTION=add DEVPATH=/class/tty/capi chroot mdev.testdir /mdev 2>&1; | 200 | env - PATH=$PATH ACTION=add DEVPATH=/class/tty/capi chroot mdev.testdir /mdev 2>&1; |
@@ -187,6 +208,7 @@ crw-rw---- 1 0 0 191,1 capi20.01 | |||
187 | crw-rw---- 1 0 0 191,20 capi20.20 | 208 | crw-rw---- 1 0 0 191,20 capi20.20 |
188 | " \ | 209 | " \ |
189 | "" "" | 210 | "" "" |
211 | SKIP= | ||
190 | 212 | ||
191 | # clean up | 213 | # clean up |
192 | rm -rf mdev.testdir | 214 | rm -rf mdev.testdir |
diff --git a/testsuite/mount.tests b/testsuite/mount.tests index 043586f05..3c7405fbd 100755 --- a/testsuite/mount.tests +++ b/testsuite/mount.tests | |||
@@ -4,19 +4,24 @@ | |||
4 | 4 | ||
5 | . ./testing.sh | 5 | . ./testing.sh |
6 | 6 | ||
7 | test -f "$bindir/.config" && . "$bindir/.config" | ||
8 | |||
7 | test "`id -u`" = 0 || { | 9 | test "`id -u`" = 0 || { |
8 | echo "SKIPPED: must be root to test this" | 10 | echo "SKIPPED: mount (must be root to test this)" |
9 | exit 0 | 11 | exit 0 |
10 | } | 12 | } |
11 | 13 | ||
12 | optional MKFS_MINIX | 14 | if test x"$CONFIG_MKFS_MINIX" != x"y" \ |
13 | if [ -n "$SKIP" ] | 15 | || test x"$CONFIG_FEATURE_MINIX2" != x"y" \ |
14 | then | 16 | || test x"$CONFIG_FEATURE_MOUNT_LOOP" != x"y" \ |
15 | echo "SKIPPED: mount" | 17 | || test x"$CONFIG_FEATURE_MOUNT_FLAGS" != x"y" \ |
16 | exit 0 | 18 | || test x"$CONFIG_FEATURE_DEVFS" = x"y" \ |
19 | ; then | ||
20 | echo "SKIPPED: mount" | ||
21 | exit 0 | ||
17 | fi | 22 | fi |
18 | 23 | ||
19 | testdir=$PWD/testdir | 24 | testdir=$PWD/mount.testdir |
20 | 25 | ||
21 | dd if=/dev/zero of=mount.image1m count=1 bs=1M 2>/dev/null || { echo "dd error"; exit 1; } | 26 | dd if=/dev/zero of=mount.image1m count=1 bs=1M 2>/dev/null || { echo "dd error"; exit 1; } |
22 | mkfs.minix -v mount.image1m >/dev/null 2>&1 || { echo "mkfs.minix error"; exit 1; } | 27 | mkfs.minix -v mount.image1m >/dev/null 2>&1 || { echo "mkfs.minix error"; exit 1; } |
diff --git a/testsuite/od.tests b/testsuite/od.tests index 0bf1f4c54..a2d015ad7 100755 --- a/testsuite/od.tests +++ b/testsuite/od.tests | |||
@@ -6,6 +6,7 @@ | |||
6 | 6 | ||
7 | # testing "test name" "options" "expected result" "file input" "stdin" | 7 | # testing "test name" "options" "expected result" "file input" "stdin" |
8 | 8 | ||
9 | optional DESKTOP | ||
9 | testing "od -b" \ | 10 | testing "od -b" \ |
10 | "od -b" \ | 11 | "od -b" \ |
11 | "\ | 12 | "\ |
@@ -13,5 +14,6 @@ testing "od -b" \ | |||
13 | 0000005 | 14 | 0000005 |
14 | " \ | 15 | " \ |
15 | "" "HELLO" | 16 | "" "HELLO" |
17 | SKIP= | ||
16 | 18 | ||
17 | exit $FAILCOUNT | 19 | exit $FAILCOUNT |
diff --git a/testsuite/patch.tests b/testsuite/patch.tests index f3e607186..749d936ea 100755 --- a/testsuite/patch.tests +++ b/testsuite/patch.tests | |||
@@ -123,4 +123,6 @@ abc | |||
123 | +456 | 123 | +456 |
124 | " \ | 124 | " \ |
125 | 125 | ||
126 | rm input.orig 2>/dev/null | ||
127 | |||
126 | exit $FAILCOUNT | 128 | exit $FAILCOUNT |
diff --git a/testsuite/pidof.tests b/testsuite/pidof.tests index 45df1a958..624b0a720 100755 --- a/testsuite/pidof.tests +++ b/testsuite/pidof.tests | |||
@@ -20,12 +20,14 @@ testing "pidof this" "pidof pidof.tests | grep -o -w $$" "$$\n" "" "" | |||
20 | 20 | ||
21 | optional FEATURE_PIDOF_SINGLE | 21 | optional FEATURE_PIDOF_SINGLE |
22 | testing "pidof -s" "pidof -s init" "1\n" "" "" | 22 | testing "pidof -s" "pidof -s init" "1\n" "" "" |
23 | SKIP= | ||
23 | 24 | ||
24 | optional FEATURE_PIDOF_OMIT | 25 | optional FEATURE_PIDOF_OMIT FEATURE_PIDOF_SINGLE |
25 | # This test fails now because process name matching logic has changed, | 26 | # This test fails now because process name matching logic has changed, |
26 | # but new logic is not "wrong" either... see find_pid_by_name.c comments | 27 | # but new logic is not "wrong" either... see find_pid_by_name.c comments |
27 | #testing "pidof -o %PPID" "pidof -o %PPID pidof.tests | grep -o -w $$" "" "" "" | 28 | #testing "pidof -o %PPID" "pidof -o %PPID pidof.tests | grep -o -w $$" "" "" "" |
28 | testing "pidof -o %PPID NOP" "pidof -o %PPID -s init" "1\n" "" "" | 29 | testing "pidof -o %PPID NOP" "pidof -o %PPID -s init" "1\n" "" "" |
29 | testing "pidof -o init" "pidof -o 1 init | grep -o -w 1" "" "" "" | 30 | testing "pidof -o init" "pidof -o 1 init | grep -o -w 1" "" "" "" |
31 | SKIP= | ||
30 | 32 | ||
31 | exit $FAILCOUNT | 33 | exit $FAILCOUNT |
diff --git a/testsuite/rx.tests b/testsuite/rx.tests index c2b8814a2..985fcdc01 100755 --- a/testsuite/rx.tests +++ b/testsuite/rx.tests | |||
@@ -18,9 +18,9 @@ testing "rx" \ | |||
18 | 00000000 43 06 06 |C..|\n\ | 18 | 00000000 43 06 06 |C..|\n\ |
19 | 00000003\n\ | 19 | 00000003\n\ |
20 | ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????" \ | 20 | ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????" \ |
21 | "" "\1\1\376\ | 21 | "" "\01\01\0376\ |
22 | ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????\ | 22 | ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????\ |
23 | \x1A\x1A\x1A\x1A\x1A\x4B\xB0\4" | 23 | \x1A\x1A\x1A\x1A\x1A\x4B\xB0\04" |
24 | 24 | ||
25 | rm -f rx.OUTFILE 2>/dev/null | 25 | rm -f rx.OUTFILE 2>/dev/null |
26 | 26 | ||
diff --git a/testsuite/sed.tests b/testsuite/sed.tests index 875c946be..88b9c4e4b 100755 --- a/testsuite/sed.tests +++ b/testsuite/sed.tests | |||
@@ -110,7 +110,7 @@ testing "sed embedded NUL" "sed -e 's/woo/bang/'" "\0bang\0woo\0" "" \ | |||
110 | testing "sed embedded NUL g" "sed -e 's/woo/bang/g'" "bang\0bang\0" "" \ | 110 | testing "sed embedded NUL g" "sed -e 's/woo/bang/g'" "bang\0bang\0" "" \ |
111 | "woo\0woo\0" | 111 | "woo\0woo\0" |
112 | test x"$SKIP_KNOWN_BUGS" = x"" && { | 112 | test x"$SKIP_KNOWN_BUGS" = x"" && { |
113 | echo -e "/woo/a he\0llo" > sed.commands | 113 | $ECHO -e "/woo/a he\0llo" > sed.commands |
114 | testing "sed NUL in command" "sed -f sed.commands" "woo\nhe\0llo\n" "" "woo" | 114 | testing "sed NUL in command" "sed -f sed.commands" "woo\nhe\0llo\n" "" "woo" |
115 | rm sed.commands | 115 | rm sed.commands |
116 | } | 116 | } |
@@ -153,7 +153,7 @@ testing "sed clusternewline" \ | |||
153 | "one\none\n111\n222\ntwo\ntwo" "one" "two" | 153 | "one\none\n111\n222\ntwo\ntwo" "one" "two" |
154 | } | 154 | } |
155 | testing "sed subst+write" \ | 155 | testing "sed subst+write" \ |
156 | "sed -e 's/i/z/' -e 'woutputw' input -; echo -n X; cat outputw" \ | 156 | "sed -e 's/i/z/' -e 'woutputw' input -; $ECHO -n X; cat outputw" \ |
157 | "thzngy\nagaznXthzngy\nagazn" "thingy" "again" | 157 | "thzngy\nagaznXthzngy\nagazn" "thingy" "again" |
158 | rm outputw | 158 | rm outputw |
159 | testing "sed trailing NUL" \ | 159 | testing "sed trailing NUL" \ |
@@ -248,4 +248,28 @@ testing "sed beginning (^) matches only once" \ | |||
248 | ">/usr</>lib<\n" "" \ | 248 | ">/usr</>lib<\n" "" \ |
249 | "/usr/lib\n" | 249 | "/usr/lib\n" |
250 | 250 | ||
251 | testing "sed c" \ | ||
252 | "sed 'crepl'" \ | ||
253 | "repl\nrepl\n" "" \ | ||
254 | "first\nsecond\n" | ||
255 | |||
256 | testing "sed nested {}s" \ | ||
257 | "sed '/asd/ { p; /s/ { s/s/c/ }; p; q }'" \ | ||
258 | "qwe\nasd\nacd\nacd\n" "" \ | ||
259 | "qwe\nasd\nzxc\n" | ||
260 | |||
261 | testing "sed a cmd ended by double backslash" \ | ||
262 | "sed -e '/| one /a \\ | ||
263 | | three \\\\' -e '/| one-/a \\ | ||
264 | | three-* \\\\'" \ | ||
265 | ' | one \\ | ||
266 | | three \\ | ||
267 | | two \\ | ||
268 | ' '' \ | ||
269 | ' | one \\ | ||
270 | | two \\ | ||
271 | ' | ||
272 | |||
273 | # testing "description" "arguments" "result" "infile" "stdin" | ||
274 | |||
251 | exit $FAILCOUNT | 275 | exit $FAILCOUNT |
diff --git a/testsuite/sort.tests b/testsuite/sort.tests index 72df80b1f..8a810f8d4 100755 --- a/testsuite/sort.tests +++ b/testsuite/sort.tests | |||
@@ -118,7 +118,7 @@ testing "sort key doesn't strip leading blanks, disables fallback global sort" \ | |||
118 | "sort -n -k2 -t ' '" " a \n 1 \n 2 \n" "" " 2 \n 1 \n a \n" | 118 | "sort -n -k2 -t ' '" " a \n 1 \n 2 \n" "" " 2 \n 1 \n a \n" |
119 | 119 | ||
120 | testing "sort file in place" \ | 120 | testing "sort file in place" \ |
121 | "strace -oZZZ sort -o input input && cat input" "\ | 121 | "sort -o input input && cat input" "\ |
122 | 111 | 122 | 111 |
123 | 222 | 123 | 222 |
124 | " "\ | 124 | " "\ |
diff --git a/testsuite/tail/tail-works b/testsuite/tail/tail-works index f3434d1a9..50eca136e 100644 --- a/testsuite/tail/tail-works +++ b/testsuite/tail/tail-works | |||
@@ -1,3 +1,5 @@ | |||
1 | # FEATURE: CONFIG_INCLUDE_SUSv2 | ||
2 | |||
1 | $ECHO -ne "abc\ndef\n123\n" >input | 3 | $ECHO -ne "abc\ndef\n123\n" >input |
2 | $ECHO -ne "def\n123\n" >logfile.ok | 4 | $ECHO -ne "def\n123\n" >logfile.ok |
3 | busybox tail -2 input > logfile.bb | 5 | busybox tail -2 input > logfile.bb |
diff --git a/testsuite/tar.tests b/testsuite/tar.tests index a96382932..f40079037 100755 --- a/testsuite/tar.tests +++ b/testsuite/tar.tests | |||
@@ -9,6 +9,7 @@ mkdir tar.tempdir && cd tar.tempdir || exit 1 | |||
9 | 9 | ||
10 | # testing "test name" "script" "expected result" "file input" "stdin" | 10 | # testing "test name" "script" "expected result" "file input" "stdin" |
11 | 11 | ||
12 | optional FEATURE_TAR_CREATE FEATURE_LS_SORTFILES | ||
12 | testing "tar hardlinks and repeated files" '\ | 13 | testing "tar hardlinks and repeated files" '\ |
13 | rm -rf input_* test.tar 2>/dev/null | 14 | rm -rf input_* test.tar 2>/dev/null |
14 | >input_hard1 | 15 | >input_hard1 |
@@ -39,7 +40,9 @@ drwxr-xr-x input_dir | |||
39 | -rw-r--r-- input_hard2 | 40 | -rw-r--r-- input_hard2 |
40 | " \ | 41 | " \ |
41 | "" "" | 42 | "" "" |
43 | SKIP= | ||
42 | 44 | ||
45 | optional FEATURE_TAR_CREATE FEATURE_LS_SORTFILES | ||
43 | testing "tar hardlinks mode" '\ | 46 | testing "tar hardlinks mode" '\ |
44 | rm -rf input_* test.tar 2>/dev/null | 47 | rm -rf input_* test.tar 2>/dev/null |
45 | >input_hard1 | 48 | >input_hard1 |
@@ -68,7 +71,9 @@ dr-xr-x--- input_dir | |||
68 | -rwxr----x input_hard2 | 71 | -rwxr----x input_hard2 |
69 | " \ | 72 | " \ |
70 | "" "" | 73 | "" "" |
74 | SKIP= | ||
71 | 75 | ||
76 | optional FEATURE_TAR_CREATE FEATURE_LS_SORTFILES | ||
72 | testing "tar symlinks mode" '\ | 77 | testing "tar symlinks mode" '\ |
73 | rm -rf input_* test.tar 2>/dev/null | 78 | rm -rf input_* test.tar 2>/dev/null |
74 | >input_file | 79 | >input_file |
@@ -79,7 +84,7 @@ chmod 550 input_dir | |||
79 | ln input_file input_dir | 84 | ln input_file input_dir |
80 | ln input_soft input_dir | 85 | ln input_soft input_dir |
81 | tar cf test.tar input_* | 86 | tar cf test.tar input_* |
82 | tar tvf test.tar | sed "s/.*[0-9] input/input/" | 87 | tar tvf test.tar | sed "s/.*[0-9] input/input/" | sort |
83 | tar xf test.tar 2>&1 | 88 | tar xf test.tar 2>&1 |
84 | echo Ok: $? | 89 | echo Ok: $? |
85 | ls -l . input_dir/* | grep input_ | sed "s/\\(^[^ ]*\\) .* input/\\1 input/" | 90 | ls -l . input_dir/* | grep input_ | sed "s/\\(^[^ ]*\\) .* input/\\1 input/" |
@@ -97,8 +102,9 @@ dr-xr-x--- input_dir | |||
97 | lrwxrwxrwx input_file | 102 | lrwxrwxrwx input_file |
98 | " \ | 103 | " \ |
99 | "" "" | 104 | "" "" |
105 | SKIP= | ||
100 | 106 | ||
101 | optional FEATURE_TAR_LONG_OPTIONS | 107 | optional FEATURE_TAR_CREATE FEATURE_TAR_LONG_OPTIONS |
102 | testing "tar --overwrite" "\ | 108 | testing "tar --overwrite" "\ |
103 | rm -rf input_* test.tar 2>/dev/null | 109 | rm -rf input_* test.tar 2>/dev/null |
104 | ln input input_hard | 110 | ln input input_hard |
diff --git a/testsuite/tar/tar_with_link_with_size b/testsuite/tar/tar_with_link_with_size index 5b61cc70b..774cd5698 100644 --- a/testsuite/tar/tar_with_link_with_size +++ b/testsuite/tar/tar_with_link_with_size | |||
@@ -1,3 +1,5 @@ | |||
1 | # FEATURE: CONFIG_FEATURE_TAR_UNAME_GNAME | ||
2 | |||
1 | # This tarball contains a softlink with size field != 0. | 3 | # This tarball contains a softlink with size field != 0. |
2 | # If not ignored, it makes hext header to be skipped | 4 | # If not ignored, it makes hext header to be skipped |
3 | # and data to be read as a header. | 5 | # and data to be read as a header. |
diff --git a/testsuite/tar/tar_with_prefix_fields b/testsuite/tar/tar_with_prefix_fields index 1c7124d52..8c1fda795 100644 --- a/testsuite/tar/tar_with_prefix_fields +++ b/testsuite/tar/tar_with_prefix_fields | |||
@@ -1,3 +1,6 @@ | |||
1 | # FEATURE: CONFIG_FEATURE_TAR_UNAME_GNAME | ||
2 | # FEATURE: CONFIG_DESKTOP | ||
3 | |||
1 | tar1_bz2() | 4 | tar1_bz2() |
2 | { | 5 | { |
3 | $ECHO -ne "\x42\x5a\x68\x39\x31\x41\x59\x26\x53\x59\x12\xd1\x86\x30\x00\x0c" | 6 | $ECHO -ne "\x42\x5a\x68\x39\x31\x41\x59\x26\x53\x59\x12\xd1\x86\x30\x00\x0c" |
diff --git a/testsuite/testing.sh b/testsuite/testing.sh index 22c640faf..913d7f8ef 100755..100644 --- a/testsuite/testing.sh +++ b/testsuite/testing.sh | |||
@@ -54,14 +54,14 @@ test x"$ECHO" != x"" || { | |||
54 | 54 | ||
55 | optional() | 55 | optional() |
56 | { | 56 | { |
57 | option=`echo ":$OPTIONFLAGS:" | grep ":$1:"` | 57 | SKIP= |
58 | # Not set? | 58 | while test "$1"; do |
59 | if [ -z "$1" ] || [ -z "$OPTIONFLAGS" ] || [ ${#option} -ne 0 ] | 59 | if test x"${OPTIONFLAGS/*:$1:*/y}" != x"y"; then |
60 | then | 60 | SKIP=1 |
61 | SKIP= | 61 | return |
62 | return | 62 | fi |
63 | fi | 63 | shift |
64 | SKIP=1 | 64 | done |
65 | } | 65 | } |
66 | 66 | ||
67 | # The testing function | 67 | # The testing function |
@@ -73,7 +73,7 @@ testing() | |||
73 | 73 | ||
74 | if [ $# -ne 5 ] | 74 | if [ $# -ne 5 ] |
75 | then | 75 | then |
76 | echo "Test $NAME has wrong number of arguments (must be 5) ($# $*)" >&2 | 76 | echo "Test $NAME has wrong number of arguments: $# (must be 5)" >&2 |
77 | exit 1 | 77 | exit 1 |
78 | fi | 78 | fi |
79 | 79 | ||
diff --git a/testsuite/tr.tests b/testsuite/tr.tests index 9706056c9..a1f83bfc6 100755 --- a/testsuite/tr.tests +++ b/testsuite/tr.tests | |||
@@ -15,17 +15,23 @@ testing "tr understands 0-9A-F" \ | |||
15 | "tr -cd '[0-9A-F]'" \ | 15 | "tr -cd '[0-9A-F]'" \ |
16 | "19AF" "" "19AFH\n" | 16 | "19AF" "" "19AFH\n" |
17 | 17 | ||
18 | optional CONFIG_FEATURE_TR_CLASSES | ||
18 | testing "tr understands [:xdigit:]" \ | 19 | testing "tr understands [:xdigit:]" \ |
19 | "tr -cd '[:xdigit:]'" \ | 20 | "tr -cd '[:xdigit:]'" \ |
20 | "19AF" "" "19AFH\n" | 21 | "19AF" "" "19AFH\n" |
22 | SKIP= | ||
21 | 23 | ||
24 | optional CONFIG_FEATURE_TR_CLASSES | ||
22 | testing "tr does not stop after [:digit:]" \ | 25 | testing "tr does not stop after [:digit:]" \ |
23 | "tr '[:digit:]y-z' 111111111123" \ | 26 | "tr '[:digit:]y-z' 111111111123" \ |
24 | "111abcx23\n" "" "789abcxyz\n" | 27 | "111abcx23\n" "" "789abcxyz\n" |
28 | SKIP= | ||
25 | 29 | ||
30 | optional CONFIG_FEATURE_TR_CLASSES | ||
26 | testing "tr has correct xdigit sequence" \ | 31 | testing "tr has correct xdigit sequence" \ |
27 | "tr '[:xdigit:]Gg' 1111111151242222333330xX" \ | 32 | "tr '[:xdigit:]Gg' 1111111151242222333330xX" \ |
28 | "#1111111151242222x333330X\n" "" \ | 33 | "#1111111151242222x333330X\n" "" \ |
29 | "#0123456789ABCDEFGabcdefg\n" | 34 | "#0123456789ABCDEFGabcdefg\n" |
35 | SKIP= | ||
30 | 36 | ||
31 | exit $FAILCOUNT | 37 | exit $FAILCOUNT |
diff --git a/testsuite/tr/tr-d-alnum-works b/testsuite/tr/tr-d-alnum-works index d440f8f3b..6540ea527 100644 --- a/testsuite/tr/tr-d-alnum-works +++ b/testsuite/tr/tr-d-alnum-works | |||
@@ -1,3 +1,5 @@ | |||
1 | # FEATURE: CONFIG_FEATURE_TR_CLASSES | ||
2 | |||
1 | echo testing | tr -d '[[:alnum:]]' > logfile.gnu | 3 | echo testing | tr -d '[[:alnum:]]' > logfile.gnu |
2 | echo testing | busybox tr -d '[[:alnum:]]' > logfile.bb | 4 | echo testing | busybox tr -d '[[:alnum:]]' > logfile.bb |
3 | 5 | ||
diff --git a/testsuite/tr/tr-rejects-wrong-class b/testsuite/tr/tr-rejects-wrong-class index 97539360d..1d488a3df 100644 --- a/testsuite/tr/tr-rejects-wrong-class +++ b/testsuite/tr/tr-rejects-wrong-class | |||
@@ -1,3 +1,5 @@ | |||
1 | # FEATURE: CONFIG_FEATURE_TR_CLASSES | ||
2 | |||
1 | echo t12esting | tr -d '[[:alpha:]]' > logfile.gnu | 3 | echo t12esting | tr -d '[[:alpha:]]' > logfile.gnu |
2 | echo t12esting | tr -d '[:alpha:]' >> logfile.gnu | 4 | echo t12esting | tr -d '[:alpha:]' >> logfile.gnu |
3 | echo t12esting | tr -d '[[:alpha:]' >> logfile.gnu | 5 | echo t12esting | tr -d '[[:alpha:]' >> logfile.gnu |
diff --git a/testsuite/tr/tr-works b/testsuite/tr/tr-works index 2c0a9d196..5e4a30ee4 100644 --- a/testsuite/tr/tr-works +++ b/testsuite/tr/tr-works | |||
@@ -1,6 +1,8 @@ | |||
1 | # FEATURE: CONFIG_FEATURE_TR_CLASSES | ||
2 | |||
1 | run_tr () | 3 | run_tr () |
2 | { | 4 | { |
3 | echo -n "echo '$1' | tr '$2' '$3': " | 5 | $ECHO -n "echo '$1' | tr '$2' '$3': " |
4 | echo "$1" | $bb tr "$2" "$3" | 6 | echo "$1" | $bb tr "$2" "$3" |
5 | echo | 7 | echo |
6 | } | 8 | } |
diff --git a/testsuite/unexpand.tests b/testsuite/unexpand.tests index 1af2fdc5f..a48e3214e 100755 --- a/testsuite/unexpand.tests +++ b/testsuite/unexpand.tests | |||
@@ -30,7 +30,9 @@ testing "unexpand case 7" "unexpand" \ | |||
30 | testing "unexpand case 8" "unexpand" \ | 30 | testing "unexpand case 8" "unexpand" \ |
31 | "a b\n" "" "a b\n" \ | 31 | "a b\n" "" "a b\n" \ |
32 | 32 | ||
33 | optional UNICODE_SUPPORT | ||
33 | testing "unexpand with unicode characher 0x394" "unexpand" \ | 34 | testing "unexpand with unicode characher 0x394" "unexpand" \ |
34 | "1ΔΔΔ5\t99999\n" "" "1ΔΔΔ5 99999\n" \ | 35 | "1ΔΔΔ5\t99999\n" "" "1ΔΔΔ5 99999\n" |
36 | SKIP= | ||
35 | 37 | ||
36 | exit $FAILCOUNT | 38 | exit $FAILCOUNT |
diff --git a/util-linux/Kbuild b/util-linux/Kbuild index 99e3efea3..4fa392398 100644 --- a/util-linux/Kbuild +++ b/util-linux/Kbuild | |||
@@ -42,5 +42,4 @@ lib-$(CONFIG_SCRIPTREPLAY) += scriptreplay.o | |||
42 | lib-$(CONFIG_SETARCH) += setarch.o | 42 | lib-$(CONFIG_SETARCH) += setarch.o |
43 | lib-$(CONFIG_SWAPONOFF) += swaponoff.o | 43 | lib-$(CONFIG_SWAPONOFF) += swaponoff.o |
44 | lib-$(CONFIG_SWITCH_ROOT) += switch_root.o | 44 | lib-$(CONFIG_SWITCH_ROOT) += switch_root.o |
45 | lib-$(CONFIG_MKFS_EXT2) += tune2fs.o | ||
46 | lib-$(CONFIG_UMOUNT) += umount.o | 45 | lib-$(CONFIG_UMOUNT) += umount.o |
diff --git a/util-linux/mkfs_ext2.c b/util-linux/mkfs_ext2.c index cf40c20eb..fd54734fc 100644 --- a/util-linux/mkfs_ext2.c +++ b/util-linux/mkfs_ext2.c | |||
@@ -10,7 +10,6 @@ | |||
10 | #include "libbb.h" | 10 | #include "libbb.h" |
11 | #include <linux/fs.h> | 11 | #include <linux/fs.h> |
12 | #include <linux/ext2_fs.h> | 12 | #include <linux/ext2_fs.h> |
13 | #include "volume_id/volume_id_internal.h" | ||
14 | 13 | ||
15 | #define ENABLE_FEATURE_MKFS_EXT2_RESERVED_GDT 0 | 14 | #define ENABLE_FEATURE_MKFS_EXT2_RESERVED_GDT 0 |
16 | #define ENABLE_FEATURE_MKFS_EXT2_DIR_INDEX 1 | 15 | #define ENABLE_FEATURE_MKFS_EXT2_DIR_INDEX 1 |
@@ -29,9 +28,9 @@ char BUG_wrong_field_size(void); | |||
29 | #define STORE_LE(field, value) \ | 28 | #define STORE_LE(field, value) \ |
30 | do { \ | 29 | do { \ |
31 | if (sizeof(field) == 4) \ | 30 | if (sizeof(field) == 4) \ |
32 | field = cpu_to_le32(value); \ | 31 | field = SWAP_LE32(value); \ |
33 | else if (sizeof(field) == 2) \ | 32 | else if (sizeof(field) == 2) \ |
34 | field = cpu_to_le16(value); \ | 33 | field = SWAP_LE16(value); \ |
35 | else if (sizeof(field) == 1) \ | 34 | else if (sizeof(field) == 1) \ |
36 | field = (value); \ | 35 | field = (value); \ |
37 | else \ | 36 | else \ |
@@ -39,7 +38,7 @@ do { \ | |||
39 | } while (0) | 38 | } while (0) |
40 | 39 | ||
41 | #define FETCH_LE32(field) \ | 40 | #define FETCH_LE32(field) \ |
42 | (sizeof(field) == 4 ? cpu_to_le32(field) : BUG_wrong_field_size()) | 41 | (sizeof(field) == 4 ? SWAP_LE32(field) : BUG_wrong_field_size()) |
43 | 42 | ||
44 | // All fields are little-endian | 43 | // All fields are little-endian |
45 | struct ext2_dir { | 44 | struct ext2_dir { |
diff --git a/util-linux/mkfs_reiser.c b/util-linux/mkfs_reiser.c index eb2c94d02..f9a0ca82a 100644 --- a/util-linux/mkfs_reiser.c +++ b/util-linux/mkfs_reiser.c | |||
@@ -8,15 +8,14 @@ | |||
8 | */ | 8 | */ |
9 | #include "libbb.h" | 9 | #include "libbb.h" |
10 | #include <linux/fs.h> | 10 | #include <linux/fs.h> |
11 | #include "volume_id/volume_id_internal.h" | ||
12 | 11 | ||
13 | char BUG_wrong_field_size(void); | 12 | char BUG_wrong_field_size(void); |
14 | #define STORE_LE(field, value) \ | 13 | #define STORE_LE(field, value) \ |
15 | do { \ | 14 | do { \ |
16 | if (sizeof(field) == 4) \ | 15 | if (sizeof(field) == 4) \ |
17 | field = cpu_to_le32(value); \ | 16 | field = SWAP_LE32(value); \ |
18 | else if (sizeof(field) == 2) \ | 17 | else if (sizeof(field) == 2) \ |
19 | field = cpu_to_le16(value); \ | 18 | field = SWAP_LE16(value); \ |
20 | else if (sizeof(field) == 1) \ | 19 | else if (sizeof(field) == 1) \ |
21 | field = (value); \ | 20 | field = (value); \ |
22 | else \ | 21 | else \ |
@@ -24,7 +23,7 @@ do { \ | |||
24 | } while (0) | 23 | } while (0) |
25 | 24 | ||
26 | #define FETCH_LE32(field) \ | 25 | #define FETCH_LE32(field) \ |
27 | (sizeof(field) == 4 ? cpu_to_le32(field) : BUG_wrong_field_size()) | 26 | (sizeof(field) == 4 ? SWAP_LE32(field) : BUG_wrong_field_size()) |
28 | 27 | ||
29 | struct journal_params { | 28 | struct journal_params { |
30 | uint32_t jp_journal_1st_block; /* where does journal start from on its device */ | 29 | uint32_t jp_journal_1st_block; /* where does journal start from on its device */ |
diff --git a/util-linux/mkfs_vfat.c b/util-linux/mkfs_vfat.c index 1363612f2..ff3e4165a 100644 --- a/util-linux/mkfs_vfat.c +++ b/util-linux/mkfs_vfat.c | |||
@@ -16,7 +16,6 @@ | |||
16 | # define BLKSSZGET _IO(0x12, 104) | 16 | # define BLKSSZGET _IO(0x12, 104) |
17 | #endif | 17 | #endif |
18 | //#include <linux/msdos_fs.h> | 18 | //#include <linux/msdos_fs.h> |
19 | #include "volume_id/volume_id_internal.h" | ||
20 | 19 | ||
21 | #define SECTOR_SIZE 512 | 20 | #define SECTOR_SIZE 512 |
22 | 21 | ||
@@ -168,15 +167,15 @@ static const char boot_code[] ALIGN1 = | |||
168 | 167 | ||
169 | 168 | ||
170 | #define MARK_CLUSTER(cluster, value) \ | 169 | #define MARK_CLUSTER(cluster, value) \ |
171 | ((uint32_t *)fat)[cluster] = cpu_to_le32(value) | 170 | ((uint32_t *)fat)[cluster] = SWAP_LE32(value) |
172 | 171 | ||
173 | void BUG_unsupported_field_size(void); | 172 | void BUG_unsupported_field_size(void); |
174 | #define STORE_LE(field, value) \ | 173 | #define STORE_LE(field, value) \ |
175 | do { \ | 174 | do { \ |
176 | if (sizeof(field) == 4) \ | 175 | if (sizeof(field) == 4) \ |
177 | field = cpu_to_le32(value); \ | 176 | field = SWAP_LE32(value); \ |
178 | else if (sizeof(field) == 2) \ | 177 | else if (sizeof(field) == 2) \ |
179 | field = cpu_to_le16(value); \ | 178 | field = SWAP_LE16(value); \ |
180 | else if (sizeof(field) == 1) \ | 179 | else if (sizeof(field) == 1) \ |
181 | field = (value); \ | 180 | field = (value); \ |
182 | else \ | 181 | else \ |
diff --git a/util-linux/swaponoff.c b/util-linux/swaponoff.c index f647a32bc..f2f52fb88 100644 --- a/util-linux/swaponoff.c +++ b/util-linux/swaponoff.c | |||
@@ -66,11 +66,20 @@ static int do_em_all(void) | |||
66 | bb_perror_msg_and_die("/etc/fstab"); | 66 | bb_perror_msg_and_die("/etc/fstab"); |
67 | 67 | ||
68 | err = 0; | 68 | err = 0; |
69 | while ((m = getmntent(f)) != NULL) | 69 | while ((m = getmntent(f)) != NULL) { |
70 | if (strcmp(m->mnt_type, MNTTYPE_SWAP) == 0) | 70 | if (strcmp(m->mnt_type, MNTTYPE_SWAP) == 0) { |
71 | err += swap_enable_disable(m->mnt_fsname); | 71 | /* swapon -a should ignore entries with noauto, |
72 | * but swapoff -a should process them */ | ||
73 | if (applet_name[5] != 'n' | ||
74 | || hasmntopt(m, MNTOPT_NOAUTO) == NULL | ||
75 | ) { | ||
76 | err += swap_enable_disable(m->mnt_fsname); | ||
77 | } | ||
78 | } | ||
79 | } | ||
72 | 80 | ||
73 | endmntent(f); | 81 | if (ENABLE_FEATURE_CLEAN_UP) |
82 | endmntent(f); | ||
74 | 83 | ||
75 | return err; | 84 | return err; |
76 | } | 85 | } |