Index: contrib/conf/mips32-gx.sh
===================================================================
--- contrib/conf/mips32-gx.sh	(revision 30ac3c34095da351bef20e8343969b068822a378)
+++ contrib/conf/mips32-gx.sh	(revision 9463b245f7fbec8cdcde658d98d96baeb010663d)
@@ -8,3 +8,3 @@
 fi
 
-gxemul $@ -E testmips -C R4000 -X image.boot -d d0:"$DISK_IMG"
+gxemul $@ -E oldtestmips -C R4000 -X image.boot -d d0:"$DISK_IMG"
Index: uspace/app/bdsh/cmds/modules/ls/ls.c
===================================================================
--- uspace/app/bdsh/cmds/modules/ls/ls.c	(revision 30ac3c34095da351bef20e8343969b068822a378)
+++ uspace/app/bdsh/cmds/modules/ls/ls.c	(revision 9463b245f7fbec8cdcde658d98d96baeb010663d)
@@ -42,4 +42,5 @@
 #include <sort.h>
 
+#include "ls.h"
 #include "errors.h"
 #include "config.h"
@@ -48,26 +49,30 @@
 #include "cmds.h"
 
-/* Various values that can be returned by ls_scope() */
-#define LS_BOGUS 0
-#define LS_FILE  1
-#define LS_DIR   2
-
-/** Structure to represent a directory entry.
- *
- * Useful to keep together important information
- * for sorting directory entries.
- */
-struct dir_elem_t {
-	char *name;
-	struct stat s;
-};
-
 static const char *cmdname = "ls";
+
+static ls_job_t ls;
 
 static struct option const long_options[] = {
 	{ "help", no_argument, 0, 'h' },
 	{ "unsort", no_argument, 0, 'u' },
+	{ "recursive", no_argument, 0, 'r' },
 	{ 0, 0, 0, 0 }
 };
+
+/* Prototypes for the ls command, excluding entry points. */
+static unsigned int ls_start(ls_job_t *);
+static void ls_print(struct dir_elem_t *);
+static int ls_cmp(void *, void *, void *);
+static signed int ls_scan_dir(const char *, DIR *, struct dir_elem_t **);
+static unsigned int ls_recursive(const char *, DIR *);
+static unsigned int ls_scope(const char *, struct dir_elem_t *);
+
+static unsigned int ls_start(ls_job_t *ls)
+{
+	ls->recursive = 0;
+	ls->sort = 1;
+
+	return 1;
+}
 
 /** Print an entry.
@@ -92,5 +97,4 @@
 }
 
-
 /** Compare 2 directory elements.
  *
@@ -127,5 +131,6 @@
  *				0 otherwise.
  */
-static void ls_scan_dir(const char *d, DIR *dirp, int sort)
+static signed int ls_scan_dir(const char *d, DIR *dirp, 
+    struct dir_elem_t **dir_list_ptr)
 {
 	int alloc_blocks = 20;
@@ -140,10 +145,10 @@
 	
 	if (!dirp)
-		return;
+		return -1;
 
 	buff = (char *) malloc(PATH_MAX);
 	if (!buff) {
 		cli_error(CL_ENOMEM, "ls: failed to scan %s", d);
-		return;
+		return -1;
 	}
 	
@@ -152,5 +157,5 @@
 		cli_error(CL_ENOMEM, "ls: failed to scan %s", d);
 		free(buff);
-		return;
+		return -1;
 	}
 	
@@ -187,5 +192,5 @@
 	}
 	
