Index: uspace/app/bdsh/cmds/modules/cat/cat.c
===================================================================
--- uspace/app/bdsh/cmds/modules/cat/cat.c	(revision 557ea4f6be3897ffde3eb918b09add1a594b9911)
+++ uspace/app/bdsh/cmds/modules/cat/cat.c	(revision 3317724ade03c3602e2ba1e125180ec5fe566732)
@@ -1,3 +1,4 @@
 /* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
+ * Copyright (c) 2011, Martin Sucha
  * All rights reserved.
  *
@@ -35,4 +36,11 @@
 #include <str.h>
 #include <fcntl.h>
+#include <io/console.h>
+#include <io/color.h>
+#include <io/style.h>
+#include <io/keycode.h>
+#include <errno.h>
+#include <vfs/vfs.h>
+#include <assert.h>
 
 #include "config.h"
@@ -48,4 +56,12 @@
 
 static const char *cat_oops = "That option is not yet supported\n";
+static const char *hexchars = "0123456789abcdef";
+
+static bool paging_enabled = false;
+static size_t chars_remaining = 0;
+static size_t lines_remaining = 0;
+static sysarg_t console_cols = 0;
+static sysarg_t console_rows = 0;
+static bool should_quit = false;
 
 static struct option const long_options[] = {
@@ -56,4 +72,5 @@
 	{ "buffer", required_argument, 0, 'b' },
 	{ "more", no_argument, 0, 'm' },
+	{ "hex", no_argument, 0, 'x' },
 	{ 0, 0, 0, 0 }
 };
@@ -75,4 +92,5 @@
 		"  -b, --buffer ##  Set the read buffer size to ##\n"
 		"  -m, --more       Pause after each screen full\n"
+		"  -x, --hex        Print bytes as hex values\n"
 		"Currently, %s is under development, some options don't work.\n",
 		cmdname, cmdname);
@@ -82,9 +100,72 @@
 }
 
-static unsigned int cat_file(const char *fname, size_t blen)
+static void waitprompt()
+{
+	console_set_pos(fphone(stdout), 0, console_rows-1);
+	console_set_color(fphone(stdout), COLOR_BLUE, COLOR_WHITE, 0);
+	printf("ENTER/SPACE/PAGE DOWN - next page, "
+	       "ESC/Q - quit, C - continue unpaged");
+	fflush(stdout);
+	console_set_style(fphone(stdout), STYLE_NORMAL);
+}
+
+static void waitkey()
+{
+	console_event_t ev;
+	
+	while (true) {
+		if (!console_get_event(fphone(stdin), &ev)) {
+			return;
+		}
+		if (ev.type == KEY_PRESS) {
+			if (ev.key == KC_ESCAPE || ev.key == KC_Q) {
+				should_quit = true;
+				return;
+			}
+			if (ev.key == KC_C) {
+				paging_enabled = false;
+				return;
+			}
+			if (ev.key == KC_ENTER || ev.key == KC_SPACE ||
+			    ev.key == KC_PAGE_DOWN) {
+				return;
+			}
+		}
+	}
+	assert(false);
+}
+
+static void newpage()
+{
+	console_clear(fphone(stdout));
+	chars_remaining = console_cols;
+	lines_remaining = console_rows-1;
+}
+
+static void paged_char(wchar_t c)
+{
+	putchar(c);
+	if (paging_enabled) {
+		chars_remaining--;
+		if (c == '\n' || chars_remaining == 0) {
+			chars_remaining = console_cols;
+			lines_remaining--;
+		}
+		if (lines_remaining == 0) {
+			fflush(stdout);
+			waitprompt();
+			waitkey();
+			newpage();
+		}
+	}
+}
+
+static unsigned int cat_file(const char *fname, size_t blen, bool hex)
 {
 	int fd, bytes = 0, count = 0, reads = 0;
 	off64_t total = 0;
 	char *buff = NULL;
+	int i;
+	size_t offset = 0;
 
 	fd = open(fname, O_RDONLY);
@@ -109,8 +190,23 @@
 			count += bytes;
 			buff[bytes] = '\0';
-			printf("%s", buff);
+			offset = 0;
+			for (i = 0; i < bytes && !should_quit; i++) {
+				if (hex) {
+					paged_char(hexchars[((uint8_t)buff[i])/16]);
+					paged_char(hexchars[((uint8_t)buff[i])%16]);
+				}
+				else {
+					wchar_t c = str_decode(buff, &offset, bytes);
+					if (c == 0) {
+						// reached end of string
+						break;
+					}
+					paged_char(c);
+				}
+				
+			}
 			reads++;
 		}
-	} while (bytes > 0);
+	} while (bytes > 0 && !should_quit);
 
 	close(fd);
@@ -131,9 +227,22 @@
 	unsigned int argc, i, ret = 0, buffer = 0;
 	int c, opt_ind;
+	bool hex = false;
+	bool more = false;
+	sysarg_t rows, cols;
+	int rc;
+	
+	// reset global state
+	// TODO: move to structure?
+	paging_enabled = false;
+	chars_remaining = 0;
+	lines_remaining = 0;
+	console_cols = 0;
+	console_rows = 0;
+	should_quit = false;
 
 	argc = cli_count_args(argv);
 
 	for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
-		c = getopt_long(argc, argv, "hvmH:t:b:", long_options, &opt_ind);
+		c = getopt_long(argc, argv, "xhvmH:t:b:", long_options, &opt_ind);
 		switch (c) {
 		case 'h':
@@ -144,15 +253,18 @@
 			return CMD_SUCCESS;
 		case 'H':
-			printf(cat_oops);
+			printf("%s", cat_oops);
 			return CMD_FAILURE;
 		case 't':
-			printf(cat_oops);
+			printf("%s", cat_oops);
 			return CMD_FAILURE;
 		case 'b':
-			printf(cat_oops);
+			printf("%s", cat_oops);
 			break;
 		case 'm':
-			printf(cat_oops);
-			return CMD_FAILURE;
+			more = true;
+			break;
+		case 'x':
+			hex = true;
+			break;
 		}
 	}
@@ -168,7 +280,19 @@
 	if (buffer <= 0)
 		buffer = CAT_DEFAULT_BUFLEN;
-
-	for (i = optind; argv[i] != NULL; i++)
-		ret += cat_file(argv[i], buffer);
+	
+	if (more) {
+		rc = console_get_size(fphone(stdout), &cols, &rows);
+		if (rc != EOK) {
+			printf("%s - cannot get console size\n", cmdname);
+			return CMD_FAILURE;
+		}
+		console_cols = cols;
+		console_rows = rows;
+		paging_enabled = true;
+		newpage();
+	}
+
+	for (i = optind; argv[i] != NULL && !should_quit; i++)
+		ret += cat_file(argv[i], buffer, hex);
 
 	if (ret)
Index: uspace/app/bdsh/cmds/modules/cat/cat.h
===================================================================
--- uspace/app/bdsh/cmds/modules/cat/cat.h	(revision 557ea4f6be3897ffde3eb918b09add1a594b9911)
+++ uspace/app/bdsh/cmds/modules/cat/cat.h	(revision 3317724ade03c3602e2ba1e125180ec5fe566732)
@@ -4,5 +4,5 @@
 /* Prototypes for the cat command, excluding entry points */
 
