Index: uspace/app/bithenge/print.c
===================================================================
--- uspace/app/bithenge/print.c	(revision 842ed1463f51ccdba3bacb329247f4a11eed8ee0)
+++ uspace/app/bithenge/print.c	(revision 6be4142b13aac4b9ed8b2805a5a6998491afc977)
@@ -38,4 +38,5 @@
 
 #include <errno.h>
+#include <stdarg.h>
 #include <stdio.h>
 #include "blob.h"
@@ -47,13 +48,34 @@
 	bool first;
 	int depth;
+	char *buffer;
+	size_t buffer_size;
 } state_t;
 
+static void state_printf(state_t *state, const char *format, ...)
+{
+	va_list ap;
+	va_start(ap, format);
+	if (state->buffer) {
+		int rc = vsnprintf(state->buffer, state->buffer_size, format,
+		    ap);
+		if (rc > 0 && (size_t)rc >= state->buffer_size)
+			rc = state->buffer_size - 1;
+		if (rc > 0) {
+			state->buffer += rc;
+			state->buffer_size -= rc;
+		}
+	} else {
+		vprintf(format, ap);
+	}
+	va_end(ap);
+}
+
 static int print_node(state_t *, bithenge_node_t *);
 
 static void newline(state_t *state)
 {
-	printf("\n");
+	state_printf(state, "\n");
 	for (int i = 0; i < state->depth; i++) {
-		printf("    ");
+		state_printf(state, "    ");
 	}
 }
@@ -74,5 +96,5 @@
 	int rc = EOK;
 	if (!state->first)
-		printf(",");
+		state_printf(state, ",");
 	newline(state);
 	state->first = false;
@@ -80,11 +102,11 @@
 	    && bithenge_node_type(key) != BITHENGE_NODE_STRING;
 	if (add_quotes)
-		printf("\"");
+		state_printf(state, "\"");
 	rc = print_node(state, key);
 	if (rc != EOK)
 		goto end;
 	if (add_quotes)
-		printf("\"");
-	printf(": ");
+		state_printf(state, "\"");
+	state_printf(state, ": ");
 	rc = print_node(state, value);
 	if (rc != EOK)
@@ -99,5 +121,5 @@
 {
 	int rc;
-	printf("{");
+	state_printf(state, "{");
 	increase_depth(state);
 	state->first = true;
@@ -109,5 +131,5 @@
 		newline(state);
 	state->first = false;
-	printf("}");
+	state_printf(state, "}");
 	return EOK;
 }
@@ -118,8 +140,8 @@
 	switch (state->type) {
 	case BITHENGE_PRINT_PYTHON:
-		printf(value ? "True" : "False");
+		state_printf(state, value ? "True" : "False");
 		break;
 	case BITHENGE_PRINT_JSON:
-		printf(value ? "true" : "false");
+		state_printf(state, value ? "true" : "false");
 		break;
 	}
@@ -130,5 +152,5 @@
 {
 	bithenge_int_t value = bithenge_integer_node_value(node);
-	printf("%" BITHENGE_PRId, value);
+	state_printf(state, "%" BITHENGE_PRId, value);
 	return EOK;
 }
@@ -137,5 +159,5 @@
 {
 	const char *value = bithenge_string_node_value(node);
-	printf("\"");
+	state_printf(state, "\"");
 	for (string_iterator_t i = string_iterator(value); !string_iterator_done(&i); ) {
 		wchar_t ch;
@@ -144,12 +166,12 @@
 			return rc;
 		if (ch == '"' || ch == '\\') {
-			printf("\\%lc", (wint_t) ch);
+			state_printf(state, "\\%lc", (wint_t) ch);
 		} else if (ch <= 0x1f) {
-			printf("\\u%04x", (unsigned int) ch);
+			state_printf(state, "\\u%04x", (unsigned int) ch);
 		} else {
-			printf("%lc", (wint_t) ch);
+			state_printf(state, "%lc", (wint_t) ch);
 		}
 	}
-	printf("\"");
+	state_printf(state, "\"");
 	return EOK;
 }
@@ -162,5 +184,6 @@
 	aoff64_t size = sizeof(buffer);
 	int rc;
-	printf(state->type == BITHENGE_PRINT_PYTHON ? "b\"" : "\"");
+	state_printf(state,
+	    state->type == BITHENGE_PRINT_PYTHON ? "b\"" : "\"");
 	do {
 		rc = bithenge_blob_read(blob, pos, buffer, &size);
@@ -168,8 +191,9 @@
 			return rc;
 		for (aoff64_t i = 0; i < size; i++)
-			printf("\\x%02x", (unsigned int)(uint8_t)buffer[i]);
+			state_printf(state, "\\x%02x",
+			    (unsigned int)(uint8_t)buffer[i]);
 		pos += size;
 	} while (size == sizeof(buffer));
-	printf("\"");
+	state_printf(state, "\"");
 	return EOK;
 }
@@ -192,5 +216,5 @@
 }
 
-/** Print a tree as text.
+/** Print a tree as text to stdout.
  * @param type The format to use.
  * @param tree The root node of the tree to print.
@@ -198,8 +222,26 @@
 int bithenge_print_node(bithenge_print_type_t type, bithenge_node_t *tree)
 {
-	state_t state = {type, true, 0};
+	state_t state = {type, true, 0, NULL, 0};
 	return print_node(&state, tree);
 }
 
+/** Print a tree as text into a buffer.
+ * @param[in,out] str Holds a pointer to the buffer; changed to point to the
+ * null character.
+ * @param[in,out] size Holds the size of the buffer; changed to hold the
+ * remaining size.
+ * @param type The format to use.
+ * @param tree The root node of the tree to print.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_print_node_to_string(char **str, size_t *size,
+    bithenge_print_type_t type, bithenge_node_t *tree)
+{
+	state_t state = {type, true, 0, *str, *size};
+	int rc = print_node(&state, tree);
+	*str = state.buffer;
+	*size = state.buffer_size;
+	return rc;
+}
+
 /** @}
  */
