netsniff-ng: ring: Fix build if tp_vlan_tpid is not available in kernel header
[netsniff-ng.git] / tprintf.c
blob43f862a300a3dbcea7ab46d58c98ef3cd42edf54
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 "tprintf.h"
15 #include "die.h"
16 #include "locking.h"
17 #include "built_in.h"
19 #define term_trailing_size 5
20 #define term_starting_size 3
22 #define term_curr_size (get_tty_size() - term_trailing_size)
24 static char buffer[1024];
26 static volatile size_t buffer_use = 0;
28 static struct spinlock buffer_lock;
30 static int get_tty_size(void)
32 #ifdef TIOCGSIZE
33 struct ttysize ts = {0};
35 return (ioctl(0, TIOCGSIZE, &ts) == 0 ? ts.ts_cols : DEFAULT_TTY_SIZE);
36 #elif defined(TIOCGWINSZ)
37 struct winsize ts;
39 return (ioctl(0, TIOCGWINSZ, &ts) == 0 ? ts.ws_col : DEFAULT_TTY_SIZE);
40 #else
41 return DEFAULT_TTY_SIZE;
42 #endif
45 static inline void __tprintf_flush_newline(void)
47 int i;
49 fputc('\n', stdout);
50 for (i = 0; i < term_starting_size; ++i)
51 fputc(' ', stdout);
54 static inline int __tprintf_flush_skip(char *buf, int i)
56 int val = buf[i];
58 if (val == ' ' || val == ',')
59 return 1;
61 return 0;
64 static void __tprintf_flush(void)
66 size_t i;
67 static ssize_t line_count = 0;
68 ssize_t term_len = term_curr_size;
69 size_t color_open = 0;
71 for (i = 0; i < buffer_use; ++i) {
72 if (buffer[i] == '\n') {
73 term_len = term_curr_size;
74 line_count = -1;
77 /* Start of an color escape sequence? */
78 if (buffer[i] == 033) {
79 if ((i + 1) < buffer_use && buffer[i + 1] == '[')
80 color_open++;
83 if (color_open == 0 && line_count >= term_len) {
84 __tprintf_flush_newline();
85 line_count = term_starting_size;
87 while (i < buffer_use &&
88 __tprintf_flush_skip(buffer, i))
89 i++;
92 /* End of the color escape sequence? */
93 if (color_open > 0 && buffer[i] == 'm')
94 color_open--;
96 fputc(buffer[i], stdout);
97 line_count++;
100 fflush(stdout);
101 buffer_use = 0;
104 void tprintf_flush(void)
106 spinlock_lock(&buffer_lock);
107 __tprintf_flush();
108 spinlock_unlock(&buffer_lock);
111 void tprintf_init(void)
113 spinlock_init(&buffer_lock);
115 setvbuf(stdout, NULL, _IONBF, 0);
116 setvbuf(stderr, NULL, _IONBF, 0);
119 void tprintf_cleanup(void)
121 tprintf_flush();
122 spinlock_destroy(&buffer_lock);
125 void tprintf(char *msg, ...)
127 ssize_t ret;
128 ssize_t avail;
129 va_list vl;
131 spinlock_lock(&buffer_lock);
133 avail = sizeof(buffer) - buffer_use;
134 bug_on(avail < 0);
136 va_start(vl, msg);
137 ret = vsnprintf(buffer + buffer_use, avail, msg, vl);
138 va_end(vl);
140 if (ret < 0)
141 panic("vsnprintf screwed up in tprintf!\n");
142 if ((size_t) ret > sizeof(buffer))
143 panic("No mem in tprintf left!\n");
144 if (ret >= avail) {
145 __tprintf_flush();
147 avail = sizeof(buffer) - buffer_use;
148 bug_on(avail < 0);
150 va_start(vl, msg);
151 ret = vsnprintf(buffer + buffer_use, avail, msg, vl);
152 va_end(vl);
154 if (ret < 0)
155 panic("vsnprintf screwed up in tprintf!\n");
158 buffer_use += ret;
160 spinlock_unlock(&buffer_lock);
163 void tputchar_safe(int c)
165 unsigned char ch = (unsigned char)(c & 0xff);
167 if (isprint(ch))
168 tprintf("%c", ch);
169 else
170 tprintf("\\0x%02x", ch);
173 void tputs_safe(const char *str, size_t len)
175 while (len--) {
176 tputchar_safe(*str);
177 str++;