make compressed help code NOMMU- and NOFORK-friendly -
no forking anymore, bunzip2 unpack routine now does all it in memory.
This commit is contained in:
parent
335b63d8d1
commit
c6758a07c6
@ -403,44 +403,32 @@ static void check_suid(const struct bb_applet *applet)
|
|||||||
|
|
||||||
static const char *unpack_usage_messages(void)
|
static const char *unpack_usage_messages(void)
|
||||||
{
|
{
|
||||||
int input[2], output[2], pid;
|
char *outbuf = NULL;
|
||||||
char *buf;
|
bunzip_data *bd;
|
||||||
|
int i;
|
||||||
|
|
||||||
if (pipe(input) < 0 || pipe(output) < 0)
|
i = start_bunzip(&bd,
|
||||||
exit(1);
|
/* src_fd: */ -1,
|
||||||
|
/* inbuf: */ packed_usage,
|
||||||
//TODO: not NOMMU friendly!
|
/* len: */ sizeof(packed_usage));
|
||||||
pid = fork();
|
/* read_bunzip can longjmp to start_bunzip, and ultimately
|
||||||
switch (pid) {
|
* end up here with i != 0 on read data errors! Not trivial */
|
||||||
case -1: /* error */
|
if (!i) {
|
||||||
exit(1);
|
/* Cannot use xmalloc: will leak bd in NOFORK case! */
|
||||||
case 0: /* child */
|
outbuf = malloc_or_warn(SIZEOF_usage_messages);
|
||||||
close(input[1]);
|
if (outbuf)
|
||||||
close(output[0]);
|
read_bunzip(bd, outbuf, SIZEOF_usage_messages);
|
||||||
uncompressStream(input[0], output[1]);
|
|
||||||
exit(0);
|
|
||||||
}
|
}
|
||||||
/* parent */
|
dealloc_bunzip(bd);
|
||||||
|
return outbuf;
|
||||||
close(input[0]);
|
|
||||||
close(output[1]);
|
|
||||||
pid = fork();
|
|
||||||
switch (pid) {
|
|
||||||
case -1: /* error */
|
|
||||||
exit(1);
|
|
||||||
case 0: /* child */
|
|
||||||
full_write(input[1], packed_usage, sizeof(packed_usage));
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
/* parent */
|
|
||||||
close(input[1]);
|
|
||||||
|
|
||||||
buf = xmalloc(SIZEOF_usage_messages);
|
|
||||||
full_read(output[0], buf, SIZEOF_usage_messages);
|
|
||||||
return buf;
|
|
||||||
}
|
}
|
||||||
|
#define dealloc_usage_messages(s) free(s)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define unpack_usage_messages() usage_messages
|
#define unpack_usage_messages() usage_messages
|
||||||
|
#define dealloc_usage_messages(s) ((void)(s))
|
||||||
|
|
||||||
#endif /* FEATURE_COMPRESS_USAGE */
|
#endif /* FEATURE_COMPRESS_USAGE */
|
||||||
|
|
||||||
|
|
||||||
@ -448,22 +436,23 @@ void bb_show_usage(void)
|
|||||||
{
|
{
|
||||||
if (ENABLE_SHOW_USAGE) {
|
if (ENABLE_SHOW_USAGE) {
|
||||||
const char *format_string;
|
const char *format_string;
|
||||||
const char *usage_string = unpack_usage_messages();
|
const char *p;
|
||||||
|
const char *usage_string = p = unpack_usage_messages();
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
i = current_applet - applets;
|
i = current_applet - applets;
|
||||||
while (i) {
|
while (i) {
|
||||||
while (*usage_string++) continue;
|
while (*p++) continue;
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
|
|
||||||
format_string = "%s\n\nUsage: %s %s\n\n";
|
format_string = "%s\n\nUsage: %s %s\n\n";
|
||||||
if (*usage_string == '\b')
|
if (*p == '\b')
|
||||||
format_string = "%s\n\nNo help available.\n\n";
|
format_string = "%s\n\nNo help available.\n\n";
|
||||||
fprintf(stderr, format_string, bb_msg_full_version,
|
fprintf(stderr, format_string, bb_msg_full_version,
|
||||||
applet_name, usage_string);
|
applet_name, p);
|
||||||
|
dealloc_usage_messages((char*)usage_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
xfunc_die();
|
xfunc_die();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2079,7 +2079,7 @@ int gzip_main(int argc, char **argv)
|
|||||||
ALLOC(ush, G1.prev, 1L << BITS);
|
ALLOC(ush, G1.prev, 1L << BITS);
|
||||||
|
|
||||||
/* Initialise the CRC32 table */
|
/* Initialise the CRC32 table */
|
||||||
G1.crc_32_tab = crc32_filltable(0);
|
G1.crc_32_tab = crc32_filltable(NULL, 0);
|
||||||
|
|
||||||
return bbunpack(argv, make_new_name_gzip, pack_gzip);
|
return bbunpack(argv, make_new_name_gzip, pack_gzip);
|
||||||
}
|
}
|
||||||
|
@ -62,34 +62,31 @@ struct group_data {
|
|||||||
/* Structure holding all the housekeeping data, including IO buffers and
|
/* Structure holding all the housekeeping data, including IO buffers and
|
||||||
memory that persists between calls to bunzip */
|
memory that persists between calls to bunzip */
|
||||||
|
|
||||||
typedef struct {
|
struct bunzip_data {
|
||||||
/* State for interrupting output loop */
|
/* State for interrupting output loop */
|
||||||
|
|
||||||
int writeCopies, writePos, writeRunCountdown, writeCount, writeCurrent;
|
int writeCopies, writePos, writeRunCountdown, writeCount, writeCurrent;
|
||||||
|
|
||||||
/* I/O tracking data (file handles, buffers, positions, etc.) */
|
/* I/O tracking data (file handles, buffers, positions, etc.) */
|
||||||
|
|
||||||
int in_fd, out_fd, inbufCount, inbufPos /*, outbufPos*/;
|
int in_fd, out_fd, inbufCount, inbufPos /*, outbufPos*/;
|
||||||
unsigned char *inbuf /*,*outbuf*/;
|
unsigned char *inbuf /*,*outbuf*/;
|
||||||
unsigned inbufBitCount, inbufBits;
|
unsigned inbufBitCount, inbufBits;
|
||||||
|
|
||||||
/* The CRC values stored in the block header and calculated from the data */
|
/* The CRC values stored in the block header and calculated from the data */
|
||||||
|
|
||||||
uint32_t headerCRC, totalCRC, writeCRC;
|
uint32_t headerCRC, totalCRC, writeCRC;
|
||||||
uint32_t *crc32Table;
|
|
||||||
/* Intermediate buffer and its size (in bytes) */
|
|
||||||
|
|
||||||
|
/* Intermediate buffer and its size (in bytes) */
|
||||||
unsigned *dbuf, dbufSize;
|
unsigned *dbuf, dbufSize;
|
||||||
|
|
||||||
/* These things are a bit too big to go on the stack */
|
/* For I/O error handling */
|
||||||
|
jmp_buf jmpbuf;
|
||||||
|
|
||||||
|
/* Big things go last (register-relative addressing can be larger for big offsets */
|
||||||
|
uint32_t crc32Table[256];
|
||||||
unsigned char selectors[32768]; /* nSelectors=15 bits */
|
unsigned char selectors[32768]; /* nSelectors=15 bits */
|
||||||
struct group_data groups[MAX_GROUPS]; /* Huffman coding tables */
|
struct group_data groups[MAX_GROUPS]; /* Huffman coding tables */
|
||||||
|
};
|
||||||
|
/* typedef struct bunzip_data bunzip_data; -- done in .h file */
|
||||||
|
|
||||||
/* For I/O error handling */
|
|
||||||
|
|
||||||
jmp_buf jmpbuf;
|
|
||||||
} bunzip_data;
|
|
||||||
|
|
||||||
/* Return the next nnn bits of input. All reads from the compressed input
|
/* Return the next nnn bits of input. All reads from the compressed input
|
||||||
are done through this function. All reads are big endian */
|
are done through this function. All reads are big endian */
|
||||||
@ -106,6 +103,7 @@ static unsigned get_bits(bunzip_data *bd, char bits_wanted)
|
|||||||
/* If we need to read more data from file into byte buffer, do so */
|
/* If we need to read more data from file into byte buffer, do so */
|
||||||
|
|
||||||
if (bd->inbufPos == bd->inbufCount) {
|
if (bd->inbufPos == bd->inbufCount) {
|
||||||
|
/* if "no input fd" case: in_fd == -1, read fails, we jump */
|
||||||
bd->inbufCount = read(bd->in_fd, bd->inbuf, IOBUF_SIZE);
|
bd->inbufCount = read(bd->in_fd, bd->inbuf, IOBUF_SIZE);
|
||||||
if (bd->inbufCount <= 0)
|
if (bd->inbufCount <= 0)
|
||||||
longjmp(bd->jmpbuf, RETVAL_UNEXPECTED_INPUT_EOF);
|
longjmp(bd->jmpbuf, RETVAL_UNEXPECTED_INPUT_EOF);
|
||||||
@ -519,7 +517,7 @@ static int get_next_block(bunzip_data *bd)
|
|||||||
are ignored, data is written to out_fd and return is RETVAL_OK or error.
|
are ignored, data is written to out_fd and return is RETVAL_OK or error.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int read_bunzip(bunzip_data *bd, char *outbuf, int len)
|
int read_bunzip(bunzip_data *bd, char *outbuf, int len)
|
||||||
{
|
{
|
||||||
const unsigned *dbuf;
|
const unsigned *dbuf;
|
||||||
int pos, current, previous, gotcount;
|
int pos, current, previous, gotcount;
|
||||||
@ -627,11 +625,16 @@ static int read_bunzip(bunzip_data *bd, char *outbuf, int len)
|
|||||||
goto decode_next_byte;
|
goto decode_next_byte;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Allocate the structure, read file header. If in_fd==-1, inbuf must contain
|
/* Allocate the structure, read file header. If in_fd==-1, inbuf must contain
|
||||||
a complete bunzip file (len bytes long). If in_fd!=-1, inbuf and len are
|
a complete bunzip file (len bytes long). If in_fd!=-1, inbuf and len are
|
||||||
ignored, and data is read from file handle into temporary buffer. */
|
ignored, and data is read from file handle into temporary buffer. */
|
||||||
|
|
||||||
static int start_bunzip(bunzip_data **bdp, int in_fd, unsigned char *inbuf,
|
/* Because bunzip2 is used for help text unpacking, and because bb_show_usage()
|
||||||
|
should work for NOFORK applets too, we must be extremely careful to not leak
|
||||||
|
any allocations! */
|
||||||
|
|
||||||
|
int start_bunzip(bunzip_data **bdp, int in_fd, const unsigned char *inbuf,
|
||||||
int len)
|
int len)
|
||||||
{
|
{
|
||||||
bunzip_data *bd;
|
bunzip_data *bd;
|
||||||
@ -653,14 +656,15 @@ static int start_bunzip(bunzip_data **bdp, int in_fd, unsigned char *inbuf,
|
|||||||
|
|
||||||
bd->in_fd = in_fd;
|
bd->in_fd = in_fd;
|
||||||
if (-1 == in_fd) {
|
if (-1 == in_fd) {
|
||||||
bd->inbuf = inbuf;
|
/* in this case, bd->inbuf is read-only */
|
||||||
|
bd->inbuf = (void*)inbuf; /* cast away const-ness */
|
||||||
bd->inbufCount = len;
|
bd->inbufCount = len;
|
||||||
} else
|
} else
|
||||||
bd->inbuf = (unsigned char *)(bd + 1);
|
bd->inbuf = (unsigned char *)(bd + 1);
|
||||||
|
|
||||||
/* Init the CRC32 table (big endian) */
|
/* Init the CRC32 table (big endian) */
|
||||||
|
|
||||||
bd->crc32Table = crc32_filltable(1);
|
crc32_filltable(bd->crc32Table, 1);
|
||||||
|
|
||||||
/* Setup for I/O error handling via longjmp */
|
/* Setup for I/O error handling via longjmp */
|
||||||
|
|
||||||
@ -670,19 +674,30 @@ static int start_bunzip(bunzip_data **bdp, int in_fd, unsigned char *inbuf,
|
|||||||
/* Ensure that file starts with "BZh['1'-'9']." */
|
/* Ensure that file starts with "BZh['1'-'9']." */
|
||||||
|
|
||||||
i = get_bits(bd, 32);
|
i = get_bits(bd, 32);
|
||||||
if (((unsigned)(i - BZh0 - 1)) >= 9) return RETVAL_NOT_BZIP_DATA;
|
if ((unsigned)(i - BZh0 - 1) >= 9) return RETVAL_NOT_BZIP_DATA;
|
||||||
|
|
||||||
/* Fourth byte (ascii '1'-'9'), indicates block size in units of 100k of
|
/* Fourth byte (ascii '1'-'9'), indicates block size in units of 100k of
|
||||||
uncompressed data. Allocate intermediate buffer for block. */
|
uncompressed data. Allocate intermediate buffer for block. */
|
||||||
|
|
||||||
bd->dbufSize = 100000 * (i - BZh0);
|
bd->dbufSize = 100000 * (i - BZh0);
|
||||||
|
|
||||||
bd->dbuf = xmalloc(bd->dbufSize * sizeof(int));
|
/* Cannot use xmalloc - may leak bd in NOFORK case! */
|
||||||
|
bd->dbuf = malloc_or_warn(bd->dbufSize * sizeof(int));
|
||||||
|
if (!bd->dbuf) {
|
||||||
|
free(bd);
|
||||||
|
xfunc_die();
|
||||||
|
}
|
||||||
return RETVAL_OK;
|
return RETVAL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Example usage: decompress src_fd to dst_fd. (Stops at end of bzip data,
|
void dealloc_bunzip(bunzip_data *bd)
|
||||||
not end of file.) */
|
{
|
||||||
|
free(bd->dbuf);
|
||||||
|
free(bd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Decompress src_fd to dst_fd. Stops at end of bzip data, not end of file. */
|
||||||
|
|
||||||
USE_DESKTOP(long long) int
|
USE_DESKTOP(long long) int
|
||||||
uncompressStream(int src_fd, int dst_fd)
|
uncompressStream(int src_fd, int dst_fd)
|
||||||
@ -693,7 +708,7 @@ uncompressStream(int src_fd, int dst_fd)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
outbuf = xmalloc(IOBUF_SIZE);
|
outbuf = xmalloc(IOBUF_SIZE);
|
||||||
i = start_bunzip(&bd, src_fd, 0, 0);
|
i = start_bunzip(&bd, src_fd, NULL, 0);
|
||||||
if (!i) {
|
if (!i) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
i = read_bunzip(bd, outbuf, IOBUF_SIZE);
|
i = read_bunzip(bd, outbuf, IOBUF_SIZE);
|
||||||
@ -719,8 +734,7 @@ uncompressStream(int src_fd, int dst_fd)
|
|||||||
} else {
|
} else {
|
||||||
bb_error_msg("decompression failed");
|
bb_error_msg("decompression failed");
|
||||||
}
|
}
|
||||||
free(bd->dbuf);
|
dealloc_bunzip(bd);
|
||||||
free(bd);
|
|
||||||
free(outbuf);
|
free(outbuf);
|
||||||
|
|
||||||
return i ? i : USE_DESKTOP(total_written) + 0;
|
return i ? i : USE_DESKTOP(total_written) + 0;
|
||||||
|
@ -1000,7 +1000,7 @@ inflate_unzip_internal(STATE_PARAM int in, int out)
|
|||||||
gunzip_bb = 0;
|
gunzip_bb = 0;
|
||||||
|
|
||||||
/* Create the crc table */
|
/* Create the crc table */
|
||||||
gunzip_crc_table = crc32_filltable(0);
|
gunzip_crc_table = crc32_filltable(NULL, 0);
|
||||||
gunzip_crc = ~0;
|
gunzip_crc = ~0;
|
||||||
|
|
||||||
/* Allocate space for buffer */
|
/* Allocate space for buffer */
|
||||||
|
@ -3,8 +3,6 @@
|
|||||||
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
|
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "libbb.h"
|
#include "libbb.h"
|
||||||
#include "unarchive.h"
|
#include "unarchive.h"
|
||||||
|
|
||||||
|
@ -11,8 +11,7 @@
|
|||||||
int cksum_main(int argc, char **argv);
|
int cksum_main(int argc, char **argv);
|
||||||
int cksum_main(int argc, char **argv)
|
int cksum_main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
uint32_t *crc32_table = crc32_filltable(NULL, 1);
|
||||||
uint32_t *crc32_table = crc32_filltable(1);
|
|
||||||
|
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
uint32_t crc;
|
uint32_t crc;
|
||||||
|
@ -403,9 +403,10 @@ extern char *xasprintf(const char *format, ...) __attribute__ ((format (printf,
|
|||||||
|
|
||||||
/* dmalloc will redefine these to it's own implementation. It is safe
|
/* dmalloc will redefine these to it's own implementation. It is safe
|
||||||
* to have the prototypes here unconditionally. */
|
* to have the prototypes here unconditionally. */
|
||||||
|
extern void *malloc_or_warn(size_t size);
|
||||||
extern void *xmalloc(size_t size);
|
extern void *xmalloc(size_t size);
|
||||||
extern void *xrealloc(void *old, size_t size);
|
|
||||||
extern void *xzalloc(size_t size);
|
extern void *xzalloc(size_t size);
|
||||||
|
extern void *xrealloc(void *old, size_t size);
|
||||||
|
|
||||||
extern ssize_t safe_read(int fd, void *buf, size_t count);
|
extern ssize_t safe_read(int fd, void *buf, size_t count);
|
||||||
extern ssize_t full_read(int fd, void *buf, size_t count);
|
extern ssize_t full_read(int fd, void *buf, size_t count);
|
||||||
@ -862,7 +863,7 @@ void md5_begin(md5_ctx_t *ctx);
|
|||||||
void md5_hash(const void *data, size_t length, md5_ctx_t *ctx);
|
void md5_hash(const void *data, size_t length, md5_ctx_t *ctx);
|
||||||
void *md5_end(void *resbuf, md5_ctx_t *ctx);
|
void *md5_end(void *resbuf, md5_ctx_t *ctx);
|
||||||
|
|
||||||
uint32_t *crc32_filltable(int endian);
|
uint32_t *crc32_filltable(uint32_t *tbl256, int endian);
|
||||||
|
|
||||||
|
|
||||||
enum { /* DO NOT CHANGE THESE VALUES! cp.c, mv.c, install.c depend on them. */
|
enum { /* DO NOT CHANGE THESE VALUES! cp.c, mv.c, install.c depend on them. */
|
||||||
|
@ -102,6 +102,11 @@ extern const llist_t *find_list_entry(const llist_t *list, const char *filename)
|
|||||||
extern const llist_t *find_list_entry2(const llist_t *list, const char *filename);
|
extern const llist_t *find_list_entry2(const llist_t *list, const char *filename);
|
||||||
|
|
||||||
extern USE_DESKTOP(long long) int uncompressStream(int src_fd, int dst_fd);
|
extern USE_DESKTOP(long long) int uncompressStream(int src_fd, int dst_fd);
|
||||||
|
/* A bit of bunzip2 internals are exposed for compressed help support: */
|
||||||
|
typedef struct bunzip_data bunzip_data;
|
||||||
|
int start_bunzip(bunzip_data **bdp, int in_fd, const unsigned char *inbuf, int len);
|
||||||
|
int read_bunzip(bunzip_data *bd, char *outbuf, int len);
|
||||||
|
void dealloc_bunzip(bunzip_data *bd);
|
||||||
|
|
||||||
typedef struct inflate_unzip_result {
|
typedef struct inflate_unzip_result {
|
||||||
off_t bytes_out;
|
off_t bytes_out;
|
||||||
|
@ -16,14 +16,15 @@
|
|||||||
|
|
||||||
#include "libbb.h"
|
#include "libbb.h"
|
||||||
|
|
||||||
uint32_t *crc32_filltable(int endian)
|
uint32_t *crc32_filltable(uint32_t *crc_table, int endian)
|
||||||
{
|
{
|
||||||
|
|
||||||
uint32_t *crc_table = xmalloc(256 * sizeof(uint32_t));
|
|
||||||
uint32_t polynomial = endian ? 0x04c11db7 : 0xedb88320;
|
uint32_t polynomial = endian ? 0x04c11db7 : 0xedb88320;
|
||||||
uint32_t c;
|
uint32_t c;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
|
if (!crc_table)
|
||||||
|
crc_table = xmalloc(256 * sizeof(uint32_t));
|
||||||
|
|
||||||
for (i = 0; i < 256; i++) {
|
for (i = 0; i < 256; i++) {
|
||||||
c = endian ? (i << 24) : i;
|
c = endian ? (i << 24) : i;
|
||||||
for (j = 8; j; j--) {
|
for (j = 8; j; j--) {
|
||||||
|
@ -102,120 +102,68 @@ int wait_pid(int *wstat, int pid)
|
|||||||
|
|
||||||
int spawn_and_wait(char **argv)
|
int spawn_and_wait(char **argv)
|
||||||
{
|
{
|
||||||
int rc;
|
|
||||||
|
|
||||||
#if ENABLE_FEATURE_EXEC_PREFER_APPLETS
|
#if ENABLE_FEATURE_EXEC_PREFER_APPLETS
|
||||||
{
|
int rc;
|
||||||
const struct bb_applet *a = find_applet_by_name(argv[0]);
|
const struct bb_applet *a = find_applet_by_name(argv[0]);
|
||||||
if (a && (a->nofork
|
|
||||||
#ifndef BB_NOMMU
|
|
||||||
|| a->noexec /* NOEXEC cannot be used on NOMMU */
|
|
||||||
#endif
|
|
||||||
)) {
|
|
||||||
int argc = 1;
|
|
||||||
char **pp = argv;
|
|
||||||
while (*++pp)
|
|
||||||
argc++;
|
|
||||||
#ifndef BB_NOMMU
|
|
||||||
if (a->nofork)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
int old_sleep = die_sleep;
|
|
||||||
int old_x = xfunc_error_retval;
|
|
||||||
die_sleep = -1; /* special flag */
|
|
||||||
/* xfunc_die() checks for it */
|
|
||||||
|
|
||||||
rc = setjmp(die_jmp);
|
if (a && (a->nofork
|
||||||
if (!rc) {
|
#ifndef BB_NOMMU
|
||||||
const struct bb_applet *old_a = current_applet;
|
|| a->noexec /* NOEXEC cannot be used on NOMMU */
|
||||||
current_applet = a;
|
#endif
|
||||||
applet_name = a->name;
|
)) {
|
||||||
|
int argc = 1;
|
||||||
|
char **pp = argv;
|
||||||
|
while (*++pp)
|
||||||
|
argc++;
|
||||||
|
#ifndef BB_NOMMU
|
||||||
|
if (a->nofork)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
int old_sleep = die_sleep;
|
||||||
|
int old_x = xfunc_error_retval;
|
||||||
|
die_sleep = -1; /* special flag */
|
||||||
|
/* xfunc_die() checks for it */
|
||||||
|
|
||||||
|
rc = setjmp(die_jmp);
|
||||||
|
if (!rc) {
|
||||||
|
const struct bb_applet *old_a = current_applet;
|
||||||
|
current_applet = a;
|
||||||
|
applet_name = a->name;
|
||||||
// what else should we save/restore?
|
// what else should we save/restore?
|
||||||
rc = a->main(argc, argv);
|
// TODO: what if applet will mangle argv vector?
|
||||||
current_applet = old_a;
|
// xargs needs argv untouched because it frees the vector!
|
||||||
applet_name = old_a->name;
|
// shouldn't we pass a copy?
|
||||||
} else {
|
rc = a->main(argc, argv);
|
||||||
/* xfunc died in NOFORK applet */
|
current_applet = old_a;
|
||||||
if (rc == -111)
|
applet_name = old_a->name;
|
||||||
rc = 0;
|
} else {
|
||||||
}
|
/* xfunc died in NOFORK applet */
|
||||||
|
if (rc == -111)
|
||||||
die_sleep = old_sleep;
|
rc = 0;
|
||||||
xfunc_error_retval = old_x;
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
#ifndef BB_NOMMU /* MMU only */
|
|
||||||
/* a->noexec is true */
|
|
||||||
rc = fork();
|
|
||||||
if (rc)
|
|
||||||
goto w;
|
|
||||||
/* child */
|
|
||||||
current_applet = a;
|
|
||||||
run_current_applet_and_exit(argc, argv);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
die_sleep = old_sleep;
|
||||||
|
xfunc_error_retval = old_x;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
#ifndef BB_NOMMU /* MMU only */
|
||||||
|
/* a->noexec is true */
|
||||||
|
rc = fork();
|
||||||
|
if (rc)
|
||||||
|
goto w;
|
||||||
|
/* child */
|
||||||
|
current_applet = a;
|
||||||
|
run_current_applet_and_exit(argc, argv);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
rc = spawn(argv);
|
rc = spawn(argv);
|
||||||
w:
|
w:
|
||||||
#else /* !FEATURE_EXEC_PREFER_APPLETS */
|
|
||||||
rc = spawn(argv);
|
|
||||||
#endif /* FEATURE_EXEC_PREFER_APPLETS */
|
|
||||||
return wait4pid(rc);
|
return wait4pid(rc);
|
||||||
}
|
#else /* !FEATURE_EXEC_PREFER_APPLETS */
|
||||||
|
return wait4pid(spawn(argv));
|
||||||
|
|
||||||
#if 0 //ndef BB_NOMMU
|
|
||||||
// Die with an error message if we can't daemonize.
|
|
||||||
void xdaemon(int nochdir, int noclose)
|
|
||||||
{
|
|
||||||
if (daemon(nochdir, noclose))
|
|
||||||
bb_perror_msg_and_die("daemon");
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 0 // def BB_NOMMU
|
|
||||||
void vfork_daemon_rexec(int nochdir, int noclose, char **argv)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
/* Maybe we are already re-execed and come here again? */
|
|
||||||
if (re_execed)
|
|
||||||
return;
|
|
||||||
|
|
||||||
setsid();
|
|
||||||
|
|
||||||
if (!nochdir)
|
|
||||||
xchdir("/");
|
|
||||||
|
|
||||||
if (!noclose) {
|
|
||||||
/* if "/dev/null" doesn't exist, bail out! */
|
|
||||||
fd = xopen(bb_dev_null, O_RDWR);
|
|
||||||
dup2(fd, STDIN_FILENO);
|
|
||||||
dup2(fd, STDOUT_FILENO);
|
|
||||||
dup2(fd, STDERR_FILENO);
|
|
||||||
while (fd > 2)
|
|
||||||
close(fd--);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (vfork()) {
|
|
||||||
case 0: /* child */
|
|
||||||
/* Make certain we are not a session leader, or else we
|
|
||||||
* might reacquire a controlling terminal */
|
|
||||||
if (vfork())
|
|
||||||
_exit(0);
|
|
||||||
/* High-order bit of first char in argv[0] is a hidden
|
|
||||||
* "we have (alrealy) re-execed, don't do it again" flag */
|
|
||||||
argv[0][0] |= 0x80;
|
|
||||||
execv(CONFIG_BUSYBOX_EXEC_PATH, argv);
|
|
||||||
bb_perror_msg_and_die("exec %s", CONFIG_BUSYBOX_EXEC_PATH);
|
|
||||||
case -1: /* error */
|
|
||||||
bb_perror_msg_and_die("vfork");
|
|
||||||
default: /* parent */
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif /* BB_NOMMU */
|
|
||||||
|
|
||||||
#ifdef BB_NOMMU
|
#ifdef BB_NOMMU
|
||||||
void forkexit_or_rexec(char **argv)
|
void forkexit_or_rexec(char **argv)
|
||||||
|
@ -20,6 +20,15 @@
|
|||||||
* Since dmalloc's prototypes overwrite the impls here as they are
|
* Since dmalloc's prototypes overwrite the impls here as they are
|
||||||
* included after these prototypes in libbb.h, all is well.
|
* included after these prototypes in libbb.h, all is well.
|
||||||
*/
|
*/
|
||||||
|
// Warn if we can't allocate size bytes of memory.
|
||||||
|
void *malloc_or_warn(size_t size)
|
||||||
|
{
|
||||||
|
void *ptr = malloc(size);
|
||||||
|
if (ptr == NULL && size != 0)
|
||||||
|
bb_error_msg(bb_msg_memory_exhausted);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
// Die if we can't allocate size bytes of memory.
|
// Die if we can't allocate size bytes of memory.
|
||||||
void *xmalloc(size_t size)
|
void *xmalloc(size_t size)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user