Bunches of fixes.  Typos, bugs, etc.
Added 'gunzip -t'.  inittab support _almost_ works (but it isn't
ready for prime time useage yet).
 -Erik
diff --git a/Changelog b/Changelog
index 37570d2..54fd3ca 100644
--- a/Changelog
+++ b/Changelog
@@ -1,11 +1,11 @@
 0.40
 	* Added the -s option to du -beppu
 	* Fixed an embarrasing segfault in head	-beppu
-	* Fixed an bug in syslogd causing it to stop logging after 20 minutes. -erik
+	* Fixed an bug in syslogd causing it to stop after 20 minutes. -erik
 	* New Apps: lsmod, rmmod -erik
 	* New Apps: fbset contributed by Randolph Chung <tausq@debian.org>.
-	* Fixed the embarrasing failure of the -p opition in the logger app. -erik
-	* Re-worked the whole source tree a bit so it will compile under glibc 2.0.7 
+	* Fixed the embarrasing failure of 'logger -p'. -erik
+	* Re-worked the source tree a bit so it will compile under glibc 2.0.7 
 	    with the 2.0.x Linux kernel.
 	* Added 'grep -q' thanks to a patch from "Konstantin Boldyshev" 
 	    <konst@voshod.com>.
@@ -13,15 +13,24 @@
 	* Fixed a bug where tar would set, and then clear SGID and SUID bits.
 	* Fixed a bug where tar would not set the user and group on device
 	    special files.
-	* cp and mv were quite broken when moving directories.  I have rewritten 
+	* cp and mv were very broken when moving directories.  I have rewritten 
 	    them so they should now work as expected.  
 	* New app: loadacm contributed by Peter Novodvorsky <petya@logic.ru>
-	    for loading application character maps for working with Unicode fonts.
+	    for loading application character maps for Unicode fonts.
 	* sed now supports addresses (numeric or regexp, with negation) and 
 	    has an append command, thanks to Marco Pantaleoni <panta@prosa.it>
 	* Fixed dmesg.  It wasn't parsing its options (-n or -s) properly.  
 	* Some cosmetic fixes to ls output formatting to make it behave more
 	    like GNU ls.
+	* Fixed a bug where tar would not restore the time to files.
+	* Fixed a major security problem with tar -- it changed ownership 
+	    of any file pointed to by a symlink to 777 (like say libc....)
+	    Ouch!!!
+	* Fixed a stupid segfault in kill.
+	* Several fixes from Friedrich Vedder <fwv@myrtle.lahn.de>:
+	    - Added gunzip -t, removed gunzip.c dead code,
+	    - fixed several typos
+	    - Glibc 2.0.7 and libc5 compile fixes
 	    
 
 	-Erik Andersen
diff --git a/Makefile b/Makefile
index 73aa2fc..4215b29 100644
--- a/Makefile
+++ b/Makefile
@@ -22,7 +22,7 @@
 
 # Comment out the following to make a debuggable build
 # Leave this off for production use.
-DODEBUG=false
+DODEBUG=true
 # If you want a static binary, turn this on.  I can't think
 # of many situations where anybody would ever want it static, 
 # but...
diff --git a/applets/busybox.c b/applets/busybox.c
index 403b140..a353069 100644
--- a/applets/busybox.c
+++ b/applets/busybox.c
@@ -102,6 +102,9 @@
 #ifdef BB_LN			//bin
     {"ln", ln_main},
 #endif
+#ifdef BB_LOADACM               //usr/bin
+    {"loadacm", loadacm_main},
+#endif    
 #ifdef BB_LOADFONT		//usr/bin
     {"loadfont", loadfont_main},
 #endif
@@ -232,9 +235,6 @@
 #ifdef BB_GZIP			//bin
     {"gzip", gzip_main},
 #endif
-#ifdef BB_LOADACM               //usr/bin
-    {"loadacm", loadacm_main},
-#endif    
     {0}
 };
 
diff --git a/archival/gunzip.c b/archival/gunzip.c
index 61391a3..84f5d02 100644
--- a/archival/gunzip.c
+++ b/archival/gunzip.c
@@ -8,7 +8,8 @@
     "gunzip [OPTION]... FILE\n\n"
     "Uncompress FILE (or standard input if FILE is '-').\n\n"
     "Options:\n"
-    "\t-c\tWrite output to standard output\n";
+    "\t-c\tWrite output to standard output\n"
+    "\t-t\tTest compressed file integrity\n";
 
 /* gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface
  * Copyright (C) 1992-1993 Jean-loup Gailly
@@ -653,7 +654,7 @@
 
 		/* local variables */
 
-int force = 0;        /* don't ask questions, compress links (-f) */
+int test_mode = 0;    /* check file integrity option */
 int foreground;       /* set if program run in foreground */
 int maxbits = BITS;   /* max bits per code for LZW */
 int method = DEFLATED;/* compression method */
@@ -714,6 +715,10 @@
 	    case 'c':
 		to_stdout = 1;
 		break;
+	    case 't':
+		test_mode = 1;
+		break;
+
 	    default:
 		usage(gunzip_usage);
 	    }
@@ -786,6 +791,9 @@
 	/* Actually do the compression/decompression. */
 	unzip(inFileNum, outFileNum);
 
+    } else if (test_mode) {
+	/* Actually do the compression/decompression. */
+	unzip(inFileNum, 2);
     } else {
 	char* pos;
 
@@ -857,17 +865,8 @@
     uch flags;     /* compression flags */
     char magic[2]; /* magic header */
 
-    /* If --force and --stdout, zcat == cat, so do not complain about
-     * premature end of file: use try_byte instead of get_byte.
-     */
-    if (force) {
-	magic[0] = (char)try_byte();
-	magic[1] = (char)try_byte();
-	/* If try_byte returned EOF, magic[1] == 0xff */
-    } else {
-	magic[0] = (char)get_byte();
-	magic[1] = (char)get_byte();
-    }
+    magic[0] = (char)get_byte();
+    magic[1] = (char)get_byte();
     method = -1;                 /* unknown yet */
     part_nb++;                   /* number of parts in gzip file */
     header_bytes = 0;
@@ -1188,7 +1187,8 @@
 {
     if (outcnt == 0) return;
 
-    write_buf(ofd, (char *)outbuf, outcnt);
+    if (!test_mode)
+	write_buf(ofd, (char *)outbuf, outcnt);
     bytes_out += (ulg)outcnt;
     outcnt = 0;
 }
@@ -1202,8 +1202,8 @@
     if (outcnt == 0) return;
     updcrc(window, outcnt);
 
-    write_buf(ofd, (char *)window, outcnt);
-
+    if (!test_mode)
+	write_buf(ofd, (char *)window, outcnt);
     bytes_out += (ulg)outcnt;
     outcnt = 0;
 }
diff --git a/archival/tar.c b/archival/tar.c
index 7167d95..a53370e 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -37,6 +37,7 @@
 #include <fcntl.h>
 #include <signal.h>
 #include <time.h>
+#include <utime.h>
 #include <sys/types.h>
 #include <sys/sysmacros.h>
 
@@ -106,8 +107,12 @@
 static int eofFlag;
 static long dataCc;
 static int outFd;
-static char outName[TAR_NAME_SIZE];
+static const char *outName;
 
+static int mode;
+static int uid;
+static int gid;
+static time_t mtime;
 
 /*
  * Static data associated with the tar file.
@@ -364,8 +369,9 @@
      * message is required on errors.
      */
     if (tostdoutFlag == FALSE) {
-	if (outFd >= 0)
-	    (void) close (outFd);
+	if (outFd >= 0) {
+	    close (outFd);
+	}
     }
 }
 
