2003-08-13 05:53:07 +04: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 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2003-08-13 05:53:07 +04: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 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2003-08-13 05:53:07 +04:00
*/
# include "includes.h"
2005-02-10 08:09:35 +03:00
# include "system/filesys.h"
2006-01-09 21:25:06 +03:00
# include "system/time.h"
2008-05-27 16:36:28 +04:00
# include "dynconfig/dynconfig.h"
2003-08-13 05:53:07 +04:00
2006-02-28 16:12:39 +03:00
/**
* @ file
* @ brief Debug logging
* */
2006-03-06 03:24:51 +03:00
/**
* this global variable determines what messages are printed
*/
2008-10-11 22:44:19 +04:00
int _debug_level = 0 ;
_PUBLIC_ int * debug_level = & _debug_level ;
2008-10-19 16:14:55 +04:00
static int debug_all_class_hack = 1 ;
int * DEBUGLEVEL_CLASS = & debug_all_class_hack ; /* For samba 3 */
static bool debug_all_class_isset_hack = true ;
bool * DEBUGLEVEL_CLASS_ISSET = & debug_all_class_isset_hack ; /* For samba 3 */
2008-10-20 15:24:16 +04:00
XFILE * dbf = NULL ; /* For Samba 3*/
2003-08-13 05:53:07 +04: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 ;
2009-06-11 12:53:14 +04:00
bool reopening_logs ;
2003-08-13 05:53:07 +04:00
} state ;
2007-08-27 21:21:16 +04:00
static bool reopen_logs_scheduled ;
static bool check_reopen_logs ( void )
2006-03-08 15:31:57 +03:00
{
if ( state . fd = = 0 | | reopen_logs_scheduled ) {
2007-08-27 21:21:16 +04:00
reopen_logs_scheduled = false ;
2006-03-08 15:31:57 +03:00
reopen_logs ( ) ;
}
2007-08-27 21:21:16 +04:00
if ( state . fd < = 0 )
return false ;
2006-03-08 15:31:57 +03:00
2007-08-27 21:21:16 +04:00
return true ;
2006-03-08 15:31:57 +03:00
}
_PUBLIC_ void debug_schedule_reopen_logs ( void )
{
2007-08-27 21:21:16 +04:00
reopen_logs_scheduled = true ;
2006-03-08 15:31:57 +03:00
}
2006-03-01 18:02:07 +03:00
static void log_timestring ( int level , const char * location , const char * func )
{
char * t = NULL ;
char * s = NULL ;
2006-03-08 15:31:57 +03:00
if ( ! check_reopen_logs ( ) ) return ;
2006-03-01 18:02:07 +03: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 03:24:51 +03:00
/**
2006-01-09 21:25:06 +03: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
*/
2008-10-11 22:44:19 +04:00
_PUBLIC_ void dbghdr ( int level , const char * location , const char * func )
2006-01-09 21:25:06 +03:00
{
2006-01-09 23:30:44 +03:00
log_timestring ( level , location , func ) ;
2006-01-09 21:25:06 +03:00
log_task_id ( ) ;
}
2008-10-11 22:44:19 +04:00
2009-02-02 13:28:19 +03:00
_PUBLIC_ void dbghdrclass ( int level , int dclass , const char * location , const char * func )
2008-10-11 22:44:19 +04:00
{
/* Simple wrapper, Samba 4 doesn't do debug classes */
dbghdr ( level , location , func ) ;
}
2006-03-06 03:24:51 +03:00
/**
2003-08-13 05:53:07 +04: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 03:24:51 +03:00
@ note You should never have to call this function directly . Call the DEBUG ( )
macro instead .
2003-08-13 05:53:07 +04:00
*/
2008-10-11 22:44:19 +04:00
_PUBLIC_ void dbgtext ( const char * format , . . . )
2003-08-13 05:53:07 +04:00
{
va_list ap ;
char * s = NULL ;
2006-03-08 15:31:57 +03:00
if ( ! check_reopen_logs ( ) ) return ;
2003-08-13 05:53:07 +04:00
va_start ( ap , format ) ;
vasprintf ( & s , format , ap ) ;
va_end ( ap ) ;
write ( state . fd , s , strlen ( s ) ) ;
free ( s ) ;
}
2006-03-20 03:28:12 +03:00
_PUBLIC_ const char * logfile = NULL ;
2006-02-28 16:12:39 +03:00
/**
2003-08-13 05:53:07 +04:00
reopen the log file ( usually called because the log file name might have changed )
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ void reopen_logs ( void )
2003-08-13 05:53:07 +04:00
{
char * fname = NULL ;
int old_fd = state . fd ;
2009-06-11 12:53:14 +04:00
if ( state . reopening_logs ) {
return ;
}
2003-08-13 05:53:07 +04:00
switch ( state . logtype ) {
case DEBUG_STDOUT :
state . fd = 1 ;
break ;
case DEBUG_STDERR :
state . fd = 2 ;
break ;
case DEBUG_FILE :
2009-06-11 12:53:14 +04:00
state . reopening_logs = true ;
2007-12-11 02:22:05 +03:00
if ( logfile & & ( * logfile ) = = ' / ' ) {
2003-08-13 05:53:07 +04:00
fname = strdup ( logfile ) ;
} else {
2005-06-13 12:12:39 +04:00
asprintf ( & fname , " %s/%s.log " , dyn_LOGFILEBASE , state . prog_name ) ;
2003-08-13 05:53:07 +04:00
}
if ( fname ) {
2005-06-13 12:12:39 +04: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 16:55:56 +03:00
old_fd = - 1 ;
2005-06-13 12:12:39 +04:00
} else {
state . fd = newfd ;
}
2003-08-13 05:53:07 +04:00
free ( fname ) ;
2005-06-13 12:12:39 +04:00
} else {
DEBUG ( 1 , ( " Failed to find name for file-based logfile! \n " ) ) ;
2003-08-13 05:53:07 +04:00
}
2009-06-11 13:08:33 +04:00
state . reopening_logs = false ;
2005-06-13 12:12:39 +04:00
2003-08-13 05:53:07 +04:00
break ;
}
if ( old_fd > 2 ) {
close ( old_fd ) ;
}
}
2006-02-28 16:12:39 +03:00
/**
2003-08-13 05:53:07 +04:00
control the name of the logfile and whether logging will be to stdout , stderr
or a file
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ void setup_logging ( const char * prog_name , enum debug_logtype new_logtype )
2003-08-13 05:53:07 +04:00
{
2005-06-13 12:12:39 +04:00
if ( state . logtype < new_logtype ) {
state . logtype = new_logtype ;
}
if ( prog_name ) {
state . prog_name = prog_name ;
}
2003-08-13 05:53:07 +04:00
reopen_logs ( ) ;
}
2006-02-28 16:12:39 +03:00
/**
2003-08-13 05:53:07 +04:00
return a string constant containing n tabs
no more than 10 tabs are returned
*/
2006-04-24 13:36:09 +04:00
_PUBLIC_ const char * do_debug_tab ( int n )
2003-08-13 05:53:07 +04: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 16:12:39 +03:00
/**
log suspicious usage - print comments and backtrace
2003-08-13 05:53:07 +04:00
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ void log_suspicious_usage ( const char * from , const char * info )
2003-08-13 05:53:07 +04:00
{
2006-03-08 15:31:57 +03:00
if ( ! debug_handlers . ops . log_suspicious_usage ) return ;
debug_handlers . ops . log_suspicious_usage ( from , info ) ;
2003-08-13 05:53:07 +04:00
}
2006-02-28 16:12:39 +03:00
/**
print suspicious usage - print comments and backtrace
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ void print_suspicious_usage ( const char * from , const char * info )
2003-08-13 05:53:07 +04:00
{
2006-03-08 15:31:57 +03:00
if ( ! debug_handlers . ops . print_suspicious_usage ) return ;
debug_handlers . ops . print_suspicious_usage ( from , info ) ;
2003-08-13 05:53:07 +04:00
}
2006-03-05 20:15:19 +03:00
_PUBLIC_ uint32_t get_task_id ( void )
2003-08-13 05:53:07 +04:00
{
if ( debug_handlers . ops . get_task_id ) {
return debug_handlers . ops . get_task_id ( ) ;
}
return getpid ( ) ;
}
2006-03-05 20:15:19 +03:00
_PUBLIC_ void log_task_id ( void )
2003-12-04 12:52:14 +03:00
{
2006-03-08 15:31:57 +03: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 12:52:14 +03:00
}
2006-01-09 21:25:06 +03:00
2006-02-28 16:12:39 +03:00
/**
2003-08-13 05:53:07 +04:00
register a set of debug handlers .
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ void register_debug_handlers ( const char * name , struct debug_ops * ops )
2003-08-13 05:53:07 +04:00
{
debug_handlers . name = name ;
debug_handlers . ops = * ops ;
}