r574: - another attempt at const cleanliness in ldb
[kai/samba.git] / source4 / lib / debug.c
1 /*
2    Unix SMB/CIFS implementation.
3    Samba debug functions
4    Copyright (C) Andrew Tridgell 2003
5    Copyright (C) James J Myers   2003
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 /* this global variable determines what messages are printed */
25 int DEBUGLEVEL;
26
27
28 /* the registered mutex handlers */
29 static struct {
30         const char *name;
31         struct debug_ops ops;
32 } debug_handlers;
33
34 /* state variables for the debug system */
35 static struct {
36         int fd;
37         enum debug_logtype logtype;
38         const char *prog_name;
39 } state;
40
41 /*
42   the backend for debug messages. Note that the DEBUG() macro has already
43   ensured that the log level has been met before this is called
44 */
45 void do_debug(const char *format, ...)
46 {
47         va_list ap;
48         char *s = NULL;
49
50         if (state.fd == 0) {
51                 reopen_logs();
52         }
53
54         if (state.fd <= 0) return;
55
56         va_start(ap, format);
57         vasprintf(&s, format, ap);
58         va_end(ap);
59
60         log_task_id();
61         
62         write(state.fd, s, strlen(s));
63         free(s);
64 }
65
66 /*
67   reopen the log file (usually called because the log file name might have changed)
68 */
69 void reopen_logs(void)
70 {
71         char *logfile = lp_logfile();
72         char *fname = NULL;
73         int old_fd = state.fd;
74
75         state.fd = 0;
76
77         switch (state.logtype) {
78         case DEBUG_STDOUT:
79                 state.fd = 1;
80                 break;
81
82         case DEBUG_STDERR:
83                 state.fd = 2;
84                 break;
85
86         case DEBUG_FILE:
87                 if ((*logfile) == '/') {
88                         fname = strdup(logfile);
89                 } else {
90                         asprintf(&fname, "%s/%s.log", dyn_LOGFILEBASE, logfile);
91                 }
92                 if (fname) {
93                         state.fd = open(fname, O_CREAT|O_APPEND|O_WRONLY, 0644);
94                         free(fname);
95                 }
96                 break;
97         }
98
99         if (old_fd > 2) {
100                 close(old_fd);
101         }
102 }
103
104 /*
105   control the name of the logfile and whether logging will be to stdout, stderr
106   or a file
107 */
108 void setup_logging(const char *prog_name, enum debug_logtype new_logtype)
109 {
110         state.logtype = new_logtype;
111         state.prog_name = prog_name;
112         reopen_logs();
113 }
114
115 /*
116   return a string constant containing n tabs
117   no more than 10 tabs are returned
118 */
119 const char *do_debug_tab(uint_t n)
120 {
121         const char *tabs[] = {"", "\t", "\t\t", "\t\t\t", "\t\t\t\t", "\t\t\t\t\t", 
122                               "\t\t\t\t\t\t", "\t\t\t\t\t\t\t", "\t\t\t\t\t\t\t\t", 
123                               "\t\t\t\t\t\t\t\t\t", "\t\t\t\t\t\t\t\t\t\t"};
124         return tabs[MIN(n, 10)];
125 }
126
127
128 /*
129   log/print suspicious usage - print comments and backtrace
130 */      
131 void log_suspicious_usage(const char *from, const char *info)
132 {
133         if (debug_handlers.ops.log_suspicious_usage) {
134                 debug_handlers.ops.log_suspicious_usage(from, info);
135         }
136 }
137 void print_suspicious_usage(const char* from, const char* info)
138 {
139         if (debug_handlers.ops.print_suspicious_usage) {
140                 debug_handlers.ops.print_suspicious_usage(from, info);
141         }
142 }
143
144 uint32 get_task_id(void)
145 {
146         if (debug_handlers.ops.get_task_id) {
147                 return debug_handlers.ops.get_task_id();
148         }
149         return getpid();
150 }
151
152 void log_task_id(void)
153 {
154         if (debug_handlers.ops.log_task_id) {
155                 debug_handlers.ops.log_task_id(state.fd);
156         }
157 }
158 /*
159   register a set of debug handlers. 
160 */
161 void register_debug_handlers(const char *name, struct debug_ops *ops)
162 {
163         debug_handlers.name = name;
164         debug_handlers.ops = *ops;
165 }