xref: /openbsd-src/lib/libc/thread/rthread_debug.c (revision c7e8ea31cd41a963f06f0a8ba93948b06aa6b4a4)
1 /* $OpenBSD: rthread_debug.c,v 1.2 2017/08/15 06:38:41 guenther Exp $ */
2 
3 /* PUBLIC DOMAIN: No Rights Reserved. Marco S Hyman <marc@snafu.org> */
4 
5 #include <pthread.h>
6 #include <stdarg.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10 
11 #include "rthread.h"
12 
13 REDIRECT_SYSCALL(issetugid);
14 
15 int _rthread_debug_level;
16 
17 /*
18  * Note: messages truncated at 255 characters.   Could use vasprintf,
19  * but don't want to use malloc here so the function can be used
20  * in signal handlers.
21  */
22 #define MAX_MSG_LEN 256
23 #define RTHREAD_ENV_DEBUG	"RTHREAD_DEBUG"
24 
25 /*
26  * format and send output to stderr if the given "level" is less than or
27  * equal to the current debug level.   Messages with a level <= 0 will
28  * always be printed.
29  */
30 void
31 _rthread_debug(int level, const char *fmt, ...)
32 {
33 	char msg[MAX_MSG_LEN];
34 	char *p;
35 	int cnt;
36 	ssize_t c;
37 
38 	if (_rthread_debug_level >= level) {
39 		va_list ap;
40 		va_start(ap, fmt);
41 		cnt = vsnprintf(msg, MAX_MSG_LEN, fmt, ap);
42 		va_end(ap);
43 		if (cnt > MAX_MSG_LEN - 1)
44 			cnt = MAX_MSG_LEN - 1;
45 		p = msg;
46 		do {
47 			c = write(STDERR_FILENO, p, cnt);
48 			if (c == -1)
49 				break;
50 			if (c != cnt)
51 				sched_yield();
52 			p += c;
53 			cnt -= c;
54 		} while (cnt > 0);
55 	}
56 }
57 
58 /*
59  * set the debug level from an environment string.  Bogus values are
60  * silently ignored.
61  */
62 void
63 _rthread_debug_init(void)
64 {
65 	char *envp;
66 	char *rem;
67 
68 	if (issetugid())
69 		return;
70 	envp = getenv(RTHREAD_ENV_DEBUG);
71 	if (envp) {
72 		_rthread_debug_level = (int) strtol(envp, &rem, 0);
73 		if (*rem || _rthread_debug_level < 0)
74 			_rthread_debug_level = 0;
75 	}
76 }
77