=== modified file 'uspace/app/bdsh/cmds/modules/cat/cat.c'
--- uspace/app/bdsh/cmds/modules/cat/cat.c	2011-09-09 15:46:21 +0000
+++ uspace/app/bdsh/cmds/modules/cat/cat.c	2012-03-30 22:30:13 +0000
@@ -51,8 +51,8 @@
 static const char *cmdname = "cat";
 #define CAT_VERSION "0.0.1"
 #define CAT_DEFAULT_BUFLEN 1024
+#define CAT_FULL_FILE 0
 
-static const char *cat_oops = "That option is not yet supported\n";
 static const char *hexchars = "0123456789abcdef";
 
 static bool paging_enabled = false;
@@ -162,12 +162,13 @@
 	}
 }
 
-static unsigned int cat_file(const char *fname, size_t blen, bool hex)
+static unsigned int cat_file(const char *fname, size_t blen, bool hex, aoff64_t head, aoff64_t tail, bool tail_first)
 {
-	int fd, bytes = 0, count = 0, reads = 0;
+	int fd, bytes = 0, reads = 0;
 	char *buff = NULL;
 	int i;
-	size_t offset = 0;
+	size_t offset = 0, copied_bytes = 0;
+	aoff64_t file_size = 0, count = 0, length = 0;
 
 	fd = open(fname, O_RDONLY);
 	if (fd < 0) {
@@ -182,30 +183,64 @@
 		return 1;
 	}
 
+	if (tail != CAT_FULL_FILE) {
+		file_size = lseek(fd, 0, SEEK_END);
+		if (head == CAT_FULL_FILE) {
+			head = file_size;
+			length = tail;
+		} else if (tail_first) {
+			length = head;
+		} else {
+			if (tail > head)
+				tail = head;
+			length = tail;
+		}
+
+		if (tail_first) {
+			lseek(fd, (tail >= file_size) ? 0 : (file_size - tail), SEEK_SET);
+		} else {
+			lseek(fd, ((head - tail) >= file_size) ? 0 : (head - tail), SEEK_SET);
+		}
+	} else
+		length = head;
+
 	do {
-		bytes = read(fd, buff, blen);
+		bytes = read(fd, buff + copied_bytes, (
+			(length != CAT_FULL_FILE && length - count <= (aoff64_t)(blen - copied_bytes)) ?
+			(size_t)(length - count) :
+			(blen - copied_bytes) ) );
+		bytes += copied_bytes;
+		copied_bytes = 0;
+
 		if (bytes > 0) {
-			count += bytes;
 			buff[bytes] = '\0';
 			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]);
+					paged_char(((count+i+1) & 0xf) == 0 ? '\n' : ' ');
 				}
 				else {
 					wchar_t c = str_decode(buff, &offset, bytes);
 					if (c == 0) {
 						/* Reached end of string */
 						break;
+					} else if (c == U_SPECIAL && offset + 2 >= (size_t)bytes) {
+						/* If an extended character is cut off due to the size of the buffer,
+						   we will copy it over to the next buffer so it can be read correctly. */
+						copied_bytes = bytes - offset + 1;
+						memcpy(buff, buff + offset - 1, copied_bytes);
+						break;
 					}
 					paged_char(c);
 				}
 				
 			}
+			count += bytes;
 			reads++;
 		}
-	} while (bytes > 0 && !should_quit);
+	} while (bytes > 0 && !should_quit && (count < length || length == CAT_FULL_FILE));
 
 	close(fd);
 	if (bytes == -1) {
@@ -224,8 +259,10 @@
 {
 	unsigned int argc, i, ret = 0, buffer = 0;
 	int c, opt_ind;
+	aoff64_t head = CAT_FULL_FILE, tail = CAT_FULL_FILE;
 	bool hex = false;
 	bool more = false;
+	bool tail_first = false;
 	sysarg_t rows, cols;
 	int rc;
 	
@@ -253,13 +290,24 @@
 			printf("%s\n", CAT_VERSION);
 			return CMD_SUCCESS;
 		case 'H':
-			printf("%s", cat_oops);
-			return CMD_FAILURE;
+			if (!optarg || str_uint64_t(optarg, NULL, 10, false, (uint64_t *)&head) != EOK ){
+				puts("Invalid head size\n");
+				return CMD_FAILURE;
+			}
+			break;
 		case 't':
-			printf("%s", cat_oops);
-			return CMD_FAILURE;
+			if (!optarg || str_uint64_t(optarg, NULL, 10, false, (uint64_t *)&tail) != EOK ){
+				puts("Invalid tail size\n");
+				return CMD_FAILURE;
+			}
+			if (head == CAT_FULL_FILE)
+				tail_first = true;
+			break;
 		case 'b':
-			printf("%s", cat_oops);
+			if (!optarg || str_size_t(optarg, NULL, 10, false, &buffer) != EOK ){
+				puts("Invalid buffer size\n");
+				return CMD_FAILURE;
+			}
 			break;
 		case 'm':
 			more = true;
@@ -278,7 +326,7 @@
 		return CMD_FAILURE;
 	}
 
-	if (buffer <= 0)
+	if (buffer < 4)
 		buffer = CAT_DEFAULT_BUFLEN;
 	
 	if (more) {
@@ -294,7 +342,7 @@
 	}
 
 	for (i = optind; argv[i] != NULL && !should_quit; i++)
-		ret += cat_file(argv[i], buffer, hex);
+		ret += cat_file(argv[i], buffer, hex, head, tail, tail_first);
 
 	if (ret)
 		return CMD_FAILURE;

=== modified file 'uspace/app/bdsh/cmds/modules/cat/cat.h'
--- uspace/app/bdsh/cmds/modules/cat/cat.h	2011-05-01 19:34:26 +0000
+++ uspace/app/bdsh/cmds/modules/cat/cat.h	2012-03-30 22:23:09 +0000
@@ -3,7 +3,7 @@
 
 /* Prototypes for the cat command, excluding entry points */
 
-static unsigned int cat_file(const char *, size_t, bool);
+static unsigned int cat_file(const char *, size_t, bool, aoff64_t, aoff64_t, bool);
 
 #endif /* CAT_H */
 

