aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-04-10 21:40:19 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-04-10 21:40:19 +0000
commitc6758a07c68033627a692cda27aebc8f6a662e7f (patch)
tree51bc0b498a5e16f8041604d913e25708cc76058f
parent335b63d8d1876ce4e172ebcc9d64544785682244 (diff)
downloadbusybox-w32-c6758a07c68033627a692cda27aebc8f6a662e7f.tar.gz
busybox-w32-c6758a07c68033627a692cda27aebc8f6a662e7f.tar.bz2
busybox-w32-c6758a07c68033627a692cda27aebc8f6a662e7f.zip
make compressed help code NOMMU- and NOFORK-friendly -
no forking anymore, bunzip2 unpack routine now does all it in memory.
-rw-r--r--applets/applets.c67
-rw-r--r--archival/gzip.c2
-rw-r--r--archival/libunarchive/decompress_bunzip2.c58
-rw-r--r--archival/libunarchive/decompress_unzip.c2
-rw-r--r--archival/libunarchive/get_header_tar_gz.c2
-rw-r--r--coreutils/cksum.c3
-rw-r--r--include/libbb.h5
-rw-r--r--include/unarchive.h5
-rw-r--r--libbb/crc32.c7
-rw-r--r--libbb/vfork_daemon_rexec.c144
-rw-r--r--libbb/xfuncs.c9
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
404static const char *unpack_usage_messages(void) 404static 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
65typedef struct { 65struct 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
522static int read_bunzip(bunzip_data *bd, char *outbuf, int len) 520int 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
634static 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
637int 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, 693void 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
687USE_DESKTOP(long long) int 702USE_DESKTOP(long long) int
688uncompressStream(int src_fd, int dst_fd) 703uncompressStream(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 @@
11int cksum_main(int argc, char **argv); 11int cksum_main(int argc, char **argv);
12int cksum_main(int argc, char **argv) 12int 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. */
406extern void *malloc_or_warn(size_t size);
406extern void *xmalloc(size_t size); 407extern void *xmalloc(size_t size);
407extern void *xrealloc(void *old, size_t size);
408extern void *xzalloc(size_t size); 408extern void *xzalloc(size_t size);
409extern void *xrealloc(void *old, size_t size);
409 410
410extern ssize_t safe_read(int fd, void *buf, size_t count); 411extern ssize_t safe_read(int fd, void *buf, size_t count);
411extern ssize_t full_read(int fd, void *buf, size_t count); 412extern ssize_t full_read(int fd, void *buf, size_t count);
@@ -862,7 +863,7 @@ void md5_begin(md5_ctx_t *ctx);
862void md5_hash(const void *data, size_t length, md5_ctx_t *ctx); 863void md5_hash(const void *data, size_t length, md5_ctx_t *ctx);
863void *md5_end(void *resbuf, md5_ctx_t *ctx); 864void *md5_end(void *resbuf, md5_ctx_t *ctx);
864 865
865uint32_t *crc32_filltable(int endian); 866uint32_t *crc32_filltable(uint32_t *tbl256, int endian);
866 867
867 868
868enum { /* DO NOT CHANGE THESE VALUES! cp.c, mv.c, install.c depend on them. */ 869enum { /* 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)
102extern const llist_t *find_list_entry2(const llist_t *list, const char *filename); 102extern const llist_t *find_list_entry2(const llist_t *list, const char *filename);
103 103
104extern USE_DESKTOP(long long) int uncompressStream(int src_fd, int dst_fd); 104extern USE_DESKTOP(long long) int uncompressStream(int src_fd, int dst_fd);
105/* A bit of bunzip2 internals are exposed for compressed help support: */
106typedef struct bunzip_data bunzip_data;
107int start_bunzip(bunzip_data **bdp, int in_fd, const unsigned char *inbuf, int len);
108int read_bunzip(bunzip_data *bd, char *outbuf, int len);
109void dealloc_bunzip(bunzip_data *bd);
105 110
106typedef struct inflate_unzip_result { 111typedef 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
19uint32_t *crc32_filltable(int endian) 19uint32_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
103int spawn_and_wait(char **argv) 103int 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.
170void 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
178void 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
221void forkexit_or_rexec(char **argv) 169void 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.
24void *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.
24void *xmalloc(size_t size) 33void *xmalloc(size_t size)
25{ 34{