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
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
1998-08-01 00:17:36 +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 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
1998-08-01 00:17:36 +04:00
*/
2014-09-08 10:32:46 +04:00
# include <talloc.h>
# include "replace.h"
2011-02-24 08:14:03 +03:00
# include "system/filesys.h"
# include "system/syslog.h"
2014-09-08 10:32:46 +04:00
# include "system/locale.h"
# include "time_basic.h"
# include "close_low_fd.h"
# include "memory.h"
# include "samba_util.h" /* LIST_SEP */
# include "debug.h"
2011-02-24 08:14:03 +03:00
/* define what facility to use for syslog */
# ifndef SYSLOG_FACILITY
# define SYSLOG_FACILITY LOG_DAEMON
# endif
1998-08-01 00:17:36 +04:00
1998-08-21 23:57:59 +04:00
/* -------------------------------------------------------------------------- **
* Defines . . .
*/
2015-03-21 00:19:09 +03:00
/*
* format_bufr [ FORMAT_BUFR_SIZE - 1 ] should always be reserved
* for a terminating null byte .
*/
2007-11-16 01:19:52 +03:00
# define FORMAT_BUFR_SIZE 1024
1998-08-21 23:57:59 +04:00
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 .
*/
2010-10-29 07:19:32 +04:00
/* state variables for the debug system */
static struct {
2011-02-24 08:14:03 +03:00
bool initialized ;
2010-10-29 09:20:22 +04:00
int fd ; /* The log file handle */
2010-10-29 07:19:32 +04:00
enum debug_logtype logtype ; /* The type of logging we are doing: eg stdout, file, stderr */
const char * prog_name ;
bool reopening_logs ;
2011-02-24 08:14:03 +03:00
bool schedule_reopen_logs ;
struct debug_settings settings ;
char * debugf ;
2012-03-08 05:21:26 +04:00
debug_callback_fn callback ;
void * callback_private ;
2011-02-24 08:14:03 +03:00
} state = {
. settings = {
. timestamp_logs = true
2011-04-01 07:55:37 +04:00
} ,
. fd = 2 /* stderr by default */
2011-02-24 08:14:03 +03:00
} ;
2010-10-29 07:19:32 +04:00
2015-03-21 00:36:58 +03:00
# if defined(WITH_SYSLOG) || defined(HAVE_SYSTEMD_JOURNAL)
2015-01-09 23:29:48 +03:00
static int debug_level_to_priority ( int level )
{
/*
* map debug levels to syslog ( ) priorities note that not all
* DEBUG ( 0 , . . . ) calls are necessarily errors
*/
static const int priority_map [ 4 ] = {
LOG_ERR , /* 0 */
LOG_WARNING , /* 1 */
LOG_NOTICE , /* 2 */
LOG_INFO , /* 3 */
} ;
int priority ;
if ( level > = ARRAY_SIZE ( priority_map ) | | level < 0 )
priority = LOG_DEBUG ;
else
priority = priority_map [ level ] ;
return priority ;
}
# endif
2015-01-09 23:49:13 +03:00
/* -------------------------------------------------------------------------- **
* Debug backends . When logging to DEBUG_FILE , send the log entries to
* all active backends .
*/
2015-01-10 00:00:02 +03:00
static void debug_file_log ( int msg_level ,
const char * msg , const char * msg_no_nl )
{
check_log_size ( ) ;
write ( state . fd , msg , strlen ( msg ) ) ;
}
2015-03-23 05:30:31 +03:00
# ifdef WITH_SYSLOG
static void debug_syslog_reload ( bool enabled , bool previously_enabled ,
const char * prog_name )
{
if ( enabled & & ! previously_enabled ) {
# ifdef LOG_DAEMON
openlog ( prog_name , LOG_PID , SYSLOG_FACILITY ) ;
# else
/* for old systems that have no facility codes. */
openlog ( prog_name , LOG_PID ) ;
# endif
return ;
}
if ( ! enabled & & previously_enabled ) {
closelog ( ) ;
}
}
static void debug_syslog_log ( int msg_level ,
const char * msg , const char * msg_no_nl )
{
int priority ;
priority = debug_level_to_priority ( msg_level ) ;
/*
* Specify the facility to interoperate with other syslog
* callers ( vfs_full_audit for example ) .
*/
priority | = SYSLOG_FACILITY ;
syslog ( priority , " %s " , msg ) ;
}
# endif /* WITH_SYSLOG */
2015-03-21 00:36:58 +03:00
# ifdef HAVE_SYSTEMD_JOURNAL
# include <systemd/sd-journal.h>
static void debug_systemd_log ( int msg_level ,
const char * msg , const char * msg_no_nl )
{
sd_journal_send ( " MESSAGE=%s " , msg_no_nl ,
" PRIORITY=%d " , debug_level_to_priority ( msg_level ) ,
" LEVEL=%d " , msg_level ,
NULL ) ;
}
# endif
2015-01-09 23:49:13 +03:00
static struct debug_backend {
const char * name ;
int log_level ;
int new_log_level ;
void ( * reload ) ( bool enabled , bool prev_enabled , const char * prog_name ) ;
void ( * log ) ( int msg_level , const char * msg , const char * msg_no_nl ) ;
} debug_backends [ ] = {
2015-01-10 00:00:02 +03:00
{
. name = " file " ,
. log = debug_file_log ,
} ,
2015-03-23 05:30:31 +03:00
# ifdef WITH_SYSLOG
{
. name = " syslog " ,
. reload = debug_syslog_reload ,
. log = debug_syslog_log ,
} ,
# endif
2015-03-21 00:36:58 +03:00
# ifdef HAVE_SYSTEMD_JOURNAL
{
. name = " systemd " ,
. log = debug_systemd_log ,
} ,
# endif
2015-01-09 23:49:13 +03:00
} ;
static struct debug_backend * debug_find_backend ( const char * name )
{
int i ;
for ( i = 0 ; i < ARRAY_SIZE ( debug_backends ) ; i + + ) {
if ( strcmp ( name , debug_backends [ i ] . name ) = = 0 ) {
return & debug_backends [ i ] ;
}
}
return NULL ;
}
/*
* parse " backend[:option][@loglevel]
*/
static void debug_backend_parse_token ( char * tok )
{
char * backend_name_option , * backend_name , * backend_level , * saveptr ;
struct debug_backend * b ;
/*
* First parse into backend [ : option ] and loglevel
*/
backend_name_option = strtok_r ( tok , " @ \0 " , & saveptr ) ;
if ( backend_name_option = = NULL ) {
return ;
}
backend_level = strtok_r ( NULL , " \0 " , & saveptr ) ;
/*
* Now parse backend [ : option ]
*/
backend_name = strtok_r ( backend_name_option , " : \0 " , & saveptr ) ;
if ( backend_name = = NULL ) {
return ;
}
/*
* No backend is using the option yet .
*/
#if 0
backend_option = strtok_r ( NULL , " \0 " , & saveptr ) ;
# endif
/*
* Find and update backend
*/
b = debug_find_backend ( backend_name ) ;
if ( b = = NULL ) {
return ;
}
if ( backend_level = = NULL ) {
b - > new_log_level = MAX_DEBUG_LEVEL ;
} else {
b - > new_log_level = atoi ( backend_level ) ;
}
}
/*
* parse " backend1[:option1][@loglevel1] backend2[option2][@loglevel2] ... "
* and enable / disable backends accordingly
*/
static void debug_set_backends ( const char * param )
{
size_t str_len = strlen ( param ) ;
char str [ str_len + 1 ] ;
char * tok , * saveptr ;
int i ;
/*
* initialize new_log_level to detect backends that have been
* disabled
*/
for ( i = 0 ; i < ARRAY_SIZE ( debug_backends ) ; i + + ) {
debug_backends [ i ] . new_log_level = - 1 ;
}
memcpy ( str , param , str_len + 1 ) ;
tok = strtok_r ( str , LIST_SEP , & saveptr ) ;
if ( tok = = NULL ) {
return ;
}
while ( tok ! = NULL ) {
debug_backend_parse_token ( tok ) ;
tok = strtok_r ( NULL , LIST_SEP , & saveptr ) ;
}
/*
* Let backends react to config changes
*/
for ( i = 0 ; i < ARRAY_SIZE ( debug_backends ) ; i + + ) {
struct debug_backend * b = & debug_backends [ i ] ;
if ( b - > reload ) {
bool enabled = b - > new_log_level > - 1 ;
bool previously_enabled = b - > log_level > - 1 ;
b - > reload ( enabled , previously_enabled , state . prog_name ) ;
}
b - > log_level = b - > new_log_level ;
}
}
static void debug_backends_log ( const char * msg , int msg_level )
{
char msg_no_nl [ FORMAT_BUFR_SIZE ] ;
int i , len ;
/*
* Some backends already add an extra newline , so also provide
* a buffer without the newline character .
*/
len = MIN ( strlen ( msg ) , FORMAT_BUFR_SIZE - 1 ) ;
if ( msg [ len - 1 ] = = ' \n ' ) {
len - - ;
}
memcpy ( msg_no_nl , msg , len ) ;
msg_no_nl [ len ] = ' \0 ' ;
for ( i = 0 ; i < ARRAY_SIZE ( debug_backends ) ; i + + ) {
if ( msg_level < = debug_backends [ i ] . log_level ) {
debug_backends [ i ] . log ( msg_level , msg , msg_no_nl ) ;
}
}
}
1998-08-01 00:17:36 +04:00
/* -------------------------------------------------------------------------- **
* External variables .
*/
2007-11-16 01:19:52 +03:00
/*
used to check if the user specified a
logfile on the command line
2004-03-26 18:40:06 +03:00
*/
2007-11-16 01:19:52 +03:00
bool override_logfile ;
2004-03-26 18:40:06 +03:00
2002-07-15 14:35:28 +04:00
/*
2011-02-24 08:14:03 +03:00
* This is to allow reading of DEBUGLEVEL_CLASS before the debug
2008-08-13 00:35:15 +04:00
* system has been initialized .
2002-07-15 14:35:28 +04:00
*/
2011-02-24 08:14:03 +03:00
static const int debug_class_list_initial [ DBGC_MAX_FIXED + 1 ] ;
2002-07-15 14:35:28 +04:00
static int debug_num_classes = 0 ;
2011-02-24 08:14:03 +03:00
int * DEBUGLEVEL_CLASS = discard_const_p ( int , debug_class_list_initial ) ;
1998-08-01 00:17:36 +04:00
/* -------------------------------------------------------------------------- **
* Internal variables .
*
* debug_count - Number of debug messages that have been output .
* Used to check log size .
*
2012-03-08 05:21:26 +04:00
* current_msg_level - Internal copy of the message debug level . Written by
1998-08-01 00:17:36 +04:00
* 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 .
2011-02-24 08:14:03 +03:00
*
2001-03-27 05:19:54 +04:00
*
2011-03-01 00:52:25 +03:00
* log_overflow - When this variable is true , never attempt to check the
2001-03-27 05:19:54 +04:00
* 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 int debug_count = 0 ;
2012-03-08 05:21:26 +04:00
static int current_msg_level = 0 ;
2014-07-29 16:58:53 +04:00
static char format_bufr [ FORMAT_BUFR_SIZE ] ;
1999-12-13 16:27:58 +03:00
static size_t format_pos = 0 ;
2011-03-01 00:52:25 +03:00
static bool log_overflow = false ;
1998-08-01 00:17:36 +04:00
2001-02-12 19:18:02 +03:00
/*
2011-02-24 08:14:03 +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 > . .
2001-10-29 11:26:45 +03:00
*/
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 */
2003-05-12 22:12:31 +04:00
" idmap " , /* DBGC_IDMAP */
2004-01-15 11:49:30 +03:00
" quota " , /* DBGC_QUOTA */
2004-05-18 21:24:59 +04:00
" acls " , /* DBGC_ACLS */
2005-04-27 22:32:37 +04:00
" locking " , /* DBGC_LOCKING */
2005-06-28 23:25:48 +04:00
" msdfs " , /* DBGC_MSDFS */
2006-03-23 02:49:09 +03:00
" dmapi " , /* DBGC_DMAPI */
2007-09-29 03:03:08 +04:00
" registry " , /* DBGC_REGISTRY */
2013-02-07 18:26:37 +04:00
" scavenger " , /* DBGC_SCAVENGER */
2013-01-14 04:13:47 +04:00
" dns " , /* DBGC_DNS */
2013-07-09 15:55:44 +04:00
" ldb " , /* DBGC_LDB */
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 . . .
*/
2011-02-24 08:14:03 +03:00
static void debug_init ( void ) ;
2006-04-08 21:25:31 +04:00
/***************************************************************************
Free memory pointed to by global pointers .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void gfree_debugsyms ( void )
{
2011-02-24 08:14:03 +03:00
TALLOC_FREE ( classname_table ) ;
2006-04-08 21:25:31 +04:00
2011-02-24 08:14:03 +03:00
if ( DEBUGLEVEL_CLASS ! = debug_class_list_initial ) {
TALLOC_FREE ( DEBUGLEVEL_CLASS ) ;
DEBUGLEVEL_CLASS = discard_const_p ( int , debug_class_list_initial ) ;
2008-08-13 00:35:15 +04:00
}
2008-01-07 14:41:18 +03:00
2011-05-09 19:43:45 +04:00
debug_num_classes = 0 ;
2008-08-13 00:35:15 +04:00
2011-02-24 08:14:03 +03:00
state . initialized = false ;
2006-04-08 21:25:31 +04:00
}
2002-07-15 14:35:28 +04:00
/****************************************************************************
utility lists registered debug class names ' s
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-02-24 08:14:03 +03:00
char * debug_list_class_names_and_levels ( void )
2002-07-15 14:35:28 +04:00
{
char * buf = NULL ;
2011-02-24 08:14:03 +03:00
unsigned int i ;
2002-07-15 14:35:28 +04:00
/* prepare strings */
2006-03-14 23:37:24 +03:00
for ( i = 0 ; i < debug_num_classes ; i + + ) {
2014-07-30 13:35:43 +04:00
buf = talloc_asprintf_append ( buf ,
2011-02-24 08:14:03 +03:00
" %s:%d%s " ,
classname_table [ i ] ,
DEBUGLEVEL_CLASS [ i ] ,
i = = ( debug_num_classes - 1 ) ? " \n " : " " ) ;
if ( buf = = NULL ) {
return NULL ;
}
2002-07-15 14:35:28 +04:00
}
2011-02-24 08:14:03 +03:00
return buf ;
2001-02-12 19:18:02 +03:00
}
/****************************************************************************
2004-07-10 00:49:43 +04:00
Utility to translate names to debug class index ' s ( internal version ) .
2001-02-12 19:18:02 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-07-10 00:49:43 +04: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
/****************************************************************************
2004-07-10 00:49:43 +04:00
Add a new debug class to the system .
2002-07-15 14:35:28 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-07-10 00:49:43 +04:00
2002-07-15 14:35:28 +04:00
int debug_add_class ( const char * classname )
{
int ndx ;
2011-02-24 08:14:03 +03:00
int * new_class_list ;
char * * new_name_list ;
2011-03-04 04:23:16 +03:00
int default_level ;
2002-07-15 14:35:28 +04:00
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 ;
2011-02-24 08:14:03 +03:00
if ( DEBUGLEVEL_CLASS = = debug_class_list_initial ) {
2002-07-15 14:35:28 +04:00
/* Initial loading... */
2011-02-24 08:14:03 +03:00
new_class_list = NULL ;
} else {
new_class_list = DEBUGLEVEL_CLASS ;
2002-07-15 14:35:28 +04:00
}
2011-03-04 04:23:16 +03:00
default_level = DEBUGLEVEL_CLASS [ DBGC_ALL ] ;
2011-02-24 08:14:03 +03:00
new_class_list = talloc_realloc ( NULL , new_class_list , int , ndx + 1 ) ;
if ( ! new_class_list )
2002-07-15 14:35:28 +04:00
return - 1 ;
2011-02-24 08:14:03 +03:00
DEBUGLEVEL_CLASS = new_class_list ;
2002-07-15 14:35:28 +04:00
2011-03-04 04:23:16 +03:00
DEBUGLEVEL_CLASS [ ndx ] = default_level ;
2011-02-24 08:14:03 +03:00
new_name_list = talloc_realloc ( NULL , classname_table , char * , ndx + 1 ) ;
if ( ! new_name_list )
2002-07-15 14:35:28 +04:00
return - 1 ;
2011-02-24 08:14:03 +03:00
classname_table = new_name_list ;
2002-07-15 14:35:28 +04:00
2011-02-24 08:14:03 +03:00
classname_table [ ndx ] = talloc_strdup ( classname_table , classname ) ;
2002-07-15 14:35:28 +04:00
if ( ! classname_table [ ndx ] )
return - 1 ;
2011-02-24 08:14:03 +03:00
debug_num_classes = ndx + 1 ;
2002-07-15 14:35:28 +04:00
return ndx ;
}
/****************************************************************************
2004-07-10 00:49:43 +04:00
Utility to translate names to debug class index ' s ( public version ) .
2002-07-15 14:35:28 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-07-10 00:49:43 +04:00
2014-12-17 19:59:52 +03:00
static int debug_lookup_classname ( const char * classname )
2002-07-15 14:35:28 +04:00
{
int ndx ;
2011-02-24 08:14:03 +03:00
2004-07-10 00:49:43 +04:00
if ( ! classname | | ! * classname )
return - 1 ;
2002-07-15 14:35:28 +04:00
ndx = debug_lookup_classname_int ( classname ) ;
if ( ndx ! = - 1 )
return ndx ;
2011-02-24 08:14:03 +03:00
DEBUG ( 0 , ( " debug_lookup_classname(%s): Unknown class \n " ,
classname ) ) ;
return debug_add_class ( classname ) ;
2002-07-15 14:35:28 +04:00
}
/****************************************************************************
2004-07-10 00:49:43 +04:00
Dump the current registered debug levels .
2002-07-15 14:35:28 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-07-10 00:49:43 +04:00
2002-07-15 14:35:28 +04:00
static void debug_dump_status ( int level )
{
int q ;
DEBUG ( level , ( " INFO: Current debug levels: \n " ) ) ;
2004-07-10 00:49:43 +04:00
for ( q = 0 ; q < debug_num_classes ; q + + ) {
2011-02-24 08:14:03 +03:00
const char * classname = classname_table [ q ] ;
DEBUGADD ( level , ( " %s: %d \n " ,
classname ,
2002-07-15 14:35:28 +04:00
DEBUGLEVEL_CLASS [ q ] ) ) ;
}
}
2014-07-29 15:05:06 +04:00
static bool debug_parse_param ( char * param )
{
char * class_name ;
char * class_level ;
char * saveptr ;
int ndx ;
class_name = strtok_r ( param , " : " , & saveptr ) ;
if ( class_name = = NULL ) {
return false ;
}
class_level = strtok_r ( NULL , " \0 " , & saveptr ) ;
if ( class_level = = NULL ) {
return false ;
}
ndx = debug_lookup_classname ( class_name ) ;
if ( ndx = = - 1 ) {
return false ;
}
DEBUGLEVEL_CLASS [ ndx ] = atoi ( class_level ) ;
return true ;
}
2001-02-12 19:18:02 +03:00
/****************************************************************************
2014-07-29 22:01:31 +04:00
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 .
2001-02-12 19:18:02 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-07-10 00:49:43 +04:00
2014-07-29 22:01:31 +04:00
bool debug_parse_levels ( const char * params_str )
2001-02-12 19:18:02 +03:00
{
2014-07-29 22:01:31 +04:00
size_t str_len = strlen ( params_str ) ;
char str [ str_len + 1 ] ;
char * tok , * saveptr ;
int i ;
2002-07-15 14:35:28 +04:00
2014-07-29 22:01:31 +04:00
/* Just in case */
debug_init ( ) ;
memcpy ( str , params_str , str_len + 1 ) ;
tok = strtok_r ( str , LIST_SEP , & saveptr ) ;
if ( tok = = NULL ) {
return true ;
}
2001-02-12 19:18:02 +03:00
2011-02-24 08:14:03 +03:00
/* Allow DBGC_ALL to be specified w/o requiring its class name e.g."10"
* v . s . " all:10 " , this is the traditional way to set DEBUGLEVEL
2001-02-12 19:18:02 +03:00
*/
2014-07-29 22:01:31 +04:00
if ( isdigit ( tok [ 0 ] ) ) {
DEBUGLEVEL_CLASS [ DBGC_ALL ] = atoi ( tok ) ;
tok = strtok_r ( NULL , LIST_SEP , & saveptr ) ;
2004-07-10 00:49:43 +04:00
} else {
2011-02-24 08:14:03 +03:00
DEBUGLEVEL_CLASS [ DBGC_ALL ] = 0 ;
2004-07-10 00:49:43 +04:00
}
2001-02-12 19:18:02 +03:00
2011-02-24 08:14:03 +03:00
/* Array is debug_num_classes long */
2014-07-29 22:01:31 +04:00
for ( i = DBGC_ALL + 1 ; i < debug_num_classes ; i + + ) {
DEBUGLEVEL_CLASS [ i ] = DEBUGLEVEL_CLASS [ DBGC_ALL ] ;
2011-02-24 08:14:03 +03:00
}
2014-07-29 14:23:04 +04:00
2014-07-29 22:01:31 +04:00
while ( tok ! = NULL ) {
2014-07-29 15:05:06 +04:00
bool ok ;
2014-07-29 22:01:31 +04:00
ok = debug_parse_param ( tok ) ;
2014-07-29 15:05:06 +04:00
if ( ! ok ) {
2014-07-29 14:23:04 +04:00
DEBUG ( 0 , ( " debug_parse_params: unrecognized debug "
2014-07-29 22:01:31 +04:00
" class name or format [%s] \n " , tok ) ) ;
2011-03-01 00:52:25 +03:00
return false ;
2001-02-12 19:18:02 +03:00
}
2014-07-29 22:01:31 +04:00
tok = strtok_r ( NULL , LIST_SEP , & saveptr ) ;
2002-07-15 14:35:28 +04:00
}
2014-07-29 20:09:10 +04:00
2014-07-29 22:01:31 +04:00
debug_dump_status ( 5 ) ;
return true ;
2001-02-12 19:18:02 +03:00
}
2011-02-24 08:14:03 +03:00
/* setup for logging of talloc warnings */
static void talloc_log_fn ( const char * msg )
2000-09-11 11:02:43 +04:00
{
2011-02-24 08:14:03 +03:00
DEBUG ( 0 , ( " %s " , msg ) ) ;
2000-09-11 11:02:43 +04:00
}
2011-02-24 08:14:03 +03:00
void debug_setup_talloc_log ( void )
2002-07-15 14:35:28 +04:00
{
2011-02-24 08:14:03 +03:00
talloc_set_log_fn ( talloc_log_fn ) ;
2002-07-15 14:35:28 +04:00
}
2011-02-24 08:14:03 +03:00
2002-07-15 14:35:28 +04:00
/****************************************************************************
Init debugging ( one time stuff )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-07-10 00:49:43 +04:00
2011-02-24 08:14:03 +03:00
static void debug_init ( void )
2000-09-11 11:02:43 +04:00
{
2015-01-09 23:49:13 +03:00
int i ;
2002-07-15 14:35:28 +04:00
const char * * p ;
2011-02-24 08:14:03 +03:00
if ( state . initialized )
2002-07-15 14:35:28 +04:00
return ;
2006-04-08 21:25:31 +04:00
2011-02-24 08:14:03 +03:00
state . initialized = true ;
debug_setup_talloc_log ( ) ;
2002-07-15 14:35:28 +04:00
2004-07-10 00:49:43 +04:00
for ( p = default_classname_table ; * p ; p + + ) {
2002-07-15 14:35:28 +04:00
debug_add_class ( * p ) ;
}
2015-01-09 23:49:13 +03:00
for ( i = 0 ; i < ARRAY_SIZE ( debug_backends ) ; i + + ) {
debug_backends [ i ] . log_level = - 1 ;
debug_backends [ i ] . new_log_level = - 1 ;
}
2000-09-11 11:02:43 +04:00
}
1998-08-01 00:17:36 +04:00
2015-01-10 00:46:32 +03:00
void debug_set_settings ( struct debug_settings * settings ,
const char * logging_param ,
int syslog_level , bool syslog_only )
2007-05-15 19:14:32 +04:00
{
2015-01-10 00:46:32 +03:00
char fake_param [ 20 ] ;
/*
* This forces in some smb . conf derived values into the debug
* system . There are no pointers in this structure , so we can
* just structure - assign it in
*/
2011-02-24 08:14:03 +03:00
state . settings = * settings ;
2015-01-10 00:46:32 +03:00
/*
* If ' logging ' is not set , create backend settings from
* deprecated ' syslog ' and ' syslog only ' paramters
*/
if ( ! logging_param ) {
if ( syslog_only ) {
snprintf ( fake_param , sizeof ( fake_param ) ,
" syslog:%d " , syslog_level - 1 ) ;
} else {
snprintf ( fake_param , sizeof ( fake_param ) ,
" syslog:%d file:%d " , syslog_level - 1 ,
MAX_DEBUG_LEVEL ) ;
}
logging_param = fake_param ;
}
debug_set_backends ( logging_param ) ;
2007-05-15 19:14:32 +04:00
}
2010-10-29 07:19:32 +04:00
/**
control the name of the logfile and whether logging will be to stdout , stderr
or a file , and set up syslog
2010-11-01 10:42:36 +03:00
new_log indicates the destination for the debug log ( an enum in
order of precedence - once set to DEBUG_FILE , it is not possible to
reset to DEBUG_STDOUT for example . This makes it easy to override
for debug to stderr on the command line , as the smb . conf cannot
reset it back to file - based logging
2010-10-29 07:19:32 +04:00
*/
void setup_logging ( const char * prog_name , enum debug_logtype new_logtype )
2000-09-12 04:47:11 +04:00
{
2002-07-15 14:35:28 +04:00
debug_init ( ) ;
2010-10-29 07:19:32 +04:00
if ( state . logtype < new_logtype ) {
state . logtype = new_logtype ;
2004-07-10 00:49:43 +04:00
}
2010-10-29 07:19:32 +04:00
if ( prog_name ) {
2015-02-25 00:09:18 +03:00
const char * p = strrchr ( prog_name , ' / ' ) ;
if ( p ) {
prog_name = p + 1 ;
}
2010-10-29 07:19:32 +04:00
state . prog_name = prog_name ;
2000-09-12 04:47:11 +04:00
}
2011-02-24 08:14:03 +03:00
reopen_logs_internal ( ) ;
2004-07-10 00:49:43 +04:00
}
2007-11-16 01:19:52 +03:00
/***************************************************************************
Set the logfile name .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void debug_set_logfile ( const char * name )
{
2011-03-29 07:41:58 +04:00
if ( name = = NULL | | * name = = 0 ) {
/* this copes with calls when smb.conf is not loaded yet */
return ;
}
2011-02-24 08:14:03 +03:00
TALLOC_FREE ( state . debugf ) ;
state . debugf = talloc_strdup ( NULL , name ) ;
2007-11-16 01:19:52 +03:00
}
2010-10-29 09:20:22 +04:00
static void debug_close_fd ( int fd )
2010-10-29 07:19:32 +04:00
{
2010-10-29 09:20:22 +04:00
if ( fd > 2 ) {
close ( fd ) ;
2010-10-29 07:19:32 +04:00
}
}
2010-11-01 12:55:04 +03:00
bool debug_get_output_is_stderr ( void )
{
return ( state . logtype = = DEBUG_DEFAULT_STDERR ) | | ( state . logtype = = DEBUG_STDERR ) ;
}
2011-07-18 11:07:25 +04:00
bool debug_get_output_is_stdout ( void )
{
return ( state . logtype = = DEBUG_DEFAULT_STDOUT ) | | ( state . logtype = = DEBUG_STDOUT ) ;
}
2012-03-08 05:21:26 +04:00
void debug_set_callback ( void * private_ptr , debug_callback_fn fn )
{
debug_init ( ) ;
if ( fn ) {
state . logtype = DEBUG_CALLBACK ;
state . callback_private = private_ptr ;
state . callback = fn ;
} else {
state . logtype = DEBUG_DEFAULT_STDERR ;
state . callback_private = NULL ;
state . callback = NULL ;
}
}
2015-01-09 23:17:49 +03:00
static void debug_callback_log ( const char * msg , int msg_level )
{
size_t msg_len = strlen ( msg ) ;
char msg_copy [ msg_len ] ;
if ( ( msg_len > 0 ) & & ( msg [ msg_len - 1 ] = = ' \n ' ) ) {
memcpy ( msg_copy , msg , msg_len - 1 ) ;
msg_copy [ msg_len - 1 ] = ' \0 ' ;
msg = msg_copy ;
}
state . callback ( state . callback_private , msg_level , msg ) ;
}
2004-07-10 00:49:43 +04:00
/**************************************************************************
reopen the log files
note that we now do this unconditionally
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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-03-27 05:19:54 +04:00
2010-10-29 07:19:32 +04:00
/**
reopen the log file ( usually called because the log file name might have changed )
*/
2011-02-24 08:14:03 +03:00
bool reopen_logs_internal ( void )
2000-08-28 07:17:22 +04:00
{
mode_t oldumask ;
2010-10-29 09:20:22 +04:00
int new_fd = 0 ;
int old_fd = 0 ;
2011-03-01 00:52:25 +03:00
bool ret = true ;
2000-08-28 07:17:22 +04:00
2010-10-29 07:19:32 +04:00
if ( state . reopening_logs ) {
return true ;
}
2011-02-24 08:14:03 +03:00
/* Now clear the SIGHUP induced flag */
state . schedule_reopen_logs = false ;
2010-10-29 07:19:32 +04:00
switch ( state . logtype ) {
2012-03-08 05:21:26 +04:00
case DEBUG_CALLBACK :
return true ;
2010-10-29 07:19:32 +04:00
case DEBUG_STDOUT :
2011-07-18 11:07:25 +04:00
case DEBUG_DEFAULT_STDOUT :
2010-10-29 14:12:12 +04:00
debug_close_fd ( state . fd ) ;
2010-10-29 09:20:22 +04:00
state . fd = 1 ;
2010-10-29 07:19:32 +04:00
return true ;
case DEBUG_DEFAULT_STDERR :
case DEBUG_STDERR :
2010-10-29 09:20:22 +04:00
debug_close_fd ( state . fd ) ;
state . fd = 2 ;
2010-10-29 07:19:32 +04:00
return true ;
case DEBUG_FILE :
break ;
}
2001-05-08 03:46:48 +04:00
2000-08-28 07:17:22 +04:00
oldumask = umask ( 022 ) ;
2007-11-16 01:19:52 +03:00
2012-06-01 03:06:17 +04:00
if ( ! state . debugf ) {
2007-11-16 01:19:52 +03:00
return false ;
}
2001-10-02 10:57:18 +04:00
2011-02-24 08:14:03 +03:00
state . reopening_logs = true ;
2000-08-28 07:17:22 +04:00
2011-02-24 08:14:03 +03:00
new_fd = open ( state . debugf , O_WRONLY | O_APPEND | O_CREAT , 0644 ) ;
2001-03-27 05:19:54 +04:00
2010-10-29 09:20:22 +04:00
if ( new_fd = = - 1 ) {
2011-03-01 00:52:25 +03:00
log_overflow = true ;
2011-03-29 07:41:58 +04:00
DEBUG ( 0 , ( " Unable to open new log file '%s': %s \n " , state . debugf , strerror ( errno ) ) ) ;
2011-03-01 00:52:25 +03:00
log_overflow = false ;
ret = false ;
2001-03-27 05:19:54 +04:00
} else {
2015-02-16 05:59:11 +03:00
smb_set_close_on_exec ( new_fd ) ;
2010-10-29 09:20:22 +04:00
old_fd = state . fd ;
state . fd = new_fd ;
debug_close_fd ( old_fd ) ;
2001-03-27 05:19:54 +04:00
}
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 ) ;
2008-11-01 05:58:14 +03:00
/* Take over stderr to catch output into logs */
2012-03-02 12:32:56 +04:00
if ( state . fd > 0 ) {
if ( dup2 ( state . fd , 2 ) = = - 1 ) {
/* Close stderr too, if dup2 can't point it -
at the logfile . There really isn ' t much
2014-07-29 22:44:28 +04:00
that can be done on such a fundamental
2012-03-02 12:32:56 +04:00
failure . . . */
2014-07-29 22:43:05 +04:00
close_low_fd ( 2 ) ;
2012-03-02 12:32:56 +04:00
}
2002-08-17 21:00:51 +04:00
}
2011-02-24 08:14:03 +03:00
state . reopening_logs = false ;
2001-03-27 05:19:54 +04:00
return ret ;
}
1998-08-01 00:17:36 +04:00
2004-07-10 00:49:43 +04:00
/**************************************************************************
Force a check of the log size .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-01 00:17:36 +04:00
void force_check_log_size ( void )
2000-04-15 04:31:56 +04:00
{
2004-07-10 00:49:43 +04:00
debug_count = 100 ;
2000-04-15 04:31:56 +04:00
}
2011-02-24 08:14:03 +03:00
_PUBLIC_ void debug_schedule_reopen_logs ( void )
{
state . schedule_reopen_logs = true ;
}
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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
bool need_to_check_log_size ( void )
2000-04-15 04:31:56 +04:00
{
int maxlog ;
2011-02-24 08:14:03 +03:00
if ( debug_count < 100 )
2011-03-01 00:52:25 +03:00
return ( false ) ;
2000-04-15 04:31:56 +04:00
2011-02-24 08:14:03 +03:00
maxlog = state . settings . max_log_size * 1024 ;
if ( state . fd < = 2 | | maxlog < = 0 ) {
2000-04-15 04:31:56 +04:00
debug_count = 0 ;
2011-03-01 00:52:25 +03:00
return ( false ) ;
2000-04-15 04:31:56 +04:00
}
2011-03-01 00:52:25 +03:00
return ( true ) ;
2000-04-15 04:31:56 +04:00
}
1998-08-01 00:17:36 +04:00
2004-07-10 00:49:43 +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 ;
2011-02-24 08:14:03 +03:00
struct stat st ;
2001-03-27 05:19:54 +04:00
2007-04-14 10:40:47 +04:00
/*
* We need to be root to check / change log - file , skip this and let the main
* loop check do a new check as root .
*/
2011-03-31 19:02:27 +04:00
# if _SAMBA_BUILD_ == 3
if ( geteuid ( ) ! = sec_initial_uid ( ) )
# else
if ( geteuid ( ) ! = 0 )
# endif
{
2011-02-24 08:14:03 +03:00
/* We don't check sec_initial_uid() here as it isn't
* available in common code and we don ' t generally
* want to rotate and the possibly lose logs in
* make test or the build farm */
2007-04-14 10:40:47 +04:00
return ;
2011-02-24 08:14:03 +03:00
}
2007-04-14 10:40:47 +04:00
2011-02-24 08:14:03 +03:00
if ( log_overflow | | ( ! state . schedule_reopen_logs & & ! need_to_check_log_size ( ) ) ) {
2001-03-27 05:19:54 +04:00
return ;
2011-02-24 08:14:03 +03:00
}
2000-04-15 04:31:56 +04:00
2011-02-24 08:14:03 +03:00
maxlog = state . settings . max_log_size * 1024 ;
2012-06-11 07:22:42 +04:00
if ( state . schedule_reopen_logs ) {
( void ) reopen_logs_internal ( ) ;
}
if ( maxlog & & ( fstat ( state . fd , & st ) = = 0
2011-02-24 08:14:03 +03:00
& & st . st_size > maxlog ) ) {
( void ) reopen_logs_internal ( ) ;
2012-06-11 07:22:42 +04:00
if ( state . fd > 2 & & ( fstat ( state . fd , & st ) = = 0
& & st . st_size > maxlog ) ) {
2014-12-15 14:09:11 +03:00
char name [ strlen ( state . debugf ) + 5 ] ;
snprintf ( name , sizeof ( name ) , " %s.old " , state . debugf ) ;
2014-07-30 13:35:43 +04:00
2012-06-11 07:22:42 +04:00
( void ) rename ( state . debugf , name ) ;
2014-07-30 13:35:43 +04:00
2012-06-11 07:22:42 +04:00
if ( ! reopen_logs_internal ( ) ) {
/* We failed to reopen a log - continue using the old name. */
( void ) rename ( name , state . debugf ) ;
2001-03-27 05:19:54 +04:00
}
}
}
1998-08-01 00:17:36 +04:00
2001-03-27 05:19:54 +04:00
/*
2010-10-29 14:12:12 +04:00
* Here ' s where we need to panic if state . fd = = 0 or - 1 ( invalid values )
2001-03-27 05:19:54 +04:00
*/
2000-04-15 04:31:56 +04:00
2010-10-29 14:12:12 +04:00
if ( state . fd < = 0 ) {
2001-03-27 05:19:54 +04:00
/* 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
*/
2010-10-29 09:20:22 +04:00
int fd = open ( " /dev/console " , O_WRONLY , 0 ) ;
2010-10-29 14:12:12 +04:00
if ( fd ! = - 1 ) {
2015-02-16 05:59:11 +03:00
smb_set_close_on_exec ( fd ) ;
2010-10-29 09:20:22 +04:00
state . fd = fd ;
2001-03-27 05:19:54 +04:00
DEBUG ( 0 , ( " check_log_size: open of debug file %s failed - using console. \n " ,
2011-02-24 08:14:03 +03:00
state . debugf ) ) ;
2001-03-27 05:19:54 +04:00
} else {
/*
* We cannot continue without a debug file handle .
*/
abort ( ) ;
}
}
debug_count = 0 ;
2004-07-10 00:49:43 +04:00
}
/*************************************************************************
Write an debug message on the debugfile .
This is called by dbghdr ( ) and format_debug_text ( ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-01 00:17:36 +04:00
2015-01-10 01:00:04 +03:00
static void Debug1 ( const char * msg )
1998-08-01 00:17:36 +04:00
{
2004-07-10 00:49:43 +04:00
int old_errno = errno ;
debug_count + + ;
2015-01-10 01:00:04 +03:00
switch ( state . logtype ) {
case DEBUG_CALLBACK :
2015-01-09 23:17:49 +03:00
debug_callback_log ( msg , current_msg_level ) ;
2015-01-10 01:00:04 +03:00
break ;
case DEBUG_STDOUT :
case DEBUG_STDERR :
case DEBUG_DEFAULT_STDOUT :
case DEBUG_DEFAULT_STDERR :
2014-07-29 20:04:25 +04:00
if ( state . fd > 0 ) {
write ( state . fd , msg , strlen ( msg ) ) ;
}
2015-01-10 01:00:04 +03:00
break ;
case DEBUG_FILE :
debug_backends_log ( msg , current_msg_level ) ;
break ;
} ;
1998-08-01 00:17:36 +04:00
2007-12-27 01:44:24 +03:00
errno = old_errno ;
2004-07-10 00:49:43 +04:00
}
1998-08-01 00:17:36 +04:00
2004-07-10 00:49:43 +04:00
/**************************************************************************
Print the buffer content via Debug1 ( ) , then reset the buffer .
Input : none
Output : none
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-12 18:51:17 +04:00
static void bufr_print ( void )
2004-07-10 00:49:43 +04:00
{
format_bufr [ format_pos ] = ' \0 ' ;
2014-07-29 20:04:25 +04:00
( void ) Debug1 ( format_bufr ) ;
2004-07-10 00:49:43 +04:00
format_pos = 0 ;
}
/***************************************************************************
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 ( const char * msg )
{
size_t i ;
2011-02-24 08:14:03 +03:00
bool timestamp = ( state . logtype = = DEBUG_FILE & & ( state . settings . timestamp_logs ) ) ;
2004-07-10 00:49:43 +04:00
2014-07-29 16:58:53 +04:00
debug_init ( ) ;
2007-12-14 10:21:59 +03:00
2004-07-10 00:49:43 +04:00
for ( i = 0 ; msg [ i ] ; i + + ) {
/* Indent two spaces at each new line. */
if ( timestamp & & 0 = = format_pos ) {
format_bufr [ 0 ] = format_bufr [ 1 ] = ' ' ;
format_pos = 2 ;
}
/* If there's room, copy the character to the format buffer. */
2015-03-21 00:19:09 +03:00
if ( format_pos < FORMAT_BUFR_SIZE - 1 )
2004-07-10 00:49:43 +04:00
format_bufr [ format_pos + + ] = msg [ i ] ;
/* If a newline is encountered, print & restart. */
if ( ' \n ' = = msg [ i ] )
bufr_print ( ) ;
/* If the buffer is full dump it out, reset it, and put out a line
* continuation indicator .
*/
2015-03-21 00:19:09 +03:00
if ( format_pos > = FORMAT_BUFR_SIZE - 1 ) {
2004-07-10 00:49:43 +04:00
bufr_print ( ) ;
( void ) Debug1 ( " +> \n " ) ;
}
}
/* Just to be safe... */
format_bufr [ format_pos ] = ' \0 ' ;
}
/***************************************************************************
Flush debug output , including the format buffer content .
Input : none
Output : none
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-12 18:51:17 +04:00
void dbgflush ( void )
2004-07-10 00:49:43 +04:00
{
bufr_print ( ) ;
}
/***************************************************************************
Print a Debug Header .
Input : level - Debug level of the message ( not the system - wide debug
level . )
2007-09-30 12:07:06 +04:00
cls - Debuglevel class of the calling module .
2004-07-10 00:49:43 +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 .
2011-03-01 00:52:25 +03:00
Output : Always true . This makes it easy to fudge a call to dbghdr ( )
2004-07-10 00:49:43 +04:00
in a macro , since the function can be called as part of a test .
Eg : ( ( level < = DEBUGLEVEL ) & & ( dbghdr ( level , " " , line ) ) )
2012-03-08 05:21:26 +04:00
Notes : This function takes care of setting current_msg_level .
2004-07-10 00:49:43 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2008-10-11 22:44:19 +04:00
bool dbghdrclass ( int level , int cls , const char * location , const char * func )
1999-12-13 16:27:58 +03:00
{
2004-07-10 00:49:43 +04:00
/* Ensure we don't lose any real errno value. */
int old_errno = errno ;
2014-07-29 19:02:22 +04:00
bool verbose = false ;
2014-07-30 13:22:59 +04:00
char header_str [ 300 ] ;
2014-07-30 13:22:21 +04:00
size_t hs_len ;
2014-07-29 19:06:17 +04:00
struct timeval tv ;
struct timeval_buf tvbuf ;
2004-07-10 00:49:43 +04:00
if ( format_pos ) {
/* 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 .
*/
2011-03-01 00:52:25 +03:00
return ( true ) ;
2004-07-10 00:49:43 +04:00
}
1998-08-01 00:17:36 +04:00
2012-03-08 05:21:26 +04:00
/* Set current_msg_level. */
current_msg_level = level ;
1998-08-01 00:17:36 +04:00
2004-07-10 00:49:43 +04:00
/* Don't print a header if we're logging to stdout. */
2010-10-29 07:19:32 +04:00
if ( state . logtype ! = DEBUG_FILE ) {
2011-03-01 00:52:25 +03:00
return ( true ) ;
2010-10-29 07:19:32 +04:00
}
1998-08-03 07:22:42 +04:00
2004-07-10 00:49:43 +04:00
/* Print the header if timestamps are turned on. If parameters are
* not yet loaded , then default to timestamps on .
*/
2014-07-29 19:02:22 +04:00
if ( ! ( state . settings . timestamp_logs | |
state . settings . debug_prefix_timestamp ) ) {
return true ;
}
1999-12-13 16:27:58 +03:00
2014-07-29 19:26:22 +04:00
GetTimeOfDay ( & tv ) ;
2014-10-10 11:46:31 +04:00
timeval_str_buf ( & tv , false , state . settings . debug_hires_timestamp ,
& tvbuf ) ;
2014-07-29 19:26:22 +04:00
2014-07-30 13:22:21 +04:00
hs_len = snprintf ( header_str , sizeof ( header_str ) , " [%s, %2d " ,
tvbuf . buf , level ) ;
if ( hs_len > = sizeof ( header_str ) ) {
goto full ;
}
1999-12-13 16:27:58 +03:00
2014-07-29 19:02:22 +04:00
if ( unlikely ( DEBUGLEVEL_CLASS [ cls ] > = 10 ) ) {
verbose = true ;
}
2011-11-16 00:50:54 +04:00
2014-07-29 19:09:00 +04:00
if ( verbose | | state . settings . debug_pid ) {
2014-07-30 13:22:21 +04:00
hs_len + = snprintf (
header_str + hs_len , sizeof ( header_str ) - hs_len ,
" , pid=%u " , ( unsigned int ) getpid ( ) ) ;
if ( hs_len > = sizeof ( header_str ) ) {
goto full ;
}
2014-07-29 19:09:00 +04:00
}
1999-12-13 16:27:58 +03:00
2014-07-29 19:02:22 +04:00
if ( verbose | | state . settings . debug_uid ) {
2014-07-30 13:22:21 +04:00
hs_len + = snprintf (
header_str + hs_len , sizeof ( header_str ) - hs_len ,
" , effective(%u, %u), real(%u, %u) " ,
( unsigned int ) geteuid ( ) , ( unsigned int ) getegid ( ) ,
( unsigned int ) getuid ( ) , ( unsigned int ) getgid ( ) ) ;
if ( hs_len > = sizeof ( header_str ) ) {
goto full ;
}
2014-07-29 19:02:22 +04:00
}
2007-09-30 12:07:06 +04:00
2014-07-29 19:02:22 +04:00
if ( ( verbose | | state . settings . debug_class )
& & ( cls ! = DBGC_ALL ) ) {
2014-07-30 13:22:21 +04:00
hs_len + = snprintf (
header_str + hs_len , sizeof ( header_str ) - hs_len ,
" , class=%s " , classname_table [ cls ] ) ;
if ( hs_len > = sizeof ( header_str ) ) {
goto full ;
}
2014-07-29 19:02:22 +04:00
}
2011-02-24 08:14:03 +03:00
2014-07-30 13:22:21 +04:00
/*
* No + = , see man man strlcat
*/
hs_len = strlcat ( header_str , " ] " , sizeof ( header_str ) ) ;
if ( hs_len > = sizeof ( header_str ) ) {
goto full ;
}
2014-07-29 19:31:48 +04:00
if ( ! state . settings . debug_prefix_timestamp ) {
2014-07-30 13:22:21 +04:00
hs_len + = snprintf (
header_str + hs_len , sizeof ( header_str ) - hs_len ,
" %s(%s) \n " , location , func ) ;
if ( hs_len > = sizeof ( header_str ) ) {
goto full ;
}
2004-07-10 00:49:43 +04:00
}
1998-08-11 19:47:26 +04:00
2014-07-30 13:22:21 +04:00
full :
2014-07-29 20:04:25 +04:00
( void ) Debug1 ( header_str ) ;
2014-07-29 19:31:48 +04:00
2004-07-10 00:49:43 +04:00
errno = old_errno ;
2011-03-01 00:52:25 +03:00
return ( true ) ;
1999-12-13 16:27:58 +03:00
}
1998-08-01 00:17:36 +04:00
2004-07-10 00:49:43 +04:00
/***************************************************************************
Add text to the body of the " current " debug message via the format buffer .
1998-08-01 00:17:36 +04:00
2004-07-10 00:49:43 +04:00
Input : format_str - Format string , as used in printf ( ) , et . al .
. . . - Variable argument list .
1998-08-01 00:17:36 +04:00
2004-07-10 00:49:43 +04:00
. . or . . va_alist - Old style variable parameter list starting point .
1998-08-01 00:17:36 +04:00
2011-03-01 00:52:25 +03:00
Output : Always true . See dbghdr ( ) for more info , though this is not
2004-07-10 00:49:43 +04:00
likely to be used in the same way .
1998-08-01 00:17:36 +04:00
2004-07-10 00:49:43 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-01 00:17:36 +04:00
2014-12-16 13:30:53 +03:00
static inline bool __dbgtext_va ( const char * format_str , va_list ap ) PRINTF_ATTRIBUTE ( 1 , 0 ) ;
static inline bool __dbgtext_va ( const char * format_str , va_list ap )
2004-07-10 00:49:43 +04:00
{
2007-11-16 01:19:52 +03:00
char * msgbuf = NULL ;
bool ret = true ;
2008-02-25 17:24:49 +03:00
int res ;
2004-07-10 00:49:43 +04:00
2008-02-25 17:24:49 +03:00
res = vasprintf ( & msgbuf , format_str , ap ) ;
if ( res ! = - 1 ) {
2007-11-16 01:19:52 +03:00
format_debug_text ( msgbuf ) ;
} else {
ret = false ;
}
SAFE_FREE ( msgbuf ) ;
return ret ;
2004-07-10 00:49:43 +04:00
}
2014-12-16 13:30:53 +03:00
bool dbgtext_va ( const char * format_str , va_list ap )
{
return __dbgtext_va ( format_str , ap ) ;
}
bool dbgtext ( const char * format_str , . . . )
{
va_list ap ;
bool ret ;
va_start ( ap , format_str ) ;
ret = __dbgtext_va ( format_str , ap ) ;
va_end ( ap ) ;
return ret ;
}