tprintf: xutils: Move tput*_safe to tprintf.c
[netsniff-ng.git] / tprintf.c
blob3fdcb869e6f84e8f39b425b2946394f9ef76b2de
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * By Daniel Borkmann <daniel@netsniff-ng.org>
4 * Copyright 2009, 2010 Daniel Borkmann.
5 * Copyright 2013 Tobias Klauser.
6 * Subject to the GPL, version 2.
7 */
9 #define _BSD_SOURCE
10 #include <ctype.h>
11 #include <stdio.h>
12 #include <stdarg.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 inline void __tprintf_flush_newline(void)
33 int i;
35 fputc('\n', stdout);
36 for (i = 0; i < term_starting_size; ++i)
37 fputc(' ', stdout);
40 static inline int __tprintf_flush_skip(char *buffer, int i, size_t max)
42 int val = buffer[i];
44 if (val == ' ' || val == ',')
45 return 1;
47 return 0;
50 static void __tprintf_flush(void)
52 int i;
53 static ssize_t line_count = 0;
54 size_t term_len = term_curr_size;
56 for (i = 0; i < buffer_use; ++i) {
57 if (buffer[i] == '\n') {
58 term_len = term_curr_size;
59 line_count = -1;
62 if (line_count == term_len) {
63 __tprintf_flush_newline();
64 line_count = term_starting_size;
66 while (i < buffer_use &&
67 __tprintf_flush_skip(buffer, i, buffer_use))
68 i++;
71 fputc(buffer[i], stdout);
72 line_count++;
75 fflush(stdout);
76 buffer_use = 0;
79 void tprintf_flush(void)
81 spinlock_lock(&buffer_lock);
82 __tprintf_flush();
83 spinlock_unlock(&buffer_lock);
86 void tprintf_init(void)
88 spinlock_init(&buffer_lock);
90 setvbuf(stdout, NULL, _IONBF, 0);
91 setvbuf(stderr, NULL, _IONBF, 0);
94 void tprintf_cleanup(void)
96 tprintf_flush();
97 spinlock_destroy(&buffer_lock);
100 void tprintf(char *msg, ...)
102 ssize_t ret;
103 ssize_t avail;
104 va_list vl;
106 spinlock_lock(&buffer_lock);
108 avail = sizeof(buffer) - buffer_use;
109 bug_on(avail < 0);
111 va_start(vl, msg);
112 ret = vsnprintf(buffer + buffer_use, avail, msg, vl);
113 va_end(vl);
115 if (ret < 0)
116 panic("vsnprintf screwed up in tprintf!\n");
117 if (ret > sizeof(buffer))
118 panic("No mem in tprintf left!\n");
119 if (ret >= avail) {
120 __tprintf_flush();
122 avail = sizeof(buffer) - buffer_use;
123 bug_on(avail < 0);
125 va_start(vl, msg);
126 ret = vsnprintf(buffer + buffer_use, avail, msg, vl);
127 va_end(vl);
129 if (ret < 0)
130 panic("vsnprintf screwed up in tprintf!\n");
133 buffer_use += ret;
135 spinlock_unlock(&buffer_lock);
138 void tputchar_safe(int c)
140 unsigned char ch = (unsigned char)(c & 0xff);
142 if (isprint(ch))
143 tprintf("%c", ch);
144 else
145 tprintf("\\0x%02x", ch);
148 void tputs_safe(const char *str, size_t len)
150 while (len--) {
151 tputchar_safe(*str);
152 str++;