add stdout, stderr redirection of peers to logfile
[archipelago] / xseg / sys / user / xseg_user.c
1 #define _GNU_SOURCE
2 #include <stdio.h>
3 #include <stdarg.h>
4 #include <time.h>
5 #include <string.h>
6 #include <dlfcn.h>
7 #include <unistd.h>
8 #include <stdint.h>
9 #include <sys/syscall.h>
10 #include <errno.h>
11 #include <sys/util.h>
12 #include <sys/time.h>
13
14 #include <sys/domain.h>
15 #include <xtypes/domain.h>
16 #include <xseg/domain.h>
17
18 #include <xtypes/xlock.h>
19
20 int (*xseg_snprintf)(char *str, size_t size, const char *format, ...) = snprintf;
21
22 char __xseg_errbuf[4096];
23
24 static struct xlock __lock = { .owner = Noone};
25
26 void __lock_domain(void)
27 {
28         (void)xlock_acquire(&__lock, 1);
29 }
30
31 void __unlock_domain(void)
32 {
33         xlock_release(&__lock);
34 }
35
36 void __load_plugin(const char *name)
37 {
38         void *dl;
39         void (*init)(void);
40         char _name[128];
41         unsigned int namelen = strlen(name);
42
43         strncpy(_name, "xseg_", 5);
44         strncpy(_name + 5, name, 80);
45         strncpy(_name + 5 + namelen, ".so", 3);
46         _name[5 + namelen + 3 ] = 0;
47         dl = dlopen(_name, RTLD_NOW);
48         if (!dl) {
49                 XSEGLOG("Cannot load plugin '%s': %s\n", _name, dlerror());
50                 return;
51         }
52
53         strncpy(_name + 5 + namelen, "_init", 5);
54         _name[127] = 0;
55         init = (void (*)(void))(long)dlsym(dl, _name);
56         if (!init) {
57                 XSEGLOG("Init function '%s' not found!\n", _name);
58                 return;
59         }
60
61         init();
62         //XSEGLOG("Plugin '%s' loaded.\n", name);
63 }
64
65 uint64_t __get_id(void)
66 {
67         return (uint64_t)syscall(SYS_gettid);
68 }
69
70 void __xseg_log(const char *msg)
71 {
72         (void)puts(msg);
73         fflush(stdout);
74 }
75
76 void *xtypes_malloc(unsigned long size)
77 {
78         return malloc(size);
79 }
80
81 void xtypes_free(void *ptr)
82 {
83         free(ptr);
84 }
85
86 void __get_current_time(struct timeval *tv) {
87         gettimeofday(tv, NULL);
88 }
89
90
91 int user_init_logctx(struct log_ctx *lc, char *peer_name, enum log_level log_level, char *logfile)
92 {
93         FILE *file;
94         /* FIXME
95          * copy peer_name
96          * check logfile length
97          */
98         lc->peer_name = peer_name;
99         lc->log_level = log_level;
100         if (!logfile) {
101                 lc->logfile = stderr;
102                 return 0;
103         }
104
105         file = fopen(logfile, "a");
106         if (!file) {
107                 lc->logfile = stderr;
108                 return -1;
109         }
110         lc->logfile = file;
111         return 0;
112 }
113 int (*init_logctx)(struct log_ctx *lc, char *peer_name, enum log_level log_level, char *logfile) = user_init_logctx;
114
115 void __xseg_log2(struct log_ctx *lc, enum log_level level, char *fmt, ...)
116 {
117         va_list ap;
118         time_t timeval; 
119         char timebuf[1024], buffer[4096];
120         char *buf = buffer;
121         char *t = NULL, *pn = NULL;
122
123         va_start(ap, fmt);
124         switch (level) {
125                 case E: t = "XSEG[EE]"; break;
126                 case W: t = "XSEG[WW]"; break;
127                 case I: t = "XSEG[II]"; break;
128                 case D: t = "XSEG[DD]"; break;
129                 default: t = "XSEG[UNKNONW]"; break;
130         }
131         pn = lc->peer_name;
132         if (!pn)
133                 pn = "Invalid peer name";
134
135         time(&timeval);
136         ctime_r(&timeval, timebuf);
137         *strchr(timebuf, '\n') = '\0';
138         
139         buf += sprintf(buf, "%s: %s: ", t, lc->peer_name);
140         buf += sprintf(buf, "%s (%ld):\n\t", timebuf, timeval);
141         buf += vsprintf(buf, fmt, ap);
142         buf += sprintf(buf, "\n");
143
144         fprintf(lc->logfile, "%s", buffer);
145         fflush(lc->logfile);
146         va_end(ap);
147
148         return;
149 }
150
151 void xseg_printtrace(void)
152 {
153         void *array[10];
154         size_t size;
155         char **strings;
156         int i;
157
158         size = backtrace (array, 10);
159         strings = backtrace_symbols (array, size);
160
161         XSEGLOG("Obtained %zd stack frames.\n", size);
162
163         for (i = 0; i < size; i++)
164                 XSEGLOG ("%s\n", strings[i]);
165
166         free (strings);
167 }