added 'videolib' snapshot
[k8-jellyphysics.git] / src / videolib / videolib_dbglog.c
blob574ffc5385a04246f7c304b235139b4747bbe084
1 /* coded by Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
2 * Understanding is not required. Only obedience.
4 * This program is free software. It comes without any warranty, to
5 * the extent permitted by applicable law. You can redistribute it
6 * and/or modify it under the terms of the Do What The Fuck You Want
7 * To Public License, Version 2, as published by Sam Hocevar. See
8 * http://sam.zoy.org/wtfpl/COPYING for more details.
9 */
10 /* debug logs */
11 #include "videolib.h"
13 #include <fcntl.h>
14 #include <stdarg.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <time.h>
19 #include <unistd.h>
21 #include <sys/stat.h>
22 #include <sys/types.h>
25 ////////////////////////////////////////////////////////////////////////////////
26 static char dbg_locker = 0;
28 void vl_dbglog_lock (void) {
29 while (__sync_bool_compare_and_swap(&dbg_locker, 0, 1)) usleep(1);
33 void vl_dbglog_unlock (void) {
35 __sync_synchronize();
36 dbg_locker = 0;
38 __sync_fetch_and_and(&dbg_locker, 0);
42 ////////////////////////////////////////////////////////////////////////////////
43 #ifdef VIDEOLIB_ENABLE_DEBUG_LOG
44 static pid_t mypid;
45 static char log_file_name[8192];
46 static char bin_path[8192];
47 static int flag_dofile = 1; /* default: yes */
48 static int flag_dostderr = 1; /* default: yes */
49 static int logfile = -1;
50 static int logfile_err = 0;
53 static __attribute__((destructor)) void _dtor_dbglog (void) {
54 vl_dbglog_lock();
55 if (logfile >= 0) {
56 close(logfile);
57 logfile = -1;
59 vl_dbglog_unlock();
63 static __attribute__((constructor)) void _ctor_dbglog (void) {
64 mypid = getpid();
65 bin_path[sizeof(bin_path)-1] = 0;
66 if (readlink("/proc/self/exe", bin_path, sizeof(bin_path)-1) < 0) {
67 strcpy(bin_path, "./");
68 } else {
69 char *p = strrchr(bin_path, '/');
70 if (p == NULL) strcpy(bin_path, "./"); else p[1] = '\0';
72 if (bin_path[strlen(bin_path)-1] != '/') strcat(bin_path, "/"); // just in case, hehe
73 log_file_name[0] = 0;
74 vl_dbglog_set_filename("debug.log");
78 void vl_dbglog_set_filename (const char *fname) {
79 vl_dbglog_lock();
80 if (fname != NULL && fname[0] && strlen(fname)) {
81 if (fname[0] != '/' && !(fname[0] == '.' && fname[1] == '/') && !(fname[0] == '.' && fname[1] == '.' && fname[2] == '/')) {
82 snprintf(log_file_name, sizeof(log_file_name), "%s%s", bin_path, fname);
83 } else {
84 snprintf(log_file_name, sizeof(log_file_name), "%s", fname);
86 } else {
87 log_file_name[0] = '\0';
89 if (logfile >= 0) {
90 close(logfile);
91 logfile = -1;
93 logfile_err = (log_file_name[0] == 0);
94 vl_dbglog_unlock();
98 int vl_dbglog_set_fileout (int doIt) {
99 int old;
100 vl_dbglog_lock();
101 old = flag_dofile;
102 flag_dofile = !!doIt;
103 vl_dbglog_unlock();
104 return old;
108 int vl_dbglog_set_stderr (int doIt) {
109 int old;
110 vl_dbglog_lock();
111 old = flag_dostderr;
112 flag_dostderr = !!doIt;
113 vl_dbglog_unlock();
114 return old;
118 void vl_dlogf (const char *fmt, ...) {
119 va_list ap;
120 va_start(ap, fmt);
121 dlogfVA(fmt, ap);
122 va_end(ap);
126 static void write_to_file (int fd, const char *pfx, const char *buf) {
127 int pfxlen = strlen(pfx);
128 while (*buf) {
129 const char *eol;
130 // first write prefix
131 if (pfxlen > 0) write(fd, pfx, pfxlen);
132 // now look for EOL
133 if ((eol = strpbrk(buf, "\r\n")) == NULL) eol = buf+strlen(buf);
134 // write string part
135 if (eol > buf) write(fd, buf, eol-buf);
136 // write EOL
137 write(fd, "\n", 1);
138 // skip EOL
139 switch ((buf = eol)[0]) {
140 case '\0': break; // done with buf
141 case '\r':
142 if (*(++buf) != '\n') break;
143 // fallthru
144 default: ++buf; break;
150 void dlogfVA (const char *fmt, va_list inap) {
151 char timebuf[128];
152 char buf[512], *dbuf = buf;
153 time_t t;
154 int buf_sz;
155 struct tm bt;
156 va_list ap;
158 if (fmt == NULL) return;
159 vl_dbglog_lock();
160 if (!flag_dofile && !flag_dostderr) goto quit;
162 t = time(NULL);
163 localtime_r(&t, &bt);
164 sprintf(timebuf, "[%05i] %04i/%02i/%02i %02i:%02i:%02i: ",
165 mypid,
166 bt.tm_year+1900, bt.tm_mon+1, bt.tm_mday,
167 bt.tm_hour, bt.tm_min, bt.tm_sec
170 memset(buf, 0, sizeof(buf));
171 va_copy(ap, inap);
172 if ((buf_sz = vsnprintf(buf, sizeof(buf), fmt, ap)) >= sizeof(buf)) {
173 va_end(ap);
174 if ((dbuf = malloc(buf_sz+1)) == NULL) goto quit; // alas, out of memory
175 va_copy(ap, inap);
176 vsnprintf(dbuf, buf_sz+1, fmt, ap);
178 va_end(ap);
180 if (flag_dofile && logfile < 0 && logfile_err == 0 && log_file_name[0]) {
181 // try to open debug log file
182 logfile = open(log_file_name, O_WRONLY|O_APPEND|O_CLOEXEC|O_CREAT, 0644);
183 ++logfile_err; // don't do this again
186 if (flag_dofile && logfile >= 0) {
187 write_to_file(logfile, timebuf, dbuf);
190 if (flag_dostderr) {
191 write(2, "\r\x1b[K", 4);
192 write_to_file(2, timebuf+13, dbuf); // skip PID and year
195 if (dbuf != buf) free(dbuf);
197 quit:
198 vl_dbglog_unlock();
201 #else
203 void vl_dbglog_set_filename (const char *fname) {}
204 int vl_dbglog_set_stderr (int doIt) { return 0; }
205 int vl_dbglog_set_fileout (int doIt) { return 0; }
207 #endif