* Fixed 'swapon -a' and 'swapoff -a', which were broken.
* Fixed 'mount -a' so it works as expected.
* Implemented 'ls -R' (enabled by enabling BB_FEATURE_LS_RECURSIVE)
 -Erik
diff --git a/Changelog b/Changelog
index da229a9..50b28cf 100644
--- a/Changelog
+++ b/Changelog
@@ -60,6 +60,9 @@
 	* "mount" now reports errors from nfsmount() and assumes NFS mount
 	    if ':' is present in the device name - Pavel Roskin
 	* Fixed exit status for killall - Pavel Roskin
+	* Fixed 'swapon -a' and 'swapoff -a', which were broken.
+	* Fixed 'mount -a' so it works as expected.
+	* Implemented 'ls -R' (enabled by enabling BB_FEATURE_LS_RECURSIVE)
 	* More doc updates
 
 
diff --git a/TODO b/TODO
index 182408b..71bb536 100644
--- a/TODO
+++ b/TODO
@@ -18,19 +18,12 @@
 
 Bugs that need fixing before the 0.44 release goes out the door:
 
- - mkfs.minix rev 1.7 completely broke the parser.  Fix it.
  - 'grep foo$ file' doesn't work
  - 'grep *foo file' segfaults
  - ps dirent race bug (need to stat the file before attempting chdir)
-  - I believe that swaponoff may also be also broken (check it).
-  - It used to be that BusyBox tar would happily overwrite existing files on
-      an extraction.  However, as of 0.42, BusyBox tar simply dies as soon as an 
-      existing file is found.
- - Make 'mount -a' work even when /proc isn't mounted (ugly bug).
  - Make 'ln -s /tmp/file .' work the way GNU ln does (i.e. makes a link to 
     /tmp/file in the current directory, rather then trying and failing to create
     a symlink named "." in the current working directory).
- - implement 'ls -R'.
  - "math" should also take input from stdin
  - "more" doesn't accept " " to scroll by one page when BB_FEATURE_USE_TERMIOS
     is not on.
diff --git a/busybox.def.h b/busybox.def.h
index 3b7c8bf..11a791e 100644
--- a/busybox.def.h
+++ b/busybox.def.h
@@ -154,6 +154,9 @@
 // enable ls -p and -F
 #define BB_FEATURE_LS_FILETYPES
 //
+// enable ls -R
+#define BB_FEATURE_LS_RECURSIVE
+//
 // Change ping implementation -- simplified, featureless, but really small.
 //#define BB_SIMPLE_PING
 //
diff --git a/coreutils/ls.c b/coreutils/ls.c
index 6ab11c4..0b1aa62 100644
--- a/coreutils/ls.c
+++ b/coreutils/ls.c
@@ -86,8 +86,9 @@
 #define DISP_DOT	8			/* show . and .. */
 #define DISP_NUMERIC	16		/* numeric uid and gid */
 #define DISP_FULLTIME	32		/* show extended time display */
-#define DIR_NOLIST	64			/* show directory as itself, not contents */
+#define DIR_NOLIST		64		/* show directory as itself, not contents */
 #define DISP_DIRNAME	128		/* show directory name (for internal use) */
+#define DISP_RECURSIVE	256		/* Do a recursive listing */
 
 #ifndef MAJOR
 #define MAJOR(dev) (((dev)>>8)&0xff)
@@ -449,6 +450,9 @@
 #ifdef BB_FEATURE_LS_FILETYPES
 	"F"
 #endif
+#ifdef BB_FEATURE_LS_RECURSIVE
+	"R"
+#endif
 	"] [filenames...]\n"
 #ifndef BB_FEATURE_TRIVIAL_HELP
 	"\nList directory contents\n\n"
@@ -477,9 +481,24 @@
 #ifdef BB_FEATURE_LS_FILETYPES
 	"\t-F\tappend indicator (one of */=@|) to entries\n"
 #endif
+#ifdef BB_FEATURE_LS_RECURSIVE
+	"\t-R\tlist subdirectories recursively\n"
+#endif
 #endif
 	;
 
+
+#ifdef BB_FEATURE_LS_RECURSIVE
+static int dirAction(const char *fileName, struct stat *statbuf, void* junk)
+{
+	int i;
+	fprintf(stdout, "\n%s:\n", fileName);
+	i = list_item(fileName);
+	newline();
+	return (i);
+}
+#endif
+
 extern int ls_main(int argc, char **argv)
 {
 	int argi = 1, i;
@@ -544,6 +563,11 @@
 				opts |= DISP_FULLTIME;
 				break;
 #endif
+#ifdef BB_FEATURE_LS_RECURSIVE
+			case 'R':
+				opts |= DISP_RECURSIVE;
+				break;
+#endif
 			default:
 				goto print_usage_message;
 			}
@@ -570,12 +594,25 @@
 #endif
 
 	/* process files specified, or current directory if none */
