1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
|
/*
* netsniff-ng - the packet sniffing beast
* Copyright 2009, 2010 Daniel Borkmann.
* Copyright 2013 Tobias Klauser.
* Subject to the GPL, version 2.
*/
#define _BSD_SOURCE
#define _DEFAULT_SOURCE
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>
#include <sys/ioctl.h>
#include "tprintf.h"
#include "die.h"
#include "locking.h"
#include "built_in.h"
#define term_trailing_size 5
#define term_starting_size 3
#define term_curr_size (get_tty_size() - term_trailing_size)
static char buffer[1024];
static volatile size_t buffer_use = 0;
static struct spinlock buffer_lock;
static int get_tty_size(void)
{
#ifdef TIOCGSIZE
struct ttysize ts = {0};
return (ioctl(0, TIOCGSIZE, &ts) == 0 ? ts.ts_cols : DEFAULT_TTY_SIZE);
#elif defined(TIOCGWINSZ)
struct winsize ts;
return (ioctl(0, TIOCGWINSZ, &ts) == 0 ? ts.ws_col : DEFAULT_TTY_SIZE);
#else
return DEFAULT_TTY_SIZE;
#endif
}
static inline void __tprintf_flush_newline(void)
{
int i;
fputc('\n', stdout);
for (i = 0; i < term_starting_size; ++i)
fputc(' ', stdout);
}
static inline int __tprintf_flush_skip(char *buf, int i)
{
int val = buf[i];
if (val == ' ' || val == ',')
return 1;
return 0;
}
static void __tprintf_flush(void)
{
size_t i;
static ssize_t line_count = 0;
ssize_t term_len = term_curr_size;
size_t color_open = 0;
for (i = 0; i < buffer_use; ++i) {
if (buffer[i] == '\n') {
term_len = term_curr_size;
line_count = -1;
}
/* Start of an color escape sequence? */
if (buffer[i] == 033) {
if ((i + 1) < buffer_use && buffer[i + 1] == '[')
color_open++;
}
if (color_open == 0 && line_count >= term_len) {
__tprintf_flush_newline();
line_count = term_starting_size;
while (i < buffer_use &&
__tprintf_flush_skip(buffer, i))
i++;
}
/* End of the color escape sequence? */
if (color_open > 0 && buffer[i] == 'm')
color_open--;
fputc(buffer[i], stdout);
line_count++;
}
fflush(stdout);
buffer_use = 0;
}
void tprintf_flush(void)
{
spinlock_lock(&buffer_lock);
__tprintf_flush();
spinlock_unlock(&buffer_lock);
}
void tprintf_init(void)
{
spinlock_init(&buffer_lock);
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
}
void tprintf_cleanup(void)
{
tprintf_flush();
spinlock_destroy(&buffer_lock);
}
void tprintf(char *msg, ...)
{
ssize_t ret;
ssize_t avail;
va_list vl;
spinlock_lock(&buffer_lock);
avail = sizeof(buffer) - buffer_use;
bug_on(avail < 0);
va_start(vl, msg);
ret = vsnprintf(buffer + buffer_use, avail, msg, vl);
va_end(vl);
if (ret < 0)
panic("vsnprintf screwed up in tprintf!\n");
if ((size_t) ret > sizeof(buffer))
panic("No mem in tprintf left!\n");
if (ret >= avail) {
__tprintf_flush();
avail = sizeof(buffer) - buffer_use;
bug_on(avail < 0);
va_start(vl, msg);
ret = vsnprintf(buffer + buffer_use, avail, msg, vl);
va_end(vl);
if (ret < 0)
panic("vsnprintf screwed up in tprintf!\n");
}
buffer_use += ret;
spinlock_unlock(&buffer_lock);
}
void tputchar_safe(int c)
{
unsigned char ch = (unsigned char)(c & 0xff);
if (isprint(ch))
tprintf("%c", ch);
else
tprintf("\\0x%02x", ch);
}
void tputs_safe(const char *str, size_t len)
{
while (len--) {
tputchar_safe(*str);
str++;
}
}
|