2003-08-13 01:53:07 +00:00
/*
Unix SMB / CIFS implementation .
Samba debug functions
Copyright ( C ) Andrew Tridgell 2003
Copyright ( C ) James J Myers 2003
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-10 02:07:03 +00:00
the Free Software Foundation ; either version 3 of the License , or
2003-08-13 01:53:07 +00:00
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
2007-07-10 02:07:03 +00:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2003-08-13 01:53:07 +00:00
*/
# include "includes.h"
2005-02-10 05:09:35 +00:00
# include "system/filesys.h"
2006-01-09 18:25:06 +00:00
# include "system/time.h"
2008-05-27 14:36:28 +02:00
# include "dynconfig/dynconfig.h"
2003-08-13 01:53:07 +00:00
2006-02-28 13:12:39 +00:00
/**
* @ file
* @ brief Debug logging
* */
2006-03-06 00:24:51 +00:00
/**
* this global variable determines what messages are printed
*/
2006-03-05 17:15:19 +00:00
_PUBLIC_ int DEBUGLEVEL ;
2003-08-13 01:53:07 +00:00
/* the registered mutex handlers */
static struct {
const char * name ;
struct debug_ops ops ;
} debug_handlers ;
/* state variables for the debug system */
static struct {
int fd ;
enum debug_logtype logtype ;
const char * prog_name ;
} state ;
2007-08-27 17:21:16 +00:00
static bool reopen_logs_scheduled ;
static bool check_reopen_logs ( void )
2006-03-08 12:31:57 +00:00
{
if ( state . fd = = 0 | | reopen_logs_scheduled ) {
2007-08-27 17:21:16 +00:00
reopen_logs_scheduled = false ;
2006-03-08 12:31:57 +00:00
reopen_logs ( ) ;
}
2007-08-27 17:21:16 +00:00
if ( state . fd < = 0 )
return false ;
2006-03-08 12:31:57 +00:00
2007-08-27 17:21:16 +00:00
return true ;
2006-03-08 12:31:57 +00:00
}
_PUBLIC_ void debug_schedule_reopen_logs ( void )
{
2007-08-27 17:21:16 +00:00
reopen_logs_scheduled = true ;
2006-03-08 12:31:57 +00:00
}
2006-03-01 15:02:07 +00:00
static void log_timestring ( int level , const char * location , const char * func )
{
char * t = NULL ;
char * s = NULL ;
2006-03-08 12:31:57 +00:00
if ( ! check_reopen_logs ( ) ) return ;
2006-03-01 15:02:07 +00:00
if ( state . logtype ! = DEBUG_FILE ) return ;
t = timestring ( NULL , time ( NULL ) ) ;
if ( ! t ) return ;
asprintf ( & s , " [%s, %d %s:%s()] \n " , t , level , location , func ) ;
talloc_free ( t ) ;
if ( ! s ) return ;
write ( state . fd , s , strlen ( s ) ) ;
free ( s ) ;
}
2006-03-06 00:24:51 +00:00
/**
2006-01-09 18:25:06 +00:00
the backend for debug messages . Note that the DEBUG ( ) macro has already
ensured that the log level has been met before this is called
*/
2006-03-05 17:15:19 +00:00
_PUBLIC_ void do_debug_header ( int level , const char * location , const char * func )
2006-01-09 18:25:06 +00:00
{
2006-01-09 20:30:44 +00:00
log_timestring ( level , location , func ) ;
2006-01-09 18:25:06 +00:00
log_task_id ( ) ;
}
2006-03-06 00:24:51 +00:00
/**
2003-08-13 01:53:07 +00:00
the backend for debug messages . Note that the DEBUG ( ) macro has already
ensured that the log level has been met before this is called
2006-03-06 00:24:51 +00:00
@ note You should never have to call this function directly . Call the DEBUG ( )
macro instead .
2003-08-13 01:53:07 +00:00
*/
2007-11-05 10:10:17 +01:00
_PUBLIC_ void do_debug ( const char * format , . . . )
2003-08-13 01:53:07 +00:00
{
va_list ap ;
char * s = NULL ;
2006-03-08 12:31:57 +00:00
if ( ! check_reopen_logs ( ) ) return ;
2003-08-13 01:53:07 +00:00
va_start ( ap , format ) ;
vasprintf ( & s , format , ap ) ;
va_end ( ap ) ;
write ( state . fd , s , strlen ( s ) ) ;
free ( s ) ;
}
2006-03-20 00:28:12 +00:00
_PUBLIC_ const char * logfile = NULL ;
2006-02-28 13:12:39 +00:00
/**
2003-08-13 01:53:07 +00:00
reopen the log file ( usually called because the log file name might have changed )
*/
2006-03-05 17:15:19 +00:00
_PUBLIC_ void reopen_logs ( void )
2003-08-13 01:53:07 +00:00
{
char * fname = NULL ;
int old_fd = state . fd ;
switch ( state . logtype ) {
case DEBUG_STDOUT :
state . fd = 1 ;
break ;
case DEBUG_STDERR :
state . fd = 2 ;
break ;
case DEBUG_FILE :
2007-12-11 00:22:05 +01:00
if ( logfile & & ( * logfile ) = = ' / ' ) {
2003-08-13 01:53:07 +00:00
fname = strdup ( logfile ) ;
} else {
2005-06-13 08:12:39 +00:00
asprintf ( & fname , " %s/%s.log " , dyn_LOGFILEBASE , state . prog_name ) ;
2003-08-13 01:53:07 +00:00
}
if ( fname ) {
2005-06-13 08:12:39 +00:00
int newfd = open ( fname , O_CREAT | O_APPEND | O_WRONLY , 0600 ) ;
if ( newfd = = - 1 ) {
DEBUG ( 1 , ( " Failed to open new logfile: %s \n " , fname ) ) ;
2006-03-06 13:55:56 +00:00
old_fd = - 1 ;
2005-06-13 08:12:39 +00:00
} else {
state . fd = newfd ;
}
2003-08-13 01:53:07 +00:00
free ( fname ) ;
2005-06-13 08:12:39 +00:00
} else {
DEBUG ( 1 , ( " Failed to find name for file-based logfile! \n " ) ) ;
2003-08-13 01:53:07 +00:00
}
2005-06-13 08:12:39 +00:00
2003-08-13 01:53:07 +00:00
break ;
}
if ( old_fd > 2 ) {
close ( old_fd ) ;
}
}
2006-02-28 13:12:39 +00:00
/**
2003-08-13 01:53:07 +00:00
control the name of the logfile and whether logging will be to stdout , stderr
or a file
*/
2006-03-05 17:15:19 +00:00
_PUBLIC_ void setup_logging ( const char * prog_name , enum debug_logtype new_logtype )
2003-08-13 01:53:07 +00:00
{
2005-06-13 08:12:39 +00:00
if ( state . logtype < new_logtype ) {
state . logtype = new_logtype ;
}
if ( prog_name ) {
state . prog_name = prog_name ;
}
2003-08-13 01:53:07 +00:00
reopen_logs ( ) ;
}
2006-02-28 13:12:39 +00:00
/**
2003-08-13 01:53:07 +00:00
return a string constant containing n tabs
no more than 10 tabs are returned
*/
2006-04-24 09:36:09 +00:00
_PUBLIC_ const char * do_debug_tab ( int n )
2003-08-13 01:53:07 +00:00
{
const char * tabs [ ] = { " " , " \t " , " \t \t " , " \t \t \t " , " \t \t \t \t " , " \t \t \t \t \t " ,
" \t \t \t \t \t \t " , " \t \t \t \t \t \t \t " , " \t \t \t \t \t \t \t \t " ,
" \t \t \t \t \t \t \t \t \t " , " \t \t \t \t \t \t \t \t \t \t " } ;
return tabs [ MIN ( n , 10 ) ] ;
}
2006-02-28 13:12:39 +00:00
/**
log suspicious usage - print comments and backtrace
2003-08-13 01:53:07 +00:00
*/
2006-03-05 17:15:19 +00:00
_PUBLIC_ void log_suspicious_usage ( const char * from , const char * info )
2003-08-13 01:53:07 +00:00
{
2006-03-08 12:31:57 +00:00
if ( ! debug_handlers . ops . log_suspicious_usage ) return ;
debug_handlers . ops . log_suspicious_usage ( from , info ) ;
2003-08-13 01:53:07 +00:00
}
2006-02-28 13:12:39 +00:00
/**
print suspicious usage - print comments and backtrace
*/
2006-03-05 17:15:19 +00:00
_PUBLIC_ void print_suspicious_usage ( const char * from , const char * info )
2003-08-13 01:53:07 +00:00
{
2006-03-08 12:31:57 +00:00
if ( ! debug_handlers . ops . print_suspicious_usage ) return ;
debug_handlers . ops . print_suspicious_usage ( from , info ) ;
2003-08-13 01:53:07 +00:00
}
2006-03-05 17:15:19 +00:00
_PUBLIC_ uint32_t get_task_id ( void )
2003-08-13 01:53:07 +00:00
{
if ( debug_handlers . ops . get_task_id ) {
return debug_handlers . ops . get_task_id ( ) ;
}
return getpid ( ) ;
}
2006-03-05 17:15:19 +00:00
_PUBLIC_ void log_task_id ( void )
2003-12-04 09:52:14 +00:00
{
2006-03-08 12:31:57 +00:00
if ( ! debug_handlers . ops . log_task_id ) return ;
if ( ! check_reopen_logs ( ) ) return ;
debug_handlers . ops . log_task_id ( state . fd ) ;
2003-12-04 09:52:14 +00:00
}
2006-01-09 18:25:06 +00:00
2006-02-28 13:12:39 +00:00
/**
2003-08-13 01:53:07 +00:00
register a set of debug handlers .
*/
2006-03-05 17:15:19 +00:00
_PUBLIC_ void register_debug_handlers ( const char * name , struct debug_ops * ops )
2003-08-13 01:53:07 +00:00
{
debug_handlers . name = name ;
debug_handlers . ops = * ops ;
}