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.
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) {
38 __sync_fetch_and_and(&dbg_locker
, 0);
42 ////////////////////////////////////////////////////////////////////////////////
43 #ifdef VIDEOLIB_ENABLE_DEBUG_LOG
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) {
63 static __attribute__((constructor
)) void _ctor_dbglog (void) {
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
, "./");
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
74 vl_dbglog_set_filename("debug.log");
78 void vl_dbglog_set_filename (const char *fname
) {
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
);
84 snprintf(log_file_name
, sizeof(log_file_name
), "%s", fname
);
87 log_file_name
[0] = '\0';
93 logfile_err
= (log_file_name
[0] == 0);
98 int vl_dbglog_set_fileout (int doIt
) {
102 flag_dofile
= !!doIt
;
108 int vl_dbglog_set_stderr (int doIt
) {
112 flag_dostderr
= !!doIt
;
118 void vl_dlogf (const char *fmt
, ...) {
126 static void write_to_file (int fd
, const char *pfx
, const char *buf
) {
127 int pfxlen
= strlen(pfx
);
130 // first write prefix
131 if (pfxlen
> 0) write(fd
, pfx
, pfxlen
);
133 if ((eol
= strpbrk(buf
, "\r\n")) == NULL
) eol
= buf
+strlen(buf
);
135 if (eol
> buf
) write(fd
, buf
, eol
-buf
);
139 switch ((buf
= eol
)[0]) {
140 case '\0': break; // done with buf
142 if (*(++buf
) != '\n') break;
144 default: ++buf
; break;
150 void dlogfVA (const char *fmt
, va_list inap
) {
152 char buf
[512], *dbuf
= buf
;
158 if (fmt
== NULL
) return;
160 if (!flag_dofile
&& !flag_dostderr
) goto quit
;
163 localtime_r(&t
, &bt
);
164 sprintf(timebuf
, "[%05i] %04i/%02i/%02i %02i:%02i:%02i: ",
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
));
172 if ((buf_sz
= vsnprintf(buf
, sizeof(buf
), fmt
, ap
)) >= sizeof(buf
)) {
174 if ((dbuf
= malloc(buf_sz
+1)) == NULL
) goto quit
; // alas, out of memory
176 vsnprintf(dbuf
, buf_sz
+1, fmt
, 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
);
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
);
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; }