1998-08-01 00:17:36 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
1998-08-01 00:17:36 +04:00
Samba utility functions
Copyright ( C ) Andrew Tridgell 1992 - 1998
2002-07-15 14:35:28 +04:00
Copyright ( C ) Elrond 2002
Copyright ( C ) Simo Sorce 2002
1998-08-01 00:17:36 +04:00
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
the Free Software Foundation ; either version 2 of the License , or
( 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
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
1998-08-21 23:57:59 +04:00
/* -------------------------------------------------------------------------- **
* Defines . . .
*
* FORMAT_BUFR_MAX - Index of the last byte of the format buffer ;
* format_bufr [ FORMAT_BUFR_MAX ] should always be reserved
2001-10-29 11:26:45 +03:00
* for a terminating null byte .
1998-08-21 23:57:59 +04:00
*/
# define FORMAT_BUFR_MAX ( sizeof( format_bufr ) - 1 )
1998-08-01 00:17:36 +04:00
/* -------------------------------------------------------------------------- **
* This module implements Samba ' s debugging utility .
*
* The syntax of a debugging log file is represented as :
*
* < debugfile > : = = { < debugmsg > }
*
* < debugmsg > : = = < debughdr > ' \n ' < debugtext >
*
* < debughdr > : = = ' [ ' TIME ' , ' LEVEL ' ] ' [ [ FILENAME ' : ' ] [ FUNCTION ' ( ) ' ] ]
*
* < debugtext > : = = { < debugline > }
*
* < debugline > : = = TEXT ' \n '
*
* TEXT is a string of characters excluding the newline character .
* LEVEL is the DEBUG level of the message ( an integer in the range 0. .10 ) .
* TIME is a timestamp .
* FILENAME is the name of the file from which the debug message was generated .
* FUNCTION is the function from which the debug message was generated .
*
* Basically , what that all means is :
*
* - A debugging log file is made up of debug messages .
*
* - Each debug message is made up of a header and text . The header is
* separated from the text by a newline .
*
* - The header begins with the timestamp and debug level of the message
* enclosed in brackets . The filename and function from which the
* message was generated may follow . The filename is terminated by a
* colon , and the function name is terminated by parenthesis .
*
* - The message text is made up of zero or more lines , each terminated by
* a newline .
*/
/* -------------------------------------------------------------------------- **
* External variables .
*
* dbf - Global debug file handle .
* debugf - Debug file name .
* DEBUGLEVEL - System - wide debug message limit . Messages with message -
* levels higher than DEBUGLEVEL will not be processed .
*/
2001-09-10 15:08:57 +04:00
XFILE * dbf = NULL ;
1998-08-01 00:17:36 +04:00
pstring debugf = " " ;
2002-07-15 14:35:28 +04:00
BOOL debug_warn_unknown_class = True ;
BOOL debug_auto_add_unknown_class = True ;
BOOL AllowDebugChange = True ;
2001-03-27 05:19:54 +04:00
2002-07-15 14:35:28 +04:00
/*
* This is to allow assignment to DEBUGLEVEL before the debug
* system has been initialised .
*/
static int debug_all_class_hack = 1 ;
static BOOL debug_all_class_isset_hack = True ;
static int debug_num_classes = 0 ;
int * DEBUGLEVEL_CLASS = & debug_all_class_hack ;
BOOL * DEBUGLEVEL_CLASS_ISSET = & debug_all_class_isset_hack ;
/* DEBUGLEVEL is #defined to *debug_level */
int DEBUGLEVEL = & debug_all_class_hack ;
1998-08-01 00:17:36 +04:00
/* -------------------------------------------------------------------------- **
* Internal variables .
*
* stdout_logging - Default False , if set to True then dbf will be set to
* stdout and debug output will go to dbf only , and not
* to syslog . Set in setup_logging ( ) and read in Debug1 ( ) .
*
* debug_count - Number of debug messages that have been output .
* Used to check log size .
*
* syslog_level - Internal copy of the message debug level . Written by
* dbghdr ( ) and read by Debug1 ( ) .
*
* format_bufr - Used to format debug messages . The dbgtext ( ) function
* prints debug messages to a string , and then passes the
* string to format_debug_text ( ) , which uses format_bufr
* to build the formatted output .
*
* format_pos - Marks the first free byte of the format_bufr .
2001-03-27 05:19:54 +04:00
*
*
* log_overflow - When this variable is True , never attempt to check the
* size of the log . This is a hack , so that we can write
* a message using DEBUG , from open_logs ( ) when we
* are unable to open a new log file for some reason .
1998-08-01 00:17:36 +04:00
*/
static BOOL stdout_logging = False ;
static int debug_count = 0 ;
1998-09-29 01:43:48 +04:00
# ifdef WITH_SYSLOG
1998-08-01 00:17:36 +04:00
static int syslog_level = 0 ;
1998-09-29 01:43:48 +04:00
# endif
1998-08-01 00:17:36 +04:00
static pstring format_bufr = { ' \0 ' } ;
1999-12-13 16:27:58 +03:00
static size_t format_pos = 0 ;
2001-03-27 05:19:54 +04:00
static BOOL log_overflow = False ;
1998-08-01 00:17:36 +04:00
2001-02-12 19:18:02 +03:00
/*
2001-10-29 11:26:45 +03:00
* Define all the debug class selection names here . Names * MUST NOT * contain
* white space . There must be one name for each DBGC_ < class name > , and they
* must be in the table in the order of DBGC_ < class name > . .
*/
2002-07-15 14:35:28 +04:00
static const char * default_classname_table [ ] = {
2001-06-01 16:04:44 +04:00
" all " , /* DBGC_ALL; index refs traditional DEBUGLEVEL */
" tdb " , /* DBGC_TDB */
2001-02-12 19:18:02 +03:00
" printdrivers " , /* DBGC_PRINTDRIVERS */
2001-06-01 16:04:44 +04:00
" lanman " , /* DBGC_LANMAN */
" smb " , /* DBGC_SMB */
2002-07-15 14:35:28 +04:00
" rpc_parse " , /* DBGC_RPC_PARSE */
" rpc_srv " , /* DBGC_RPC_SRV */
" rpc_cli " , /* DBGC_RPC_CLI */
" passdb " , /* DBGC_PASSDB */
2002-09-25 19:19:00 +04:00
" sam " , /* DBGC_SAM */
2002-07-15 14:35:28 +04:00
" auth " , /* DBGC_AUTH */
" winbind " , /* DBGC_WINBIND */
2002-09-25 19:19:00 +04:00
" vfs " , /* DBGC_VFS */
2002-07-15 14:35:28 +04:00
NULL
2001-02-12 19:18:02 +03:00
} ;
2002-07-15 14:35:28 +04:00
static char * * classname_table = NULL ;
1998-08-01 00:17:36 +04:00
/* -------------------------------------------------------------------------- **
* Functions . . .
*/
2002-07-15 14:35:28 +04:00
/****************************************************************************
utility lists registered debug class names ' s
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define MAX_CLASS_NAME_SIZE 1024
static char * debug_list_class_names_and_levels ( void )
{
int i , dim ;
char * * list ;
char * buf = NULL ;
char * b ;
BOOL err = False ;
if ( DEBUGLEVEL_CLASS = = & debug_all_class_hack )
return NULL ;
list = calloc ( debug_num_classes + 1 , sizeof ( char * ) ) ;
if ( ! list )
return NULL ;
/* prepare strings */
for ( i = 0 , dim = 0 ; i < debug_num_classes ; i + + ) {
int l = asprintf ( & list [ i ] ,
" %s:%d " ,
classname_table [ i ] ,
DEBUGLEVEL_CLASS_ISSET [ i ] ? DEBUGLEVEL_CLASS [ i ] : DEBUGLEVEL ) ;
if ( l < 0 | | l > MAX_CLASS_NAME_SIZE ) {
err = True ;
goto done ;
}
dim + = l ;
}
/* create single string list */
b = buf = malloc ( dim ) ;
if ( ! buf ) {
err = True ;
goto done ;
}
for ( i = 0 ; i < debug_num_classes ; i + + ) {
int l = strlen ( list [ i ] ) ;
strncpy ( b , list [ i ] , l ) ;
b = b + l ;
}
b [ - 1 ] = ' \0 ' ;
done :
/* free strings list */
for ( i = 0 ; i < debug_num_classes ; i + + )
if ( list [ i ] ) free ( list [ i ] ) ;
free ( list ) ;
if ( err ) {
if ( buf )
free ( buf ) ;
return NULL ;
} else {
return buf ;
}
}
2001-02-12 19:18:02 +03:00
/****************************************************************************
utility access to debug class names ' s
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
const char * debug_classname_from_index ( int ndx )
2001-02-12 19:18:02 +03:00
{
2002-07-15 14:35:28 +04:00
if ( ndx < 0 | | ndx > = debug_num_classes )
return NULL ;
else
return classname_table [ ndx ] ;
2001-02-12 19:18:02 +03:00
}
/****************************************************************************
2002-07-15 14:35:28 +04:00
utility to translate names to debug class index ' s ( internal version )
2001-02-12 19:18:02 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
static int debug_lookup_classname_int ( const char * classname )
2001-02-12 19:18:02 +03:00
{
int i ;
if ( ! classname ) return - 1 ;
2002-07-15 14:35:28 +04:00
for ( i = 0 ; i < debug_num_classes ; i + + ) {
2001-02-12 19:18:02 +03:00
if ( strcmp ( classname , classname_table [ i ] ) = = 0 )
return i ;
}
return - 1 ;
}
2002-07-15 14:35:28 +04:00
/****************************************************************************
Add a new debug class to the system
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int debug_add_class ( const char * classname )
{
int ndx ;
void * new_ptr ;
if ( ! classname )
return - 1 ;
/* check the init has yet been called */
debug_init ( ) ;
ndx = debug_lookup_classname_int ( classname ) ;
if ( ndx > = 0 )
return ndx ;
ndx = debug_num_classes ;
new_ptr = DEBUGLEVEL_CLASS ;
if ( DEBUGLEVEL_CLASS = = & debug_all_class_hack )
{
/* Initial loading... */
new_ptr = NULL ;
}
new_ptr = Realloc ( new_ptr ,
sizeof ( int ) * ( debug_num_classes + 1 ) ) ;
if ( ! new_ptr )
return - 1 ;
DEBUGLEVEL_CLASS = new_ptr ;
DEBUGLEVEL_CLASS [ ndx ] = 0 ;
/* debug_level is the pointer used for the DEBUGLEVEL-thingy */
if ( ndx = = 0 )
{
/* Transfer the initial level from debug_all_class_hack */
DEBUGLEVEL_CLASS [ ndx ] = DEBUGLEVEL ;
}
debug_level = DEBUGLEVEL_CLASS ;
new_ptr = DEBUGLEVEL_CLASS_ISSET ;
if ( new_ptr = = & debug_all_class_isset_hack )
{
new_ptr = NULL ;
}
new_ptr = Realloc ( new_ptr ,
sizeof ( BOOL ) * ( debug_num_classes + 1 ) ) ;
if ( ! new_ptr )
return - 1 ;
DEBUGLEVEL_CLASS_ISSET = new_ptr ;
DEBUGLEVEL_CLASS_ISSET [ ndx ] = False ;
new_ptr = Realloc ( classname_table ,
sizeof ( char * ) * ( debug_num_classes + 1 ) ) ;
if ( ! new_ptr )
return - 1 ;
classname_table = new_ptr ;
classname_table [ ndx ] = strdup ( classname ) ;
if ( ! classname_table [ ndx ] )
return - 1 ;
debug_num_classes + + ;
return ndx ;
}
/****************************************************************************
utility to translate names to debug class index ' s ( public version )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int debug_lookup_classname ( const char * classname )
{
int ndx ;
if ( ! classname | | ! * classname ) return - 1 ;
ndx = debug_lookup_classname_int ( classname ) ;
if ( ndx ! = - 1 )
return ndx ;
if ( debug_warn_unknown_class )
{
DEBUG ( 0 , ( " debug_lookup_classname(%s): Unknown class \n " ,
classname ) ) ;
}
if ( debug_auto_add_unknown_class )
{
return debug_add_class ( classname ) ;
}
return - 1 ;
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
dump the current registered debug levels
2002-07-15 14:35:28 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void debug_dump_status ( int level )
{
int q ;
DEBUG ( level , ( " INFO: Current debug levels: \n " ) ) ;
for ( q = 0 ; q < debug_num_classes ; q + + )
{
DEBUGADD ( level , ( " %s: %s/%d \n " ,
classname_table [ q ] ,
( DEBUGLEVEL_CLASS_ISSET [ q ]
? " True " : " False " ) ,
DEBUGLEVEL_CLASS [ q ] ) ) ;
}
}
2001-02-12 19:18:02 +03:00
/****************************************************************************
parse the debug levels from smbcontrol . Example debug level parameter :
printdrivers : 7
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
static BOOL debug_parse_params ( char * * params )
2001-02-12 19:18:02 +03:00
{
2001-02-13 19:28:48 +03:00
int i , ndx ;
2001-02-12 19:18:02 +03:00
char * class_name ;
char * class_level ;
2002-07-15 14:35:28 +04:00
if ( ! params )
return False ;
2001-02-12 19:18:02 +03:00
2001-10-29 11:26:45 +03:00
/* Allow DBGC_ALL to be specified w/o requiring its class name e.g."10"
2001-02-12 19:18:02 +03:00
* v . s . " all:10 " , this is the traditional way to set DEBUGLEVEL
*/
2001-04-28 02:02:23 +04:00
if ( isdigit ( ( int ) params [ 0 ] [ 0 ] ) ) {
2002-09-25 19:19:00 +04:00
DEBUGLEVEL_CLASS [ DBGC_ALL ] = atoi ( params [ 0 ] ) ;
DEBUGLEVEL_CLASS_ISSET [ DBGC_ALL ] = True ;
2001-02-12 19:18:02 +03:00
i = 1 ; /* start processing at the next params */
}
else
2001-10-29 11:26:45 +03:00
i = 0 ; /* DBGC_ALL not specified OR class name was included */
2001-02-12 19:18:02 +03:00
/* Fill in new debug class levels */
2002-07-15 14:35:28 +04:00
for ( ; i < debug_num_classes & & params [ i ] ; i + + ) {
2001-02-12 19:18:02 +03:00
if ( ( class_name = strtok ( params [ i ] , " : " ) ) & &
( class_level = strtok ( NULL , " \0 " ) ) & &
2001-02-13 19:28:48 +03:00
( ( ndx = debug_lookup_classname ( class_name ) ) ! = - 1 ) ) {
2002-09-25 19:19:00 +04:00
DEBUGLEVEL_CLASS [ ndx ] = atoi ( class_level ) ;
DEBUGLEVEL_CLASS_ISSET [ ndx ] = True ;
2001-02-12 19:18:02 +03:00
} else {
DEBUG ( 0 , ( " debug_parse_params: unrecognized debug class name or format [%s] \n " , params [ i ] ) ) ;
return False ;
}
}
return True ;
}
/****************************************************************************
parse the debug levels from smb . conf . Example debug level string :
3 tdb : 5 printdrivers : 7
Note : the 1 st param has no " name: " preceeding it .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
BOOL debug_parse_levels ( const char * params_str )
2001-02-12 19:18:02 +03:00
{
2002-07-15 14:35:28 +04:00
char * * params ;
/* Just in case */
debug_init ( ) ;
2001-02-12 19:18:02 +03:00
2002-01-08 00:32:22 +03:00
if ( AllowDebugChange = = False )
return True ;
2001-06-01 16:04:44 +04:00
2002-08-17 21:00:51 +04:00
params = str_list_make ( params_str , NULL ) ;
2001-06-01 16:04:44 +04:00
2002-09-25 19:19:00 +04:00
if ( debug_parse_params ( params ) )
2002-07-15 14:35:28 +04:00
{
debug_dump_status ( 5 ) ;
str_list_free ( & params ) ;
2001-02-12 19:18:02 +03:00
return True ;
2002-07-15 14:35:28 +04:00
} else {
str_list_free ( & params ) ;
2001-02-12 19:18:02 +03:00
return False ;
2002-07-15 14:35:28 +04:00
}
2001-02-12 19:18:02 +03:00
}
2000-09-11 11:02:43 +04:00
/****************************************************************************
receive a " set debug level " message
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
static void debug_message ( int msg_type , pid_t src , void * buf , size_t len )
2000-09-11 11:02:43 +04:00
{
2002-07-15 14:35:28 +04:00
const char * params_str = buf ;
/* Check, it's a proper string! */
if ( params_str [ len - 1 ] ! = ' \0 ' )
{
DEBUG ( 1 , ( " Invalid debug message from pid %u to pid %u \n " ,
( unsigned int ) src , ( unsigned int ) getpid ( ) ) ) ;
return ;
}
2001-06-01 16:04:44 +04:00
2002-07-15 14:35:28 +04:00
DEBUG ( 3 , ( " INFO: Remote set of debug to `%s' (pid %u from pid %u) \n " ,
params_str , ( unsigned int ) getpid ( ) , ( unsigned int ) src ) ) ;
2001-02-12 19:18:02 +03:00
2002-07-15 14:35:28 +04:00
debug_parse_levels ( params_str ) ;
2000-09-11 11:02:43 +04:00
}
2001-02-12 19:18:02 +03:00
2000-09-11 11:02:43 +04:00
/****************************************************************************
send a " set debug level " message
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
void debug_message_send ( pid_t pid , const char * params_str )
{
if ( ! params_str )
return ;
message_send_pid ( pid , MSG_DEBUG , params_str , strlen ( params_str ) + 1 ,
False ) ;
}
/****************************************************************************
Return current debug level .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void debuglevel_message ( int msg_type , pid_t src , void * buf , size_t len )
{
char * debug_level_classes ;
DEBUG ( 1 , ( " INFO: Received REQ_DEBUGLEVEL message from PID %u \n " , ( unsigned int ) src ) ) ;
if ( ( debug_level_classes = debug_list_class_names_and_levels ( ) ) ) {
/*{ debug_level_classes = "test:1000";*/
message_send_pid ( src , MSG_DEBUGLEVEL , debug_level_classes , strlen ( debug_level_classes ) + 1 , True ) ;
SAFE_FREE ( debug_level_classes ) ;
} else {
DEBUG ( 0 , ( " debuglevel_message: error retrieving class levels! \n " ) ) ;
}
}
/****************************************************************************
Init debugging ( one time stuff )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void debug_init ( void )
2000-09-11 11:02:43 +04:00
{
2002-07-15 14:35:28 +04:00
static BOOL initialised = False ;
const char * * p ;
if ( initialised )
return ;
initialised = True ;
message_register ( MSG_DEBUG , debug_message ) ;
message_register ( MSG_REQ_DEBUGLEVEL , debuglevel_message ) ;
for ( p = default_classname_table ; * p ; p + + )
{
debug_add_class ( * p ) ;
}
2000-09-11 11:02:43 +04:00
}
1998-08-01 00:17:36 +04:00
/* ************************************************************************** **
* get ready for syslog stuff
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
2002-07-15 14:35:28 +04:00
void setup_logging ( const char * pname , BOOL interactive )
2000-09-12 04:47:11 +04:00
{
2002-07-15 14:35:28 +04:00
debug_init ( ) ;
1998-08-01 00:17:36 +04:00
2001-03-11 03:32:10 +03:00
/* reset to allow multiple setup calls, going from interactive to
non - interactive */
stdout_logging = False ;
dbf = NULL ;
2000-09-12 04:47:11 +04:00
if ( interactive ) {
stdout_logging = True ;
2001-09-10 15:08:57 +04:00
dbf = x_stdout ;
2000-09-12 04:47:11 +04:00
}
# ifdef WITH_SYSLOG
else {
2002-07-15 14:35:28 +04:00
const char * p = strrchr_m ( pname , ' / ' ) ;
2000-09-12 04:47:11 +04:00
if ( p )
pname = p + 1 ;
1998-08-01 00:17:36 +04:00
# ifdef LOG_DAEMON
2000-09-12 04:47:11 +04:00
openlog ( pname , LOG_PID , SYSLOG_FACILITY ) ;
2001-10-29 11:26:45 +03:00
# else
/* for old systems that have no facility codes. */
2000-09-12 04:47:11 +04:00
openlog ( pname , LOG_PID ) ;
1998-08-01 00:17:36 +04:00
# endif
2000-09-12 04:47:11 +04:00
}
1998-08-01 00:17:36 +04:00
# endif
2000-09-12 04:47:11 +04:00
} /* setup_logging */
1998-08-01 00:17:36 +04:00
/* ************************************************************************** **
* reopen the log files
2000-08-28 07:17:22 +04:00
* note that we now do this unconditionally
2001-03-27 05:19:54 +04:00
* We attempt to open the new debug fp before closing the old . This means
* if we run out of fd ' s we just keep using the old fd rather than aborting .
* Fix from dgibson @ linuxcare . com .
1998-08-01 00:17:36 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
2001-03-27 05:19:54 +04:00
BOOL reopen_logs ( void )
2000-08-28 07:17:22 +04:00
{
pstring fname ;
mode_t oldumask ;
2001-09-10 15:08:57 +04:00
XFILE * new_dbf = NULL ;
2001-03-27 05:19:54 +04:00
BOOL ret = True ;
2000-08-28 07:17:22 +04:00
2001-05-08 03:46:48 +04:00
if ( stdout_logging )
return True ;
2000-08-28 07:17:22 +04:00
oldumask = umask ( 022 ) ;
1998-08-01 00:17:36 +04:00
2000-08-28 07:17:22 +04:00
pstrcpy ( fname , debugf ) ;
2001-10-02 10:57:18 +04:00
if ( lp_loaded ( ) ) {
char * logfname ;
logfname = lp_logfile ( ) ;
if ( * logfname )
pstrcpy ( fname , logfname ) ;
}
2000-08-28 07:17:22 +04:00
pstrcpy ( debugf , fname ) ;
2002-11-09 20:08:58 +03:00
new_dbf = x_fopen ( debugf , O_WRONLY | O_APPEND | O_CREAT , 0644 ) ;
2001-03-27 05:19:54 +04:00
if ( ! new_dbf ) {
log_overflow = True ;
DEBUG ( 0 , ( " Unable to open new log file %s: %s \n " , debugf , strerror ( errno ) ) ) ;
log_overflow = False ;
2001-10-27 11:17:21 +04:00
if ( dbf )
x_fflush ( dbf ) ;
2001-03-27 05:19:54 +04:00
ret = False ;
} else {
2001-09-10 15:08:57 +04:00
x_setbuf ( new_dbf , NULL ) ;
2001-03-27 05:19:54 +04:00
if ( dbf )
2001-09-10 15:08:57 +04:00
( void ) x_fclose ( dbf ) ;
2001-03-27 05:19:54 +04:00
dbf = new_dbf ;
}
2000-08-28 07:17:22 +04:00
/* Fix from klausr@ITAP.Physik.Uni-Stuttgart.De
* to fix problem where smbd ' s that generate less
* than 100 messages keep growing the log .
*/
force_check_log_size ( ) ;
( void ) umask ( oldumask ) ;
2002-08-17 21:00:51 +04:00
/* Take over stderr to catch ouput into logs */
2002-10-26 06:20:59 +04:00
if ( dbf & & sys_dup2 ( x_fileno ( dbf ) , 2 ) = = - 1 ) {
2002-08-17 21:00:51 +04:00
close_low_fds ( True ) ; /* Close stderr too, if dup2 can't point it
at the logfile */
}
2001-03-27 05:19:54 +04:00
return ret ;
}
1998-08-01 00:17:36 +04:00
/* ************************************************************************** **
* Force a check of the log size .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
void force_check_log_size ( void )
2000-04-15 04:31:56 +04:00
{
1998-08-01 00:17:36 +04:00
debug_count = 100 ;
2000-04-15 04:31:56 +04:00
}
/***************************************************************************
Check to see if there is any need to check if the logfile has grown too big .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL need_to_check_log_size ( void )
{
int maxlog ;
if ( debug_count + + < 100 )
return ( False ) ;
maxlog = lp_max_log_size ( ) * 1024 ;
if ( ! dbf | | maxlog < = 0 ) {
debug_count = 0 ;
return ( False ) ;
}
return ( True ) ;
}
1998-08-01 00:17:36 +04:00
/* ************************************************************************** **
* Check to see if the log has grown to be too big .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
2000-04-15 04:31:56 +04:00
void check_log_size ( void )
1999-12-13 16:27:58 +03:00
{
2001-03-27 05:19:54 +04:00
int maxlog ;
SMB_STRUCT_STAT st ;
/*
* We need to be root to check / change log - file , skip this and let the main
* loop check do a new check as root .
*/
if ( geteuid ( ) ! = 0 )
return ;
1998-08-01 00:17:36 +04:00
2001-03-27 05:19:54 +04:00
if ( log_overflow | | ! need_to_check_log_size ( ) )
return ;
2000-04-15 04:31:56 +04:00
2001-03-27 05:19:54 +04:00
maxlog = lp_max_log_size ( ) * 1024 ;
1998-08-01 00:17:36 +04:00
2001-09-10 15:08:57 +04:00
if ( sys_fstat ( x_fileno ( dbf ) , & st ) = = 0 & & st . st_size > maxlog ) {
2001-03-27 05:19:54 +04:00
( void ) reopen_logs ( ) ;
if ( dbf & & get_file_size ( debugf ) > maxlog ) {
pstring name ;
slprintf ( name , sizeof ( name ) - 1 , " %s.old " , debugf ) ;
( void ) rename ( debugf , name ) ;
if ( ! reopen_logs ( ) ) {
/* We failed to reopen a log - continue using the old name. */
( void ) rename ( name , debugf ) ;
}
}
}
1998-08-01 00:17:36 +04:00
2001-03-27 05:19:54 +04:00
/*
* Here ' s where we need to panic if dbf = = NULL . .
*/
2000-04-15 04:31:56 +04:00
2001-03-27 05:19:54 +04:00
if ( dbf = = NULL ) {
/* This code should only be reached in very strange
2001-10-29 11:26:45 +03:00
* circumstances . If we merely fail to open the new log we
* should stick with the old one . ergo this should only be
* reached when opening the logs for the first time : at
* startup or when the log level is increased from zero .
* - dwg 6 June 2000
*/
2001-09-10 15:08:57 +04:00
dbf = x_fopen ( " /dev/console " , O_WRONLY , 0 ) ;
2001-03-27 05:19:54 +04:00
if ( dbf ) {
DEBUG ( 0 , ( " check_log_size: open of debug file %s failed - using console. \n " ,
debugf ) ) ;
} else {
/*
* We cannot continue without a debug file handle .
*/
abort ( ) ;
}
}
debug_count = 0 ;
1999-12-13 16:27:58 +03:00
} /* check_log_size */
1998-08-01 00:17:36 +04:00
/* ************************************************************************** **
* Write an debug message on the debugfile .
* This is called by dbghdr ( ) and format_debug_text ( ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
2002-11-15 17:06:35 +03:00
int Debug1 ( const char * format_str , . . . )
1998-08-01 00:17:36 +04:00
{
va_list ap ;
int old_errno = errno ;
if ( stdout_logging )
{
va_start ( ap , format_str ) ;
2000-02-15 22:36:47 +03:00
if ( dbf )
2001-09-10 15:08:57 +04:00
( void ) x_vfprintf ( dbf , format_str , ap ) ;
1998-08-01 00:17:36 +04:00
va_end ( ap ) ;
errno = old_errno ;
return ( 0 ) ;
}
1998-08-03 07:22:42 +04:00
# ifdef WITH_SYSLOG
1998-08-01 00:17:36 +04:00
if ( ! lp_syslog_only ( ) )
# endif
{
if ( ! dbf )
{
1998-09-18 03:06:57 +04:00
mode_t oldumask = umask ( 022 ) ;
1998-08-01 00:17:36 +04:00
2002-11-09 20:08:58 +03:00
dbf = x_fopen ( debugf , O_WRONLY | O_APPEND | O_CREAT , 0644 ) ;
1998-08-11 22:07:18 +04:00
( void ) umask ( oldumask ) ;
1998-08-01 00:17:36 +04:00
if ( dbf )
{
2001-09-10 15:08:57 +04:00
x_setbuf ( dbf , NULL ) ;
1998-08-01 00:17:36 +04:00
}
else
{
errno = old_errno ;
return ( 0 ) ;
}
}
}
1998-08-03 07:22:42 +04:00
# ifdef WITH_SYSLOG
1998-08-01 00:17:36 +04:00
if ( syslog_level < lp_syslog ( ) )
{
/* map debug levels to syslog() priorities
* note that not all DEBUG ( 0 , . . . ) calls are
* necessarily errors
*/
static int priority_map [ ] = {
LOG_ERR , /* 0 */
LOG_WARNING , /* 1 */
LOG_NOTICE , /* 2 */
LOG_INFO , /* 3 */
} ;
int priority ;
pstring msgbuf ;
if ( syslog_level > = ( sizeof ( priority_map ) / sizeof ( priority_map [ 0 ] ) )
| | syslog_level < 0 )
priority = LOG_DEBUG ;
else
priority = priority_map [ syslog_level ] ;
va_start ( ap , format_str ) ;
vslprintf ( msgbuf , sizeof ( msgbuf ) - 1 , format_str , ap ) ;
va_end ( ap ) ;
msgbuf [ 255 ] = ' \0 ' ;
syslog ( priority , " %s " , msgbuf ) ;
}
# endif
1999-12-13 16:27:58 +03:00
check_log_size ( ) ;
1998-08-03 07:22:42 +04:00
# ifdef WITH_SYSLOG
1998-08-01 00:17:36 +04:00
if ( ! lp_syslog_only ( ) )
# endif
{
va_start ( ap , format_str ) ;
2000-02-15 22:36:47 +03:00
if ( dbf )
2001-09-10 15:08:57 +04:00
( void ) x_vfprintf ( dbf , format_str , ap ) ;
1998-08-01 00:17:36 +04:00
va_end ( ap ) ;
2000-02-15 22:36:47 +03:00
if ( dbf )
2001-09-10 15:08:57 +04:00
( void ) x_fflush ( dbf ) ;
1998-08-01 00:17:36 +04:00
}
errno = old_errno ;
return ( 0 ) ;
} /* Debug1 */
1998-08-12 18:51:17 +04:00
/* ************************************************************************** **
* Print the buffer content via Debug1 ( ) , then reset the buffer .
*
* Input : none
* Output : none
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
static void bufr_print ( void )
{
format_bufr [ format_pos ] = ' \0 ' ;
( void ) Debug1 ( " %s " , format_bufr ) ;
format_pos = 0 ;
} /* bufr_print */
1998-08-01 00:17:36 +04:00
/* ************************************************************************** **
* Format the debug message text .
*
* Input : msg - Text to be added to the " current " debug message text .
*
* Output : none .
*
* Notes : The purpose of this is two - fold . First , each call to syslog ( )
* ( used by Debug1 ( ) , see above ) generates a new line of syslog
* output . This is fixed by storing the partial lines until the
* newline character is encountered . Second , printing the debug
* message lines when a newline is encountered allows us to add
* spaces , thus indenting the body of the message and making it
* more readable .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
static void format_debug_text ( char * msg )
{
1999-12-13 16:27:58 +03:00
size_t i ;
BOOL timestamp = ( ! stdout_logging & & ( lp_timestamp_logs ( ) | |
1998-08-30 09:57:21 +04:00
! ( lp_loaded ( ) ) ) ) ;
1998-08-01 00:17:36 +04:00
for ( i = 0 ; msg [ i ] ; i + + )
{
/* Indent two spaces at each new line. */
1998-08-30 09:57:21 +04:00
if ( timestamp & & 0 = = format_pos )
1998-08-01 00:17:36 +04:00
{
format_bufr [ 0 ] = format_bufr [ 1 ] = ' ' ;
format_pos = 2 ;
}
/* If there's room, copy the character to the format buffer. */
1998-08-21 23:57:59 +04:00
if ( format_pos < FORMAT_BUFR_MAX )
1998-08-01 00:17:36 +04:00
format_bufr [ format_pos + + ] = msg [ i ] ;
/* If a newline is encountered, print & restart. */
if ( ' \n ' = = msg [ i ] )
1998-08-12 18:51:17 +04:00
bufr_print ( ) ;
1998-08-21 23:57:59 +04:00
/* If the buffer is full dump it out, reset it, and put out a line
* continuation indicator .
*/
if ( format_pos > = FORMAT_BUFR_MAX )
{
bufr_print ( ) ;
( void ) Debug1 ( " +> \n " ) ;
}
1998-08-01 00:17:36 +04:00
}
/* Just to be safe... */
format_bufr [ format_pos ] = ' \0 ' ;
} /* format_debug_text */
1998-08-12 18:51:17 +04:00
/* ************************************************************************** **
* Flush debug output , including the format buffer content .
*
* Input : none
* Output : none
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
void dbgflush ( void )
{
bufr_print ( ) ;
2000-02-15 22:36:47 +03:00
if ( dbf )
2001-09-10 15:08:57 +04:00
( void ) x_fflush ( dbf ) ;
1998-08-12 18:51:17 +04:00
} /* dbgflush */
1998-08-01 00:17:36 +04:00
/* ************************************************************************** **
* Print a Debug Header .
*
* Input : level - Debug level of the message ( not the system - wide debug
2001-10-29 11:26:45 +03:00
* level . )
1998-08-01 00:17:36 +04:00
* file - Pointer to a string containing the name of the file
* from which this function was called , or an empty string
* if the __FILE__ macro is not implemented .
* func - Pointer to a string containing the name of the function
* from which this function was called , or an empty string
* if the __FUNCTION__ macro is not implemented .
* line - line number of the call to dbghdr , assuming __LINE__
* works .
*
* Output : Always True . This makes it easy to fudge a call to dbghdr ( )
* in a macro , since the function can be called as part of a test .
* Eg : ( ( level < = DEBUGLEVEL ) & & ( dbghdr ( level , " " , line ) ) )
*
* Notes : This function takes care of setting syslog_level .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
1999-12-13 16:27:58 +03:00
2002-11-15 17:06:35 +03:00
BOOL dbghdr ( int level , const char * file , const char * func , int line )
1999-12-13 16:27:58 +03:00
{
/* Ensure we don't lose any real errno value. */
int old_errno = errno ;
if ( format_pos ) {
1998-08-01 00:17:36 +04:00
/* This is a fudge. If there is stuff sitting in the format_bufr, then
* the * right * thing to do is to call
* format_debug_text ( " \n " ) ;
* to write the remainder , and then proceed with the new header .
* Unfortunately , there are several places in the code at which
* the DEBUG ( ) macro is used to build partial lines . That in mind ,
* we ' ll work under the assumption that an incomplete line indicates
* that a new header is * not * desired .
*/
return ( True ) ;
1999-12-13 16:27:58 +03:00
}
1998-08-01 00:17:36 +04:00
1998-09-29 01:43:48 +04:00
# ifdef WITH_SYSLOG
1998-08-01 00:17:36 +04:00
/* Set syslog_level. */
syslog_level = level ;
1998-09-29 01:43:48 +04:00
# endif
1998-08-01 00:17:36 +04:00
1998-08-03 07:22:42 +04:00
/* Don't print a header if we're logging to stdout. */
if ( stdout_logging )
return ( True ) ;
1998-08-11 19:47:26 +04:00
/* Print the header if timestamps are turned on. If parameters are
* not yet loaded , then default to timestamps on .
*/
1999-12-13 16:27:58 +03:00
if ( lp_timestamp_logs ( ) | | ! ( lp_loaded ( ) ) ) {
char header_str [ 200 ] ;
header_str [ 0 ] = ' \0 ' ;
if ( lp_debug_pid ( ) )
2000-05-02 06:23:41 +04:00
slprintf ( header_str , sizeof ( header_str ) - 1 , " , pid=%u " , ( unsigned int ) sys_getpid ( ) ) ;
1999-12-13 16:27:58 +03:00
if ( lp_debug_uid ( ) ) {
size_t hs_len = strlen ( header_str ) ;
slprintf ( header_str + hs_len ,
sizeof ( header_str ) - 1 - hs_len ,
" , effective(%u, %u), real(%u, %u) " ,
( unsigned int ) geteuid ( ) , ( unsigned int ) getegid ( ) ,
( unsigned int ) getuid ( ) , ( unsigned int ) getgid ( ) ) ;
}
1998-08-11 19:47:26 +04:00
/* Print it all out at once to prevent split syslog output. */
1999-12-13 16:27:58 +03:00
( void ) Debug1 ( " [%s, %d%s] %s:%s(%d) \n " ,
timestring ( lp_debug_hires_timestamp ( ) ) , level ,
header_str , file , func , line ) ;
}
1998-08-11 19:47:26 +04:00
1999-12-13 16:27:58 +03:00
errno = old_errno ;
1998-08-01 00:17:36 +04:00
return ( True ) ;
1999-12-13 16:27:58 +03:00
}
1998-08-01 00:17:36 +04:00
/* ************************************************************************** **
* Add text to the body of the " current " debug message via the format buffer .
*
* Input : format_str - Format string , as used in printf ( ) , et . al .
* . . . - Variable argument list .
*
* . . or . . va_alist - Old style variable parameter list starting point .
*
* Output : Always True . See dbghdr ( ) for more info , though this is not
* likely to be used in the same way .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
2002-11-15 17:06:35 +03:00
BOOL dbgtext ( const char * format_str , . . . )
1998-08-01 00:17:36 +04:00
{
va_list ap ;
pstring msgbuf ;
va_start ( ap , format_str ) ;
vslprintf ( msgbuf , sizeof ( msgbuf ) - 1 , format_str , ap ) ;
va_end ( ap ) ;
format_debug_text ( msgbuf ) ;
return ( True ) ;
} /* dbgtext */
/* ************************************************************************** */