@@ -378,29 +384,25 @@
 static void
 readHeader (const TarHeader * hp, int fileCount, char **fileTable)
 {
-    int mode;
-    int uid;
-    int gid;
     int checkSum;
-    unsigned int major;
-    unsigned int minor;
-    long size;
-    time_t mtime;
-    const char *name;
     int cc;
     int hardLink;
     int softLink;
     int devFileFlag;
+    unsigned int major;
+    unsigned int minor;
+    long size;
+    struct utimbuf utb;
 
     /* 
      * If the block is completely empty, then this is the end of the
      * archive file.  If the name is null, then just skip this header.
      */
-    name = hp->name;
+    outName = hp->name;
 
-    if (*name == '\0') {
+    if (*outName == '\0') {
 	for (cc = TAR_BLOCK_SIZE; cc > 0; cc--) {
-	    if (*name++)
+	    if (*outName++)
 		return;
 	}
 
@@ -447,16 +449,16 @@
     /* 
      * Check for a directory.
      */
-    if (name[strlen (name) - 1] == '/')
+    if (outName[strlen (outName) - 1] == '/')
 	mode |= S_IFDIR;
 
     /* 
      * Check for absolute paths in the file.
      * If we find any, then warn the user and make them relative.
      */
-    if (*name == '/') {
-	while (*name == '/')
-	    name++;
+    if (*outName == '/') {
+	while (*outName == '/')
+	    outName++;
 
 	if (warnedRoot==FALSE) {
 	    fprintf (stderr,
@@ -470,7 +472,7 @@
      * See if we want this file to be restored.
      * If not, then set up to skip it.
      */
-    if (wantFileName (name, fileCount, fileTable) == FALSE) {
+    if (wantFileName (outName, fileCount, fileTable) == FALSE) {
 	if ( !hardLink && !softLink && (S_ISREG (mode) || S_ISCHR (mode)
 		    || S_ISBLK (mode) || S_ISSOCK(mode) || S_ISFIFO(mode) ) ) {
 	    inHeader = (size == 0)? TRUE : FALSE;
@@ -494,7 +496,7 @@
 	    else
 		printf ("%9ld %s ", size, timeString (mtime));
 	}
-	printf ("%s", name);
+	printf ("%s", outName);
 
 	if (hardLink)
 	    printf (" (link to \"%s\")", hp->linkName);
@@ -515,22 +517,35 @@
      * We really want to extract the file.
      */
     if (verboseFlag==TRUE)
-	printf ("x %s\n", name);
+	printf ("x %s\n", outName);
 
     if (hardLink) {
-	if (link (hp->linkName, name) < 0)
-	    perror (name);
-	chown(name, uid, gid);
-	chmod(name, mode);
+	if (link (hp->linkName, outName) < 0)
+	    perror (outName);
+	/* Set the file time */
+	utb.actime = mtime;
+	utb.modtime = mtime;
+	utime (outName, &utb);
+	/* Set the file permissions */
+	chown(outName, uid, gid);
+	chmod(outName, mode);
 	return;
     }
 
     if (softLink) {
 #ifdef	S_ISLNK
-	if (symlink (hp->linkName, name) < 0)
-	    perror (name);
-	chown(name, uid, gid);
-	chmod(name, mode);
+	if (symlink (hp->linkName, outName) < 0)
+	    perror (outName);
+	/* Try to change ownership of the symlink.
+	 * If libs doesn't support that, don't bother.
+	 * Changing the pointed-to file is the Wrong Thing(tm).
+	 */
+#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1)
+	lchown(outName, uid, gid);
+#endif
+
+	/* Do not change permissions or date on symlink,
+	 * since it changes the pointed to file instead.  duh. */
 #else
 	fprintf (stderr, "Cannot create symbolic links\n");
 #endif
@@ -545,10 +560,14 @@
      * If the file is a directory, then just create the path.
      */
     if (S_ISDIR (mode)) {
-	createPath (name, mode);
-	chown(name, uid, gid);
-	chmod(name, mode);
-
+	createPath (outName, mode);
+	/* Set the file time */
+	utb.actime = mtime;
+	utb.modtime = mtime;
+	utime (outName, &utb);
+	/* Set the file permissions */
+	chown(outName, uid, gid);
+	chmod(outName, mode);
 	return;
     }
 
@@ -556,7 +575,7 @@
      * There is a file to write.
      * First create the path to it if necessary with default permissions.
      */
-    createPath (name, 0777);
+    createPath (outName, 0777);
 
     inHeader = (size == 0)? TRUE : FALSE;
     dataCc = size;
@@ -569,21 +588,26 @@
     else {
 	if ( S_ISCHR(mode) || S_ISBLK(mode) || S_ISSOCK(mode) ) {
 	    devFileFlag = TRUE;
-	    outFd = mknod (name, mode, makedev(major, minor) );
+	    outFd = mknod (outName, mode, makedev(major, minor) );
 	}
 	else if (S_ISFIFO(mode) ) {
 	    devFileFlag = TRUE;
-	    outFd = mkfifo(name, mode);
+	    outFd = mkfifo(outName, mode);
 	} else {
-	    outFd = open (name, O_WRONLY | O_CREAT | O_TRUNC, mode);
+	    outFd = open (outName, O_WRONLY | O_CREAT | O_TRUNC, mode);
 	}
 	if (outFd < 0) {
-	    perror (name);
+	    perror (outName);
 	    skipFileFlag = TRUE;
 	    return;
 	}
-	chown(name, uid, gid);
-	chmod(name, mode);
+	/* Set the file time */
+	utb.actime = mtime;
+	utb.modtime = mtime;
+	utime (outName, &utb);
+	/* Set the file permissions */
+	chown(outName, uid, gid);
+	chmod(outName, mode);
     }
 
 
@@ -591,7 +615,7 @@
      * If the file is empty, then that's all we need to do.
      */
     if (size == 0 && (tostdoutFlag == FALSE) && (devFileFlag == FALSE)) {
-	(void) close (outFd);
+	close (outFd);
 	outFd = -1;
     }
 }
@@ -625,7 +649,7 @@
     if (fullWrite (outFd, cp, count) < 0) {
 	perror (outName);
 	if (tostdoutFlag == FALSE) {
-	    (void) close (outFd);
+	    close (outFd);
 	    outFd = -1;
 	}
 	skipFileFlag = TRUE;
@@ -633,13 +657,21 @@
     }
 
     /* 
-     * If the write failed, close the file and disable further
-     * writes to this file.
+     * Check if we are done writing to the file now.
      */
     if (dataCc <= 0 && tostdoutFlag == FALSE) {
+	struct utimbuf utb;
 	if (close (outFd))
 	    perror (outName);
 
+	/* Set the file time */
+	utb.actime = mtime;
+	utb.modtime = mtime;
+	utime (outName, &utb);
+	/* Set the file permissions */
+	chown(outName, uid, gid);
+	chmod(outName, mode);
+
 	outFd = -1;
     }
 }
@@ -720,7 +752,6 @@
 static void saveFile (const char *fileName, int seeLinks)
 {
     int status;
-    int mode;
     struct stat statbuf;
 
     if (verboseFlag==TRUE)
diff --git a/busybox.c b/busybox.c
index 403b140..a353069 100644
--- a/busybox.c
+++ b/busybox.c
@@ -102,6 +102,9 @@
 #ifdef BB_LN			//bin
     {"ln", ln_main},
 #endif
+#ifdef BB_LOADACM               //usr/bin
+    {"loadacm", loadacm_main},
+#endif    
 #ifdef BB_LOADFONT		//usr/bin
     {"loadfont", loadfont_main},
 #endif
@@ -232,9 +235,6 @@
 #ifdef BB_GZIP			//bin
     {"gzip", gzip_main},
 #endif
-#ifdef BB_LOADACM               //usr/bin
-    {"loadacm", loadacm_main},
-#endif    
     {0}
 };
 
diff --git a/busybox.def.h b/busybox.def.h
index 3982a1c..503410f 100644
--- a/busybox.def.h
+++ b/busybox.def.h
@@ -36,7 +36,7 @@
 //#define BB_LOADACM
 //#define BB_LOADFONT
 //#define BB_LOADKMAP
-#define BB_LOGGER
+//#define BB_LOGGER
 #define BB_LS
 #define BB_LSMOD
 //#define BB_MAKEDEVS
@@ -68,7 +68,7 @@
 #define BB_SORT
 #define BB_SWAPONOFF
 #define BB_SYNC
-#define BB_SYSLOGD
+//#define BB_SYSLOGD
 #define BB_TAIL
 #define BB_TAR
 #define BB_TEE
@@ -90,8 +90,6 @@
 // pretty/useful).
 //
 //
-// enable a second console on TTY2 in init
-#define BB_FEATURE_INIT_SECOND_CONSOLE
 // enable features that use the /proc filesystem
 #define BB_FEATURE_USE_PROCFS
 //Enable init being called as /linuxrc
diff --git a/busybox_functions.h b/busybox_functions.h
deleted file mode 100644
index 61fc484..0000000
--- a/busybox_functions.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef __BUSYBOX_FUNCTIONS_H__
-#define __BUSYBOX_FUNCTIONS_H__
-
-int
-mkswap(char *device_name, int pages, int check);
-/* pages = 0 for autodetection */
-
-int
-fdflush(char *filename);
-
-#endif /* __BUSYBOX_FUNCTIONS_H__ */
diff --git a/coreutils/cp.c b/coreutils/cp.c
index 8346019..4af73c2 100644
--- a/coreutils/cp.c
+++ b/coreutils/cp.c
@@ -33,7 +33,7 @@
     "\n"
     "\t-a\tsame as -dpR\n"
     "\t-d\tpreserve links\n"
-    "\t-p\tpreserve file attributes if possable\n"
+    "\t-p\tpreserve file attributes if possible\n"
     "\t-R\tcopy directories recursively\n";
 
 
diff --git a/cp.c b/cp.c
index 8346019..4af73c2 100644
--- a/cp.c
+++ b/cp.c
@@ -33,7 +33,7 @@
     "\n"
     "\t-a\tsame as -dpR\n"
     "\t-d\tpreserve links\n"
-    "\t-p\tpreserve file attributes if possable\n"
+    "\t-p\tpreserve file attributes if possible\n"
     "\t-R\tcopy directories recursively\n";
 
 
diff --git a/editors/sed.c b/editors/sed.c
index 8e5f695..2577724 100644
--- a/editors/sed.c
+++ b/editors/sed.c
@@ -46,7 +46,7 @@
     "\t  /REGEXP/  Match specified regexp\n"
     "\t  (! inverts the meaning of the match)\n\n"
     "\tand COMMAND can be:\n"
-    "\t  s/regexp/replacement/[gp]\n"
+    "\t  s/regexp/replacement/[igp]\n"
     "\t     which attempt to match regexp against the pattern space\n"
     "\t     and if successful replaces the matched portion with replacement.\n\n"
     "\t  aTEXT\n"
diff --git a/gunzip.c b/gunzip.c
index 61391a3..84f5d02 100644
--- a/gunzip.c
+++ b/gunzip.c
@@ -8,7 +8,8 @@
     "gunzip [OPTION]... FILE\n\n"
     "Uncompress FILE (or standard input if FILE is '-').\n\n"
     "Options:\n"
-    "\t-c\tWrite output to standard output\n";
+    "\t-c\tWrite output to standard output\n"
+    "\t-t\tTest compressed file integrity\n";
 
 /* gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface
  * Copyright (C) 1992-1993 Jean-loup Gailly
@@ -653,7 +654,7 @@
 
 		/* local variables */
 
-int force = 0;        /* don't ask questions, compress links (-f) */
+int test_mode = 0;    /* check file integrity option */
 int foreground;       /* set if program run in foreground */
 int maxbits = BITS;   /* max bits per code for LZW */
 int method = DEFLATED;/* compression method */
@@ -714,6 +715,10 @@
 	    case 'c':
 		to_stdout = 1;
 		break;
+	    case 't':
+		test_mode = 1;
+		break;
+
 	    default:
 		usage(gunzip_usage);
 	    }
@@ -786,6 +791,9 @@
 	/* Actually do the compression/decompression. */
 	unzip(inFileNum, outFileNum);
 
+    } else if (test_mode) {
+	/* Actually do the compression/decompression. */
+	unzip(inFileNum, 2);
     } else {
 	char* pos;
 
@@ -857,17 +865,8 @@
     uch flags;     /* compression flags */
     char magic[2]; /* magic header */
 
-    /* If --force and --stdout, zcat == cat, so do not complain about
-     * premature end of file: use try_byte instead of get_byte.
-     */
-    if (force) {
-	magic[0] = (char)try_byte();
-	magic[1] = (char)try_byte();
-	/* If try_byte returned EOF, magic[1] == 0xff */
-    } else {
-	magic[0] = (char)get_byte();
-	magic[1] = (char)get_byte();
-    }
+    magic[0] = (char)get_byte();
+    magic[1] = (char)get_byte();
     method = -1;                 /* unknown yet */
     part_nb++;                   /* number of parts in gzip file */
     header_bytes = 0;
@@ -1188,7 +1187,8 @@
 {
     if (outcnt == 0) return;
 
-    write_buf(ofd, (char *)outbuf, outcnt);
+    if (!test_mode)
+	write_buf(ofd, (char *)outbuf, outcnt);
     bytes_out += (ulg)outcnt;
     outcnt = 0;
 }
@@ -1202,8 +1202,8 @@
     if (outcnt == 0) return;
     updcrc(window, outcnt);
 
-    write_buf(ofd, (char *)window, outcnt);
-
+    if (!test_mode)
+	write_buf(ofd, (char *)window, outcnt);
     bytes_out += (ulg)outcnt;
     outcnt = 0;
 }
diff --git a/init.c b/init.c
index b71c9f7..be04ec3 100644
--- a/init.c
+++ b/init.c
@@ -23,6 +23,7 @@
 
 #include "internal.h"
 #include <stdio.h>
+#include <string.h>
 #include <stdlib.h>
 #include <stdarg.h>
 #include <unistd.h>
@@ -55,22 +56,57 @@
 #endif
 
 
-#define VT_PRIMARY      "/dev/tty1"	/* Primary virtual console */
-#define VT_SECONDARY    "/dev/tty2"	/* Virtual console */
-#define VT_LOG          "/dev/tty3"	/* Virtual console */
-#define SERIAL_CON0     "/dev/ttyS0"    /* Primary serial console */
-#define SERIAL_CON1     "/dev/ttyS1"    /* Serial console */
-#define GETTY           "/sbin/getty"	/* Default location of getty */
-#define SHELL           "/bin/sh"	/* Default shell */
-#define INITTAB          "/etc/inittab"	/* inittab file location */
-#ifndef BB_INIT_SCRIPT
-#define BB_INIT_SCRIPT	"/etc/init.d/rcS"	/* Initscript. */
-#endif
-
-#if 1
+#define VT_PRIMARY      "/dev/tty1"	  /* Primary virtual console */
+#define VT_SECONDARY    "/dev/tty2"	  /* Virtual console */
+#define VT_LOG          "/dev/tty3"	  /* Virtual console */
+#define SERIAL_CON0     "/dev/ttyS0"      /* Primary serial console */
+#define SERIAL_CON1     "/dev/ttyS1"      /* Serial console */
+#define SHELL           "/bin/sh"	  /* Default shell */
+#define REBOOT          "/sbin/reboot"	  /* Default ctrl-alt-del command */
+#define INITTAB         "/etc/inittab"	  /* inittab file location */
+#define INIT_SCRIPT	"/etc/init.d/rcS" /* Default sysinit script. */
 
 #define LOG             0x1
 #define CONSOLE         0x2
+
+/* Allowed init action types */
+typedef enum {
+    SYSINIT=1,
+    CTRLALTDEL,
+    RESPAWN,
+    ASKFIRST,
+    WAIT,
+    ONCE
+} initActionEnum;
+
+/* And now a list of the actions we support in the version of init */
+typedef struct initActionType{
+    const char*	name;
+    initActionEnum action;
+} initActionType;
+
+static const struct initActionType actions[] = {
+    {"sysinit",     SYSINIT},
+    {"ctrlaltdel",  CTRLALTDEL},
+    {"respawn",     RESPAWN},
+    {"askfirst",    ASKFIRST},
+    {"wait",        WAIT},
+    {"once",        ONCE},
+    {0}
+};
+
+/* Set up a linked list of initactions, to be read from inittab */
+typedef struct initActionTag initAction;
+struct initActionTag {
+    pid_t pid;
+    char process[256];
+    char *console;
+    initAction *nextPtr;
+    initActionEnum action;
+};
+initAction* initActionList = NULL;
+
+
 static char *console = _PATH_CONSOLE;
 static char *second_console = VT_SECONDARY;
 static char *log = VT_LOG;
@@ -100,8 +136,9 @@
  * device may be bitwise-or'd from LOG | CONSOLE */
 void message(int device, char *fmt, ...)
 {
-    int fd;
     va_list arguments;
+    int fd;
+
 #ifdef BB_SYSLOGD
 
     /* Log the message to syslogd */
@@ -298,16 +335,18 @@
 }
 
 
-static pid_t run(const char * const* command, 
+static pid_t run(char* command, 
 	char *terminal, int get_enter)
 {
-    int fd;
+    int i;
     pid_t pid;
-    const char * const* cmd = command+1;
+    char* tmpCmd;
+    char* cmd[255];
     static const char press_enter[] =
 	"\nPlease press Enter to activate this console. ";
 
     if ((pid = fork()) == 0) {
+	int fd;
 	/* Clean up */
 	close(0);
 	close(1);
@@ -321,7 +360,7 @@
 	signal(SIGTERM, SIG_DFL);
 
 	if ((fd = device_open(terminal, O_RDWR)) < 0) {
-	    message(LOG, "Bummer, can't open %s\r\n", terminal);
+	    message(LOG|CONSOLE, "Bummer, can't open %s\r\n", terminal);
 	    exit(-1);
 	}
 	dup(fd);
@@ -340,21 +379,32 @@
 	     */
 	    char c;
 	    message(LOG, "Waiting for enter to start '%s' (pid %d, console %s)\r\n", 
-		    *cmd, getpid(), terminal );
-	    write(1, press_enter, sizeof(press_enter) - 1);
-	    read(0, &c, 1);
+		    command, getpid(), terminal );
+	    write(fileno(stdout), press_enter, sizeof(press_enter) - 1);
+	    read(fileno(stdin), &c, 1);
 	}
 
+	/* Convert command (char*) into cmd (char**, one word per string) */
+	for (tmpCmd=command, i=0; (tmpCmd=strsep(&command, " \t")) != NULL;) {
+	    if (*tmpCmd != '\0') {
+		cmd[i] = tmpCmd;
+		tmpCmd++;
+		i++;
+	    }
+	}
+	cmd[i] = NULL;
+
 	/* Log the process name and args */
-	message(LOG|CONSOLE, "Starting pid %d, console %s: '", getpid(), terminal);
-	while ( *cmd) message(LOG|CONSOLE, "%s ", *cmd++);
-	message(LOG|CONSOLE, "'\r\n");
-	
+	message(LOG, "Starting pid %d, console %s: '%s'\r\n", 
+		getpid(), terminal, cmd[0]);
+
 	/* Now run it.  The new program will take over this PID, 
 	 * so nothing further in init.c should be run. */
-	execvp(*command, (char**)command+1);
+	execvp(cmd[0], cmd);
 
-	message(LOG, "Bummer, could not run '%s'\n", command);
+	/* We're still here?  Some error happened. */
+	message(LOG|CONSOLE, "Bummer, could not run '%s': %s\n", cmd[0],
+		strerror(errno));
 	exit(-1);
     }
     return pid;
@@ -365,15 +415,13 @@
 static void check_memory()
 {
     struct stat statbuf;
-    const char* const swap_on_cmd[] = 
-	    { "/bin/swapon", "swapon", "-a", 0};
 
     if (mem_total() > 3500)
 	return;
 
     if (stat("/etc/fstab", &statbuf) == 0) {
 	/* Try to turn on swap */
-	waitfor(run(swap_on_cmd, log, FALSE));
+	waitfor(run("/bin/swapon swapon -a", log, FALSE));
 	if (mem_total() < 3500)
 	    goto goodnight;
     } else
@@ -385,33 +433,28 @@
 	while (1) sleep(1);
 }
 
+#ifndef DEBUG_INIT
 static void shutdown_system(void)
 {
-    const char* const swap_off_cmd[] = { "swapoff", "swapoff", "-a", 0};
-    const char* const umount_cmd[] = { "umount", "umount", "-a", 0};
-
-#ifndef DEBUG_INIT
     /* Allow Ctrl-Alt-Del to reboot system. */
     reboot(RB_ENABLE_CAD);
-#endif
     message(CONSOLE, "\r\nThe system is going down NOW !!\r\n");
     sync();
+
     /* Send signals to every process _except_ pid 1 */
     message(CONSOLE, "Sending SIGHUP to all processes.\r\n");
-#ifndef DEBUG_INIT
     kill(-1, SIGHUP);
-#endif
     sleep(2);
     sync();
+
     message(CONSOLE, "Sending SIGKILL to all processes.\r\n");
-#ifndef DEBUG_INIT
     kill(-1, SIGKILL);
-#endif
     sleep(1);
+
     message(CONSOLE, "Disabling swap.\r\n");
-    waitfor(run( swap_off_cmd, console, FALSE));
+    waitfor(run( "swapoff -a", console, FALSE));
     message(CONSOLE, "Unmounting filesystems.\r\n");
-    waitfor(run( umount_cmd, console, FALSE));
+    waitfor(run( "umount -a", console, FALSE));
     sync();
     if (kernel_version > 0 && kernel_version <= 2 * 65536 + 2 * 256 + 11) {
 	/* bdflush, kupdate not needed for kernels >2.2.11 */
@@ -427,14 +470,12 @@
     message(CONSOLE,
 	    "The system is halted. Press CTRL-ALT-DEL or turn off power\r\n");
     sync();
-#ifndef DEBUG_INIT
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
     if (sig == SIGUSR2)
 	reboot(RB_POWER_OFF);
     else
 #endif
-	reboot(RB_HALT_SYSTEM);
-#endif
+    reboot(RB_HALT_SYSTEM);
     exit(0);
 }
 
@@ -443,64 +484,157 @@
     shutdown_system();
     message(CONSOLE, "Please stand by while rebooting the system.\r\n");
     sync();
-#ifndef DEBUG_INIT
     reboot(RB_AUTOBOOT);
-#endif
     exit(0);
 }
 
+static void ctrl_alt_del_signal(int sig)
+{
+    initAction* a;
+    /* Run whatever we are supposed to run */
+    for( a=initActionList ; a; a=a->nextPtr) {
+	if (a->action == CTRLALTDEL) {
+	    waitfor(run(a->process, console, FALSE));
+	}
+    }
+}
+#endif
+
+void new_initAction (const struct initActionType *a, 
+	char* process, char* console)
+{
+    initAction* newAction;
+    newAction = calloc ((size_t)(1), sizeof(initAction));
+    if (!newAction) {
+	fprintf(stderr, "Memory allocation failure\n");
+	while (1) sleep(1);
+    }
+    newAction->nextPtr = initActionList;
+    initActionList = newAction;
+    strncpy( newAction->process, process, 255);
+    newAction->action = a->action;
+    newAction->console = console;
+    newAction->pid = 0;
+}
+
+void delete_initAction (initAction *action)
+{
+    initAction *a, *b=NULL;
+    for( a=initActionList ; a; b=a, a=a->nextPtr) {
+	if (a == action && b != NULL) {
+	    b->nextPtr=a->nextPtr;
+	    free( a);
+	    break;
+	}
+    }
+}
+
+void parse_inittab(void) 
+{
+    FILE* file;
+    char buf[256];
+    char *p, *q, *r;
+    const struct initActionType *a = actions;
+    int foundIt;
+
+
+    file = fopen(INITTAB, "r");
+    if (file == NULL) {
+	/* No inittab file -- set up some default behavior */
+
+	/* Askfirst shell on tty1 */
+	new_initAction( &(actions[3]), SHELL, console );
+	/* Askfirst shell on tty2 */
+	if (second_console != NULL) 
+	    new_initAction( &(actions[3]), SHELL, second_console );
+	/* Control-alt-del */
+	new_initAction( &(actions[1]), REBOOT, console );
+	/* sysinit */
+	new_initAction( &(actions[0]), INIT_SCRIPT, console );
+
+	return;
+    }
+
+    while ( fgets(buf, 255, file) != NULL) {
+	foundIt=FALSE;
+	for(p = buf; *p == ' ' || *p == '\t'; p++);
+	if (*p == '#' || *p == '\n') continue;
+
+	/* Trim the trailing \n */
+	q = strrchr( p, '\n');
+	if (q != NULL)
+	    *q='\0';
+
+	/* Skip past the ID field and the runlevel 
+	 * field (both are ignored) */
+	p = strchr( p, ':');
+
+	/* Now peal off the process field from the end
+	 * of the string */
+	q = strrchr( p, ':');
+	if ( q == NULL || *(q+1) == '\0' ) {
+	    fprintf(stderr, "Bad inittab entry: %s\n", buf);
+	    continue;
+	} else {
+	    *q='\0';
+	    ++q;
+	}
+
+	/* Now peal off the action field */
+	r = strrchr( p, ':');
+	if ( r == NULL || *(r+1) == '\0') {
+	    fprintf(stderr, "Bad inittab entry: %s\n", buf);
+	    continue;
+	} else {
+	    ++r;
+	}
+
+	/* Ok, now process it */
+	a = actions;
+	while (a->name != 0) {
+	    if (strcmp(a->name, r) == 0) {
+		new_initAction( a, q, NULL);
+		foundIt=TRUE;
+	    }
+	    a++;
+	}
+	if (foundIt==TRUE)
+	    continue;
+	else {
+	    /* Choke on an unknown action */
+	    fprintf(stderr, "Bad inittab entry: %s\n", buf);
+	}
+    }
+    return;
+}
+
+
 extern int init_main(int argc, char **argv)
 {
-    int run_rc = FALSE;
+    initAction *a;
+    pid_t wpid;
+    int status;
     int single = FALSE;
-    int wait_for_enter_tty1 = TRUE;
-    int wait_for_enter_tty2 = TRUE;
-    pid_t pid1 = 0;
-    pid_t pid2 = 0;
-    struct stat statbuf;
-    char which_vt1[30];
-    char which_vt2[30];
-    const char* const rc_script_command[] = { BB_INIT_SCRIPT, BB_INIT_SCRIPT, 0};
-    const char* const getty1_command[] = { GETTY, GETTY, "38400", which_vt1, 0};
-    const char* const getty2_command[] = { GETTY, GETTY, "38400", which_vt2, 0};
-    const char* const shell_command[] = { SHELL, "-" SHELL, 0};
-    const char* const* tty1_command = shell_command;
-    const char* const* tty2_command = shell_command;
-#ifdef BB_INIT_CMD_IF_RC_SCRIPT_EXITS
-    const char* const rc_exit_command[] = { "BB_INIT_CMD_IF_RC_SCRIPT_EXITS", 
-					    "BB_INIT_CMD_IF_RC_SCRIPT_EXITS", 0 };
-#endif
 
-#ifdef DEBUG_INIT
-    char *hello_msg_format =
-	"init(%d) started:  BusyBox v%s (%s) multi-call binary\r\n";
-#else
-    char *hello_msg_format =
-	"init started:  BusyBox v%s (%s) multi-call binary\r\n";
-#endif
 
-    
 #ifndef DEBUG_INIT
     /* Expect to be PID 1 iff we are run as init (not linuxrc) */
     if (getpid() != 1 && strstr(argv[0], "init")!=NULL ) {
 	usage( "init\n\nInit is the parent of all processes.\n\n"
 		"This version of init is designed to be run only by the kernel\n");
     }
-#endif
 
-    /* Set up sig handlers  -- be sure to
-     * clear all of these in run() */
+    /* Set up sig handlers  -- be sure to clear all of these in run() */
     signal(SIGUSR1, halt_signal);
     signal(SIGUSR2, reboot_signal);
-    signal(SIGINT, reboot_signal);
+    signal(SIGINT, ctrl_alt_del_signal);
     signal(SIGTERM, reboot_signal);
 
     /* Turn off rebooting via CTL-ALT-DEL -- we get a 
      * SIGINT on CAD so we can shut things down gracefully... */
-#ifndef DEBUG_INIT
     reboot(RB_DISABLE_CAD);
 #endif 
-
+    
     /* Figure out where the default console should be */
     console_init();
 
@@ -517,9 +651,13 @@
    
     /* Hello world */
 #ifndef DEBUG_INIT
-    message(CONSOLE|LOG, hello_msg_format, BB_VER, BB_BT);
+    message(CONSOLE|LOG, 
+	    "init started:  BusyBox v%s (%s) multi-call binary\r\n", 
+	    BB_VER, BB_BT);
 #else
-    message(CONSOLE|LOG, hello_msg_format, getpid(), BB_VER, BB_BT);
+    message(CONSOLE|LOG, 
+	    "init(%d) started:  BusyBox v%s (%s) multi-call binary\r\n", 
+	    getpid(), BB_VER, BB_BT);
 #endif
 
     
@@ -537,150 +675,77 @@
     if ( argc > 1 && (!strcmp(argv[1], "single") || 
 		!strcmp(argv[1], "-s") || !strcmp(argv[1], "1"))) {
 	single = TRUE;
-	tty1_command = shell_command;
-	tty2_command = shell_command;
+	/* Ask first then start a shell on tty2 */
+	if (second_console != NULL) 
+	    new_initAction( &(actions[3]), SHELL, second_console);
+	/* Ask first then start a shell on tty1 */
+	new_initAction( &(actions[3]), SHELL, console);
+    } else {
+	/* Not in single user mode -- see what inittab says */
+	parse_inittab();
     }
 
-    /* Make sure an init script exists before trying to run it */
-    if (single==FALSE && stat(BB_INIT_SCRIPT, &statbuf)==0) {
-	run_rc = TRUE;
-	wait_for_enter_tty1 = FALSE;
-	tty1_command = rc_script_command;
-    }
-    
-    /* Make sure /sbin/getty exists before trying to run it */
-    if (stat(GETTY, &statbuf)==0) {
-	char* where;
-	/* First do tty2 */
-	wait_for_enter_tty2 = FALSE;
-	where = strrchr( second_console, '/');
-	if ( where != NULL) {
-	    where++;
-	    strncpy( which_vt2, where, sizeof(which_vt2));
-	}
-	tty2_command = getty2_command;
+    /* Now run everything that needs to be run */
 
-	/* Check on hooking a getty onto tty1 */
-	if (run_rc == FALSE && single==FALSE) {
-	    wait_for_enter_tty1 = FALSE;
-	    where = strrchr( console, '/');
-	    if ( where != NULL) {
-		where++;
-		strncpy( which_vt1, where, sizeof(which_vt1));
-	    }
-	    tty1_command = getty1_command;
+    /* First run sysinit */
+    for( a=initActionList ; a; a=a->nextPtr) {
+	if (a->action == SYSINIT) {
+	    waitfor(run(a->process, console, FALSE));
+	    /* Now remove the "sysinit" entry from the list */
+	    delete_initAction( a);
 	}
     }
-    
+    /* Next run anything that wants to block */
+    for( a=initActionList ; a; a=a->nextPtr) {
+	if (a->action == WAIT) {
+	    waitfor(run(a->process, console, FALSE));
+	    /* Now remove the "wait" entry from the list */
+	    delete_initAction( a);
+	}
+    }
+    /* Next run anything to be run only once */
+    for( a=initActionList ; a; a=a->nextPtr) {
+	if (a->action == ONCE) {
+	    run(a->process, console, FALSE);
+	    /* Now remove the "once" entry from the list */
+	    delete_initAction( a);
+	}
+    }
 
-    /* Ok, now launch the tty1_command and tty2_command */
+    /* Now run the looping stuff */
     for (;;) {
-	pid_t wpid;
-	int status;
+	for( a=initActionList ; a; a=a->nextPtr) {
+	    /* Only run stuff with pid==0.  If they have
+	     * a pid, that means they are still running */
+	    if (a->pid == 0) {
+		switch(a->action) {
+		    case RESPAWN:
+			/* run the respawn stuff */
+			a->pid = run(a->process, console, FALSE);
+			break;
+		    case ASKFIRST:
+			/* run the askfirst stuff */
+			a->pid = waitfor(run(a->process, console, TRUE));
+			break;
+		    /* silence the compiler's whining */
+		    default:
+			break;
+		}
+	    }
+	}
 
-	if (pid1 == 0 && tty1_command) {
-	    pid1 = run(tty1_command, console, wait_for_enter_tty1);
-	}
-#ifdef BB_FEATURE_INIT_SECOND_CONSOLE
-	if (pid2 == 0 && tty2_command && second_console) {
-	    pid2 = run(tty2_command, second_console, wait_for_enter_tty2);
-	}
-#endif
 	wpid = wait(&status);
+	/* Find out who died and clean up their corpse */
 	if (wpid > 0 ) {
 	    message(LOG, "pid %d exited, status=%x.\n", wpid, status);
-	}
-	/* Don't respawn init script if it exits */
-	if (wpid == pid1) {
-	    if (run_rc == FALSE) {
-		pid1 = 0;
+	    for( a=initActionList ; a; a=a->nextPtr) {
+		if (a->pid==wpid) {
+		    a->pid=0;
+		}
 	    }
-#ifdef BB_INIT_CMD_IF_RC_SCRIPT_EXITS
-	    else {
-		pid1 = 0;
-		run_rc=FALSE;
-		wait_for_enter_tty1=TRUE;
-		tty1_command=rc_exit_command;
-	    }
-#endif
 	}
-#ifdef BB_FEATURE_INIT_SECOND_CONSOLE
-	if (wpid == pid2) {
-	    pid2 = 0;
-	}
-#endif
+
 	sleep(1);
     }
 }
 
-#else
-
-
-void parse_inittab(void) 
-{
-    FILE* file;
-    char buf[256];
-    char action[256]="";
-    char process[256]="";
-    char *p, *q;
-
-
-    if ((file = fopen(INITTAB, "r")) < 0) {
-	/* No inittab file -- set up some default behavior */
-
-	/* FIXME */
-	return;
-    }
-
-    while ( fgets(buf, 255, file) != NULL) {
-	for(p = buf; *p == ' ' || *p == '\t'; p++);
-	if (*p == '#' || *p == '\n') continue;
-
-	/* Trim the trailing \n */
-	q = strrchr( p, '\n');
-	if (q != NULL)
-	    *q='\0';
-
-	/* Skip past the ID field and the runlevel 
-	 * field (both are ignored) */
-	p = strchr( p, ':');
-
-	/* Now peal off the process field from the end
-	 * of the string */
-	q = strrchr( p, ':');
-	if ( q == NULL || q+1 == NULL)
-	    goto choke;
-	*q='\0';
-	strcpy( process, ++q);
-	fprintf(stderr, "process=%s\n", process);
-
-	
-	/* Now peal off the action field */
-	q = strrchr( p, ':');
-	if ( q == NULL || q+1 == NULL)
-	    goto choke;
-	strcpy( action, ++q);
-	fprintf(stderr, "action=%s\n", action);
-
-
-	/* Ok, now do the right thing */
-
-    }
-    return;
-
-choke:
-    //message(CONSOLE, "Bad entry:");
-    fprintf(stderr, "Bad inittab entry: %s", buf);
-    while (1) sleep(1);
-    
-}
-
-
-extern int init_main(int argc, char **argv)
-{
-    parse_inittab();
-    exit( TRUE);
-}
-
-
-#endif
diff --git a/init/init.c b/init/init.c
index b71c9f7..be04ec3 100644
--- a/init/init.c
+++ b/init/init.c
@@ -23,6 +23,7 @@
 
 #include "internal.h"
 #include <stdio.h>
+#include <string.h>
 #include <stdlib.h>
 #include <stdarg.h>
 #include <unistd.h>
@@ -55,22 +56,57 @@
 #endif
 
 
-#define VT_PRIMARY      "/dev/tty1"	/* Primary virtual console */
-#define VT_SECONDARY    "/dev/tty2"	/* Virtual console */
-#define VT_LOG          "/dev/tty3"	/* Virtual console */
-#define SERIAL_CON0     "/dev/ttyS0"    /* Primary serial console */
-#define SERIAL_CON1     "/dev/ttyS1"    /* Serial console */
-#define GETTY           "/sbin/getty"	/* Default location of getty */
-#define SHELL           "/bin/sh"	/* Default shell */
-#define INITTAB          "/etc/inittab"	/* inittab file location */
-#ifndef BB_INIT_SCRIPT
-#define BB_INIT_SCRIPT	"/etc/init.d/rcS"	/* Initscript. */
-#endif
-
-#if 1
+#define VT_PRIMARY      "/dev/tty1"	  /* Primary virtual console */
+#define VT_SECONDARY    "/dev/tty2"	  /* Virtual console */
+#define VT_LOG          "/dev/tty3"	  /* Virtual console */
+#define SERIAL_CON0     "/dev/ttyS0"      /* Primary serial console */
+#define SERIAL_CON1     "/dev/ttyS1"      /* Serial console */
+#define SHELL           "/bin/sh"	  /* Default shell */
+#define REBOOT          "/sbin/reboot"	  /* Default ctrl-alt-del command */
+#define INITTAB         "/etc/inittab"	  /* inittab file location */
+#define INIT_SCRIPT	"/etc/init.d/rcS" /* Default sysinit script. */
 
 #define LOG             0x1
 #define CONSOLE         0x2
+
+/* Allowed init action types */
+typedef enum {
+    SYSINIT=1,
+    CTRLALTDEL,
+    RESPAWN,
+    ASKFIRST,
+    WAIT,
+    ONCE
+} initActionEnum;
+
+/* And now a list of the actions we support in the version of init */
+typedef struct initActionType{
+    const char*	name;
+    initActionEnum action;
+} initActionType;
+
+static const struct initActionType actions[] = {
+    {"sysinit",     SYSINIT},
+    {"ctrlaltdel",  CTRLALTDEL},
+    {"respawn",     RESPAWN},
+    {"askfirst",    ASKFIRST},
+    {"wait",        WAIT},
+    {"once",        ONCE},
+    {0}
+};
+
+/* Set up a linked list of initactions, to be read from inittab */
+typedef struct initActionTag initAction;
+struct initActionTag {
+    pid_t pid;
+    char process[256];
+    char *console;
+    initAction *nextPtr;
+    initActionEnum action;
+};
+initAction* initActionList = NULL;
+
+
 static char *console = _PATH_CONSOLE;
 static char *second_console = VT_SECONDARY;
 static char *log = VT_LOG;
@@ -100,8 +136,9 @@
  * device may be bitwise-or'd from LOG | CONSOLE */
 void message(int device, char *fmt, ...)
 {
-    int fd;
     va_list arguments;
+    int fd;
+
 #ifdef BB_SYSLOGD
 
     /* Log the message to syslogd */
@@ -298,16 +335,18 @@
 }
 
 
-static pid_t run(const char * const* command, 
+static pid_t run(char* command, 
 	char *terminal, int get_enter)
 {
-    int fd;
+    int i;
     pid_t pid;
-    const char * const* cmd = command+1;
+    char* tmpCmd;
+    char* cmd[255];
     static const char press_enter[] =
 	"\nPlease press Enter to activate this console. ";
 
     if ((pid = fork()) == 0) {
+	int fd;
 	/* Clean up */
 	close(0);
 	close(1);
@@ -321,7 +360,7 @@
 	signal(SIGTERM, SIG_DFL);
 
 	if ((fd = device_open(terminal, O_RDWR)) < 0) {
-	    message(LOG, "Bummer, can't open %s\r\n", terminal);
+	    message(LOG|CONSOLE, "Bummer, can't open %s\r\n", terminal);
 	    exit(-1);
 	}
 	dup(fd);
@@ -340,21 +379,32 @@
 	     */
 	    char c;
 	    message(LOG, "Waiting for enter to start '%s' (pid %d, console %s)\r\n", 
-		    *cmd, getpid(), terminal );
-	    write(1, press_enter, sizeof(press_enter) - 1);
-	    read(0, &c, 1);
+		    command, getpid(), terminal );
+	    write(fileno(stdout), press_enter, sizeof(press_enter) - 1);
+	    read(fileno(stdin), &c, 1);
 	}
 
+	/* Convert command (char*) into cmd (char**, one word per string) */
+	for (tmpCmd=command, i=0; (tmpCmd=strsep(&command, " \t")) != NULL;) {
+	    if (*tmpCmd != '\0') {
+		cmd[i] = tmpCmd;
+		tmpCmd++;
+		i++;
+	    }
+	}
+	cmd[i] = NULL;
+
 	/* Log the process name and args */
-	message(LOG|CONSOLE, "Starting pid %d, console %s: '", getpid(), terminal);
-	while ( *cmd) message(LOG|CONSOLE, "%s ", *cmd++);
-	message(LOG|CONSOLE, "'\r\n");
-	
+	message(LOG, "Starting pid %d, console %s: '%s'\r\n", 
+		getpid(), terminal, cmd[0]);
+
 	/* Now run it.  The new program will take over this PID, 
 	 * so nothing further in init.c should be run. */
-	execvp(*command, (char**)command+1);
+	execvp(cmd[0], cmd);
 
-	message(LOG, "Bummer, could not run '%s'\n", command);
+	/* We're still here?  Some error happened. */
+	message(LOG|CONSOLE, "Bummer, could not run '%s': %s\n", cmd[0],
+		strerror(errno));
 	exit(-1);
     }
     return pid;
@@ -365,15 +415,13 @@
 static void check_memory()
 {
     struct stat statbuf;
-    const char* const swap_on_cmd[] = 
-	    { "/bin/swapon", "swapon", "-a", 0};
 
     if (mem_total() > 3500)
 	return;
 
     if (stat("/etc/fstab", &statbuf) == 0) {
 	/* Try to turn on swap */
-	waitfor(run(swap_on_cmd, log, FALSE));
+	waitfor(run("/bin/swapon swapon -a", log, FALSE));
 	if (mem_total() < 3500)
 	    goto goodnight;
     } else
@@ -385,33 +433,28 @@
 	while (1) sleep(1);
 }
 
+#ifndef DEBUG_INIT
 static void shutdown_system(void)
 {
-    const char* const swap_off_cmd[] = { "swapoff", "swapoff", "-a", 0};
-    const char* const umount_cmd[] = { "umount", "umount", "-a", 0};
-
-#ifndef DEBUG_INIT
     /* Allow Ctrl-Alt-Del to reboot system. */
     reboot(RB_ENABLE_CAD);
-#endif
     message(CONSOLE, "\r\nThe system is going down NOW !!\r\n");
     sync();
+
     /* Send signals to every process _except_ pid 1 */
     message(CONSOLE, "Sending SIGHUP to all processes.\r\n");
-#ifndef DEBUG_INIT
     kill(-1, SIGHUP);
-#endif
     sleep(2);
     sync();
+
     message(CONSOLE, "Sending SIGKILL to all processes.\r\n");
-#ifndef DEBUG_INIT
     kill(-1, SIGKILL);
-#endif
     sleep(1);
+
     message(CONSOLE, "Disabling swap.\r\n");
-    waitfor(run( swap_off_cmd, console, FALSE));
+    waitfor(run( "swapoff -a", console, FALSE));
     message(CONSOLE, "Unmounting filesystems.\r\n");
-    waitfor(run( umount_cmd, console, FALSE));
+    waitfor(run( "umount -a", console, FALSE));
     sync();
     if (kernel_version > 0 && kernel_version <= 2 * 65536 + 2 * 256 + 11) {
 	/* bdflush, kupdate not needed for kernels >2.2.11 */
@@ -427,14 +470,12 @@
     message(CONSOLE,
 	    "The system is halted. Press CTRL-ALT-DEL or turn off power\r\n");
     sync();
-#ifndef DEBUG_INIT
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
     if (sig == SIGUSR2)
 	reboot(RB_POWER_OFF);
     else
 #endif
-	reboot(RB_HALT_SYSTEM);
-#endif
+    reboot(RB_HALT_SYSTEM);
     exit(0);
 }
 
@@ -443,64 +484,157 @@
     shutdown_system();
     message(CONSOLE, "Please stand by while rebooting the system.\r\n");
     sync();
-#ifndef DEBUG_INIT
     reboot(RB_AUTOBOOT);
-#endif
     exit(0);
 }
 
+static void ctrl_alt_del_signal(int sig)
+{
+    initAction* a;
+    /* Run whatever we are supposed to run */
+    for( a=initActionList ; a; a=a->nextPtr) {
+	if (a->action == CTRLALTDEL) {
+	    waitfor(run(a->process, console, FALSE));
+	}
+    }
+}
+#endif
+
+void new_initAction (const struct initActionType *a, 
+	char* process, char* console)
+{
+    initAction* newAction;
+    newAction = calloc ((size_t)(1), sizeof(initAction));
+    if (!newAction) {
+	fprintf(stderr, "Memory allocation failure\n");
+	while (1) sleep(1);
+    }
+    newAction->nextPtr = initActionList;
+    initActionList = newAction;
+    strncpy( newAction->process, process, 255);
+    newAction->action = a->action;
+    newAction->console = console;
+    newAction->pid = 0;
+}
+
+void delete_initAction (initAction *action)
+{
+    initAction *a, *b=NULL;
+    for( a=initActionList ; a; b=a, a=a->nextPtr) {
+	if (a == action && b != NULL) {
+	    b->nextPtr=a->nextPtr;
+	    free( a);
+	    break;
+	}
+    }
+}
+
+void parse_inittab(void) 
+{
+    FILE* file;
+    char buf[256];
+    char *p, *q, *r;
+    const struct initActionType *a = actions;
+    int foundIt;
+
+
+    file = fopen(INITTAB, "r");
+    if (file == NULL) {
+	/* No inittab file -- set up some default behavior */
+
+	/* Askfirst shell on tty1 */
+	new_initAction( &(actions[3]), SHELL, console );
+	/* Askfirst shell on tty2 */
+	if (second_console != NULL) 
+	    new_initAction( &(actions[3]), SHELL, second_console );
+	/* Control-alt-del */
+	new_initAction( &(actions[1]), REBOOT, console );
+	/* sysinit */
+	new_initAction( &(actions[0]), INIT_SCRIPT, console );
+
+	return;
+    }
+
+    while ( fgets(buf, 255, file) != NULL) {
+	foundIt=FALSE;
+	for(p = buf; *p == ' ' || *p == '\t'; p++);
+	if (*p == '#' || *p == '\n') continue;
+
+	/* Trim the trailing \n */
+	q = strrchr( p, '\n');
+	if (q != NULL)
+	    *q='\0';
+
+	/* Skip past the ID field and the runlevel 
+	 * field (both are ignored) */
+	p = strchr( p, ':');
+
+	/* Now peal off the process field from the end
+	 * of the string */
+	q = strrchr( p, ':');
+	if ( q == NULL || *(q+1) == '\0' ) {
+	    fprintf(stderr, "Bad inittab entry: %s\n", buf);
+	    continue;
+	} else {
+	    *q='\0';
+	    ++q;
+	}
+
+	/* Now peal off the action field */
+	r = strrchr( p, ':');
+	if ( r == NULL || *(r+1) == '\0') {
+	    fprintf(stderr, "Bad inittab entry: %s\n", buf);
+	    continue;
+	} else {
+	    ++r;
+	}
+
+	/* Ok, now process it */
+	a = actions;
+	while (a->name != 0) {
+	    if (strcmp(a->name, r) == 0) {
+		new_initAction( a, q, NULL);
+		foundIt=TRUE;
+	    }
+	    a++;
+	}
+	if (foundIt==TRUE)
+	    continue;
+	else {
+	    /* Choke on an unknown action */
+	    fprintf(stderr, "Bad inittab entry: %s\n", buf);
+	}
+    }
+    return;
+}
+
+
 extern int init_main(int argc, char **argv)
 {
-    int run_rc = FALSE;
+    initAction *a;
+    pid_t wpid;
+    int status;
     int single = FALSE;
-    int wait_for_enter_tty1 = TRUE;
-    int wait_for_enter_tty2 = TRUE;
-    pid_t pid1 = 0;
-    pid_t pid2 = 0;
-    struct stat statbuf;
-    char which_vt1[30];
-    char which_vt2[30];
-    const char* const rc_script_command[] = { BB_INIT_SCRIPT, BB_INIT_SCRIPT, 0};
-    const char* const getty1_command[] = { GETTY, GETTY, "38400", which_vt1, 0};
-    const char* const getty2_command[] = { GETTY, GETTY, "38400", which_vt2, 0};
-    const char* const shell_command[] = { SHELL, "-" SHELL, 0};
-    const char* const* tty1_command = shell_command;
-    const char* const* tty2_command = shell_command;
-#ifdef BB_INIT_CMD_IF_RC_SCRIPT_EXITS
-    const char* const rc_exit_command[] = { "BB_INIT_CMD_IF_RC_SCRIPT_EXITS", 
-					    "BB_INIT_CMD_IF_RC_SCRIPT_EXITS", 0 };
-#endif
 
-#ifdef DEBUG_INIT
-    char *hello_msg_format =
-	"init(%d) started:  BusyBox v%s (%s) multi-call binary\r\n";
-#else
-    char *hello_msg_format =
-	"init started:  BusyBox v%s (%s) multi-call binary\r\n";
-#endif
 
-    
 #ifndef DEBUG_INIT
     /* Expect to be PID 1 iff we are run as init (not linuxrc) */
     if (getpid() != 1 && strstr(argv[0], "init")!=NULL ) {
 	usage( "init\n\nInit is the parent of all processes.\n\n"
 		"This version of init is designed to be run only by the kernel\n");
     }
-#endif
 
-    /* Set up sig handlers  -- be sure to
-     * clear all of these in run() */
+    /* Set up sig handlers  -- be sure to clear all of these in run() */
     signal(SIGUSR1, halt_signal);
     signal(SIGUSR2, reboot_signal);
-    signal(SIGINT, reboot_signal);
+    signal(SIGINT, ctrl_alt_del_signal);
     signal(SIGTERM, reboot_signal);
 
     /* Turn off rebooting via CTL-ALT-DEL -- we get a 
      * SIGINT on CAD so we can shut things down gracefully... */
-#ifndef DEBUG_INIT
     reboot(RB_DISABLE_CAD);
 #endif 
-
+    
     /* Figure out where the default console should be */
     console_init();
 
@@ -517,9 +651,13 @@
    
     /* Hello world */
 #ifndef DEBUG_INIT
-    message(CONSOLE|LOG, hello_msg_format, BB_VER, BB_BT);
+    message(CONSOLE|LOG, 
+	    "init started:  BusyBox v%s (%s) multi-call binary\r\n", 
+	    BB_VER, BB_BT);
 #else
-    message(CONSOLE|LOG, hello_msg_format, getpid(), BB_VER, BB_BT);
+    message(CONSOLE|LOG, 
+	    "init(%d) started:  BusyBox v%s (%s) multi-call binary\r\n", 
+	    getpid(), BB_VER, BB_BT);
 #endif
 
     
@@ -537,150 +675,77 @@
     if ( argc > 1 && (!strcmp(argv[1], "single") || 
 		!strcmp(argv[1], "-s") || !strcmp(argv[1], "1"))) {
 	single = TRUE;
-	tty1_command = shell_command;
-	tty2_command = shell_command;
+	/* Ask first then start a shell on tty2 */
+	if (second_console != NULL) 
+	    new_initAction( &(actions[3]), SHELL, second_console);
+	/* Ask first then start a shell on tty1 */
+	new_initAction( &(actions[3]), SHELL, console);
+    } else {
+	/* Not in single user mode -- see what inittab says */
+	parse_inittab();
     }
 
-    /* Make sure an init script exists before trying to run it */
-    if (single==FALSE && stat(BB_INIT_SCRIPT, &statbuf)==0) {
-	run_rc = TRUE;
-	wait_for_enter_tty1 = FALSE;
-	tty1_command = rc_script_command;
-    }
-    
-    /* Make sure /sbin/getty exists before trying to run it */
-    if (stat(GETTY, &statbuf)==0) {
-	char* where;
-	/* First do tty2 */
-	wait_for_enter_tty2 = FALSE;
-	where = strrchr( second_console, '/');
-	if ( where != NULL) {
-	    where++;
-	    strncpy( which_vt2, where, sizeof(which_vt2));
-	}
-	tty2_command = getty2_command;
+    /* Now run everything that needs to be run */
 
-	/* Check on hooking a getty onto tty1 */
-	if (run_rc == FALSE && single==FALSE) {
-	    wait_for_enter_tty1 = FALSE;
-	    where = strrchr( console, '/');
-	    if ( where != NULL) {
-		where++;
-		strncpy( which_vt1, where, sizeof(which_vt1));
-	    }
-	    tty1_command = getty1_command;
+    /* First run sysinit */
+    for( a=initActionList ; a; a=a->nextPtr) {
+	if (a->action == SYSINIT) {
+	    waitfor(run(a->process, console, FALSE));
+	    /* Now remove the "sysinit" entry from the list */
+	    delete_initAction( a);
 	}
     }
-    
+    /* Next run anything that wants to block */
+    for( a=initActionList ; a; a=a->nextPtr) {
+	if (a->action == WAIT) {
+	    waitfor(run(a->process, console, FALSE));
+	    /* Now remove the "wait" entry from the list */
+	    delete_initAction( a);
+	}
+    }
+    /* Next run anything to be run only once */
+    for( a=initActionList ; a; a=a->nextPtr) {
+	if (a->action == ONCE) {
+	    run(a->process, console, FALSE);
+	    /* Now remove the "once" entry from the list */
+	    delete_initAction( a);
+	}
+    }
 
-    /* Ok, now launch the tty1_command and tty2_command */
+    /* Now run the looping stuff */
     for (;;) {
-	pid_t wpid;
-	int status;
+	for( a=initActionList ; a; a=a->nextPtr) {
+	    /* Only run stuff with pid==0.  If they have
+	     * a pid, that means they are still running */
+	    if (a->pid == 0) {
+		switch(a->action) {
+		    case RESPAWN:
+			/* run the respawn stuff */
+			a->pid = run(a->process, console, FALSE);
+			break;
+		    case ASKFIRST:
+			/* run the askfirst stuff */
+			a->pid = waitfor(run(a->process, console, TRUE));
+			break;
+		    /* silence the compiler's whining */
+		    default:
+			break;
+		}
+	    }
+	}
 
-	if (pid1 == 0 && tty1_command) {
-	    pid1 = run(tty1_command, console, wait_for_enter_tty1);
-	}
-#ifdef BB_FEATURE_INIT_SECOND_CONSOLE
-	if (pid2 == 0 && tty2_command && second_console) {
-	    pid2 = run(tty2_command, second_console, wait_for_enter_tty2);
-	}
-#endif
 	wpid = wait(&status);
+	/* Find out who died and clean up their corpse */
 	if (wpid > 0 ) {
 	    message(LOG, "pid %d exited, status=%x.\n", wpid, status);
-	}
-	/* Don't respawn init script if it exits */
-	if (wpid == pid1) {
-	    if (run_rc == FALSE) {
-		pid1 = 0;
+	    for( a=initActionList ; a; a=a->nextPtr) {
+		if (a->pid==wpid) {
+		    a->pid=0;
+		}
 	    }
-#ifdef BB_INIT_CMD_IF_RC_SCRIPT_EXITS
-	    else {
-		pid1 = 0;
-		run_rc=FALSE;
-		wait_for_enter_tty1=TRUE;
-		tty1_command=rc_exit_command;
-	    }
-#endif
 	}
-#ifdef BB_FEATURE_INIT_SECOND_CONSOLE
-	if (wpid == pid2) {
-	    pid2 = 0;
-	}
-#endif
+
 	sleep(1);
     }
 }
 
-#else
-
-
-void parse_inittab(void) 
-{
-    FILE* file;
-    char buf[256];
-    char action[256]="";
-    char process[256]="";
-    char *p, *q;
-
-
-    if ((file = fopen(INITTAB, "r")) < 0) {
-	/* No inittab file -- set up some default behavior */
-
-	/* FIXME */
-	return;
-    }
-
-    while ( fgets(buf, 255, file) != NULL) {
-	for(p = buf; *p == ' ' || *p == '\t'; p++);
-	if (*p == '#' || *p == '\n') continue;
-
-	/* Trim the trailing \n */
-	q = strrchr( p, '\n');
-	if (q != NULL)
-	    *q='\0';
-
-	/* Skip past the ID field and the runlevel 
-	 * field (both are ignored) */
-	p = strchr( p, ':');
-
-	/* Now peal off the process field from the end
-	 * of the string */
-	q = strrchr( p, ':');
-	if ( q == NULL || q+1 == NULL)
-	    goto choke;
-	*q='\0';
-	strcpy( process, ++q);
-	fprintf(stderr, "process=%s\n", process);
-
-	
-	/* Now peal off the action field */
-	q = strrchr( p, ':');
-	if ( q == NULL || q+1 == NULL)
-	    goto choke;
-	strcpy( action, ++q);
-	fprintf(stderr, "action=%s\n", action);
-
-
-	/* Ok, now do the right thing */
-
-    }
-    return;
-
-choke:
-    //message(CONSOLE, "Bad entry:");
-    fprintf(stderr, "Bad inittab entry: %s", buf);
-    while (1) sleep(1);
-    
-}
-
-
-extern int init_main(int argc, char **argv)
-{
-    parse_inittab();
-    exit( TRUE);
-}
-
-
-#endif
diff --git a/internal.h b/internal.h
index 1e42982..6804e2d 100644
--- a/internal.h
+++ b/internal.h
@@ -169,6 +169,9 @@
 extern long getNum (const char *cp);
 extern pid_t findInitPid();
 
+#if (__GLIBC__ < 2) && defined BB_SYSLOGD
+extern int vdprintf(int d, const char *format, va_list ap);
+#endif
 
 #if defined BB_MTAB
 #define whine_if_fstab_is_missing() {} 
diff --git a/kill.c b/kill.c
index 0ba6d76..e72b734 100644
--- a/kill.c
+++ b/kill.c
@@ -183,7 +183,7 @@
 
 do_it_now:
 
-    while (argc >= 1) {
+    while (--argc >= 0) {
         int pid;
 	struct stat statbuf;
 	char pidpath[20]="/proc/";
@@ -198,6 +198,7 @@
             fprintf(stderr, "kill: (%d) - No such pid\n", pid);
             exit( FALSE);
 	}
+	fprintf(stderr, "sig = %d\n", sig);
         if (kill (pid, sig) != 0) {
             perror (*argv);
             exit ( FALSE);
diff --git a/procps/kill.c b/procps/kill.c
index 0ba6d76..e72b734 100644
--- a/procps/kill.c
+++ b/procps/kill.c
@@ -183,7 +183,7 @@
 
 do_it_now:
 
-    while (argc >= 1) {
+    while (--argc >= 0) {
         int pid;
 	struct stat statbuf;
 	char pidpath[20]="/proc/";
@@ -198,6 +198,7 @@
             fprintf(stderr, "kill: (%d) - No such pid\n", pid);
             exit( FALSE);
 	}
+	fprintf(stderr, "sig = %d\n", sig);
         if (kill (pid, sig) != 0) {
             perror (*argv);
             exit ( FALSE);
diff --git a/sed.c b/sed.c
index 8e5f695..2577724 100644
--- a/sed.c
+++ b/sed.c
@@ -46,7 +46,7 @@
     "\t  /REGEXP/  Match specified regexp\n"
     "\t  (! inverts the meaning of the match)\n\n"
     "\tand COMMAND can be:\n"
-    "\t  s/regexp/replacement/[gp]\n"
+    "\t  s/regexp/replacement/[igp]\n"
     "\t     which attempt to match regexp against the pattern space\n"
     "\t     and if successful replaces the matched portion with replacement.\n\n"
     "\t  aTEXT\n"
diff --git a/tar.c b/tar.c
index 7167d95..a53370e 100644
--- a/tar.c
+++ b/tar.c
@@ -37,6 +37,7 @@
 #include <fcntl.h>
 #include <signal.h>
 #include <time.h>
+#include <utime.h>
 #include <sys/types.h>
 #include <sys/sysmacros.h>
 
@@ -106,8 +107,12 @@
 static int eofFlag;
 static long dataCc;
 static int outFd;
-static char outName[TAR_NAME_SIZE];
+static const char *outName;
 
+static int mode;
+static int uid;
+static int gid;
+static time_t mtime;
 
 /*
  * Static data associated with the tar file.
@@ -364,8 +369,9 @@
      * message is required on errors.
      */
     if (tostdoutFlag == FALSE) {
-	if (outFd >= 0)
-	    (void) close (outFd);
+	if (outFd >= 0) {
+	    close (outFd);
+	}
     }
 }
 
@@ -378,29 +384,25 @@
 static void
 readHeader (const TarHeader * hp, int fileCount, char **fileTable)
 {
-    int mode;
-    int uid;
-    int gid;
     int checkSum;
-    unsigned int major;
-    unsigned int minor;
-    long size;
-    time_t mtime;
-    const char *name;
     int cc;
     int hardLink;
     int softLink;
     int devFileFlag;
+    unsigned int major;
+    unsigned int minor;
+    long size;
+    struct utimbuf utb;
 
     /* 
      * If the block is completely empty, then this is the end of the
      * archive file.  If the name is null, then just skip this header.
      */
-    name = hp->name;
+    outName = hp->name;
 
-    if (*name == '\0') {
+    if (*outName == '\0') {
 	for (cc = TAR_BLOCK_SIZE; cc > 0; cc--) {
-	    if (*name++)
+	    if (*outName++)
 		return;
 	}
 
@@ -447,16 +449,16 @@
     /* 
      * Check for a directory.
      */
-    if (name[strlen (name) - 1] == '/')
+    if (outName[strlen (outName) - 1] == '/')
 	mode |= S_IFDIR;
 
     /* 
      * Check for absolute paths in the file.
      * If we find any, then warn the user and make them relative.
      */
-    if (*name == '/') {
-	while (*name == '/')
-	    name++;
+    if (*outName == '/') {
+	while (*outName == '/')
+	    outName++;
 
 	if (warnedRoot==FALSE) {
 	    fprintf (stderr,
@@ -470,7 +472,7 @@
      * See if we want this file to be restored.
      * If not, then set up to skip it.
      */
-    if (wantFileName (name, fileCount, fileTable) == FALSE) {
+    if (wantFileName (outName, fileCount, fileTable) == FALSE) {
 	if ( !hardLink && !softLink && (S_ISREG (mode) || S_ISCHR (mode)
 		    || S_ISBLK (mode) || S_ISSOCK(mode) || S_ISFIFO(mode) ) ) {
 	    inHeader = (size == 0)? TRUE : FALSE;
@@ -494,7 +496,7 @@
 	    else
 		printf ("%9ld %s ", size, timeString (mtime));
 	}
-	printf ("%s", name);
+	printf ("%s", outName);
 
 	if (hardLink)
 	    printf (" (link to \"%s\")", hp->linkName);
@@ -515,22 +517,35 @@
      * We really want to extract the file.
      */
     if (verboseFlag==TRUE)
-	printf ("x %s\n", name);
+	printf ("x %s\n", outName);
 
     if (hardLink) {
-	if (link (hp->linkName, name) < 0)
-	    perror (name);
-	chown(name, uid, gid);
-	chmod(name, mode);
+	if (link (hp->linkName, outName) < 0)
+	    perror (outName);
+	/* Set the file time */
+	utb.actime = mtime;
+	utb.modtime = mtime;
+	utime (outName, &utb);
+	/* Set the file permissions */
+	chown(outName, uid, gid);
+	chmod(outName, mode);
 	return;
     }
 
     if (softLink) {
 #ifdef	S_ISLNK
-	if (symlink (hp->linkName, name) < 0)
-	    perror (name);
-	chown(name, uid, gid);
-	chmod(name, mode);
+	if (symlink (hp->linkName, outName) < 0)
+	    perror (outName);
+	/* Try to change ownership of the symlink.
+	 * If libs doesn't support that, don't bother.
+	 * Changing the pointed-to file is the Wrong Thing(tm).
+	 */
+#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1)
+	lchown(outName, uid, gid);
+#endif
+
+	/* Do not change permissions or date on symlink,
+	 * since it changes the pointed to file instead.  duh. */
 #else
 	fprintf (stderr, "Cannot create symbolic links\n");
 #endif
@@ -545,10 +560,14 @@
      * If the file is a directory, then just create the path.
      */
     if (S_ISDIR (mode)) {
-	createPath (name, mode);
-	chown(name, uid, gid);
-	chmod(name, mode);
-
+	createPath (outName, mode);
+	/* Set the file time */
+	utb.actime = mtime;
+	utb.modtime = mtime;
+	utime (outName, &utb);
+	/* Set the file permissions */
+	chown(outName, uid, gid);
+	chmod(outName, mode);
 	return;
     }
 
@@ -556,7 +575,7 @@
      * There is a file to write.
      * First create the path to it if necessary with default permissions.
      */
-    createPath (name, 0777);
+    createPath (outName, 0777);
 
     inHeader = (size == 0)? TRUE : FALSE;
     dataCc = size;
@@ -569,21 +588,26 @@
     else {
 	if ( S_ISCHR(mode) || S_ISBLK(mode) || S_ISSOCK(mode) ) {
 	    devFileFlag = TRUE;
-	    outFd = mknod (name, mode, makedev(major, minor) );
+	    outFd = mknod (outName, mode, makedev(major, minor) );
 	}
 	else if (S_ISFIFO(mode) ) {
 	    devFileFlag = TRUE;
-	    outFd = mkfifo(name, mode);
+	    outFd = mkfifo(outName, mode);
 	} else {
-	    outFd = open (name, O_WRONLY | O_CREAT | O_TRUNC, mode);
+	    outFd = open (outName, O_WRONLY | O_CREAT | O_TRUNC, mode);
 	}
 	if (outFd < 0) {
-	    perror (name);
+	    perror (outName);
 	    skipFileFlag = TRUE;
 	    return;
 	}
-	chown(name, uid, gid);
-	chmod(name, mode);
+	/* Set the file time */
+	utb.actime = mtime;
+	utb.modtime = mtime;
+	utime (outName, &utb);
+	/* Set the file permissions */
+	chown(outName, uid, gid);
+	chmod(outName, mode);
     }
 
 
@@ -591,7 +615,7 @@
      * If the file is empty, then that's all we need to do.
      */
     if (size == 0 && (tostdoutFlag == FALSE) && (devFileFlag == FALSE)) {
-	(void) close (outFd);
+	close (outFd);
 	outFd = -1;
     }
 }
@@ -625,7 +649,7 @@
     if (fullWrite (outFd, cp, count) < 0) {
 	perror (outName);
 	if (tostdoutFlag == FALSE) {
-	    (void) close (outFd);
+	    close (outFd);
 	    outFd = -1;
 	}
 	skipFileFlag = TRUE;
@@ -633,13 +657,21 @@
     }
 
     /* 
-     * If the write failed, close the file and disable further
-     * writes to this file.
+     * Check if we are done writing to the file now.
      */
     if (dataCc <= 0 && tostdoutFlag == FALSE) {
+	struct utimbuf utb;
 	if (close (outFd))
 	    perror (outName);
 
+	/* Set the file time */
+	utb.actime = mtime;
+	utb.modtime = mtime;
+	utime (outName, &utb);
+	/* Set the file permissions */
+	chown(outName, uid, gid);
+	chmod(outName, mode);
+
 	outFd = -1;
     }
 }
@@ -720,7 +752,6 @@
 static void saveFile (const char *fileName, int seeLinks)
 {
     int status;
-    int mode;
     struct stat statbuf;
 
     if (verboseFlag==TRUE)
diff --git a/utility.c b/utility.c
index 2a840f7..c20025c 100644
--- a/utility.c
+++ b/utility.c
@@ -379,7 +379,7 @@
 #endif
 
 
-#if defined (BB_CHOWN) || defined (BB_CP) || defined (BB_FIND) || defined (BB_LS) || defined (BB_INSMOD)
+#if defined (BB_CHMOD_CHOWN_CHGRP) || defined (BB_CP) || defined (BB_FIND) || defined (BB_LS) || defined (BB_INSMOD)
 /*
  * Walk down all the directories under the specified 
  * location, and do something (something specified
@@ -969,7 +969,7 @@
 
 
 
-#if defined BB_DF | defined BB_MTAB
+#if defined BB_DF || defined BB_MTAB
 /*
  * Given a block device, find the mount table entry if that block device
  * is mounted.
@@ -1008,7 +1008,6 @@
     endmntent(mountTable);
     return mountEntry;
 }
-
 #endif
 
 
@@ -1111,4 +1110,15 @@
 }
 #endif
 
+#if (__GLIBC__ < 2) && (defined BB_SYSLOGD || defined BB_INIT)
+extern int vdprintf(int d, const char *format, va_list ap)
+{
+    char buf[BUF_SIZE];
+    int len;
+
+    len = vsprintf(buf, format, ap);
+    return write(d, buf, len);
+}
+#endif
+
 /* END CODE */