-	i = 0;
-	if (argi == argc)
-		i = list_item(".");
-	while (argi < argc)
-		i |= list_item(argv[argi++]);
-	newline();
+#ifdef BB_FEATURE_LS_RECURSIVE
+	if (opts & DISP_RECURSIVE) {
+		i = 0;
+		if (argi == argc) {
+			i = recursiveAction(".", TRUE, FALSE, FALSE, NULL, dirAction, NULL);
+		}
+		while (argi < argc) {
+			i |= recursiveAction(argv[argi++], TRUE, FALSE, FALSE, NULL, dirAction, NULL);
+		}
+	} else 
+#endif
+	{
+		i = 0;
+		if (argi == argc)
+			i = list_item(".");
+		while (argi < argc)
+			i |= list_item(argv[argi++]);
+		newline();
+	}
 	exit(i);
 
   print_usage_message:
diff --git a/docs/busybox.pod b/docs/busybox.pod
index 7b76e7e..3cd45f7 100644
--- a/docs/busybox.pod
+++ b/docs/busybox.pod
@@ -956,7 +956,7 @@
 
 =item ls
 
-Usage: ls [B<-1acdelnpuxACF>] [filenames...]
+Usage: ls [B<-1acdelnpuxACFR>] [filenames...]
 
 Options:
 
@@ -974,6 +974,7 @@
 	-A	do not list implied . and ..
 	-C	list entries by columns
 	-F	append indicator (one of */=@|) to entries
+	-R  list subdirectories recursively
 
 -------------------------------
 
@@ -1947,4 +1948,4 @@
 
 =cut
 
-# $Id: busybox.pod,v 1.35 2000/06/06 16:15:23 andersen Exp $
+# $Id: busybox.pod,v 1.36 2000/06/07 17:28:53 andersen Exp $
diff --git a/ls.c b/ls.c
index 6ab11c4..0b1aa62 100644
--- a/ls.c
+++ b/ls.c
@@ -86,8 +86,9 @@
 #define DISP_DOT	8			/* show . and .. */
 #define DISP_NUMERIC	16		/* numeric uid and gid */
 #define DISP_FULLTIME	32		/* show extended time display */
-#define DIR_NOLIST	64			/* show directory as itself, not contents */
+#define DIR_NOLIST		64		/* show directory as itself, not contents */
 #define DISP_DIRNAME	128		/* show directory name (for internal use) */
+#define DISP_RECURSIVE	256		/* Do a recursive listing */
 
 #ifndef MAJOR
 #define MAJOR(dev) (((dev)>>8)&0xff)
@@ -449,6 +450,9 @@
 #ifdef BB_FEATURE_LS_FILETYPES
 	"F"
 #endif
+#ifdef BB_FEATURE_LS_RECURSIVE
+	"R"
+#endif
 	"] [filenames...]\n"
 #ifndef BB_FEATURE_TRIVIAL_HELP
 	"\nList directory contents\n\n"
@@ -477,9 +481,24 @@
 #ifdef BB_FEATURE_LS_FILETYPES
 	"\t-F\tappend indicator (one of */=@|) to entries\n"
 #endif
+#ifdef BB_FEATURE_LS_RECURSIVE
+	"\t-R\tlist subdirectories recursively\n"
+#endif
 #endif
 	;
 
+
+#ifdef BB_FEATURE_LS_RECURSIVE
+static int dirAction(const char *fileName, struct stat *statbuf, void* junk)
+{
+	int i;
+	fprintf(stdout, "\n%s:\n", fileName);
+	i = list_item(fileName);
+	newline();
+	return (i);
+}
+#endif
+
 extern int ls_main(int argc, char **argv)
 {
 	int argi = 1, i;
@@ -544,6 +563,11 @@
 				opts |= DISP_FULLTIME;
 				break;
 #endif
+#ifdef BB_FEATURE_LS_RECURSIVE
+			case 'R':
+				opts |= DISP_RECURSIVE;
+				break;
+#endif
 			default:
 				goto print_usage_message;
 			}
@@ -570,12 +594,25 @@
 #endif
 
 	/* process files specified, or current directory if none */
-	i = 0;
-	if (argi == argc)
-		i = list_item(".");
-	while (argi < argc)
-		i |= list_item(argv[argi++]);
-	newline();
+#ifdef BB_FEATURE_LS_RECURSIVE
+	if (opts & DISP_RECURSIVE) {
+		i = 0;
+		if (argi == argc) {
+			i = recursiveAction(".", TRUE, FALSE, FALSE, NULL, dirAction, NULL);
+		}
+		while (argi < argc) {
+			i |= recursiveAction(argv[argi++], TRUE, FALSE, FALSE, NULL, dirAction, NULL);
+		}
+	} else 
+#endif
+	{
+		i = 0;
+		if (argi == argc)
+			i = list_item(".");
+		while (argi < argc)
+			i |= list_item(argv[argi++]);
+		newline();
+	}
 	exit(i);
 
   print_usage_message:
