=== modified file 'kernel/generic/include/console/console.h'
--- kernel/generic/include/console/console.h	2012-11-23 20:25:27 +0000
+++ kernel/generic/include/console/console.h	2013-07-26 02:09:08 +0000
@@ -64,6 +64,9 @@
 extern void klog_init(void);
 extern void klog_update(void *);
 
+extern void kpager_setup(int line_max);
+extern void kpager_keypress(void);
+
 extern wchar_t getc(indev_t *indev);
 extern size_t gets(indev_t *indev, char *buf, size_t buflen);
 extern sysarg_t sys_klog(int cmd, const void *buf, size_t size);

=== modified file 'kernel/generic/src/console/cmd.c'
--- kernel/generic/src/console/cmd.c	2012-11-23 15:52:03 +0000
+++ kernel/generic/src/console/cmd.c	2013-07-26 06:06:55 +0000
@@ -83,6 +83,19 @@
 	.argc = 0
 };
 
+/* Data and methods for 'pager' command. */
+static int cmd_pager(cmd_arg_t *argv);
+static cmd_arg_t pager_argv = {
+	.type = ARG_TYPE_INT,
+};
+static cmd_info_t pager_info = {
+	.name = "pager",
+	.description = "Hold kconsole commands' output until key pressed.",
+	.func = cmd_pager,
+	.argc = 1,
+	.argv = &pager_argv
+};
+
 /* Data and methods for pio_read_8 command */
 static int cmd_pio_read_8(cmd_arg_t *argv);
 static cmd_arg_t pio_read_8_argv[] = { { .type = ARG_TYPE_INT } };
@@ -585,6 +598,7 @@
 	&help_info,
 	&ipc_info,
 	&kill_info,
+	&pager_info,
 	&physmem_info,
 	&reboot_info,
 	&sched_info,
@@ -685,6 +699,23 @@
 	return 1;
 }
 
+/** KConsole pager utility. Hold line printing and resume on key press.
+ *
+ * @param argv Argument vector.
+ *
+ * @return 0 on failure, 1 on success.
+ */
+int cmd_pager(cmd_arg_t *argv)
+{
+	if (argv[0].intval == 0)
+		printf("Pager off.\n");
+	else
+		printf("Pager on and set to %d lines.\n", argv[0].intval);
+
+	kpager_setup(argv[0].intval);	
+	return 1;
+}
+
 /** Read 1 byte from phys memory or io port.
  *
  * @param argv Argument vector.

=== modified file 'kernel/generic/src/console/console.c'
--- kernel/generic/src/console/console.c	2012-12-02 16:42:21 +0000
+++ kernel/generic/src/console/console.c	2013-07-26 06:04:47 +0000
@@ -80,6 +80,31 @@
 /** Physical memory area used for klog buffer */
 static parea_t klog_parea;
 
+/** Kernel console pager cyclic buffer store characters not yet confirmed
+ *  to be printed. Characters are not stored in klog so kcon commands' output
+ *  does not block other msgs. */
+#define KPAGER_PAGES    KLOG_PAGES
+#define KPAGER_LENGTH   (KPAGER_PAGES * PAGE_SIZE / sizeof(wchar_t))
+
+/** Kernel console pager cyclic buffer */
+wchar_t kpager[KPAGER_LENGTH] __attribute__((aligned(PAGE_SIZE)));
+
+/** First kernel console pager characters */
+static size_t kpager_start = 0;
+
+/** Number of valid kernel console pager characters */
+static size_t kpager_len = 0;
+
+/** Number of stored (not printed) kernel console pager characters */
+static size_t kpager_stored = 0;
+
+/** Number of max lines to print at once.
+ *  Rest is stored in kernel console pager buffer */
+static int kpager_line_max = 0;
+
+/** Number of currently printed lines without user interaction */
+static int kpager_line_count = 0;
+
 static indev_t stdin_sink;
 static outdev_t stdout_source;
 
@@ -264,10 +289,125 @@
 	spinlock_unlock(&klog_lock);
 }
 
