diff options
author | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2007-04-10 21:40:19 +0000 |
---|---|---|
committer | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2007-04-10 21:40:19 +0000 |
commit | 6ba5abac8daa48b47c2905d306740cfd4387af6d (patch) | |
tree | 51bc0b498a5e16f8041604d913e25708cc76058f | |
parent | 48b6c559ccf5bc74eaa7e334310e9edf367033e2 (diff) | |
download | busybox-w32-6ba5abac8daa48b47c2905d306740cfd4387af6d.tar.gz busybox-w32-6ba5abac8daa48b47c2905d306740cfd4387af6d.tar.bz2 busybox-w32-6ba5abac8daa48b47c2905d306740cfd4387af6d.zip |
make compressed help code NOMMU- and NOFORK-friendly -
no forking anymore, bunzip2 unpack routine now does all it in memory.
git-svn-id: svn://busybox.net/trunk/busybox@18392 69ca8d6d-28ef-0310-b511-8ec308f3f277
-rw-r--r-- | applets/applets.c | 67 | ||||
-rw-r--r-- | archival/gzip.c | 2 | ||||
-rw-r--r-- | archival/libunarchive/decompress_bunzip2.c | 58 | ||||
-rw-r--r-- | archival/libunarchive/decompress_unzip.c | 2 | ||||
-rw-r--r-- | archival/libunarchive/get_header_tar_gz.c | 2 | ||||
-rw-r--r-- | coreutils/cksum.c | 3 | ||||
-rw-r--r-- | include/libbb.h | 5 | ||||
-rw-r--r-- | include/unarchive.h | 5 | ||||
-rw-r--r-- | libbb/crc32.c | 7 | ||||
-rw-r--r-- | libbb/vfork_daemon_rexec.c | 144 | ||||
-rw-r--r-- | libbb/xfuncs.c | 9 |
11 files changed, 134 insertions, 170 deletions
diff --git a/applets/applets.c b/applets/applets.c index 3441a7886..2f677372d 100644 --- a/applets/applets.c +++ b/applets/applets.c | |||
@@ -403,44 +403,32 @@ static void check_suid(const struct bb_applet *applet) | |||
403 | 403 | ||
404 | static const char *unpack_usage_messages(void) | 404 | static const char *unpack_usage_messages(void) |
405 | { | 405 | { |
406 | int input[2], output[2], pid; | 406 | char *outbuf = NULL; |
407 | char *buf; | 407 | bunzip_data *bd; |
408 | 408 | int i; | |
409 | if (pipe(input) < 0 || pipe(output) < 0) | ||
410 | exit(1); | ||
411 | |||
412 | //TODO: not NOMMU friendly! | ||
413 | pid = fork(); | ||
414 | switch (pid) { | ||
415 | case -1: /* error */ | ||
416 | exit(1); | ||
417 | case 0: /* child */ | ||
418 | close(input[1]); | ||
419 | close(output[0]); | ||
420 | uncompressStream(input[0], output[1]); | ||
421 | exit(0); | ||
422 | } | ||
423 | /* parent */ | ||
424 | |||
425 | close(input[0]); | ||
426 | close(output[1]); | ||
427 | pid = fork(); | ||
428 | switch (pid) { | ||
429 | case -1: /* error */ | ||
430 | exit(1); | ||
431 | case 0: /* child */ | ||
432 | full_write(input[1], packed_usage, sizeof(packed_usage)); | ||
433 | exit(0); | ||
434 | } | ||
435 | /* parent */ | ||
436 | close(input[1]); | ||
437 | 409 | ||
438 | buf = xmalloc(SIZEOF_usage_messages); | 410 | i = start_bunzip(&bd, |
439 | full_read(output[0], buf, SIZEOF_usage_messages); | 411 | /* src_fd: */ -1, |
440 | return buf; | 412 | /* inbuf: */ packed_usage, |
413 | /* len: */ sizeof(packed_usage)); | ||
414 | /* read_bunzip can longjmp to start_bunzip, and ultimately | ||
415 | * end up here with i != 0 on read data errors! Not trivial */ | ||
416 | if (!i) { | ||
417 | /* Cannot use xmalloc: will leak bd in NOFORK case! */ | ||
418 | outbuf = malloc_or_warn(SIZEOF_usage_messages); | ||
419 | if (outbuf) | ||
420 | read_bunzip(bd, outbuf, SIZEOF_usage_messages); | ||
421 | } | ||
422 | dealloc_bunzip(bd); | ||
423 | return outbuf; | ||
441 | } | 424 | } |
425 | #define dealloc_usage_messages(s) free(s) | ||
426 | |||
442 | #else | 427 | #else |
428 | |||
443 | #define unpack_usage_messages() usage_messages | 429 | #define unpack_usage_messages() usage_messages |
430 | #define dealloc_usage_messages(s) ((void)(s)) | ||
431 | |||
444 | #endif /* FEATURE_COMPRESS_USAGE */ | 432 | #endif /* FEATURE_COMPRESS_USAGE */ |
445 | 433 | ||
446 | 434 | ||
@@ -448,22 +436,23 @@ void bb_show_usage(void) | |||
448 | { | 436 | { |
449 | if (ENABLE_SHOW_USAGE) { | 437 | if (ENABLE_SHOW_USAGE) { |
450 | const char *format_string; | 438 | const char *format_string; |
451 | const char *usage_string = unpack_usage_messages(); | 439 | const char *p; |
440 | const char *usage_string = p = unpack_usage_messages(); | ||
452 | int i; | 441 | int i; |
453 | 442 | ||
454 | i = current_applet - applets; | 443 | i = current_applet - applets; |
455 | while (i) { | 444 | while (i) { |
456 | while (*usage_string++) continue; | 445 | while (*p++) continue; |
457 | i--; | 446 | i--; |
458 | } | 447 | } |
459 | 448 | ||
460 | format_string = "%s\n\nUsage: %s %s\n\n"; | 449 | format_string = "%s\n\nUsage: %s %s\n\n"; |
461 | if (*usage_string == '\b') | 450 | if (*p == '\b') |
462 | format_string = "%s\n\nNo help available.\n\n"; | 451 | format_string = "%s\n\nNo help available.\n\n"; |
463 | fprintf(stderr, format_string, bb_msg_full_version, | 452 | fprintf(stderr, format_string, bb_msg_full_version, |
464 | applet_name, usage_string); | 453 | applet_name, p); |
454 | dealloc_usage_messages((char*)usage_string); | ||
465 | } | 455 | } |
466 | |||
467 | xfunc_die(); | 456 | xfunc_die(); |
468 | } | 457 | } |
469 | 458 | ||
diff --git a/archival/gzip.c b/archival/gzip.c index 39391dfda..561f1088c 100644 --- a/archival/gzip.c +++ b/archival/gzip.c | |||
@@ -2079,7 +2079,7 @@ int gzip_main(int argc, char **argv) | |||
2079 | ALLOC(ush, G1.prev, 1L << BITS); | 2079 | ALLOC(ush, G1.prev, 1L << BITS); |
2080 | 2080 | ||
2081 | /* Initialise the CRC32 table */ | 2081 | /* Initialise the CRC32 table */ |
2082 | G1.crc_32_tab = crc32_filltable(0); | 2082 | G1.crc_32_tab = crc32_filltable(NULL, 0); |
2083 | 2083 | ||
2084 | return bbunpack(argv, make_new_name_gzip, pack_gzip); | 2084 | return bbunpack(argv, make_new_name_gzip, pack_gzip); |
2085 | } | 2085 | } |
diff --git a/archival/libunarchive/decompress_bunzip2.c b/archival/libunarchive/decompress_bunzip2.c index d4db40ece..3f0b0f6f2 100644 --- a/archival/libunarchive/decompress_bunzip2.c +++ b/archival/libunarchive/decompress_bunzip2.c | |||
@@ -62,34 +62,31 @@ struct group_data { | |||
62 | /* Structure holding all the housekeeping data, including IO buffers and | 62 | /* Structure holding all the housekeeping data, including IO buffers and |
63 | memory that persists between calls to bunzip */ | 63 | memory that persists between calls to bunzip */ |
64 | 64 | ||
65 | typedef struct { | 65 | struct bunzip_data { |
66 | /* State for interrupting output loop */ | 66 | /* State for interrupting output loop */ |
67 | |||
68 | int writeCopies, writePos, writeRunCountdown, writeCount, writeCurrent; | 67 | int writeCopies, writePos, writeRunCountdown, writeCount, writeCurrent; |
69 | 68 | ||
70 | /* I/O tracking data (file handles, buffers, positions, etc.) */ | 69 | /* I/O tracking data (file handles, buffers, positions, etc.) */ |
71 | |||
72 | int in_fd, out_fd, inbufCount, inbufPos /*, outbufPos*/; | 70 | int in_fd, out_fd, inbufCount, inbufPos /*, outbufPos*/; |
73 | unsigned char *inbuf /*,*outbuf*/; | 71 | unsigned char *inbuf /*,*outbuf*/; |
74 | unsigned inbufBitCount, inbufBits; | 72 | unsigned inbufBitCount, inbufBits; |
75 | 73 | ||
76 | /* The CRC values stored in the block header and calculated from the data */ | 74 | /* The CRC values stored in the block header and calculated from the data */ |
77 | |||
78 | uint32_t headerCRC, totalCRC, writeCRC; | 75 | uint32_t headerCRC, totalCRC, writeCRC; |
79 | uint32_t *crc32Table; | ||
80 | /* Intermediate buffer and its size (in bytes) */ | ||
81 | 76 | ||
77 | /* Intermediate buffer and its size (in bytes) */ | ||
82 | unsigned *dbuf, dbufSize; | 78 | unsigned *dbuf, dbufSize; |
83 | 79 | ||
84 | /* These things are a bit too big to go on the stack */ | 80 | /* For I/O error handling */ |
81 | jmp_buf jmpbuf; | ||
85 | 82 | ||
83 | /* Big things go last (register-relative addressing can be larger for big offsets */ | ||
84 | uint32_t crc32Table[256]; | ||
86 | unsigned char selectors[32768]; /* nSelectors=15 bits */ | 85 | unsigned char selectors[32768]; /* nSelectors=15 bits */ |
87 | struct group_data groups[MAX_GROUPS]; /* Huffman coding tables */ | 86 | struct group_data groups[MAX_GROUPS]; /* Huffman coding tables */ |
87 | }; | ||
88 | /* typedef struct bunzip_data bunzip_data; -- done in .h file */ | ||
88 | 89 | ||
89 | /* For I/O error handling */ | ||
90 | |||
91 | jmp_buf jmpbuf; | ||
92 | } bunzip_data; | ||
93 | 90 | ||
94 | /* Return the next nnn bits of input. All reads from the compressed input | 91 | /* Return the next nnn bits of input. All reads from the compressed input |
95 | are done through this function. All reads are big endian */ | 92 | are done through this function. All reads are big endian */ |
@@ -106,6 +103,7 @@ static unsigned get_bits(bunzip_data *bd, char bits_wanted) | |||
106 | /* If we need to read more data from file into byte buffer, do so */ | 103 | /* If we need to read more data from file into byte buffer, do so */ |
107 | 104 | ||
108 | if (bd->inbufPos == bd->inbufCount) { | 105 | if (bd->inbufPos == bd->inbufCount) { |
106 | /* if "no input fd" case: in_fd == -1, read fails, we jump */ | ||
109 | bd->inbufCount = read(bd->in_fd, bd->inbuf, IOBUF_SIZE); | 107 | bd->inbufCount = read(bd->in_fd, bd->inbuf, IOBUF_SIZE); |
110 | if (bd->inbufCount <= 0) | 108 | if (bd->inbufCount <= 0) |
111 | longjmp(bd->jmpbuf, RETVAL_UNEXPECTED_INPUT_EOF); | 109 | longjmp(bd->jmpbuf, RETVAL_UNEXPECTED_INPUT_EOF); |
@@ -519,7 +517,7 @@ static int get_next_block(bunzip_data *bd) | |||
519 | are ignored, data is written to out_fd and return is RETVAL_OK or error. | 517 | are ignored, data is written to out_fd and return is RETVAL_OK or error. |
520 | */ | 518 | */ |
521 | 519 | ||
522 | static int read_bunzip(bunzip_data *bd, char *outbuf, int len) | 520 | int read_bunzip(bunzip_data *bd, char *outbuf, int len) |
523 | { | 521 | { |
524 | const unsigned *dbuf; | 522 | const unsigned *dbuf; |
525 | int pos, current, previous, gotcount; | 523 | int pos, current, previous, gotcount; |
@@ -627,11 +625,16 @@ static int read_bunzip(bunzip_data *bd, char *outbuf, int len) | |||
627 | goto decode_next_byte; | 625 | goto decode_next_byte; |
628 | } | 626 | } |
629 | 627 | ||
628 | |||
630 | /* Allocate the structure, read file header. If in_fd==-1, inbuf must contain | 629 | /* Allocate the structure, read file header. If in_fd==-1, inbuf must contain |
631 | a complete bunzip file (len bytes long). If in_fd!=-1, inbuf and len are | 630 | a complete bunzip file (len bytes long). If in_fd!=-1, inbuf and len are |
632 | ignored, and data is read from file handle into temporary buffer. */ | 631 | ignored, and data is read from file handle into temporary buffer. */ |
633 | 632 | ||
634 | static int start_bunzip(bunzip_data **bdp, int in_fd, unsigned char *inbuf, | 633 | /* Because bunzip2 is used for help text unpacking, and because bb_show_usage() |
634 | should work for NOFORK applets too, we must be extremely careful to not leak | ||
635 | any allocations! */ | ||
636 | |||
637 | int start_bunzip(bunzip_data **bdp, int in_fd, const unsigned char *inbuf, | ||
635 | int len) | 638 | int len) |
636 | { | 639 | { |
637 | bunzip_data *bd; | 640 | bunzip_data *bd; |
@@ -653,14 +656,15 @@ static int start_bunzip(bunzip_data **bdp, int in_fd, unsigned char *inbuf, | |||
653 | 656 | ||
654 | bd->in_fd = in_fd; | 657 | bd->in_fd = in_fd; |
655 | if (-1 == in_fd) { | 658 | if (-1 == in_fd) { |
656 | bd->inbuf = inbuf; | 659 | /* in this case, bd->inbuf is read-only */ |
660 | bd->inbuf = (void*)inbuf; /* cast away const-ness */ | ||
657 | bd->inbufCount = len; | 661 | bd->inbufCount = len; |
658 | } else | 662 | } else |
659 | bd->inbuf = (unsigned char *)(bd + 1); | 663 | bd->inbuf = (unsigned char *)(bd + 1); |
660 | 664 | ||
661 | /* Init the CRC32 table (big endian) */ | 665 | /* Init the CRC32 table (big endian) */ |
662 | 666 | ||
663 | bd->crc32Table = crc32_filltable(1); | 667 | crc32_filltable(bd->crc32Table, 1); |
664 | 668 | ||
665 | /* Setup for I/O error handling via longjmp */ | 669 | /* Setup for I/O error handling via longjmp */ |
666 | 670 | ||
@@ -670,19 +674,30 @@ static int start_bunzip(bunzip_data **bdp, int in_fd, unsigned char *inbuf, | |||
670 | /* Ensure that file starts with "BZh['1'-'9']." */ | 674 | /* Ensure that file starts with "BZh['1'-'9']." */ |
671 | 675 | ||
672 | i = get_bits(bd, 32); | 676 | i = get_bits(bd, 32); |
673 | if (((unsigned)(i - BZh0 - 1)) >= 9) return RETVAL_NOT_BZIP_DATA; | 677 | if ((unsigned)(i - BZh0 - 1) >= 9) return RETVAL_NOT_BZIP_DATA; |
674 | 678 | ||
675 | /* Fourth byte (ascii '1'-'9'), indicates block size in units of 100k of | 679 | /* Fourth byte (ascii '1'-'9'), indicates block size in units of 100k of |
676 | uncompressed data. Allocate intermediate buffer for block. */ | 680 | uncompressed data. Allocate intermediate buffer for block. */ |
677 | 681 | ||
678 | bd->dbufSize = 100000 * (i - BZh0); | 682 | bd->dbufSize = 100000 * (i - BZh0); |
679 | 683 | ||
680 | bd->dbuf = xmalloc(bd->dbufSize * sizeof(int)); | 684 | /* Cannot use xmalloc - may leak bd in NOFORK case! */ |
685 | bd->dbuf = malloc_or_warn(bd->dbufSize * sizeof(int)); | ||
686 | if (!bd->dbuf) { | ||
687 | free(bd); | ||
688 | xfunc_die(); | ||
689 | } | ||
681 | return RETVAL_OK; | 690 | return RETVAL_OK; |
682 | } | 691 | } |
683 | 692 | ||
684 | /* Example usage: decompress src_fd to dst_fd. (Stops at end of bzip data, | 693 | void dealloc_bunzip(bunzip_data *bd) |
685 | not end of file.) */ | 694 | { |
695 | free(bd->dbuf); | ||
696 | free(bd); | ||
697 | } | ||
698 | |||
699 | |||
700 | /* Decompress src_fd to dst_fd. Stops at end of bzip data, not end of file. */ | ||
686 | 701 | ||
687 | USE_DESKTOP(long long) int | 702 | USE_DESKTOP(long long) int |
688 | uncompressStream(int src_fd, int dst_fd) | 703 | uncompressStream(int src_fd, int dst_fd) |
@@ -693,7 +708,7 @@ uncompressStream(int src_fd, int dst_fd) | |||
693 | int i; | 708 | int i; |
694 | 709 | ||
695 | outbuf = xmalloc(IOBUF_SIZE); | 710 | outbuf = xmalloc(IOBUF_SIZE); |
696 | i = start_bunzip(&bd, src_fd, 0, 0); | 711 | i = start_bunzip(&bd, src_fd, NULL, 0); |
697 | if (!i) { | 712 | if (!i) { |
698 | for (;;) { | 713 | for (;;) { |
699 | i = read_bunzip(bd, outbuf, IOBUF_SIZE); | 714 | i = read_bunzip(bd, outbuf, IOBUF_SIZE); |
@@ -719,8 +734,7 @@ uncompressStream(int src_fd, int dst_fd) | |||
719 | } else { | 734 | } else { |
720 | bb_error_msg("decompression failed"); | 735 | bb_error_msg("decompression failed"); |
721 | } | 736 | } |
722 | free(bd->dbuf); | 737 | dealloc_bunzip(bd); |
723 | free(bd); | ||
724 | free(outbuf); | 738 | free(outbuf); |
725 | 739 | ||
726 | return i ? i : USE_DESKTOP(total_written) + 0; | 740 | return i ? i : USE_DESKTOP(total_written) + 0; |
diff --git a/archival/libunarchive/decompress_unzip.c b/archival/libunarchive/decompress_unzip.c index 331fe34d8..19ce5097a 100644 --- a/archival/libunarchive/decompress_unzip.c +++ b/archival/libunarchive/decompress_unzip.c | |||
@@ -1000,7 +1000,7 @@ inflate_unzip_internal(STATE_PARAM int in, int out) | |||
1000 | gunzip_bb = 0; | 1000 | gunzip_bb = 0; |
1001 | 1001 | ||
1002 | /* Create the crc table */ | 1002 | /* Create the crc table */ |
1003 | gunzip_crc_table = crc32_filltable(0); | 1003 | gunzip_crc_table = crc32_filltable(NULL, 0); |
1004 | gunzip_crc = ~0; | 1004 | gunzip_crc = ~0; |
1005 | 1005 | ||
1006 | /* Allocate space for buffer */ | 1006 | /* Allocate space for buffer */ |
diff --git a/archival/libunarchive/get_header_tar_gz.c b/archival/libunarchive/get_header_tar_gz.c index 1f07e4e64..69126e0ba 100644 --- a/archival/libunarchive/get_header_tar_gz.c +++ b/archival/libunarchive/get_header_tar_gz.c | |||
@@ -3,8 +3,6 @@ | |||
3 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. | 3 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <stdlib.h> | ||
7 | |||
8 | #include "libbb.h" | 6 | #include "libbb.h" |
9 | #include "unarchive.h" | 7 | #include "unarchive.h" |
10 | 8 | ||
diff --git a/coreutils/cksum.c b/coreutils/cksum.c index 66a255c4e..70febdf3a 100644 --- a/coreutils/cksum.c +++ b/coreutils/cksum.c | |||
@@ -11,8 +11,7 @@ | |||
11 | int cksum_main(int argc, char **argv); | 11 | int cksum_main(int argc, char **argv); |
12 | int cksum_main(int argc, char **argv) | 12 | int cksum_main(int argc, char **argv) |
13 | { | 13 | { |
14 | 14 | uint32_t *crc32_table = crc32_filltable(NULL, 1); | |
15 | uint32_t *crc32_table = crc32_filltable(1); | ||
16 | 15 | ||
17 | FILE *fp; | 16 | FILE *fp; |
18 | uint32_t crc; | 17 | uint32_t crc; |
diff --git a/include/libbb.h b/include/libbb.h index 6fff441c5..2be13891c 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -403,9 +403,10 @@ extern char *xasprintf(const char *format, ...) __attribute__ ((format (printf, | |||
403 | 403 | ||
404 | /* dmalloc will redefine these to it's own implementation. It is safe | 404 | /* dmalloc will redefine these to it's own implementation. It is safe |
405 | * to have the prototypes here unconditionally. */ | 405 | * to have the prototypes here unconditionally. */ |
406 | extern void *malloc_or_warn(size_t size); | ||
406 | extern void *xmalloc(size_t size); | 407 | extern void *xmalloc(size_t size); |
407 | extern void *xrealloc(void *old, size_t size); | ||
408 | extern void *xzalloc(size_t size); | 408 | extern void *xzalloc(size_t size); |
409 | extern void *xrealloc(void *old, size_t size); | ||
409 | 410 | ||
410 | extern ssize_t safe_read(int fd, void *buf, size_t count); | 411 | extern ssize_t safe_read(int fd, void *buf, size_t count); |
411 | extern ssize_t full_read(int fd, void *buf, size_t count); | 412 | extern ssize_t full_read(int fd, void *buf, size_t count); |
@@ -862,7 +863,7 @@ void md5_begin(md5_ctx_t *ctx); | |||
862 | void md5_hash(const void *data, size_t length, md5_ctx_t *ctx); | 863 | void md5_hash(const void *data, size_t length, md5_ctx_t *ctx); |
863 | void *md5_end(void *resbuf, md5_ctx_t *ctx); | 864 | void *md5_end(void *resbuf, md5_ctx_t *ctx); |
864 | 865 | ||
865 | uint32_t *crc32_filltable(int endian); | 866 | uint32_t *crc32_filltable(uint32_t *tbl256, int endian); |
866 | 867 | ||
867 | 868 | ||
868 | enum { /* DO NOT CHANGE THESE VALUES! cp.c, mv.c, install.c depend on them. */ | 869 | enum { /* DO NOT CHANGE THESE VALUES! cp.c, mv.c, install.c depend on them. */ |
diff --git a/include/unarchive.h b/include/unarchive.h index 36b56a925..8aa90becc 100644 --- a/include/unarchive.h +++ b/include/unarchive.h | |||
@@ -102,6 +102,11 @@ extern const llist_t *find_list_entry(const llist_t *list, const char *filename) | |||
102 | extern const llist_t *find_list_entry2(const llist_t *list, const char *filename); | 102 | extern const llist_t *find_list_entry2(const llist_t *list, const char *filename); |
103 | 103 | ||
104 | extern USE_DESKTOP(long long) int uncompressStream(int src_fd, int dst_fd); | 104 | extern USE_DESKTOP(long long) int uncompressStream(int src_fd, int dst_fd); |
105 | /* A bit of bunzip2 internals are exposed for compressed help support: */ | ||
106 | typedef struct bunzip_data bunzip_data; | ||
107 | int start_bunzip(bunzip_data **bdp, int in_fd, const unsigned char *inbuf, int len); | ||
108 | int read_bunzip(bunzip_data *bd, char *outbuf, int len); | ||
109 | void dealloc_bunzip(bunzip_data *bd); | ||
105 | 110 | ||
106 | typedef struct inflate_unzip_result { | 111 | typedef struct inflate_unzip_result { |
107 | off_t bytes_out; | 112 | off_t bytes_out; |
diff --git a/libbb/crc32.c b/libbb/crc32.c index 1e4a57e8a..acbc45827 100644 --- a/libbb/crc32.c +++ b/libbb/crc32.c | |||
@@ -16,14 +16,15 @@ | |||
16 | 16 | ||
17 | #include "libbb.h" | 17 | #include "libbb.h" |
18 | 18 | ||
19 | uint32_t *crc32_filltable(int endian) | 19 | uint32_t *crc32_filltable(uint32_t *crc_table, int endian) |
20 | { | 20 | { |
21 | |||
22 | uint32_t *crc_table = xmalloc(256 * sizeof(uint32_t)); | ||
23 | uint32_t polynomial = endian ? 0x04c11db7 : 0xedb88320; | 21 | uint32_t polynomial = endian ? 0x04c11db7 : 0xedb88320; |
24 | uint32_t c; | 22 | uint32_t c; |
25 | int i, j; | 23 | int i, j; |
26 | 24 | ||
25 | if (!crc_table) | ||
26 | crc_table = xmalloc(256 * sizeof(uint32_t)); | ||
27 | |||
27 | for (i = 0; i < 256; i++) { | 28 | for (i = 0; i < 256; i++) { |
28 | c = endian ? (i << 24) : i; | 29 | c = endian ? (i << 24) : i; |
29 | for (j = 8; j; j--) { | 30 | for (j = 8; j; j--) { |
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index dabd1a6d6..cf88a2b28 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c | |||
@@ -102,120 +102,68 @@ int wait_pid(int *wstat, int pid) | |||
102 | 102 | ||
103 | int spawn_and_wait(char **argv) | 103 | int spawn_and_wait(char **argv) |
104 | { | 104 | { |
105 | #if ENABLE_FEATURE_EXEC_PREFER_APPLETS | ||
105 | int rc; | 106 | int rc; |
107 | const struct bb_applet *a = find_applet_by_name(argv[0]); | ||
106 | 108 | ||
107 | #if ENABLE_FEATURE_EXEC_PREFER_APPLETS | 109 | if (a && (a->nofork |
108 | { | ||
109 | const struct bb_applet *a = find_applet_by_name(argv[0]); | ||
110 | if (a && (a->nofork | ||
111 | #ifndef BB_NOMMU | 110 | #ifndef BB_NOMMU |
112 | || a->noexec /* NOEXEC cannot be used on NOMMU */ | 111 | || a->noexec /* NOEXEC cannot be used on NOMMU */ |
113 | #endif | 112 | #endif |
114 | )) { | 113 | )) { |
115 | int argc = 1; | 114 | int argc = 1; |
116 | char **pp = argv; | 115 | char **pp = argv; |
117 | while (*++pp) | 116 | while (*++pp) |
118 | argc++; | 117 | argc++; |
119 | #ifndef BB_NOMMU | 118 | #ifndef BB_NOMMU |
120 | if (a->nofork) | 119 | if (a->nofork) |
121 | #endif | 120 | #endif |
122 | { | 121 | { |
123 | int old_sleep = die_sleep; | 122 | int old_sleep = die_sleep; |
124 | int old_x = xfunc_error_retval; | 123 | int old_x = xfunc_error_retval; |
125 | die_sleep = -1; /* special flag */ | 124 | die_sleep = -1; /* special flag */ |
126 | /* xfunc_die() checks for it */ | 125 | /* xfunc_die() checks for it */ |
127 | 126 | ||
128 | rc = setjmp(die_jmp); | 127 | rc = setjmp(die_jmp); |
129 | if (!rc) { | 128 | if (!rc) { |
130 | const struct bb_applet *old_a = current_applet; | 129 | const struct bb_applet *old_a = current_applet; |
131 | current_applet = a; | 130 | current_applet = a; |
132 | applet_name = a->name; | 131 | applet_name = a->name; |
133 | // what else should we save/restore? | 132 | // what else should we save/restore? |
134 | rc = a->main(argc, argv); | 133 | // TODO: what if applet will mangle argv vector? |
135 | current_applet = old_a; | 134 | // xargs needs argv untouched because it frees the vector! |
136 | applet_name = old_a->name; | 135 | // shouldn't we pass a copy? |
137 | } else { | 136 | rc = a->main(argc, argv); |
138 | /* xfunc died in NOFORK applet */ | 137 | current_applet = old_a; |
139 | if (rc == -111) | 138 | applet_name = old_a->name; |
140 | rc = 0; | 139 | } else { |
141 | } | 140 | /* xfunc died in NOFORK applet */ |
142 | 141 | if (rc == -111) | |
143 | die_sleep = old_sleep; | 142 | rc = 0; |
144 | xfunc_error_retval = old_x; | ||
145 | return rc; | ||
146 | } | 143 | } |
144 | |||
145 | die_sleep = old_sleep; | ||
146 | xfunc_error_retval = old_x; | ||
147 | return rc; | ||
148 | } | ||
147 | #ifndef BB_NOMMU /* MMU only */ | 149 | #ifndef BB_NOMMU /* MMU only */ |
148 | /* a->noexec is true */ | 150 | /* a->noexec is true */ |
149 | rc = fork(); | 151 | rc = fork(); |
150 | if (rc) | 152 | if (rc) |
151 | goto w; | 153 | goto w; |
152 | /* child */ | 154 | /* child */ |
153 | current_applet = a; | 155 | current_applet = a; |
154 | run_current_applet_and_exit(argc, argv); | 156 | run_current_applet_and_exit(argc, argv); |
155 | #endif | 157 | #endif |
156 | } | ||
157 | |||
158 | } | 158 | } |
159 | rc = spawn(argv); | 159 | rc = spawn(argv); |
160 | w: | 160 | w: |
161 | #else /* !FEATURE_EXEC_PREFER_APPLETS */ | ||
162 | rc = spawn(argv); | ||
163 | #endif /* FEATURE_EXEC_PREFER_APPLETS */ | ||
164 | return wait4pid(rc); | 161 | return wait4pid(rc); |
165 | } | 162 | #else /* !FEATURE_EXEC_PREFER_APPLETS */ |
166 | 163 | return wait4pid(spawn(argv)); | |
167 | |||
168 | #if 0 //ndef BB_NOMMU | ||
169 | // Die with an error message if we can't daemonize. | ||
170 | void xdaemon(int nochdir, int noclose) | ||
171 | { | ||
172 | if (daemon(nochdir, noclose)) | ||
173 | bb_perror_msg_and_die("daemon"); | ||
174 | } | ||
175 | #endif | 164 | #endif |
176 | |||
177 | #if 0 // def BB_NOMMU | ||
178 | void vfork_daemon_rexec(int nochdir, int noclose, char **argv) | ||
179 | { | ||
180 | int fd; | ||
181 | |||
182 | /* Maybe we are already re-execed and come here again? */ | ||
183 | if (re_execed) | ||
184 | return; | ||
185 | |||
186 | setsid(); | ||
187 | |||
188 | if (!nochdir) | ||
189 | xchdir("/"); | ||
190 | |||
191 | if (!noclose) { | ||
192 | /* if "/dev/null" doesn't exist, bail out! */ | ||
193 | fd = xopen(bb_dev_null, O_RDWR); | ||
194 | dup2(fd, STDIN_FILENO); | ||
195 | dup2(fd, STDOUT_FILENO); | ||
196 | dup2(fd, STDERR_FILENO); | ||
197 | while (fd > 2) | ||
198 | close(fd--); | ||
199 | } | ||
200 | |||
201 | switch (vfork()) { | ||
202 | case 0: /* child */ | ||
203 | /* Make certain we are not a session leader, or else we | ||
204 | * might reacquire a controlling terminal */ | ||
205 | if (vfork()) | ||
206 | _exit(0); | ||
207 | /* High-order bit of first char in argv[0] is a hidden | ||
208 | * "we have (alrealy) re-execed, don't do it again" flag */ | ||
209 | argv[0][0] |= 0x80; | ||
210 | execv(CONFIG_BUSYBOX_EXEC_PATH, argv); | ||
211 | bb_perror_msg_and_die("exec %s", CONFIG_BUSYBOX_EXEC_PATH); | ||
212 | case -1: /* error */ | ||
213 | bb_perror_msg_and_die("vfork"); | ||
214 | default: /* parent */ | ||
215 | exit(0); | ||
216 | } | ||
217 | } | 165 | } |
218 | #endif /* BB_NOMMU */ | 166 | |
219 | 167 | ||
220 | #ifdef BB_NOMMU | 168 | #ifdef BB_NOMMU |
221 | void forkexit_or_rexec(char **argv) | 169 | void forkexit_or_rexec(char **argv) |
diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c index b9d013a24..dde91a2ba 100644 --- a/libbb/xfuncs.c +++ b/libbb/xfuncs.c | |||
@@ -20,6 +20,15 @@ | |||
20 | * Since dmalloc's prototypes overwrite the impls here as they are | 20 | * Since dmalloc's prototypes overwrite the impls here as they are |
21 | * included after these prototypes in libbb.h, all is well. | 21 | * included after these prototypes in libbb.h, all is well. |
22 | */ | 22 | */ |
23 | // Warn if we can't allocate size bytes of memory. | ||
24 | void *malloc_or_warn(size_t size) | ||
25 | { | ||
26 | void *ptr = malloc(size); | ||
27 | if (ptr == NULL && size != 0) | ||
28 | bb_error_msg(bb_msg_memory_exhausted); | ||
29 | return ptr; | ||
30 | } | ||
31 | |||
23 | // Die if we can't allocate size bytes of memory. | 32 | // Die if we can't allocate size bytes of memory. |
24 | void *xmalloc(size_t size) | 33 | void *xmalloc(size_t size) |
25 | { | 34 | { |