Merge pull request #58 from electronjoe/a1cf780cccc4819eb360cda1e0e94e17935cb8c7
[netsniff-ng-old.git] / tprintf.c
blob46e9574a20a280ae9b2fcfe3bf8fdc5c9e6d7799
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2009, 2010 Daniel Borkmann.
4 * Copyright 2013 Tobias Klauser.
5 * Subject to the GPL, version 2.
6 */
8 #define _BSD_SOURCE
9 #include <ctype.h>
10 #include <stdio.h>
11 #include <stdarg.h>
12 #include <sys/ioctl.h>
14 #include "xutils.h"
15 #include "tprintf.h"
16 #include "die.h"
17 #include "locking.h"
18 #include "built_in.h"
20 #define term_trailing_size 5
21 #define term_starting_size 3
23 #define term_curr_size (get_tty_size() - term_trailing_size)
25 static char buffer[1024];
27 static volatile size_t buffer_use = 0;
29 static struct spinlock buffer_lock;
31 static int get_tty_size(void)
33 #ifdef TIOCGSIZE
34 struct ttysize ts = {0};
36 return (ioctl(0, TIOCGSIZE, &ts) == 0 ? ts.ts_cols : DEFAULT_TTY_SIZE);
37 #elif defined(TIOCGWINSZ)
38 struct winsize ts;
40 return (ioctl(0, TIOCGWINSZ, &ts) == 0 ? ts.ws_col : DEFAULT_TTY_SIZE);
41 #else
42 return DEFAULT_TTY_SIZE;
43 #endif
46 static inline void __tprintf_flush_newline(void)
48 int i;
50 fputc('\n', stdout);
51 for (i = 0; i < term_starting_size; ++i)
52 fputc(' ', stdout);
55 static inline int __tprintf_flush_skip(char *buffer, int i, size_t max)
57 int val = buffer[i];
59 if (val == ' ' || val == ',')
60 return 1;
62 return 0;
65 static void __tprintf_flush(void)
67 int i;
68 static ssize_t line_count = 0;
69 size_t term_len = term_curr_size;
71 for (i = 0; i < buffer_use; ++i) {
72 if (buffer[i] == '\n') {
73 term_len = term_curr_size;
74 line_count = -1;
77 if (line_count == term_len) {
78 __tprintf_flush_newline();
79 line_count = term_starting_size;
81 while (i < buffer_use &&
82 __tprintf_flush_skip(buffer, i, buffer_use))
83 i++;
86 fputc(buffer[i], stdout);
87 line_count++;
90 fflush(stdout);
91 buffer_use = 0;
94 void tprintf_flush(void)
96 spinlock_lock(&buffer_lock);
97 __tprintf_flush();
98 spinlock_unlock(&buffer_lock);
101 void tprintf_init(void)
103 spinlock_init(&buffer_lock);
105 setvbuf(stdout, NULL, _IONBF, 0);
106 setvbuf(stderr, NULL, _IONBF, 0);
109 void tprintf_cleanup(void)
111 tprintf_flush();
112 spinlock_destroy(&buffer_lock);
115 void tprintf(char *msg, ...)
117 ssize_t ret;
118 ssize_t avail;
119 va_list vl;
121 spinlock_lock(&buffer_lock);
123 avail = sizeof(buffer) - buffer_use;
124 bug_on(avail < 0);
126 va_start(vl, msg);
127 ret = vsnprintf(buffer + buffer_use, avail, msg, vl);
128 va_end(vl);
130 if (ret < 0)
131 panic("vsnprintf screwed up in tprintf!\n");
132 if (ret > sizeof(buffer))
133 panic("No mem in tprintf left!\n");
134 if (ret >= avail) {
135 __tprintf_flush();
137 avail = sizeof(buffer) - buffer_use;
138 bug_on(avail < 0);
140 va_start(vl, msg);
141 ret = vsnprintf(buffer + buffer_use, avail, msg, vl);
142 va_end(vl);
144 if (ret < 0)
145 panic("vsnprintf screwed up in tprintf!\n");
148 buffer_use += ret;
150 spinlock_unlock(&buffer_lock);
153 void tputchar_safe(int c)
155 unsigned char ch = (unsigned char)(c & 0xff);
157 if (isprint(ch))
158 tprintf("%c", ch);
159 else
160 tprintf("\\0x%02x", ch);
163 void tputs_safe(const char *str, size_t len)
165 while (len--) {
166 tputchar_safe(*str);
167 str++;