+/** Turn kpager on or off. Positive integer only.
+ *
+ * @param line_max Value above zero turn paging on. Zero turn paging off.
+ *
+ */
+void kpager_setup(int line_max)
+{
+	kpager_line_max = line_max;
+	kpager_line_count = 0;
+}
+
+/** More lines can be printed. */
+void kpager_keypress(void)
+{
+	kpager_line_count = 0;
+}
+
+/** Store the character in kpager buffer. */
+void kpager_buf_store(const wchar_t ch);
+void kpager_buf_store(const wchar_t ch)
+{
+	kpager[(kpager_start + kpager_len) % KPAGER_LENGTH] = ch;
+	if (kpager_len < KPAGER_LENGTH)
+		kpager_len++;
+	else
+		kpager_start = (kpager_start + 1) % KPAGER_LENGTH;
+	kpager_stored++;
+}
+
+/** Print lines possible. Store the character at the end if buffer is not empty.
+ *  Printed characters are also copied to klog.
+ *
+ * @return True if no more characters to print from buffer. False otherwise.
+ *
+ */ 
+bool kpager_buf_print(const wchar_t ch);
+bool kpager_buf_print(const wchar_t ch)
+{
+	while (kpager_stored > 0) {
+		wchar_t tmp = kpager[(kpager_start + kpager_len - kpager_stored) % KPAGER_LENGTH];
+		kpager_stored--;
+		
+		stdout->op->write(stdout, tmp);
+		
+		/* Store character in the cyclic kernel log */
+		spinlock_lock(&klog_lock);
+		klog[(klog_start + klog_len) % KLOG_LENGTH] = tmp;
+		if (klog_len < KLOG_LENGTH)
+			klog_len++;
+		else
+			klog_start = (klog_start + 1) % KLOG_LENGTH;
+		spinlock_unlock(&klog_lock);
+
+		if (tmp == '\n') {
+			kpager_line_count++;
+			bool prdy = (kpager_line_max == 0 || kpager_line_count < kpager_line_max);
+			if (!prdy) { 
+				kpager_buf_store(ch);
+				return false;
+			}
+		}
+	}
+	return true;
+}
+
+/** Check if the current thread is 'kconsole'.
+ *
+ * @return True for 'kconsole' thread. Else otherwise.
+ *
+ */
+bool is_kconsole_thread(void);
+bool is_kconsole_thread(void)
+{
+	if (!THREAD)
+		return false;
+
+	// TODO checking tid or thread ptr would be better, faster?
+	ASSERT(THREAD_NAME_BUFLEN>4);
+	return THREAD->name[0] == 'k' && THREAD->name[1] == 'c' 
+		&& THREAD->name[2] == 'o' && THREAD->name[3] == 'n';
+}
+
+/** Run kernel console paging. 
+ *
+ * @return False if character is buffered in kpager and should not be printed.
+ *
+ */
+bool kpaging(const wchar_t ch, bool ordy);
+bool kpaging(const wchar_t ch, bool ordy)
+{
+	bool kcon_thread = is_kconsole_thread();
+	if (!kcon_thread)
+		return true;
+
+	/* true - can print atleast a line more */
+	bool prdy = (kpager_line_max == 0 || kpager_line_count < kpager_line_max);
+	
+	if (!prdy) {
+		kpager_buf_store(ch);
+		return false;
+	} else if (ordy && prdy) { 
+		if (!kpager_buf_print(ch))
+			return false;
+	/* Move to klog if (!ordy && ordy) ? */ 
+	}
+	if (ch == '\n')
+		kpager_line_count++;
+
+	return true;
+}
+
 void putchar(const wchar_t ch)
 {
 	bool ordy = ((stdout) && (stdout->op->write));
-	
+
+	/* Handle paging and return if nothing to print or buf */ 
+	if (!kpaging(ch, ordy))
+		return;
+
 	spinlock_lock(&klog_lock);
 	
 	/* Print charaters stored in kernel log */

=== modified file 'kernel/generic/src/console/kconsole.c'
--- kernel/generic/src/console/kconsole.c	2012-11-12 01:04:45 +0000
+++ kernel/generic/src/console/kconsole.c	2013-07-26 03:02:48 +0000
@@ -291,6 +291,7 @@
 	
 	while (true) {
 		wchar_t ch = indev_pop_character(indev);
+		kpager_keypress();
 		
 		if (ch == '\n') {
 			/* Enter */
@@ -747,7 +748,7 @@
 		size_t len = wstr_length(tmp);
 		if (!len)
 			continue;
-		
+	
 		wstr_to_str(cmdline, STR_BOUNDS(MAX_CMDLINE), tmp);
 		
 		if ((!kcon) && (len == 4) && (str_lcmp(cmdline, "exit", 4) == 0))
@@ -756,7 +757,7 @@
 		cmd_info_t *cmd_info = parse_cmdline(cmdline, STR_BOUNDS(MAX_CMDLINE));
 		if (!cmd_info)
 			continue;
-		
+
 		(void) cmd_info->func(cmd_info->argv);
 	}
 	free(cmdline);

