tprintf: fix va_list arg exhaustion
[netsniff-ng-old.git] / src / tprintf.c
blob4022b295dd5191e0a3cecef77bd27fd1347c3d1b
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * By Daniel Borkmann <daniel@netsniff-ng.org>
4 * Copyright 2009, 2010 Daniel Borkmann.
5 * Subject to the GPL, version 2.
6 */
8 #define _BSD_SOURCE
9 #include <stdio.h>
10 #include <stdarg.h>
12 #include "xsys.h"
13 #include "tprintf.h"
14 #include "die.h"
15 #include "locking.h"
16 #include "built_in.h"
18 static char buffer[1024];
19 static size_t buffer_use = 0;
21 static struct spinlock buffer_lock;
22 static size_t lcount = 0;
24 size_t tprintf_get_free_count(void)
26 size_t ret;
28 spinlock_lock(&buffer_lock);
29 ret = get_tty_size() - 5 - lcount;
30 spinlock_unlock(&buffer_lock);
32 return ret;
36 * We want to print our stuff terminal aligned. Since we're printing packets
37 * we're in slowpath anyways. If stdin/stdout are connected to a terminal
38 * then default size = 1024; else size = 4096.
40 void tprintf_flush(void)
42 char *ptr = buffer;
43 size_t flush_len = get_tty_size() - 5;
45 while (buffer_use-- > 0) {
46 if (lcount == flush_len) {
47 fputs("\n ", stdout);
48 lcount = 3;
49 while (buffer_use > 0 && (*ptr == ' ' ||
50 *ptr == ',' || *ptr == '\n')) {
51 buffer_use--;
52 ptr++;
56 if (*ptr == '\n') {
57 flush_len = get_tty_size() - 5;
58 lcount = -1;
61 /* Collect in stream buffer. */
62 fputc(*ptr, stdout);
63 ptr++;
64 lcount++;
67 fflush(stdout);
68 buffer_use++;
70 bug_on(buffer_use > 0);
73 void tprintf_init(void)
75 spinlock_init(&buffer_lock);
76 memset(buffer, 0, sizeof(buffer));
79 void tprintf_cleanup(void)
81 spinlock_lock(&buffer_lock);
82 tprintf_flush();
83 spinlock_unlock(&buffer_lock);
84 spinlock_destroy(&buffer_lock);
87 void tprintf(char *msg, ...)
89 int ret;
90 ssize_t avail;
91 va_list vl;
93 spinlock_lock(&buffer_lock);
94 avail = sizeof(buffer) - buffer_use;
96 va_start(vl, msg);
97 ret = vsnprintf(buffer + buffer_use, avail, msg, vl);
98 va_end(vl);
99 if (ret < 0)
100 panic("vsnprintf screwed up in tprintf!\n");
101 if (ret > sizeof(buffer))
102 panic("No mem in tprintf left!\n");
103 if (ret >= avail) {
104 buffer[buffer_use] = 0;
105 tprintf_flush();
107 avail = sizeof(buffer) - buffer_use;
108 va_start(vl, msg);
109 ret = vsnprintf(buffer + buffer_use, avail, msg, vl);
110 va_end(vl);
111 if (ret < 0)
112 panic("vsnprintf screwed up in tprintf!\n");
115 buffer_use += ret;
116 spinlock_unlock(&buffer_lock);