* fix an issue that execve attempts to parse directory as elf file.
[lunaix-os.git] / lunaix-os / kernel / kprint / kprintf.c
1 #include <lunaix/fs/twifs.h>
2 #include <lunaix/fs/twimap.h>
3 #include <lunaix/syscall.h>
4 #include <lunaix/syslog.h>
5 #include <lunaix/device.h>
6 #include <lunaix/owloysius.h>
7
8 #include <hal/term.h>
9
10 #include <klibc/strfmt.h>
11
12 #include "kp_records.h"
13
14 #define MAX_BUFSZ 512
15 #define MAX_BUFSZ_HLF 256
16 #define MAX_KPENT_NUM 1024
17
18 static char tmp_buf[MAX_BUFSZ];
19
20 static struct kp_records kprecs = {
21     .kp_ents = { .ents = { .next = &kprecs.kp_ents.ents,
22                            .prev = &kprecs.kp_ents.ents } },
23     .max_recs = MAX_KPENT_NUM,
24     .kp_ent_wp = &kprecs.kp_ents.ents
25 };
26 export_symbol(debug, kprintf, kprecs);
27
28 static char*
29 shift_level(const char* str, int* level)
30 {
31     if (str[0] == KMSG_LVLSTART) {
32         *level = KMSG_LOGLEVEL(str[1]);
33
34         return str += 2;
35     }
36
37     *level = KLOG_INFO;
38     return str;
39 }
40
41 static inline void
42 kprintf_ml(const char* component, int level, const char* fmt, va_list args)
43 {
44     char* buf = &tmp_buf[MAX_BUFSZ_HLF];
45     ksnprintf(buf, MAX_BUFSZ_HLF, "%s: %s\n", component, fmt);
46
47     size_t sz = ksnprintfv(tmp_buf, buf, MAX_BUFSZ_HLF, args);
48     kprec_put(&kprecs, level, tmp_buf, sz);
49
50     if (likely(sysconsole)) {
51         sysconsole->ops.write(sysconsole, tmp_buf, 0, sz);
52     }
53 }
54
55 void
56 kprintf_m(const char* component, const char* fmt, va_list args)
57 {
58     int level;
59     fmt = shift_level(fmt, &level);
60
61     kprintf_ml(component, level, fmt, args);
62 }
63
64 static void
65 __twimap_kprintf_read(struct twimap* map)
66 {
67     struct kp_records* __kprecs = twimap_data(map, struct kp_records*);
68
69     /*
70         XXX we can foreach all records in a single twimap read call,
71             as records is monotonic increasing by design.
72     */
73     struct kp_entry *pos, *n;
74     llist_for_each(pos, n, __kprecs->kp_ent_wp, ents)
75     {
76         time_t s = pos->time / 1000;
77         time_t ms = pos->time % 1000;
78         twimap_printf(map, "[%05d.%03d] %s\n", s, ms, pos->content);
79     }
80 }
81
82 static void
83 kprintf_mapping_init()
84 {
85     twimap_entry_simple(NULL, "kmsg", &kprecs, __twimap_kprintf_read);
86 }
87 EXPORT_TWIFS_PLUGIN(kprintf, kprintf_mapping_init);
88
89
90 void 
91 kprintf_dump_logs() {
92     if (unlikely(!sysconsole)) {
93         return;
94     }
95
96     struct kp_entry *pos, *n;
97     llist_for_each(pos, n, kprecs.kp_ent_wp, ents)
98     {
99         sysconsole->ops.write(sysconsole, pos->content, 0, pos->len);
100     }
101 }
102
103 __DEFINE_LXSYSCALL3(void, syslog, int, level, const char*, fmt, va_list, args)
104 {
105     kprintf_ml("syslog", level, fmt, args);
106 }