Commit b85bf75c authored by Pavel Emelyanov's avatar Pavel Emelyanov

log: Introduce a simple printf-like logging engine

It's supposed to be used by parasite and restorer blob. It
has API equal to the core one -- with setfd, set_loglevel and
(the main thing) print_on_level fn. It currently supports only
strings, decimal and hex numbers (int and long).
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 37a7b35e
...@@ -8,11 +8,14 @@ extern void log_fini(void); ...@@ -8,11 +8,14 @@ extern void log_fini(void);
extern int log_init_by_pid(void); extern int log_init_by_pid(void);
extern void log_closedir(void); extern void log_closedir(void);
extern void log_set_fd(int fd);
extern int log_get_fd(void); extern int log_get_fd(void);
extern void log_set_loglevel(unsigned int loglevel); extern void log_set_loglevel(unsigned int loglevel);
extern unsigned int log_get_loglevel(void); extern unsigned int log_get_loglevel(void);
extern int vprint_num(char *buf, int blen, int num, char **ps);
extern void print_on_level(unsigned int loglevel, const char *format, ...) extern void print_on_level(unsigned int loglevel, const char *format, ...)
__attribute__ ((__format__ (__printf__, 2, 3))); __attribute__ ((__format__ (__printf__, 2, 3)));
......
#include <stdarg.h>
#include "syscall.h"
#include "log.h"
#include "log-levels.h"
static int logfd = -1;
static int cur_loglevel = DEFAULT_LOGLEVEL;
void log_set_fd(int fd)
{
sys_close(logfd);
logfd = fd;
}
void log_set_loglevel(unsigned int level)
{
cur_loglevel = level;
}
static void print_string(const char *msg)
{
int size = 0;
while (msg[size])
size++;
sys_write(logfd, msg, size);
}
int vprint_num(char *buf, int blen, int num, char **ps)
{
int neg = 0;
char *s;
s = &buf[blen - 1];
if (num < 0) {
neg = 1;
num = -num;
} else if (num == 0) {
*s = '0';
s--;
goto done;
}
while (num > 0) {
*s = (num % 10) + '0';
s--;
num /= 10;
}
if (neg) {
*s = '-';
s--;
}
done:
s++;
*ps = s;
return blen - (s - buf);
}
static void print_num(int num)
{
char buf[11], *s;
int len;
len = vprint_num(buf, sizeof(buf), num, &s);
sys_write(logfd, s, len);
}
static void print_num_l(long num)
{
int neg = 0;
char buf[21], *s;
s = &buf[20];
if (num < 0) {
neg = 1;
num = -num;
} else if (num == 0) {
*s = '0';
s--;
goto done;
}
while (num > 0) {
*s = (num % 10) + '0';
s--;
num /= 10;
}
if (neg) {
*s = '-';
s--;
}
done:
s++;
sys_write(logfd, s, sizeof(buf) - (s - buf));
}
static void hexdigit(unsigned int v, char *to, char **z)
{
*to = "0123456789abcdef"[v & 0xf];
if (*to != '0')
*z = to;
}
static void print_hex(unsigned int num)
{
char buf[10], *z = &buf[9];
hexdigit(num >> 0, &buf[9], &z);
hexdigit(num >> 4, &buf[8], &z);
hexdigit(num >> 8, &buf[7], &z);
hexdigit(num >> 12, &buf[6], &z);
hexdigit(num >> 16, &buf[5], &z);
hexdigit(num >> 20, &buf[4], &z);
hexdigit(num >> 24, &buf[3], &z);
hexdigit(num >> 28, &buf[2], &z);
z -= 2;
z[0] = '0';
z[1] = 'x';
sys_write(logfd, z, sizeof(buf) - (z - buf));
}
static void print_hex_l(unsigned long num)
{
char buf[18], *z = &buf[17];
hexdigit(num >> 0, &buf[17], &z);
hexdigit(num >> 4, &buf[16], &z);
hexdigit(num >> 8, &buf[15], &z);
hexdigit(num >> 12, &buf[14], &z);
hexdigit(num >> 16, &buf[13], &z);
hexdigit(num >> 20, &buf[12], &z);
hexdigit(num >> 24, &buf[11], &z);
hexdigit(num >> 28, &buf[10], &z);
hexdigit(num >> 32, &buf[9], &z);
hexdigit(num >> 36, &buf[8], &z);
hexdigit(num >> 40, &buf[7], &z);
hexdigit(num >> 44, &buf[6], &z);
hexdigit(num >> 48, &buf[5], &z);
hexdigit(num >> 52, &buf[4], &z);
hexdigit(num >> 56, &buf[3], &z);
hexdigit(num >> 60, &buf[2], &z);
z -= 2;
z[0] = '0';
z[1] = 'x';
sys_write(logfd, z, sizeof(buf) - (z - buf));
}
void print_on_level(unsigned int loglevel, const char *format, ...)
{
va_list args;
const char *s = format, *p;
if (loglevel > cur_loglevel)
return;
va_start(args, format);
p = s;
while (1) {
int along = 0;
if (*s != '\0' && *s != '%') {
s++;
continue;
}
sys_write(logfd, p, s - p);
if (*s == '\0')
break;
s++;
if (*s == 'l') {
along = 1;
s++;
}
switch (*s) {
case 's':
print_string(va_arg(args, char *));
break;
case 'd':
if (along)
print_num_l(va_arg(args, long));
else
print_num(va_arg(args, int));
break;
case 'x':
if (along)
print_hex_l(va_arg(args, long));
else
print_hex(va_arg(args, unsigned int));
break;
}
s++;
p = s;
}
va_end(args);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment