aboutsummaryrefslogtreecommitdiffstats
path: root/init/log.c
blob: 3ddd4db646b93c96c35def7a3c8336530548c4ae (plain)
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
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <sys/file.h>
#include <sys/time.h>
#include <unistd.h>

#include <log.h>
#include <util.h>

static const char *colors[] = {
    [EMERG_LOGLEVEL] = ANSI_BLINK ANSI_REVERSE ANSI_BOLD ANSI_RED,
    [ALERT_LOGLEVEL] = ANSI_REVERSE ANSI_BOLD ANSI_RED,
    [CRIT_LOGLEVEL] = ANSI_BOLD ANSI_RED,
    [ERR_LOGLEVEL] = ANSI_RED,
    [WARNING_LOGLEVEL] = ANSI_BOLD,
    [NOTICE_LOGLEVEL] = ANSI_BRIGHT_WHITE,
    [INFO_LOGLEVEL] = ANSI_RESET,
    [DEBUG_LOGLEVEL] = ANSI_ITALIC ANSI_BRIGHT_BLUE,
};

int console_lock = 0;

int print(const char *fmt, ...)
{
    int loglevel = DEFAULT_LOGLEVEL;
    if(fmt[0] == LOG_SOH_ASCII) {
        loglevel = (fmt[1] - 0x30) % 10;
        fmt += 2;
    }

    /* not going to be printed? dont bother! */
    if(loglevel > CONSOLE_LOGLEVEL)
        return 0;

    /* we essentially print the user's raw input to its own buffer,
       later we will parse it and print out ANSI colors and what not */
    char buf[512];

    va_list ap;
    va_start(ap, fmt);
    vsnprintf(buf, 512, fmt, ap);
    va_end(ap);
    buf[512 - 1] = '\0';

    size_t colon = 0;
    for(; colon < strlen(buf); ++colon) {
        if(buf[colon] == ':')
            break;
    }

    char tsbuf[64] = "\0";
    struct timeval time;
    gettimeofday(&time, NULL);
    snprintf(tsbuf, sizeof(tsbuf), "[%5ld.%06ld] ", (long)time.tv_sec % 100000, (long)time.tv_usec);

    /* spin lock, at the cost of architecture portability
       concurrency is something that we need to adjust for, and the
       console will be scrambled and unreadable if we allow writing all
       at the same time. I considered simply writing all at once, but
       ended up just not caring enough to the point where spinlocks
       prevail. */
    __asm__(".spin_lock:");
    __asm__("mov rax, 1");
    __asm__("xchg rax, [console_lock]");
    __asm__("test rax, rax");
    __asm__("jnz .spin_lock");

    /* we want to support stuff without colons, but frankly I havent
       tested this at time of writing. will find out later */
    writeputs(ANSI_RESET ANSI_GREEN);
    writeputs(tsbuf);
    writeputs(ANSI_RESET);
    if(buf[colon] == ':') {
        writeputs(colors[loglevel]);
        writeputs(ANSI_YELLOW);
        write(STDOUT_FILENO, buf, colon);
        writeputs(ANSI_RESET);
    }
    writeputs(colors[loglevel]);
    if(colon && *(buf + colon)) {
        writeputs(buf + colon);
    } else {
        writeputs(buf);
    }
    writeputs(ANSI_RESET);
    write(STDOUT_FILENO, "\n", 1);

    console_lock = 0;
    return 0;
}