build: Define _DEFAULT_SOURCE to fix compilation warnings with glibc>=2.20
[netsniff-ng.git] / tprintf.c
blob90aa7d63285134e50b0cc865de0009629252b237
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 #define _DEFAULT_SOURCE
10 #include <ctype.h>
11 #include <stdio.h>
12 #include <stdarg.h>
13 #include <sys/ioctl.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 *buf, int i)
57 int val = buf[i];
59 if (val == ' ' || val == ',')
60 return 1;
62 return 0;
65 static void __tprintf_flush(void)
67 size_t i;
68 static ssize_t line_count = 0;
69 ssize_t term_len = term_curr_size;
70 size_t color_open = 0;
72 for (i = 0; i < buffer_use; ++i) {
73 if (buffer[i] == '\n') {
74 term_len = term_curr_size;
75 line_count = -1;
78 /* Start of an color escape sequence? */
79 if (buffer[i] == 033) {
80 if ((i + 1) < buffer_use && buffer[i + 1] == '[')
81 color_open++;
84 if (color_open == 0 && line_count >= term_len) {
85 __tprintf_flush_newline();
86 line_count = term_starting_size;
88 while (i < buffer_use &&
89 __tprintf_flush_skip(buffer, i))
90 i++;
93 /* End of the color escape sequence? */
94 if (color_open > 0 && buffer[i] == 'm')
95 color_open--;
97 fputc(buffer[i], stdout);
98 line_count++;
101 fflush(stdout);
102 buffer_use = 0;
105 void tprintf_flush(void)
107 spinlock_lock(&buffer_lock);
108 __tprintf_flush();
109 spinlock_unlock(&buffer_lock);
112 void tprintf_init(void)
114 spinlock_init(&buffer_lock);
116 setvbuf(stdout, NULL, _IONBF, 0);
117 setvbuf(stderr, NULL, _IONBF, 0);
120 void tprintf_cleanup(void)
122 tprintf_flush();
123 spinlock_destroy(&buffer_lock);
126 void tprintf(char *msg, ...)
128 ssize_t ret;
129 ssize_t avail;
130 va_list vl;
132 spinlock_lock(&buffer_lock);
134 avail = sizeof(buffer) - buffer_use;
135 bug_on(avail < 0);
137 va_start(vl, msg);
138 ret = vsnprintf(buffer + buffer_use, avail, msg, vl);
139 va_end(vl);
141 if (ret < 0)
142 panic("vsnprintf screwed up in tprintf!\n");
143 if ((size_t) ret > sizeof(buffer))
144 panic("No mem in tprintf left!\n");
145 if (ret >= avail) {
146 __tprintf_flush();
148 avail = sizeof(buffer) - buffer_use;
149 bug_on(avail < 0);
151 va_start(vl, msg);
152 ret = vsnprintf(buffer + buffer_use, avail, msg, vl);
153 va_end(vl);
155 if (ret < 0)
156 panic("vsnprintf screwed up in tprintf!\n");
159 buffer_use += ret;
161 spinlock_unlock(&buffer_lock);
164 void tputchar_safe(int c)
166 unsigned char ch = (unsigned char)(c & 0xff);
168 if (isprint(ch))
169 tprintf("%c", ch);
170 else
171 tprintf("\\0x%02x", ch);
174 void tputs_safe(const char *str, size_t len)
176 while (len--) {
177 tputchar_safe(*str);
178 str++;