make compressed help code NOMMU- and NOFORK-friendly -
no forking anymore, bunzip2 unpack routine now does all it in memory.
diff --git a/archival/libunarchive/decompress_bunzip2.c b/archival/libunarchive/decompress_bunzip2.c
index d4db40e..3f0b0f6 100644
--- a/archival/libunarchive/decompress_bunzip2.c
+++ b/archival/libunarchive/decompress_bunzip2.c
@@ -62,34 +62,31 @@
 /* Structure holding all the housekeeping data, including IO buffers and
    memory that persists between calls to bunzip */
 
-typedef struct {
+struct bunzip_data {
 	/* State for interrupting output loop */
-
 	int writeCopies, writePos, writeRunCountdown, writeCount, writeCurrent;
 
 	/* I/O tracking data (file handles, buffers, positions, etc.) */
-
 	int in_fd, out_fd, inbufCount, inbufPos /*, outbufPos*/;
 	unsigned char *inbuf /*,*outbuf*/;
 	unsigned inbufBitCount, inbufBits;
 
 	/* The CRC values stored in the block header and calculated from the data */
-
 	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;
 
-	/* 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 */
 	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
    are done through this function.  All reads are big endian */
@@ -106,6 +103,7 @@
 		/* If we need to read more data from file into byte buffer, do so */
 
 		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);
 			if (bd->inbufCount <= 0)
 				longjmp(bd->jmpbuf, RETVAL_UNEXPECTED_INPUT_EOF);
@@ -519,7 +517,7 @@
    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;
 	int pos, current, previous, gotcount;
@@ -627,11 +625,16 @@
 	goto decode_next_byte;
 }
 
+
 /* 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
    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)
 {
 	bunzip_data *bd;
@@ -653,14 +656,15 @@
 
 	bd->in_fd = 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;
 	} else
 		bd->inbuf = (unsigned char *)(bd + 1);
 
 	/* Init the CRC32 table (big endian) */
 
-	bd->crc32Table = crc32_filltable(1);
+	crc32_filltable(bd->crc32Table, 1);
 
 	/* Setup for I/O error handling via longjmp */
 
@@ -670,19 +674,30 @@
 	/* Ensure that file starts with "BZh['1'-'9']." */
 
 	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
 	   uncompressed data.  Allocate intermediate buffer for block. */
 
 	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;
 }
 
-/* Example usage: decompress src_fd to dst_fd.  (Stops at end of bzip data,
-   not end of file.) */
+void dealloc_bunzip(bunzip_data *bd)
+{
+        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
 uncompressStream(int src_fd, int dst_fd)
@@ -693,7 +708,7 @@
 	int i;
 
 	outbuf = xmalloc(IOBUF_SIZE);
-	i = start_bunzip(&bd, src_fd, 0, 0);
+	i = start_bunzip(&bd, src_fd, NULL, 0);
 	if (!i) {
 		for (;;) {
 			i = read_bunzip(bd, outbuf, IOBUF_SIZE);
@@ -719,8 +734,7 @@
 	} else {
 		bb_error_msg("decompression failed");
 	}
-	free(bd->dbuf);
-	free(bd);
+	dealloc_bunzip(bd);
 	free(outbuf);
 
 	return i ? i : USE_DESKTOP(total_written) + 0;