[libc] add n versions of sprintf and vprintf
diff --git a/include/printf.h b/include/printf.h
index 5006530..2d09120 100644
--- a/include/printf.h
+++ b/include/printf.h
@@ -33,7 +33,9 @@
 
 int printf(const char *fmt, ...);
 int sprintf(char *str, const char *fmt, ...) __PRINTFLIKE(2, 3);
+int snprintf(char *str, size_t len, const char *fmt, ...) __PRINTFLIKE(3, 4);
 int vsprintf(char *str, const char *fmt, va_list ap);
+int vsnprintf(char *str, size_t len, const char *fmt, va_list ap);
 
 #if defined(__cplusplus)
 }
diff --git a/lib/libc/printf.c b/lib/libc/printf.c
index af9379e..b7bf2bb 100644
--- a/lib/libc/printf.c
+++ b/lib/libc/printf.c
@@ -66,6 +66,18 @@
 	return err;
 }
 
+int snprintf(char *str, size_t len, const char *fmt, ...)
+{
+	int err;
+
+	va_list ap;
+	va_start(ap, fmt);
+	err = vsnprintf(str, len, fmt, ap);
+	va_end(ap);
+
+	return err;
+}
+
 
 #define LONGFLAG     0x00000001
 #define LONGLONGFLAG 0x00000002
@@ -134,6 +146,11 @@
 
 int vsprintf(char *str, const char *fmt, va_list ap)
 {
+	return vsnprintf(str, INT_MAX, fmt, ap);
+}
+
+int vsnprintf(char *str, size_t len, const char *fmt, va_list ap)
+{
 	char c;
 	unsigned char uc;
 	const char *s;
@@ -141,10 +158,11 @@
 	void *ptr;
 	int flags;
 	unsigned int format_num;
-	int chars_written = 0;
+	size_t chars_written = 0;
 	char num_buffer[32];
 
-#define OUTPUT_CHAR(c) do { (*str++ = c); chars_written++; } while(0)
+#define OUTPUT_CHAR(c) do { (*str++ = c); chars_written++; if (chars_written + 1 == len) goto done; } while(0)
+#define OUTPUT_CHAR_NOLENCHECK(c) do { (*str++ = c); chars_written++; } while(0)
 
 	for(;;) {	
 		/* handle regular chars that aren't format related */
@@ -309,11 +327,13 @@
 		continue;
 	}
 
+done:
 	/* null terminate */
-	OUTPUT_CHAR('\0');
+	OUTPUT_CHAR_NOLENCHECK('\0');
 	chars_written--; /* don't count the null */
 
 #undef OUTPUT_CHAR
+#undef OUTPUT_CHAR_NOLENCHECK
 
 	return chars_written;
 }