1 /**
2 * gam_error.c: the debugging intrastructure
3 *
4 * Allow to use GAM_DEBUG environment variable or SIG_USR2 for
5 * dynamic debugging of clients and server.
6 *
7 * Daniel Veillard <veillard@redhat.com>
8 * See the Copyright file.
9 */
10 #include <config.h>
11 #include <stdio.h>
12 #include <stdarg.h>
13 #include <stdlib.h>
14 #include <signal.h>
15 #include <errno.h>
16 #include "gam_error.h"
17
18 typedef void (*signal_handler) (int);
19
20 extern void gam_show_debug(void);
21 extern void gam_got_signal (void);
22
23 int gam_debug_active = 0;
24 static int initialized = 0;
25 static int do_debug = 0;
26 static int got_signal = 0;
27 static FILE *debug_out = NULL;
28
29 static void
gam_error_handle_signal(void)30 gam_error_handle_signal(void)
31 {
32 if (got_signal == 0)
33 return;
34
35 got_signal = 0;
36
37 if (do_debug == 0) {
38 if (debug_out != stderr) {
39 char path[50] = "/tmp/gamin_debug_XXXXXX";
40 int fd = mkstemp(path);
41
42 if (fd >= 0) {
43 debug_out = fdopen(fd, "a");
44 if (debug_out != NULL) {
45 do_debug = 1;
46 gam_debug_active = 1;
47 gam_show_debug();
48 }
49 }
50 }
51 } else {
52 if (debug_out != stderr) {
53 do_debug = 0;
54 gam_debug_active = 0;
55 if (debug_out != NULL) {
56 fflush(debug_out);
57 fclose(debug_out);
58 debug_out = NULL;
59 }
60 }
61 }
62 }
63
64
65 static void
gam_error_signal(int no)66 gam_error_signal(int no)
67 {
68 got_signal = !got_signal;
69 gam_debug_active = -1; /* force going into gam_debug() */
70 gam_got_signal ();
71 }
72
73 /**
74 * gam_error_init:
75 *
76 * Initialization routine for the error and debug handling.
77 */
78 void
gam_error_init(void)79 gam_error_init(void)
80 {
81 if (initialized == 0) {
82 struct sigaction oldact;
83
84 initialized = 1;
85
86 if (getenv("GAM_DEBUG") != NULL) {
87 debug_out = stderr;
88 gam_debug_active = 1;
89 do_debug = 1;
90 /* Fake the signal */
91 got_signal = 1;
92 gam_error_handle_signal();
93 }
94
95 /* if there is already an handler, leave it as is to
96 * avoid disturbing the application's behaviour */
97 if (sigaction (SIGUSR2, NULL, &oldact) == 0) {
98 if (oldact.sa_handler == NULL && oldact.sa_sigaction == NULL)
99 signal(SIGUSR2, gam_error_signal);
100 }
101 }
102 }
103
104 /**
105 * gam_error_init:
106 *
107 * Checking routine to call from time to time to handle asynchronous
108 * error debugging events.
109 */
110 void
gam_error_check(void)111 gam_error_check(void)
112 {
113 if (initialized == 0)
114 gam_error_init();
115
116 if (got_signal)
117 gam_error_handle_signal();
118 }
119
120 int
gam_errno(void)121 gam_errno(void)
122 {
123 return (errno);
124 }
125
126 /**
127 * gam_error:
128 * @file: the filename where the error was detected
129 * @line: the line where the error was detected
130 * @function: the function where the error was detected
131 * @format: *printf format
132 * @...: extra arguments
133 *
134 * Log an error, currently only stderr, but could go into syslog
135 */
136 void
gam_error(const char * file,int line,const char * function,const char * format,...)137 gam_error(const char *file, int line, const char *function,
138 const char *format, ...)
139 {
140 va_list args;
141
142 if (initialized == 0)
143 gam_error_init();
144
145 if (got_signal)
146 gam_error_handle_signal();
147
148 if ((file == NULL) || (function == NULL) || (format == NULL))
149 return;
150
151 va_start(args, format);
152 vfprintf((debug_out ? debug_out : stderr), format, args);
153 va_end(args);
154
155 if (debug_out)
156 fflush(debug_out);
157 }
158
159 /**
160 * gam_debug:
161 * @file: the filename where the error was detected
162 * @line: the line where the error was detected
163 * @function: the function where the error was detected
164 * @format: *printf format
165 * @...: extra arguments
166 *
167 * Log a debug message, fi those are activated by the GAM_DEBUG environment
168 */
169 void
gam_debug(const char * file,int line,const char * function,const char * format,...)170 gam_debug(const char *file, int line, const char *function,
171 const char *format, ...)
172 {
173 va_list args;
174
175 if (initialized == 0)
176 gam_error_init();
177
178 if (got_signal)
179 gam_error_handle_signal();
180
181 if ((do_debug == 0) || (gam_debug_active == 0))
182 return;
183
184 if ((file == NULL) || (function == NULL) || (format == NULL))
185 return;
186
187 va_start(args, format);
188 vfprintf((debug_out ? debug_out : stdout), format, args);
189 va_end(args);
190 if (debug_out)
191 fflush(debug_out);
192 }
193