-	if (sort) {
+	if (ls.sort) {
 		if (!qsort(&tosort[0], nbdirs, sizeof(struct dir_elem_t),
 		    ls_cmp, NULL)) {
@@ -196,4 +201,23 @@
 	for (i = 0; i < nbdirs; i++)
 		ls_print(&tosort[i]);
+
+	/* Populate the directory list. */
+	if (ls.recursive) {
+		tmp = (struct dir_elem_t *) realloc(*dir_list_ptr, 
+		    nbdirs * sizeof(struct dir_elem_t));
+		if (!tmp) {
+			cli_error(CL_ENOMEM, "ls: failed to scan %s", d);
+			goto out;
+		} 
+		*dir_list_ptr = tmp;
+
+		for (i = 0; i < nbdirs; i++) {
+			(*dir_list_ptr)[i].name = str_dup(tosort[i].name);
+			if (!(*dir_list_ptr)[i].name) {
+				cli_error(CL_ENOMEM, "ls: failed to scan %s", d);
+				goto out;
+			}
+		}
+	}
 	
 out:
@@ -202,4 +226,103 @@
 	free(tosort);
 	free(buff);
+
+	return nbdirs;
+}
+
+/** Visit a directory recursively.
+ *
+ * ls_recursive visits all the subdirectories recursively and
+ * prints the files and directories in them.
+ *
+ * @param path	Path the current directory being visited.
+ * @param dirp	Directory stream.
+ */
+static unsigned int ls_recursive(const char *path, DIR *dirp)
+{
+	int i, nbdirs, ret;
+	unsigned int scope;
+	char *subdir_path;
+	DIR *subdirp;
+	struct dir_elem_t *dir_list;
+	
+	const char * const trailing_slash = "/";
+
+	nbdirs = 0;
+	dir_list = (struct dir_elem_t *) malloc(sizeof(struct dir_elem_t));
+
+	printf("\n%s:\n", path);
+
+	subdir_path = (char *) malloc(PATH_MAX);
+	if (!subdir_path) {
+		ret = CMD_FAILURE;
+		goto out;
+	}
+
+	nbdirs = ls_scan_dir(path, dirp, &dir_list); 
+	if (nbdirs == -1) {
+		ret = CMD_FAILURE;
+		goto out;
+	}
+
+	for (i = 0; i < nbdirs; ++i) {
+		memset(subdir_path, 0, PATH_MAX);
+
+		if (str_size(subdir_path) + str_size(path) + 1 <= PATH_MAX)
+			str_append(subdir_path, PATH_MAX, path);
+		if (path[str_size(path)-1] != '/' &&
+		    str_size(subdir_path) + str_size(trailing_slash) + 1 <= PATH_MAX)
+			str_append(subdir_path, PATH_MAX, trailing_slash);
+		if (str_size(subdir_path) +
+		    str_size(dir_list[i].name) + 1 <= PATH_MAX)
+			str_append(subdir_path, PATH_MAX, dir_list[i].name);
+
+		scope = ls_scope(subdir_path, &dir_list[i]);
+		switch (scope) {
+		case LS_FILE:
+			break;
+		case LS_DIR:
+			subdirp = opendir(subdir_path);
+			if (!subdirp) {
+				/* May have been deleted between scoping it and opening it */
+				cli_error(CL_EFAIL, "Could not stat %s", dir_list[i].name);
+				ret = CMD_FAILURE;
+				goto out;
+			}
+
+			ret = ls_recursive(subdir_path, subdirp);
+			closedir(subdirp);
+			if (ret == CMD_FAILURE)
+				goto out;
+			break;
+		case LS_BOGUS:
+			ret = CMD_FAILURE;
+			goto out;
+		}	
+	}
+   
+	ret = CMD_SUCCESS; 
+
+out:
+	for (i = 0; i < nbdirs; i++)
+		free(dir_list[i].name);
+	free(dir_list);
+	free(subdir_path);
+
+	return ret;
+}
+
+static unsigned int ls_scope(const char *path, struct dir_elem_t *de)
+{
+	if (stat(path, &de->s)) {
+		cli_error(CL_ENOENT, path);
+		return LS_BOGUS;
+	}
+
+	if (de->s.is_file)
+		return LS_FILE;
+	else if (de->s.is_directory)
+		return LS_DIR;
+
+	return LS_BOGUS;
 }
 
@@ -215,5 +338,6 @@
 		"Options:\n"
 		"  -h, --help       A short option summary\n"
-		"  -u, --unsort     Do not sort directory entries\n",
+		"  -u, --unsort     Do not sort directory entries\n"
+		"  -r, --recursive  List subdirectories recursively\n",
 		cmdname);
 	}
@@ -228,10 +352,16 @@
 	DIR *dirp;
 	int c, opt_ind;
-	int sort = 1;
+	int ret = 0;
+	unsigned int scope;
+
+	if (!ls_start(&ls)) {
+		cli_error(CL_EFAIL, "%s: Could not initialize", cmdname);
+		return CMD_FAILURE;
+	}
 
 	argc = cli_count_args(argv);
 	
 	for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
-		c = getopt_long(argc, argv, "hu", long_options, &opt_ind);
+		c = getopt_long(argc, argv, "hur", long_options, &opt_ind);
 		switch (c) {
 		case 'h':
@@ -239,5 +369,8 @@
 			return CMD_SUCCESS;
 		case 'u':
-			sort = 0;
+			ls.sort = 0;
+			break;
+		case 'r':
+			ls.recursive = 1;
 			break;
 		}
@@ -251,5 +384,5 @@
 		return CMD_FAILURE;
 	}
-	memset(de.name, 0, sizeof(PATH_MAX));
+	memset(de.name, 0, PATH_MAX);
 	
 	if (argc == 0)
@@ -257,14 +390,11 @@
 	else
 		str_cpy(de.name, PATH_MAX, argv[optind]);
-	
-	if (stat(de.name, &de.s)) {
-		cli_error(CL_ENOENT, de.name);
-		free(de.name);
-		return CMD_FAILURE;
-	}
-
-	if (de.s.is_file) {
+
+	scope = ls_scope(de.name, &de);
+	switch (scope) {
+	case LS_FILE:
 		ls_print(&de);
-	} else {
+		break;
+	case LS_DIR:
 		dirp = opendir(de.name);
 		if (!dirp) {
@@ -274,11 +404,21 @@
 			return CMD_FAILURE;
 		}
-		ls_scan_dir(de.name, dirp, sort);
+		if (ls.recursive)
+			ret = ls_recursive(de.name, dirp);
+		else  
+			ret = ls_scan_dir(de.name, dirp, NULL);
+
 		closedir(dirp);
+		break;
+	case LS_BOGUS:
+		return CMD_FAILURE;
 	}
 
 	free(de.name);
 
-	return CMD_SUCCESS;
-}
-
+	if (ret == -1 || ret == CMD_FAILURE)
+		return CMD_FAILURE;
+	else
+		return CMD_SUCCESS;
+}
+
Index: uspace/app/bdsh/cmds/modules/ls/ls.h
===================================================================
--- uspace/app/bdsh/cmds/modules/ls/ls.h	(revision 9463b245f7fbec8cdcde658d98d96baeb010663d)
+++ uspace/app/bdsh/cmds/modules/ls/ls.h	(revision 9463b245f7fbec8cdcde658d98d96baeb010663d)
@@ -0,0 +1,26 @@
+#ifndef LS_H
+#define LS_H
+
+/* Various values that can be returned by ls_scope() */
+#define LS_BOGUS 0
+#define LS_FILE  1
+#define LS_DIR   2
+
+typedef struct {
+	/* Options set at runtime. */
+	unsigned int recursive;
+	unsigned int sort;
+
+} ls_job_t;
+
+/** Structure to represent a directory entry.
+ *
+ * Useful to keep together important information
+ * for sorting directory entries.
+ */
+struct dir_elem_t {
+	char *name;
+	struct stat s;
+};
+
+#endif