diff --git a/mount.c b/mount.c
index ee6c947..76f048b 100644
--- a/mount.c
+++ b/mount.c
@@ -154,8 +154,7 @@
 			}
 		}
 #endif
-		status =
-			mount(specialfile, dir, filesystemtype, flags, string_flags);
+		status = mount(specialfile, dir, filesystemtype, flags, string_flags);
 	}
 
 
@@ -176,6 +175,11 @@
 		del_loop(specialfile);
 	}
 #endif
+
+	if (errno == EPERM) {
+		fatalError("mount: permission denied. Are you root?\n");
+	}
+
 	return (FALSE);
 }
 
@@ -307,7 +311,7 @@
 						  fakeIt, mtab_opts);
 	}
 
-	if (status == FALSE && whineOnErrors == TRUE) {
+	if (status == FALSE) {
 		if (whineOnErrors == TRUE) {
 			fprintf(stderr, "Mounting %s on %s failed: %s\n",
 					blockDevice, directory, strerror(errno));
@@ -458,24 +462,19 @@
 			// If the filesystem isn't noauto, 
 			// and isn't swap or nfs, then mount it
 			if ((!strstr(m->mnt_opts, "noauto")) &&
-				(!strstr(m->mnt_type, "swap")) &&
-				(!strstr(m->mnt_type, "nfs"))) {
+					(!strstr(m->mnt_type, "swap")) &&
+					(!strstr(m->mnt_type, "nfs"))) {
 				flags = 0;
 				*string_flags = '\0';
 				parse_mount_options(m->mnt_opts, &flags, string_flags);
-				/* 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, FALSE)) 
+							flags, string_flags, useMtab, fakeIt,
+							extra_opts, FALSE)==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);
+							flags|MS_REMOUNT, string_flags, useMtab, fakeIt,
+							extra_opts, TRUE);
 				}
 			}
 		}
diff --git a/swaponoff.c b/swaponoff.c
index 0f8c4f5..83aadd0 100644
--- a/swaponoff.c
+++ b/swaponoff.c
@@ -83,7 +83,7 @@
 		exit(FALSE);
 	}
 	while ((m = getmntent(f)) != NULL) {
-		if (!strstr(m->mnt_type, MNTTYPE_SWAP)) {
+		if (strcmp(m->mnt_type, MNTTYPE_SWAP)==0) {
 			swap_enable_disable(m->mnt_fsname);
 		}
 	}
diff --git a/util-linux/mount.c b/util-linux/mount.c
index ee6c947..76f048b 100644
--- a/util-linux/mount.c
+++ b/util-linux/mount.c
@@ -154,8 +154,7 @@
 			}
 		}
 #endif
-		status =
-			mount(specialfile, dir, filesystemtype, flags, string_flags);
+		status = mount(specialfile, dir, filesystemtype, flags, string_flags);
 	}
 
 
@@ -176,6 +175,11 @@
 		del_loop(specialfile);
 	}
 #endif
+
+	if (errno == EPERM) {
+		fatalError("mount: permission denied. Are you root?\n");
+	}
+
 	return (FALSE);
 }
 
@@ -307,7 +311,7 @@
 						  fakeIt, mtab_opts);
 	}
 
-	if (status == FALSE && whineOnErrors == TRUE) {
+	if (status == FALSE) {
 		if (whineOnErrors == TRUE) {
 			fprintf(stderr, "Mounting %s on %s failed: %s\n",
 					blockDevice, directory, strerror(errno));
@@ -458,24 +462,19 @@
 			// If the filesystem isn't noauto, 
 			// and isn't swap or nfs, then mount it
 			if ((!strstr(m->mnt_opts, "noauto")) &&
-				(!strstr(m->mnt_type, "swap")) &&
-				(!strstr(m->mnt_type, "nfs"))) {
+					(!strstr(m->mnt_type, "swap")) &&
+					(!strstr(m->mnt_type, "nfs"))) {
 				flags = 0;
 				*string_flags = '\0';
 				parse_mount_options(m->mnt_opts, &flags, string_flags);
-				/* 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, FALSE)) 
+							flags, string_flags, useMtab, fakeIt,
+							extra_opts, FALSE)==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);
+							flags|MS_REMOUNT, string_flags, useMtab, fakeIt,
+							extra_opts, TRUE);
 				}
 			}
 		}
diff --git a/util-linux/swaponoff.c b/util-linux/swaponoff.c
index 0f8c4f5..83aadd0 100644
--- a/util-linux/swaponoff.c
+++ b/util-linux/swaponoff.c
@@ -83,7 +83,7 @@
 		exit(FALSE);
 	}
 	while ((m = getmntent(f)) != NULL) {
-		if (!strstr(m->mnt_type, MNTTYPE_SWAP)) {
+		if (strcmp(m->mnt_type, MNTTYPE_SWAP)==0) {
 			swap_enable_disable(m->mnt_fsname);
 		}
 	}