Fixed the init problem where it wouldn't unmount filesystems
on reboot.  Also fixed swapoff -a so it works.
 -Erik
diff --git a/Changelog b/Changelog
index 7ecc4fb..42ec296 100644
--- a/Changelog
+++ b/Changelog
@@ -84,6 +84,8 @@
 	    - `fdflush', `length' and `printf' crashed when run without arguments
 	    - `fdflush' tried to flush itself using *argv
 	    - added "skip" and "seek" to dd.
+	* swapoff -a was not working.  Now it is.
+	* init did not cleanly unmount filesystems on reboot.  Now it does.
 
 
 	-Erik Andersen
diff --git a/Makefile b/Makefile
index 490d393..6543e1f 100644
--- a/Makefile
+++ b/Makefile
@@ -62,7 +62,7 @@
 
 # -D_GNU_SOURCE is needed because environ is used in init.c
 ifeq ($(DODEBUG),true)
-    CFLAGS += -Wall -g -D_GNU_SOURCE -DDEBUG_INIT
+    CFLAGS += -Wall -g -D_GNU_SOURCE
     STRIP   =
     LDFLAGS =
 else
diff --git a/busybox.def.h b/busybox.def.h
index f8c6e6e..e2f5dd3 100644
--- a/busybox.def.h
+++ b/busybox.def.h
@@ -59,7 +59,6 @@
 #define BB_MOUNT
 #define BB_NFSMOUNT
 //#define BB_MT
-//#define BB_MTAB
 #define BB_NSLOOKUP
 #define BB_PING
 #define BB_POWEROFF
diff --git a/init.c b/init.c
index 899dca4..2f2203b 100644
--- a/init.c
+++ b/init.c
@@ -22,6 +22,11 @@
  *
  */
 
+/* Turn this on to disable all the dangerous 
+   rebooting stuff when debugging.
+#define DEBUG_INIT
+*/
+
 #include "internal.h"
 #include <stdio.h>
 #include <string.h>
@@ -78,7 +83,8 @@
 	RESPAWN,
 	ASKFIRST,
 	WAIT,
-	ONCE
+	ONCE,
+	CTRLALTDEL
 } initActionEnum;
 
 /* And now a list of the actions we support in the version of init */
@@ -93,6 +99,7 @@
 	{"askfirst", ASKFIRST},
 	{"wait", WAIT},
 	{"once", ONCE},
+	{"ctrlaltdel", CTRLALTDEL},
 	{0}
 };
 
@@ -113,6 +120,7 @@
 static int kernelVersion = 0;
 static char termType[32] = "TERM=ansi";
 static char console[32] = _PATH_CONSOLE;
+static void delete_initAction(initAction * action);
 
 
 /* print a message to the specified device:
@@ -131,8 +139,8 @@
 		va_start(arguments, fmt);
 		vsnprintf(msg, sizeof(msg), fmt, arguments);
 		va_end(arguments);
-		openlog("init", 0, LOG_DAEMON);
-		syslog(LOG_DAEMON | LOG_NOTICE, msg);
+		openlog("init", 0, LOG_USER);
+		syslog(LOG_USER|LOG_INFO, msg);
 		closelog();
 	}
 #else
@@ -146,11 +154,12 @@
 			log_fd = -2;
 			/* log to main console instead */
 			device = CONSOLE;
-		} else if ((log_fd = device_open(log, O_RDWR | O_NDELAY)) < 0) {
-			log_fd = -1;
+		} else if ((log_fd = device_open(log, O_RDWR|O_NDELAY)) < 0) {
+			log_fd = -2;
 			fprintf(stderr, "Bummer, can't write to log on %s!\r\n", log);
 			fflush(stderr);
-			return;
+			log = NULL;
+			device = CONSOLE;
 		}
 	}
 	if ((device & LOG) && (log_fd >= 0)) {
@@ -303,10 +312,10 @@
 		/* check for serial console and disable logging to tty3 & running a
 		   * shell to tty2 */
 		if (ioctl(0, TIOCGSERIAL, &sr) == 0) {
-			message(LOG | CONSOLE,
-					"serial console detected.  Disabling virtual terminals.\r\n");
 			log = NULL;
 			secondConsole = NULL;
+			message(LOG | CONSOLE,
+					"serial console detected.  Disabling virtual terminals.\r\n");
 		}
 		close(fd);
 	}
@@ -319,6 +328,7 @@
 	pid_t pid;
 	char *tmpCmd;
 	char *cmd[255];
+	char buf[255];
 	static const char press_enter[] =
 
 		"\nPlease press Enter to activate this console. ";
@@ -333,7 +343,9 @@
 
 
 	if ((pid = fork()) == 0) {
+#ifdef DEBUG_INIT
 		pid_t shell_pgid = getpid();
+#endif
 
 		/* Clean up */
 		close(0);
@@ -369,30 +381,40 @@
 			 */
 			char c;
 
+#ifdef DEBUG_INIT
 			message(LOG, "Waiting for enter to start '%s' (pid %d, console %s)\r\n",
 					command, shell_pgid, terminal);
+#endif
 			write(fileno(stdout), press_enter, sizeof(press_enter) - 1);
 			read(fileno(stdin), &c, 1);
 		}
 
-		/* Log the process name and args */
-		message(LOG, "Starting pid %d, console %s: '",
-				shell_pgid, terminal, command);
-
-		/* 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;
 #ifdef DEBUG_INIT
-				message(LOG, "%s ", tmpCmd);
+		/* Log the process name and args */
+		message(LOG, "Starting pid %d, console %s: '%s'\r\n",
+				shell_pgid, terminal, command);
 #endif
-				tmpCmd++;
-				i++;
+
+		/* See if any special /bin/sh requiring characters are present */
+		if (strpbrk(command, "~`!$^&*()=|\\{}[];\"'<>?") != NULL) {
+			cmd[0] = SHELL;
+			cmd[1] = "-c";
+			strcpy(buf, "exec ");
+			strncat(buf, command, sizeof(buf) - strlen(buf) - 1);
+			cmd[2] = buf;
+			cmd[3] = NULL;
+		} else {
+			/* 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;
 		}
-		cmd[i] = NULL;
-		message(LOG, "'\r\n");
 
 		/* Now run it.  The new program will take over this PID, 
 		 * so nothing further in init.c should be run. */
@@ -413,9 +435,8 @@
 
 	while (1) {
 		wpid = wait(&status);
-		if (wpid > 0) {
-			message(LOG, "Process '%s' (pid %d) exited.\n", command, wpid);
-			break;
+		if (wpid > 0 && wpid != pid) {
+			continue;
 		}
 		if (wpid == pid)
 			break;
@@ -424,7 +445,7 @@
 }
 
 /* Make sure there is enough memory to do something useful. *
- * Calls swapon if needed so be sure /proc is mounted. */
+ * Calls "swapon -a" if needed so be sure /etc/fstab is present... */
 static void check_memory()
 {
 	struct stat statBuf;
@@ -434,7 +455,7 @@
 
 	if (stat("/etc/fstab", &statBuf) == 0) {
 		/* Try to turn on swap */
-		waitfor("/bin/swapon swapon -a", log, FALSE);
+		system("/sbin/swapon swapon -a");
 		if (mem_total() < 3500)
 			goto goodnight;
 	} else
@@ -448,31 +469,45 @@
 		sleep(1);
 }
 
+/* Run all commands to be run right before halt/reboot */
+static void run_lastAction(void)
+{
+	initAction *a;
+	for (a = initActionList; a; a = a->nextPtr) {
+		if (a->action == CTRLALTDEL) {
+			waitfor(a->process, a->console, FALSE);
+			delete_initAction(a);
+		}
+	}
+}
+
+
 #ifndef DEBUG_INIT
 static void shutdown_system(void)
 {
+
 	/* first disable our SIGHUP signal */
 	signal(SIGHUP, SIG_DFL);
 
 	/* Allow Ctrl-Alt-Del to reboot system. */
 	reboot(RB_ENABLE_CAD);
-	message(CONSOLE, "\r\nThe system is going down NOW !!\r\n");
+
+	message(CONSOLE|LOG, "\r\nThe system is going down NOW !!\r\n");
 	sync();
 
 	/* Send signals to every process _except_ pid 1 */
-	message(CONSOLE, "Sending SIGTERM to all processes.\r\n");
+	message(CONSOLE|LOG, "Sending SIGTERM to all processes.\r\n");
 	kill(-1, SIGTERM);
-	sleep(5);
+	sleep(1);
 	sync();
 
-	message(CONSOLE, "Sending SIGKILL to all processes.\r\n");
+	message(CONSOLE|LOG, "Sending SIGKILL to all processes.\r\n");
 	kill(-1, SIGKILL);
-	sleep(5);
+	sleep(1);
 
-	message(CONSOLE, "Disabling swap.\r\n");
-	waitfor("swapoff -a", console, FALSE);
-	message(CONSOLE, "Unmounting filesystems.\r\n");
-	waitfor("umount -a -r", console, FALSE);
+	/* run everything to be run at "ctrlaltdel" */
+	run_lastAction();
+
 	sync();
 	if (kernelVersion > 0 && kernelVersion <= 2 * 65536 + 2 * 256 + 11) {
 		/* bdflush, kupdate not needed for kernels >2.2.11 */
@@ -484,14 +519,14 @@
 static void halt_signal(int sig)
 {
 	shutdown_system();
-	message(CONSOLE,
+	message(CONSOLE|LOG,
 			"The system is halted. Press %s or turn off power\r\n",
 			(secondConsole == NULL)	/* serial console */
 			? "Reset" : "CTRL-ALT-DEL");
 	sync();
 
 	/* allow time for last message to reach serial console */
-	sleep(5);
+	sleep(2);
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
 	if (sig == SIGUSR2)
@@ -505,7 +540,7 @@
 static void reboot_signal(int sig)
 {
 	shutdown_system();
-	message(CONSOLE, "Please stand by while rebooting the system.\r\n");
+	message(CONSOLE|LOG, "Please stand by while rebooting the system.\r\n");
 	sync();
 
 	/* allow time for last message to reach serial console */
@@ -631,7 +666,7 @@
 //      newAction->process, newAction->action, newAction->console);
 }
 
-void delete_initAction(initAction * action)
+static void delete_initAction(initAction * action)
 {
 	initAction *a, *b = NULL;
 
@@ -669,6 +704,10 @@
 	if (file == NULL) {
 		/* No inittab file -- set up some default behavior */
 #endif
+		/* Swapoff on halt/reboot */
+		new_initAction(CTRLALTDEL, "/bin/umount -a -r > /dev/null 2>&1", console);
+		/* Umount all filesystems on halt/reboot */
+		new_initAction(CTRLALTDEL, "/bin/umount -a -r > /dev/null 2>&1", console);
 		/* Askfirst shell on tty1 */
 		new_initAction(ASKFIRST, SHELL, console);
 		/* Askfirst shell on tty2 */
@@ -756,6 +795,8 @@
 #endif
 }
 
+
+
 extern int init_main(int argc, char **argv)
 {
 	initAction *a;
@@ -768,9 +809,6 @@
 		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");
 	}
-	/* Fix up argv[0] to be certain we claim to be init */
-	strncpy(argv[0], "init", strlen(argv[0]));
-
 	/* Set up sig handlers  -- be sure to
 	 * clear all of these in run() */
 	signal(SIGUSR1, halt_signal);
@@ -838,6 +876,10 @@
 		 * of "askfirst" shells */
 		parse_inittab();
 	}
+	
+	/* Fix up argv[0] to be certain we claim to be init */
+	strncpy(argv[0], "init", strlen(argv[0])+1);
+	strncpy(argv[1], "\0", strlen(argv[1])+1);
 
 	/* Now run everything that needs to be run */
 
diff --git a/init/init.c b/init/init.c
index 899dca4..2f2203b 100644
--- a/init/init.c
+++ b/init/init.c
@@ -22,6 +22,11 @@
  *
  */
 
+/* Turn this on to disable all the dangerous 
+   rebooting stuff when debugging.
+#define DEBUG_INIT
+*/
+
 #include "internal.h"
 #include <stdio.h>
 #include <string.h>
@@ -78,7 +83,8 @@
 	RESPAWN,
 	ASKFIRST,
 	WAIT,
-	ONCE
+	ONCE,
+	CTRLALTDEL
 } initActionEnum;
 
 /* And now a list of the actions we support in the version of init */
@@ -93,6 +99,7 @@
 	{"askfirst", ASKFIRST},
 	{"wait", WAIT},
 	{"once", ONCE},
+	{"ctrlaltdel", CTRLALTDEL},
 	{0}
 };
 
@@ -113,6 +120,7 @@
 static int kernelVersion = 0;
 static char termType[32] = "TERM=ansi";
 static char console[32] = _PATH_CONSOLE;
+static void delete_initAction(initAction * action);
 
 
 /* print a message to the specified device:
@@ -131,8 +139,8 @@
 		va_start(arguments, fmt);
 		vsnprintf(msg, sizeof(msg), fmt, arguments);
 		va_end(arguments);
-		openlog("init", 0, LOG_DAEMON);
-		syslog(LOG_DAEMON | LOG_NOTICE, msg);
+		openlog("init", 0, LOG_USER);
+		syslog(LOG_USER|LOG_INFO, msg);
 		closelog();
 	}
 #else
@@ -146,11 +154,12 @@
 			log_fd = -2;
 			/* log to main console instead */
 			device = CONSOLE;
-		} else if ((log_fd = device_open(log, O_RDWR | O_NDELAY)) < 0) {
-			log_fd = -1;
+		} else if ((log_fd = device_open(log, O_RDWR|O_NDELAY)) < 0) {
+			log_fd = -2;
 			fprintf(stderr, "Bummer, can't write to log on %s!\r\n", log);
 			fflush(stderr);
-			return;
+			log = NULL;
+			device = CONSOLE;
 		}
 	}
 	if ((device & LOG) && (log_fd >= 0)) {
@@ -303,10 +312,10 @@
 		/* check for serial console and disable logging to tty3 & running a
 		   * shell to tty2 */
 		if (ioctl(0, TIOCGSERIAL, &sr) == 0) {
-			message(LOG | CONSOLE,
-					"serial console detected.  Disabling virtual terminals.\r\n");
 			log = NULL;
 			secondConsole = NULL;
+			message(LOG | CONSOLE,
+					"serial console detected.  Disabling virtual terminals.\r\n");
 		}
 		close(fd);
 	}
@@ -319,6 +328,7 @@
 	pid_t pid;
 	char *tmpCmd;
 	char *cmd[255];
+	char buf[255];
 	static const char press_enter[] =
 
 		"\nPlease press Enter to activate this console. ";
@@ -333,7 +343,9 @@
 
 
 	if ((pid = fork()) == 0) {
+#ifdef DEBUG_INIT
 		pid_t shell_pgid = getpid();
+#endif
 
 		/* Clean up */
 		close(0);
@@ -369,30 +381,40 @@
 			 */
 			char c;
 
+#ifdef DEBUG_INIT
 			message(LOG, "Waiting for enter to start '%s' (pid %d, console %s)\r\n",
 					command, shell_pgid, terminal);
+#endif
 			write(fileno(stdout), press_enter, sizeof(press_enter) - 1);
 			read(fileno(stdin), &c, 1);
 		}
 
-		/* Log the process name and args */
-		message(LOG, "Starting pid %d, console %s: '",
-				shell_pgid, terminal, command);
-
-		/* 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;
 #ifdef DEBUG_INIT
-				message(LOG, "%s ", tmpCmd);
+		/* Log the process name and args */
+		message(LOG, "Starting pid %d, console %s: '%s'\r\n",
+				shell_pgid, terminal, command);
 #endif
-				tmpCmd++;
-				i++;
+
+		/* See if any special /bin/sh requiring characters are present */
+		if (strpbrk(command, "~`!$^&*()=|\\{}[];\"'<>?") != NULL) {
+			cmd[0] = SHELL;
+			cmd[1] = "-c";
+			strcpy(buf, "exec ");
+			strncat(buf, command, sizeof(buf) - strlen(buf) - 1);
+			cmd[2] = buf;
+			cmd[3] = NULL;
+		} else {
+			/* 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;
 		}
-		cmd[i] = NULL;
-		message(LOG, "'\r\n");
 
 		/* Now run it.  The new program will take over this PID, 
 		 * so nothing further in init.c should be run. */
@@ -413,9 +435,8 @@
 
 	while (1) {
 		wpid = wait(&status);
-		if (wpid > 0) {
-			message(LOG, "Process '%s' (pid %d) exited.\n", command, wpid);
-			break;
+		if (wpid > 0 && wpid != pid) {
+			continue;
 		}
 		if (wpid == pid)
 			break;
@@ -424,7 +445,7 @@
 }
 
 /* Make sure there is enough memory to do something useful. *
- * Calls swapon if needed so be sure /proc is mounted. */
+ * Calls "swapon -a" if needed so be sure /etc/fstab is present... */
 static void check_memory()
 {
 	struct stat statBuf;
@@ -434,7 +455,7 @@
 
 	if (stat("/etc/fstab", &statBuf) == 0) {
 		/* Try to turn on swap */
-		waitfor("/bin/swapon swapon -a", log, FALSE);
+		system("/sbin/swapon swapon -a");
 		if (mem_total() < 3500)
 			goto goodnight;
 	} else
@@ -448,31 +469,45 @@
 		sleep(1);
 }
 
+/* Run all commands to be run right before halt/reboot */
+static void run_lastAction(void)
+{
+	initAction *a;
+	for (a = initActionList; a; a = a->nextPtr) {
+		if (a->action == CTRLALTDEL) {
+			waitfor(a->process, a->console, FALSE);
+			delete_initAction(a);
+		}
+	}
+}
+
+
 #ifndef DEBUG_INIT
 static void shutdown_system(void)
 {
+
 	/* first disable our SIGHUP signal */
 	signal(SIGHUP, SIG_DFL);
 
 	/* Allow Ctrl-Alt-Del to reboot system. */
 	reboot(RB_ENABLE_CAD);
-	message(CONSOLE, "\r\nThe system is going down NOW !!\r\n");
+
+	message(CONSOLE|LOG, "\r\nThe system is going down NOW !!\r\n");
 	sync();
 
 	/* Send signals to every process _except_ pid 1 */
-	message(CONSOLE, "Sending SIGTERM to all processes.\r\n");
+	message(CONSOLE|LOG, "Sending SIGTERM to all processes.\r\n");
 	kill(-1, SIGTERM);
-	sleep(5);
+	sleep(1);
 	sync();
 
-	message(CONSOLE, "Sending SIGKILL to all processes.\r\n");
+	message(CONSOLE|LOG, "Sending SIGKILL to all processes.\r\n");
 	kill(-1, SIGKILL);
-	sleep(5);
+	sleep(1);
 
-	message(CONSOLE, "Disabling swap.\r\n");
-	waitfor("swapoff -a", console, FALSE);
-	message(CONSOLE, "Unmounting filesystems.\r\n");
-	waitfor("umount -a -r", console, FALSE);
+	/* run everything to be run at "ctrlaltdel" */
+	run_lastAction();
+
 	sync();
 	if (kernelVersion > 0 && kernelVersion <= 2 * 65536 + 2 * 256 + 11) {
 		/* bdflush, kupdate not needed for kernels >2.2.11 */
@@ -484,14 +519,14 @@
 static void halt_signal(int sig)
 {
 	shutdown_system();
-	message(CONSOLE,
+	message(CONSOLE|LOG,
 			"The system is halted. Press %s or turn off power\r\n",
 			(secondConsole == NULL)	/* serial console */
 			? "Reset" : "CTRL-ALT-DEL");
 	sync();
 
 	/* allow time for last message to reach serial console */
-	sleep(5);
+	sleep(2);
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
 	if (sig == SIGUSR2)
@@ -505,7 +540,7 @@
 static void reboot_signal(int sig)
 {
 	shutdown_system();
-	message(CONSOLE, "Please stand by while rebooting the system.\r\n");
+	message(CONSOLE|LOG, "Please stand by while rebooting the system.\r\n");
 	sync();
 
 	/* allow time for last message to reach serial console */
@@ -631,7 +666,7 @@
 //      newAction->process, newAction->action, newAction->console);
 }
 
-void delete_initAction(initAction * action)
+static void delete_initAction(initAction * action)
 {
 	initAction *a, *b = NULL;
 
@@ -669,6 +704,10 @@
 	if (file == NULL) {
 		/* No inittab file -- set up some default behavior */
 #endif
+		/* Swapoff on halt/reboot */
+		new_initAction(CTRLALTDEL, "/bin/umount -a -r > /dev/null 2>&1", console);
+		/* Umount all filesystems on halt/reboot */
+		new_initAction(CTRLALTDEL, "/bin/umount -a -r > /dev/null 2>&1", console);
 		/* Askfirst shell on tty1 */
 		new_initAction(ASKFIRST, SHELL, console);
 		/* Askfirst shell on tty2 */
@@ -756,6 +795,8 @@
 #endif
 }
 
+
+
 extern int init_main(int argc, char **argv)
 {
 	initAction *a;
@@ -768,9 +809,6 @@
 		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");
 	}
-	/* Fix up argv[0] to be certain we claim to be init */
-	strncpy(argv[0], "init", strlen(argv[0]));
-
 	/* Set up sig handlers  -- be sure to
 	 * clear all of these in run() */
 	signal(SIGUSR1, halt_signal);
@@ -838,6 +876,10 @@
 		 * of "askfirst" shells */
 		parse_inittab();
 	}
+	
+	/* Fix up argv[0] to be certain we claim to be init */
+	strncpy(argv[0], "init", strlen(argv[0])+1);
+	strncpy(argv[1], "\0", strlen(argv[1])+1);
 
 	/* Now run everything that needs to be run */
 
diff --git a/internal.h b/internal.h
index 22f4f2f..090fcc8 100644
--- a/internal.h
+++ b/internal.h
@@ -31,6 +31,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <sys/stat.h>
+//#include <sys/param.h>
 #include <mntent.h>
 
 
@@ -186,6 +187,7 @@
 #if defined BB_INIT || defined BB_SYSLOGD
 extern int device_open(char *device, int mode);
 #endif
+extern void whine_if_fstab_is_missing();
 
 #if defined BB_FEATURE_MOUNT_LOOP
 extern int del_loop(const char *device);
diff --git a/mount.c b/mount.c
index c3e3bbd..37f789d 100644
--- a/mount.c
+++ b/mount.c
@@ -53,7 +53,7 @@
 #include <linux/loop.h>
 
 
-static int use_loop = 0;
+static int use_loop = FALSE;
 #endif
 
 extern const char mtab_file[];	/* Defined in utility.c */
@@ -114,13 +114,14 @@
 		 char *mtab_opts)
 {
 	int status = 0;
+	char *lofile = NULL;
 
 #if defined BB_MTAB
 	if (fakeIt == FALSE)
 #endif
 	{
 #if defined BB_FEATURE_MOUNT_LOOP
-		if (use_loop) {
+		if (use_loop==TRUE) {
 			int loro = flags & MS_RDONLY;
 			char *lofile = specialfile;
 
@@ -137,6 +138,7 @@
 				fprintf(stderr, "WARNING: loop device is read-only\n");
 				flags &= ~MS_RDONLY;
 			}
+			use_loop = FALSE;
 		}
 #endif
 		status =
@@ -157,7 +159,7 @@
 
 	/* Bummer.  mount failed.  Clean up */
 #if defined BB_FEATURE_MOUNT_LOOP
-	if (specialfile != NULL) {
+	if (lofile != NULL) {
 		del_loop(specialfile);
 	}
 #endif
@@ -166,20 +168,6 @@
 
 
 
-#if defined BB_MTAB
-#define whine_if_fstab_is_missing() {}
-#else
-extern void whine_if_fstab_is_missing()
-{
-	struct stat statBuf;
-
-	if (stat("/etc/fstab", &statBuf) < 0)
-		fprintf(stderr,
-				"/etc/fstab file missing -- install one to name /dev/root.\n\n");
-}
-#endif
-
-
 /* Seperate standard mount options from the nonstandard string options */
 static void
 parse_mount_options(char *options, unsigned long *flags, char *strflags)
@@ -204,7 +192,7 @@
 		}
 #if defined BB_FEATURE_MOUNT_LOOP
 		if (gotone == FALSE && !strcasecmp("loop", options)) {	/* loop device support */
-			use_loop = 1;
+			use_loop = TRUE;
 			gotone = TRUE;
 		}
 #endif
@@ -229,7 +217,7 @@
 int
 mount_one(char *blockDevice, char *directory, char *filesystemType,
 		  unsigned long flags, char *string_flags, int useMtab, int fakeIt,
-		  char *mtab_opts)
+		  char *mtab_opts, int whineOnErrors)
 {
 	int status = 0;
 
@@ -270,9 +258,11 @@
 						  fakeIt, mtab_opts);
 	}
 
-	if (status == FALSE) {
-		fprintf(stderr, "Mounting %s on %s failed: %s\n",
-				blockDevice, directory, strerror(errno));
+	if (status == FALSE && whineOnErrors == TRUE) {
+		if (whineOnErrors == TRUE) {
+			fprintf(stderr, "Mounting %s on %s failed: %s\n",
+					blockDevice, directory, strerror(errno));
+		}
 		return (FALSE);
 	}
 	return (TRUE);
@@ -387,18 +377,28 @@
 			exit(FALSE);
 		}
 		while ((m = getmntent(f)) != NULL) {
-			// If the file system isn't noauto, and isn't mounted on /, 
+			// If the file system isn't noauto, 
 			// and isn't swap or nfs, then mount it
 			if ((!strstr(m->mnt_opts, "noauto")) &&
-				(m->mnt_dir[1] != '\0') &&
 				(!strstr(m->mnt_type, "swap")) &&
 				(!strstr(m->mnt_type, "nfs"))) {
 				flags = 0;
 				*string_flags = '\0';
 				parse_mount_options(m->mnt_opts, &flags, string_flags);
-				mount_one(m->mnt_fsname, m->mnt_dir, m->mnt_type,
+				/* If the directory is /, try to remount
+				 * with the options specified in fstab */
+				if (m->mnt_dir[0] == '/' && m->mnt_dir[1] == '\0') {
+					flags |= MS_REMOUNT;
+				}
+				if (mount_one(m->mnt_fsname, m->mnt_dir, m->mnt_type,
 						  flags, string_flags, useMtab, fakeIt,
-						  extra_opts);
+						  extra_opts, FALSE)) 
+				{
+					/* Try again, but this time try a remount */
+					mount_one(m->mnt_fsname, m->mnt_dir, m->mnt_type,
+							  flags|MS_REMOUNT, string_flags, useMtab, fakeIt,
+							  extra_opts, TRUE);
+				}
 			}
 		}
 		endmntent(f);
@@ -414,7 +414,7 @@
 #endif
 			exit(mount_one(device, directory, filesystemType,
 						   flags, string_flags, useMtab, fakeIt,
-						   extra_opts));
+						   extra_opts, TRUE));
 		} else {
 			goto goodbye;
 		}
diff --git a/swaponoff.c b/swaponoff.c
index 6bda222..bc096ea 100644
--- a/swaponoff.c
+++ b/swaponoff.c
@@ -36,13 +36,16 @@
 static const char *appName;
 
 static const char swapoff_usage[] =
+	"swapoff [OPTION] [device]\n\n"
+	"Stop swapping virtual memory pages on the given device.\n\n"
+	"Options:\n"
+	"\t-a\tStop swapping on all swap devices\n";
 
-	"swapoff device\n"
-	"\nStop swapping virtual memory pages on the given device.\n";
 static const char swapon_usage[] =
-
-	"swapon device\n"
-	"\nStart swapping virtual memory pages on the given device.\n";
+	"swapon [OPTION] [device]\n\n"
+	"Start swapping virtual memory pages on the given device.\n\n"
+	"Options:\n"
+	"\t-a\tStart swapping on all swap devices\n";
 
 
 #define SWAPON_APP   1
@@ -85,12 +88,6 @@
 
 extern int swap_on_off_main(int argc, char **argv)
 {
-	struct stat statBuf;
-
-	if (stat("/etc/fstab", &statBuf) < 0)
-		fprintf(stderr,
-				"/etc/fstab file missing -- Please install one.\n\n");
-
 	if (strcmp(*argv, "swapon") == 0) {
 		appName = *argv;
 		whichApp = SWAPON_APP;
@@ -100,8 +97,9 @@
 		whichApp = SWAPOFF_APP;
 	}
 
-	if (argc < 2)
+	if (argc != 2) {
 		goto usage_and_exit;
+	}
 	argc--;
 	argv++;
 
@@ -110,6 +108,7 @@
 		while (*++(*argv))
 			switch (**argv) {
 			case 'a':
+				whine_if_fstab_is_missing();
 				do_em_all();
 				break;
 			default:
diff --git a/umount.c b/umount.c
index a2ca8c7..b58b1a0 100644
--- a/umount.c
+++ b/umount.c
@@ -29,6 +29,7 @@
 #include <fstab.h>
 #include <errno.h>
 
+
 static const char umount_usage[] =
 	"umount [flags] filesystem|directory\n\n"
 	"Flags:\n" "\t-a:\tUnmount all file systems"
@@ -57,113 +58,6 @@
 static int doRemount = FALSE;
 extern const char mtab_file[];	/* Defined in utility.c */
 
-#define MIN(x,y) (x > y ? x : y)
-
-static int do_umount(const char *name, int useMtab)
-{
-	int status;
-	char *blockDevice = mtab_getinfo(name, MTAB_GETDEVICE);
-
-	if (blockDevice && strcmp(blockDevice, name) == 0)
-		name = mtab_getinfo(blockDevice, MTAB_GETMOUNTPT);
-
-	status = umount(name);
-
-#if defined BB_FEATURE_MOUNT_LOOP
-	if (blockDevice != NULL && !strncmp("/dev/loop", blockDevice, 9))
-		/* this was a loop device, delete it */
-		del_loop(blockDevice);
-#endif
-#if defined BB_FEATURE_REMOUNT
-	if (status != 0 && doRemount == TRUE && errno == EBUSY) {
-		status = mount(blockDevice, name, NULL,
-					   MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL);
-		if (status == 0) {
-			fprintf(stderr, "umount: %s busy - remounted read-only\n",
-					blockDevice);
-			/* TODO: update mtab if BB_MTAB is defined */
-		} else {
-			fprintf(stderr, "umount: Cannot remount %s read-only\n",
-					blockDevice);
-		}
-	}
-#endif
-	if (status == 0) {
-#if defined BB_MTAB
-		if (useMtab == TRUE)
-			erase_mtab(name);
-#endif
-		return (TRUE);
-	}
-	return (FALSE);
-}
-
-static int umount_all(int useMtab)
-{
-	int status = TRUE;
-	char *mountpt;
-	void *iter;
-
-	for (mountpt = mtab_first(&iter); mountpt; mountpt = mtab_next(&iter)) {
-		status = do_umount(mountpt, useMtab);
-		if (status != 0) {
-			/* Don't bother retrying the umount on busy devices */
-			if (errno == EBUSY) {
-				perror(mountpt);
-				continue;
-			}
-			status = do_umount(mountpt, useMtab);
-			if (status != 0) {
-				printf("Couldn't umount %s on %s: %s\n",
-					   mountpt, mtab_getinfo(mountpt, MTAB_GETDEVICE),
-					   strerror(errno));
-			}
-		}
-	}
-	return (status);
-}
-
-extern int umount_main(int argc, char **argv)
-{
-	if (argc < 2) {
-		usage(umount_usage);
-	}
-
-	/* Parse any options */
-	while (--argc > 0 && **(++argv) == '-') {
-		while (*++(*argv))
-			switch (**argv) {
-			case 'a':
-				umountAll = TRUE;
-				break;
-#ifdef BB_MTAB
-			case 'n':
-				useMtab = FALSE;
-				break;
-#endif
-#ifdef BB_FEATURE_REMOUNT
-			case 'r':
-				doRemount = TRUE;
-				break;
-#endif
-			default:
-				usage(umount_usage);
-			}
-	}
-
-	mtab_read();
-	if (umountAll == TRUE) {
-		exit(umount_all(useMtab));
-	}
-	if (do_umount(*argv, useMtab) == 0)
-		exit(TRUE);
-	else {
-		perror("umount");
-		exit(FALSE);
-	}
-}
-
-
 
 /* These functions are here because the getmntent functions do not appear
  * to be re-entrant, which leads to all sorts of problems when we try to
@@ -257,3 +151,111 @@
 		this = next;
 	}
 }
+
+static int do_umount(const char *name, int useMtab)
+{
+	int status;
+	char *blockDevice = mtab_getinfo(name, MTAB_GETDEVICE);
+
+	if (blockDevice && strcmp(blockDevice, name) == 0)
+		name = mtab_getinfo(blockDevice, MTAB_GETMOUNTPT);
+
+	status = umount(name);
+
+#if defined BB_FEATURE_MOUNT_LOOP
+	if (blockDevice != NULL && !strncmp("/dev/loop", blockDevice, 9))
+		/* this was a loop device, delete it */
+		del_loop(blockDevice);
+#endif
+#if defined BB_FEATURE_REMOUNT
+	if (status != 0 && doRemount == TRUE && errno == EBUSY) {
+		status = mount(blockDevice, name, NULL,
+					   MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL);
+		if (status == 0) {
+			fprintf(stderr, "umount: %s busy - remounted read-only\n",
+					blockDevice);
+			/* TODO: update mtab if BB_MTAB is defined */
+		} else {
+			fprintf(stderr, "umount: Cannot remount %s read-only\n",
+					blockDevice);
+		}
+	}
+#endif
+	if (status == 0) {
+#if defined BB_MTAB
+		if (useMtab == TRUE)
+			erase_mtab(name);
+#endif
+		return (TRUE);
+	}
+	return (FALSE);
+}
+
+static int umount_all(int useMtab)
+{
+	int status = TRUE;
+	char *mountpt;
+	void *iter;
+
+	for (mountpt = mtab_first(&iter); mountpt; mountpt = mtab_next(&iter)) {
+		/* Never umount /proc on a umount -a */
+		if (strstr(mountpt, "proc")!= NULL)
+			continue;
+		status = do_umount(mountpt, useMtab);
+		if (status != 0) {
+			/* Don't bother retrying the umount on busy devices */
+			if (errno == EBUSY) {
+				perror(mountpt);
+				continue;
+			}
+			status = do_umount(mountpt, useMtab);
+			if (status != 0) {
+				printf("Couldn't umount %s on %s: %s\n",
+					   mountpt, mtab_getinfo(mountpt, MTAB_GETDEVICE),
+					   strerror(errno));
+			}
+		}
+	}
+	return (status);
+}
+
+extern int umount_main(int argc, char **argv)
+{
+	if (argc < 2) {
+		usage(umount_usage);
+	}
+
+	/* Parse any options */
+	while (--argc > 0 && **(++argv) == '-') {
+		while (*++(*argv))
+			switch (**argv) {
+			case 'a':
+				umountAll = TRUE;
+				break;
+#ifdef BB_MTAB
+			case 'n':
+				useMtab = FALSE;
+				break;
+#endif
+#ifdef BB_FEATURE_REMOUNT
+			case 'r':
+				doRemount = TRUE;
+				break;
+#endif
+			default:
+				usage(umount_usage);
+			}
+	}
+
+	mtab_read();
+	if (umountAll == TRUE) {
+		exit(umount_all(useMtab));
+	}
+	if (do_umount(*argv, useMtab) == 0)
+		exit(TRUE);
+	else {
+		perror("umount");
+		exit(FALSE);
+	}
+}
+
diff --git a/util-linux/mount.c b/util-linux/mount.c
index c3e3bbd..37f789d 100644
--- a/util-linux/mount.c
+++ b/util-linux/mount.c
@@ -53,7 +53,7 @@
 #include <linux/loop.h>
 
 
-static int use_loop = 0;
+static int use_loop = FALSE;
 #endif
 
 extern const char mtab_file[];	/* Defined in utility.c */
@@ -114,13 +114,14 @@
 		 char *mtab_opts)
 {
 	int status = 0;
+	char *lofile = NULL;
 
 #if defined BB_MTAB
 	if (fakeIt == FALSE)
 #endif
 	{
 #if defined BB_FEATURE_MOUNT_LOOP
-		if (use_loop) {
+		if (use_loop==TRUE) {
 			int loro = flags & MS_RDONLY;
 			char *lofile = specialfile;
 
@@ -137,6 +138,7 @@
 				fprintf(stderr, "WARNING: loop device is read-only\n");
 				flags &= ~MS_RDONLY;
 			}
+			use_loop = FALSE;
 		}
 #endif
 		status =
@@ -157,7 +159,7 @@
 
 	/* Bummer.  mount failed.  Clean up */
 #if defined BB_FEATURE_MOUNT_LOOP
-	if (specialfile != NULL) {
+	if (lofile != NULL) {
 		del_loop(specialfile);
 	}
 #endif
@@ -166,20 +168,6 @@
 
 
 
-#if defined BB_MTAB
-#define whine_if_fstab_is_missing() {}
-#else
-extern void whine_if_fstab_is_missing()
-{
-	struct stat statBuf;
-
-	if (stat("/etc/fstab", &statBuf) < 0)
-		fprintf(stderr,
-				"/etc/fstab file missing -- install one to name /dev/root.\n\n");
-}
-#endif
-
-
 /* Seperate standard mount options from the nonstandard string options */
 static void
 parse_mount_options(char *options, unsigned long *flags, char *strflags)
@@ -204,7 +192,7 @@
 		}
 #if defined BB_FEATURE_MOUNT_LOOP
 		if (gotone == FALSE && !strcasecmp("loop", options)) {	/* loop device support */
-			use_loop = 1;
+			use_loop = TRUE;
 			gotone = TRUE;
 		}
 #endif
@@ -229,7 +217,7 @@
 int
 mount_one(char *blockDevice, char *directory, char *filesystemType,
 		  unsigned long flags, char *string_flags, int useMtab, int fakeIt,
-		  char *mtab_opts)
+		  char *mtab_opts, int whineOnErrors)
 {
 	int status = 0;
 
@@ -270,9 +258,11 @@
 						  fakeIt, mtab_opts);
 	}
 
-	if (status == FALSE) {
-		fprintf(stderr, "Mounting %s on %s failed: %s\n",
-				blockDevice, directory, strerror(errno));
+	if (status == FALSE && whineOnErrors == TRUE) {
+		if (whineOnErrors == TRUE) {
+			fprintf(stderr, "Mounting %s on %s failed: %s\n",
+					blockDevice, directory, strerror(errno));
+		}
 		return (FALSE);
 	}
 	return (TRUE);
@@ -387,18 +377,28 @@
 			exit(FALSE);
 		}
 		while ((m = getmntent(f)) != NULL) {
-			// If the file system isn't noauto, and isn't mounted on /, 
+			// If the file system isn't noauto, 
 			// and isn't swap or nfs, then mount it
 			if ((!strstr(m->mnt_opts, "noauto")) &&
-				(m->mnt_dir[1] != '\0') &&
 				(!strstr(m->mnt_type, "swap")) &&
 				(!strstr(m->mnt_type, "nfs"))) {
 				flags = 0;
 				*string_flags = '\0';
 				parse_mount_options(m->mnt_opts, &flags, string_flags);
-				mount_one(m->mnt_fsname, m->mnt_dir, m->mnt_type,
+				/* If the directory is /, try to remount
+				 * with the options specified in fstab */
+				if (m->mnt_dir[0] == '/' && m->mnt_dir[1] == '\0') {
+					flags |= MS_REMOUNT;
+				}
+				if (mount_one(m->mnt_fsname, m->mnt_dir, m->mnt_type,
 						  flags, string_flags, useMtab, fakeIt,
-						  extra_opts);
+						  extra_opts, FALSE)) 
+				{
+					/* Try again, but this time try a remount */
+					mount_one(m->mnt_fsname, m->mnt_dir, m->mnt_type,
+							  flags|MS_REMOUNT, string_flags, useMtab, fakeIt,
+							  extra_opts, TRUE);
+				}
 			}
 		}
 		endmntent(f);
@@ -414,7 +414,7 @@
 #endif
 			exit(mount_one(device, directory, filesystemType,
 						   flags, string_flags, useMtab, fakeIt,
-						   extra_opts));
+						   extra_opts, TRUE));
 		} else {
 			goto goodbye;
 		}
diff --git a/util-linux/swaponoff.c b/util-linux/swaponoff.c
index 6bda222..bc096ea 100644
--- a/util-linux/swaponoff.c
+++ b/util-linux/swaponoff.c
@@ -36,13 +36,16 @@
 static const char *appName;
 
 static const char swapoff_usage[] =
+	"swapoff [OPTION] [device]\n\n"
+	"Stop swapping virtual memory pages on the given device.\n\n"
+	"Options:\n"
+	"\t-a\tStop swapping on all swap devices\n";
 
-	"swapoff device\n"
-	"\nStop swapping virtual memory pages on the given device.\n";
 static const char swapon_usage[] =
-
-	"swapon device\n"
-	"\nStart swapping virtual memory pages on the given device.\n";
+	"swapon [OPTION] [device]\n\n"
+	"Start swapping virtual memory pages on the given device.\n\n"
+	"Options:\n"
+	"\t-a\tStart swapping on all swap devices\n";
 
 
 #define SWAPON_APP   1
@@ -85,12 +88,6 @@
 
 extern int swap_on_off_main(int argc, char **argv)
 {
-	struct stat statBuf;
-
-	if (stat("/etc/fstab", &statBuf) < 0)
-		fprintf(stderr,
-				"/etc/fstab file missing -- Please install one.\n\n");
-
 	if (strcmp(*argv, "swapon") == 0) {
 		appName = *argv;
 		whichApp = SWAPON_APP;
@@ -100,8 +97,9 @@
 		whichApp = SWAPOFF_APP;
 	}
 
-	if (argc < 2)
+	if (argc != 2) {
 		goto usage_and_exit;
+	}
 	argc--;
 	argv++;
 
@@ -110,6 +108,7 @@
 		while (*++(*argv))
 			switch (**argv) {
 			case 'a':
+				whine_if_fstab_is_missing();
 				do_em_all();
 				break;
 			default:
diff --git a/util-linux/umount.c b/util-linux/umount.c
index a2ca8c7..b58b1a0 100644
--- a/util-linux/umount.c
+++ b/util-linux/umount.c
@@ -29,6 +29,7 @@
 #include <fstab.h>
 #include <errno.h>
 
+
 static const char umount_usage[] =
 	"umount [flags] filesystem|directory\n\n"
 	"Flags:\n" "\t-a:\tUnmount all file systems"
@@ -57,113 +58,6 @@
 static int doRemount = FALSE;
 extern const char mtab_file[];	/* Defined in utility.c */
 
-#define MIN(x,y) (x > y ? x : y)
-
-static int do_umount(const char *name, int useMtab)
-{
-	int status;
-	char *blockDevice = mtab_getinfo(name, MTAB_GETDEVICE);
-
-	if (blockDevice && strcmp(blockDevice, name) == 0)
-		name = mtab_getinfo(blockDevice, MTAB_GETMOUNTPT);
-
-	status = umount(name);
-
-#if defined BB_FEATURE_MOUNT_LOOP
-	if (blockDevice != NULL && !strncmp("/dev/loop", blockDevice, 9))
-		/* this was a loop device, delete it */
-		del_loop(blockDevice);
-#endif
-#if defined BB_FEATURE_REMOUNT
-	if (status != 0 && doRemount == TRUE && errno == EBUSY) {
-		status = mount(blockDevice, name, NULL,
-					   MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL);
-		if (status == 0) {
-			fprintf(stderr, "umount: %s busy - remounted read-only\n",
-					blockDevice);
-			/* TODO: update mtab if BB_MTAB is defined */
-		} else {
-			fprintf(stderr, "umount: Cannot remount %s read-only\n",
-					blockDevice);
-		}
-	}
-#endif
-	if (status == 0) {
-#if defined BB_MTAB
-		if (useMtab == TRUE)
-			erase_mtab(name);
-#endif
-		return (TRUE);
-	}
-	return (FALSE);
-}
-
-static int umount_all(int useMtab)
-{
-	int status = TRUE;
-	char *mountpt;
-	void *iter;
-
-	for (mountpt = mtab_first(&iter); mountpt; mountpt = mtab_next(&iter)) {
-		status = do_umount(mountpt, useMtab);
-		if (status != 0) {
-			/* Don't bother retrying the umount on busy devices */
-			if (errno == EBUSY) {
-				perror(mountpt);
-				continue;
-			}
-			status = do_umount(mountpt, useMtab);
-			if (status != 0) {
-				printf("Couldn't umount %s on %s: %s\n",
-					   mountpt, mtab_getinfo(mountpt, MTAB_GETDEVICE),
-					   strerror(errno));
-			}
-		}
-	}
-	return (status);
-}
-
-extern int umount_main(int argc, char **argv)
-{
-	if (argc < 2) {
-		usage(umount_usage);
-	}
-
-	/* Parse any options */
-	while (--argc > 0 && **(++argv) == '-') {
-		while (*++(*argv))
-			switch (**argv) {
-			case 'a':
-				umountAll = TRUE;
-				break;
-#ifdef BB_MTAB
-			case 'n':
-				useMtab = FALSE;
-				break;
-#endif
-#ifdef BB_FEATURE_REMOUNT
-			case 'r':
-				doRemount = TRUE;
-				break;
-#endif
-			default:
-				usage(umount_usage);
-			}
-	}
-
-	mtab_read();
-	if (umountAll == TRUE) {
-		exit(umount_all(useMtab));
-	}
-	if (do_umount(*argv, useMtab) == 0)
-		exit(TRUE);
-	else {
-		perror("umount");
-		exit(FALSE);
-	}
-}
-
-
 
 /* These functions are here because the getmntent functions do not appear
  * to be re-entrant, which leads to all sorts of problems when we try to
@@ -257,3 +151,111 @@
 		this = next;
 	}
 }
+
+static int do_umount(const char *name, int useMtab)
+{
+	int status;
+	char *blockDevice = mtab_getinfo(name, MTAB_GETDEVICE);
+
+	if (blockDevice && strcmp(blockDevice, name) == 0)
+		name = mtab_getinfo(blockDevice, MTAB_GETMOUNTPT);
+
+	status = umount(name);
+
+#if defined BB_FEATURE_MOUNT_LOOP
+	if (blockDevice != NULL && !strncmp("/dev/loop", blockDevice, 9))
+		/* this was a loop device, delete it */
+		del_loop(blockDevice);
+#endif
+#if defined BB_FEATURE_REMOUNT
+	if (status != 0 && doRemount == TRUE && errno == EBUSY) {
+		status = mount(blockDevice, name, NULL,
+					   MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL);
+		if (status == 0) {
+			fprintf(stderr, "umount: %s busy - remounted read-only\n",
+					blockDevice);
+			/* TODO: update mtab if BB_MTAB is defined */
+		} else {
+			fprintf(stderr, "umount: Cannot remount %s read-only\n",
+					blockDevice);
+		}
+	}
+#endif
+	if (status == 0) {
+#if defined BB_MTAB
+		if (useMtab == TRUE)
+			erase_mtab(name);
+#endif
+		return (TRUE);
+	}
+	return (FALSE);
+}
+
+static int umount_all(int useMtab)
+{
+	int status = TRUE;
+	char *mountpt;
+	void *iter;
+
+	for (mountpt = mtab_first(&iter); mountpt; mountpt = mtab_next(&iter)) {
+		/* Never umount /proc on a umount -a */
+		if (strstr(mountpt, "proc")!= NULL)
+			continue;
+		status = do_umount(mountpt, useMtab);
+		if (status != 0) {
+			/* Don't bother retrying the umount on busy devices */
+			if (errno == EBUSY) {
+				perror(mountpt);
+				continue;
+			}
+			status = do_umount(mountpt, useMtab);
+			if (status != 0) {
+				printf("Couldn't umount %s on %s: %s\n",
+					   mountpt, mtab_getinfo(mountpt, MTAB_GETDEVICE),
+					   strerror(errno));
+			}
+		}
+	}
+	return (status);
+}
+
+extern int umount_main(int argc, char **argv)
+{
+	if (argc < 2) {
+		usage(umount_usage);
+	}
+
+	/* Parse any options */
+	while (--argc > 0 && **(++argv) == '-') {
+		while (*++(*argv))
+			switch (**argv) {
+			case 'a':
+				umountAll = TRUE;
+				break;
+#ifdef BB_MTAB
+			case 'n':
+				useMtab = FALSE;
+				break;
+#endif
+#ifdef BB_FEATURE_REMOUNT
+			case 'r':
+				doRemount = TRUE;
+				break;
+#endif
+			default:
+				usage(umount_usage);
+			}
+	}
+
+	mtab_read();
+	if (umountAll == TRUE) {
+		exit(umount_all(useMtab));
+	}
+	if (do_umount(*argv, useMtab) == 0)
+		exit(TRUE);
+	else {
+		perror("umount");
+		exit(FALSE);
+	}
+}
+
diff --git a/utility.c b/utility.c
index 7f46f9b..00a1c69 100644
--- a/utility.c
+++ b/utility.c
@@ -1298,5 +1298,19 @@
 }
 #endif							/* BB_FEATURE_MOUNT_LOOP */
 
+#if defined BB_MTAB
+#define whine_if_fstab_is_missing() {}
+#else
+extern void whine_if_fstab_is_missing()
+{
+	struct stat statBuf;
+
+	if (stat("/etc/fstab", &statBuf) < 0)
+		fprintf(stderr,
+				"/etc/fstab file missing -- install one to name /dev/root.\n\n");
+}
+#endif
+
+
 
 /* END CODE */