-static unsigned int cat_file(const char *, size_t);
+static unsigned int cat_file(const char *, size_t, bool);
 
 #endif /* CAT_H */
Index: uspace/app/bdsh/cmds/modules/cp/cp.c
===================================================================
--- uspace/app/bdsh/cmds/modules/cp/cp.c	(revision 557ea4f6be3897ffde3eb918b09add1a594b9911)
+++ uspace/app/bdsh/cmds/modules/cp/cp.c	(revision 3317724ade03c3602e2ba1e125180ec5fe566732)
@@ -108,4 +108,5 @@
 	for (;;) {
 		ssize_t res;
+		size_t written = 0;
 
 		bytes = read(fd1, buff, blen);
@@ -120,7 +121,8 @@
 			 * returned less data than requested.
 			 */
-			bytes = write(fd2, buff, res);
+			bytes = write(fd2, buff + written, res);
 			if (bytes < 0)
 				goto err;
+			written += bytes;
 			res -= bytes;
 		} while (res > 0);
Index: uspace/app/bdsh/cmds/modules/rm/rm.c
===================================================================
--- uspace/app/bdsh/cmds/modules/rm/rm.c	(revision 557ea4f6be3897ffde3eb918b09add1a594b9911)
+++ uspace/app/bdsh/cmds/modules/rm/rm.c	(revision 3317724ade03c3602e2ba1e125180ec5fe566732)
@@ -101,7 +101,42 @@
 }
 
+static unsigned int rm_recursive_not_empty_dirs(const char *path)
+{
+	DIR *dirp;
+	struct dirent *dp;
+	char buff[PATH_MAX];
+	unsigned int scope;
+	unsigned int ret = 0;
+
+	dirp = opendir(path);
+	if (!dirp) {
+		/* May have been deleted between scoping it and opening it */
+		cli_error(CL_EFAIL, "Could not open %s", path);
+		return ret;
+	}
+
+	memset(buff, 0, sizeof(buff));
+	while ((dp = readdir(dirp))) {
+		snprintf(buff, PATH_MAX - 1, "%s/%s", path, dp->d_name);
+		scope = rm_scope(buff);
+		switch (scope) {
+		case RM_BOGUS:
+			break;
+		case RM_FILE:
+			ret += rm_single(buff);
+			break;
+		case RM_DIR:
+			ret += rm_recursive(buff);
+			break;
+		}
+	}
+	
+	return ret;
+}
+
 static unsigned int rm_recursive(const char *path)
 {
 	int rc;
+	unsigned int ret = 0;
 
 	/* First see if it will just go away */
@@ -111,7 +146,14 @@
 
 	/* Its not empty, recursively scan it */
-	cli_error(CL_ENOTSUP,
-		"Can not remove %s, directory not empty", path);
-	return 1;
+	ret = rm_recursive_not_empty_dirs(path);
+
+	/* Delete directory */
+	rc = rmdir(path);
+	if (rc == 0)
+		return ret;
+
+	cli_error(CL_ENOTSUP, "Can not remove %s", path);
+
+	return ret + 1;
 }
 
@@ -227,5 +269,5 @@
 		}
 		memset(buff, 0, sizeof(buff));
-		snprintf(buff, len, argv[i]);
+		snprintf(buff, len, "%s", argv[i]);
 
 		scope = rm_scope(buff);
