This commit was generated by cvs2svn to compensate for changes in r30,
[kai/samba-autobuild/.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         write(state.fd, s, strlen(s));
61         free(s);
62 }
63
64 /*
65   reopen the log file (usually called because the log file name might have changed)
66 */
67 void reopen_logs(void)
68 {
69         char *logfile = lp_logfile();
70         char *fname = NULL;
71         int old_fd = state.fd;
72
73         state.fd = 0;
74
75         switch (state.logtype) {
76         case DEBUG_STDOUT:
77                 state.fd = 1;
78                 break;
79
80         case DEBUG_STDERR:
81                 state.fd = 2;
82                 break;
83
84         case DEBUG_FILE:
85                 if ((*logfile) == '/') {
86                         fname = strdup(logfile);
87                 } else {
88                         asprintf(&fname, "%s/%s.log", dyn_LOGFILEBASE, logfile);
89                 }
90                 if (fname) {
91                         state.fd = open(fname, O_CREAT|O_APPEND|O_WRONLY, 0644);
92                         free(fname);
93                 }
94                 break;
95         }
96
97         if (old_fd > 2) {
98                 close(old_fd);
99         }
100 }
101
102 /*
103   control the name of the logfile and whether logging will be to stdout, stderr
104   or a file
105 */
106 void setup_logging(const char *prog_name, enum debug_logtype new_logtype)
107 {
108         state.logtype = new_logtype;
109         state.prog_name = prog_name;
110         reopen_logs();
111 }
112
113 /*
114   return a string constant containing n tabs
115   no more than 10 tabs are returned
116 */
117 const char *do_debug_tab(uint_t n)
118 {
119         const char *tabs[] = {"", "\t", "\t\t", "\t\t\t", "\t\t\t\t", "\t\t\t\t\t", 
120                               "\t\t\t\t\t\t", "\t\t\t\t\t\t\t", "\t\t\t\t\t\t\t\t", 
121                               "\t\t\t\t\t\t\t\t\t", "\t\t\t\t\t\t\t\t\t\t"};
122         return tabs[MIN(n, 10)];
123 }
124
125
126 /*
127   log/print suspicious usage - print comments and backtrace
128 */      
129 void log_suspicious_usage(const char *from, const char *info)
130 {
131         if (debug_handlers.ops.log_suspicious_usage) {
132                 return debug_handlers.ops.log_suspicious_usage(from, info);
133         }
134 }
135 void print_suspicious_usage(const char* from, const char* info)
136 {
137         if (debug_handlers.ops.print_suspicious_usage) {
138                 return debug_handlers.ops.print_suspicious_usage(from, info);
139         }
140 }
141
142 uint32 get_task_id(void)
143 {
144         if (debug_handlers.ops.get_task_id) {
145                 return debug_handlers.ops.get_task_id();
146         }
147         return getpid();
148 }
149
150 /*
151   register a set of debug handlers. 
152 */
153 void register_debug_handlers(const char *name, struct debug_ops *ops)
154 {
155         debug_handlers.name = name;
156         debug_handlers.ops = *ops;
157 }