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 "replace.h"
2015-07-12 09:30:36 +03:00
# include <talloc.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"
2017-02-01 03:58:46 +03:00
# include "util_strlist.h" /* LIST_SEP */
# include "blocking.h"
2014-09-08 10:32:46 +04:00
# 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
2016-06-22 12:13:15 +03:00
# if defined(WITH_SYSLOG) || defined(HAVE_LIBSYSTEMD_JOURNAL) || defined(HAVE_LIBSYSTEMD)
2015-01-09 23:29:48 +03:00
static int debug_level_to_priority ( int level )
{
/*
2015-06-06 01:09:34 +03:00
* map debug levels to syslog ( ) priorities
2015-01-09 23:29:48 +03:00
*/
2015-06-06 01:09:34 +03:00
static const int priority_map [ ] = {
2015-01-09 23:29:48 +03:00
LOG_ERR , /* 0 */
LOG_WARNING , /* 1 */
LOG_NOTICE , /* 2 */
2015-06-06 01:09:34 +03:00
LOG_NOTICE , /* 3 */
LOG_NOTICE , /* 4 */
LOG_NOTICE , /* 5 */
LOG_INFO , /* 6 */
LOG_INFO , /* 7 */
LOG_INFO , /* 8 */
LOG_INFO , /* 9 */
2015-01-09 23:29:48 +03:00
} ;
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 )
{
2016-03-23 01:01:10 +03:00
ssize_t ret ;
2015-01-10 00:00:02 +03:00
check_log_size ( ) ;
2016-03-23 01:01:10 +03:00
do {
ret = write ( state . fd , msg , strlen ( msg ) ) ;
} while ( ret = = - 1 & & errno = = EINTR ) ;
2015-01-10 00:00:02 +03:00
}
2015-03-23 05:30:31 +03:00
# ifdef WITH_SYSLOG
static void debug_syslog_reload ( bool enabled , bool previously_enabled ,
2017-01-07 21:34:46 +03:00
const char * prog_name , char * option )
2015-03-23 05:30:31 +03:00
{
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 */
2016-06-22 12:13:15 +03:00
# if defined(HAVE_LIBSYSTEMD_JOURNAL) || defined(HAVE_LIBSYSTEMD)
2015-03-21 00:36:58 +03:00
# 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-10 02:17:08 +03:00
# ifdef HAVE_LTTNG_TRACEF
# include <lttng/tracef.h>
static void debug_lttng_log ( int msg_level ,
const char * msg , const char * msg_no_nl )
{
tracef ( msg_no_nl ) ;
}
# endif /* WITH_LTTNG_TRACEF */
2015-02-20 02:32:44 +03:00
# ifdef HAVE_GPFS
# include "gpfswrap.h"
static void debug_gpfs_reload ( bool enabled , bool previously_enabled ,
2017-01-07 21:34:46 +03:00
const char * prog_name , char * option )
2015-02-20 02:32:44 +03:00
{
gpfswrap_init ( ) ;
if ( enabled & & ! previously_enabled ) {
gpfswrap_init_trace ( ) ;
return ;
}
if ( ! enabled & & previously_enabled ) {
gpfswrap_fini_trace ( ) ;
return ;
}
if ( enabled ) {
/*
* Trigger GPFS library to adjust state if necessary .
*/
gpfswrap_query_trace ( ) ;
}
}
static void debug_gpfs_log ( int msg_level ,
const char * msg , const char * msg_no_nl )
{
gpfswrap_add_trace ( msg_level , msg_no_nl ) ;
}
# endif /* HAVE_GPFS */
2017-01-07 16:36:24 +03:00
# define DEBUG_RINGBUF_SIZE (1024 * 1024)
# define DEBUG_RINGBUF_SIZE_OPT "size="
static char * debug_ringbuf ;
static size_t debug_ringbuf_size ;
static size_t debug_ringbuf_ofs ;
/* We ensure in debug_ringbuf_log() that this is always \0 terminated */
char * debug_get_ringbuf ( void )
{
return debug_ringbuf ;
}
/* Return the size of the ringbuf (including a \0 terminator) */
size_t debug_get_ringbuf_size ( void )
{
return debug_ringbuf_size ;
}
static void debug_ringbuf_reload ( bool enabled , bool previously_enabled ,
const char * prog_name , char * option )
{
bool cmp ;
size_t optlen = strlen ( DEBUG_RINGBUF_SIZE_OPT ) ;
debug_ringbuf_size = DEBUG_RINGBUF_SIZE ;
debug_ringbuf_ofs = 0 ;
SAFE_FREE ( debug_ringbuf ) ;
if ( ! enabled ) {
return ;
}
if ( option ! = NULL ) {
cmp = strncmp ( option , DEBUG_RINGBUF_SIZE_OPT , optlen ) ;
if ( cmp = = 0 ) {
debug_ringbuf_size = ( size_t ) strtoull (
option + optlen , NULL , 10 ) ;
}
}
debug_ringbuf = calloc ( debug_ringbuf_size , sizeof ( char ) ) ;
if ( debug_ringbuf = = NULL ) {
return ;
}
}
static void debug_ringbuf_log ( int msg_level ,
const char * msg ,
const char * msg_no_nl )
{
size_t msglen = strlen ( msg ) ;
size_t allowed_size ;
if ( debug_ringbuf = = NULL ) {
return ;
}
/* Ensure the buffer is always \0 terminated */
allowed_size = debug_ringbuf_size - 1 ;
if ( msglen > allowed_size ) {
return ;
}
if ( ( debug_ringbuf_ofs + msglen ) < debug_ringbuf_ofs ) {
return ;
}
if ( ( debug_ringbuf_ofs + msglen ) > allowed_size ) {
debug_ringbuf_ofs = 0 ;
}
memcpy ( debug_ringbuf + debug_ringbuf_ofs , msg , msglen ) ;
debug_ringbuf_ofs + = msglen ;
}
2015-01-09 23:49:13 +03:00
static struct debug_backend {
const char * name ;
int log_level ;
int new_log_level ;
2017-01-07 21:34:46 +03:00
void ( * reload ) ( bool enabled , bool prev_enabled ,
const char * prog_name , char * option ) ;
2015-01-09 23:49:13 +03:00
void ( * log ) ( int msg_level , const char * msg , const char * msg_no_nl ) ;
2017-01-07 21:34:46 +03:00
char * option ;
2015-01-09 23:49:13 +03:00
} 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
2016-06-22 12:13:15 +03:00
# if defined(HAVE_LIBSYSTEMD_JOURNAL) || defined(HAVE_LIBSYSTEMD)
2015-03-21 00:36:58 +03:00
{
. name = " systemd " ,
. log = debug_systemd_log ,
} ,
# endif
2015-01-10 02:17:08 +03:00
# ifdef HAVE_LTTNG_TRACEF
{
. name = " lttng " ,
. log = debug_lttng_log ,
} ,
# endif
2015-02-20 02:32:44 +03:00
# ifdef HAVE_GPFS
{
. name = " gpfs " ,
. reload = debug_gpfs_reload ,
. log = debug_gpfs_log ,
} ,
# endif
2017-01-07 16:36:24 +03:00
{
. name = " ringbuf " ,
. log = debug_ringbuf_log ,
. reload = debug_ringbuf_reload ,
} ,
2015-01-09 23:49:13 +03:00
} ;
static struct debug_backend * debug_find_backend ( const char * name )
{
2016-10-13 12:18:50 +03:00
unsigned i ;
2015-01-09 23:49:13 +03:00
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 ;
2017-01-07 21:34:46 +03:00
char * backend_option ;
2015-01-09 23:49:13 +03:00
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 ;
}
backend_option = strtok_r ( NULL , " \0 " , & saveptr ) ;
/*
* 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 ) ;
}
2017-01-07 21:34:46 +03:00
if ( backend_option ! = NULL ) {
b - > option = strdup ( backend_option ) ;
if ( b - > option = = NULL ) {
return ;
}
}
2015-01-09 23:49:13 +03:00
}
/*
* 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 ;
2016-10-13 12:18:50 +03:00
unsigned i ;
2015-01-09 23:49:13 +03:00
/*
* initialize new_log_level to detect backends that have been
* disabled
*/
for ( i = 0 ; i < ARRAY_SIZE ( debug_backends ) ; i + + ) {
2017-01-07 21:34:46 +03:00
SAFE_FREE ( debug_backends [ i ] . option ) ;
2015-01-09 23:49:13 +03:00
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 ;
2017-01-07 21:34:46 +03:00
b - > reload ( enabled , previously_enabled , state . prog_name ,
b - > option ) ;
2015-01-09 23:49:13 +03:00
}
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 ] ;
2018-05-08 10:31:51 +03:00
size_t i ;
size_t len ;
2015-01-09 23:49:13 +03:00
/*
* Some backends already add an extra newline , so also provide
* a buffer without the newline character .
*/
len = MIN ( strlen ( msg ) , FORMAT_BUFR_SIZE - 1 ) ;
2017-04-18 00:09:24 +03:00
if ( ( len > 0 ) & & ( msg [ len - 1 ] = = ' \n ' ) ) {
2015-01-09 23:49:13 +03:00
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
2015-05-13 17:03:38 +03:00
static const char * default_classname_table [ ] = {
[ DBGC_ALL ] = " all " ,
[ DBGC_TDB ] = " tdb " ,
[ DBGC_PRINTDRIVERS ] = " printdrivers " ,
[ DBGC_LANMAN ] = " lanman " ,
[ DBGC_SMB ] = " smb " ,
[ DBGC_RPC_PARSE ] = " rpc_parse " ,
[ DBGC_RPC_SRV ] = " rpc_srv " ,
[ DBGC_RPC_CLI ] = " rpc_cli " ,
[ DBGC_PASSDB ] = " passdb " ,
[ DBGC_SAM ] = " sam " ,
[ DBGC_AUTH ] = " auth " ,
[ DBGC_WINBIND ] = " winbind " ,
[ DBGC_VFS ] = " vfs " ,
[ DBGC_IDMAP ] = " idmap " ,
[ DBGC_QUOTA ] = " quota " ,
[ DBGC_ACLS ] = " acls " ,
[ DBGC_LOCKING ] = " locking " ,
[ DBGC_MSDFS ] = " msdfs " ,
[ DBGC_DMAPI ] = " dmapi " ,
[ DBGC_REGISTRY ] = " registry " ,
[ DBGC_SCAVENGER ] = " scavenger " ,
[ DBGC_DNS ] = " dns " ,
[ DBGC_LDB ] = " ldb " ,
2015-06-28 21:44:37 +03:00
[ DBGC_TEVENT ] = " tevent " ,
2017-02-20 01:39:17 +03:00
[ DBGC_AUTH_AUDIT ] = " auth_audit " ,
2017-03-06 06:16:51 +03:00
[ DBGC_AUTH_AUDIT_JSON ] = " auth_json_audit " ,
2017-05-15 23:32:03 +03:00
[ DBGC_KERBEROS ] = " kerberos " ,
2017-09-06 07:37:34 +03:00
[ DBGC_DRS_REPL ] = " drs_repl " ,
2018-03-21 22:01:05 +03:00
[ DBGC_SMB2 ] = " smb2 " ,
2018-03-21 22:52:49 +03:00
[ DBGC_SMB2_CREDITS ] = " smb2_credits " ,
2018-04-04 02:56:30 +03:00
[ DBGC_DSDB_AUDIT ] = " dsdb_audit " ,
[ DBGC_DSDB_AUDIT_JSON ] = " dsdb_json_audit " ,
[ DBGC_DSDB_PWD_AUDIT ] = " dsdb_password_audit " ,
[ DBGC_DSDB_PWD_AUDIT_JSON ] = " dsdb_password_json_audit " ,
[ DBGC_DSDB_TXN_AUDIT ] = " dsdb_transaction_audit " ,
[ DBGC_DSDB_TXN_AUDIT_JSON ] = " dsdb_transaction_json_audit " ,
2018-04-23 03:24:34 +03:00
[ DBGC_DSDB_GROUP_AUDIT ] = " dsdb_group_audit " ,
[ DBGC_DSDB_GROUP_AUDIT_JSON ] = " dsdb_group_json_audit " ,
2015-05-13 17:03:38 +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
*/
2015-05-13 17:03:38 +03:00
static const int debug_class_list_initial [ ARRAY_SIZE ( default_classname_table ) ] ;
2002-07-15 14:35:28 +04:00
2018-05-08 10:31:51 +03:00
static size_t 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
*/
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 )
{
2017-01-07 21:34:46 +03:00
unsigned i ;
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 ;
2017-01-07 21:34:46 +03:00
for ( i = 0 ; i < ARRAY_SIZE ( debug_backends ) ; i + + ) {
SAFE_FREE ( debug_backends [ i ] . option ) ;
}
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 ;
2018-05-08 10:31:51 +03:00
size_t 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
{
2018-05-08 10:31:51 +03:00
size_t i ;
2001-02-12 19:18:02 +03:00
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 )
{
2018-05-08 10:31:51 +03:00
size_t q ;
2002-07-15 14:35:28 +04:00
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 ;
2016-06-22 10:36:00 +03:00
char * saveptr = NULL ;
2014-07-29 15:05:06 +04:00
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 ;
2018-05-08 10:31:51 +03:00
size_t 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-05-13 17:03:38 +03:00
size_t i ;
2002-07-15 14:35:28 +04:00
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
2015-05-13 17:03:38 +03:00
for ( i = 0 ; i < ARRAY_SIZE ( default_classname_table ) ; i + + ) {
debug_add_class ( default_classname_table [ i ] ) ;
2002-07-15 14:35:28 +04:00
}
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-03-25 13:56:57 +03:00
char fake_param [ 256 ] ;
size_t len = 0 ;
2015-01-10 00:46:32 +03:00
/*
* 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
2015-07-27 00:02:57 +03:00
* deprecated ' syslog ' and ' syslog only ' parameters
2015-01-10 00:46:32 +03:00
*/
2015-03-25 13:56:57 +03:00
if ( logging_param ! = NULL ) {
len = strlen ( logging_param ) ;
}
if ( len = = 0 ) {
2015-01-10 00:46:32 +03:00
if ( syslog_only ) {
snprintf ( fake_param , sizeof ( fake_param ) ,
2015-06-03 17:34:31 +03:00
" syslog@%d " , syslog_level - 1 ) ;
2015-01-10 00:46:32 +03:00
} else {
snprintf ( fake_param , sizeof ( fake_param ) ,
2015-06-03 17:34:31 +03:00
" syslog@%d file@%d " , syslog_level - 1 ,
2015-01-10 00:46:32 +03:00
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 ) ;
s3: util: Do not take over stderr when there is no log file
In case we don't have either a /var/log/samba directory, or pass a
non-existent log directory through '-l' option, all commands that are
daemonized with '-D' option hang when executed within a subshell.
An example on how to trigger that:
# rm -r /var/log/samba
# s=$(nmbd -D -s /etc/samba/smb.conf -l /foo123)
(never returns)
So, when the above command is executed within a subshell the following
happens:
(a) Parent shell creates a pipe, sets write side of it to fd 1
(stdout), call read() on read-side fd, forks off a new child process
and then executes nmbd in it.
(b) nmbd sets up initial logging to go through fd 1 (stdout) by
calling setup_logging(..., DEBUG_DEFAULT_STDOUT). 'state.fd' is now
set to 1.
(c) reopen_logs() is called by the first time which then calls
reopen_logs_internal()
(d) in reopen_logs_internal(), it attempts to create log.nmbd file in
/foo123 directory and fails because directory doesn't exist.
(e) Regardless whether the log file was created or not, it calls
dup2(state.fd, 2) which dups fd 1 into fd 2.
(f) At some point, fd 0 and 1 are closed and set to /dev/null
The problem with that is because parent shell in (a) is still blocked in
read() call and the new write side of the pipe is now fd 2 -- after
dup2() in (e) -- and remains unclosed.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=13578
Signed-off-by: Paulo Alcantara <palcantara@suse.de>
Reviewed-by: Jim McDonough <jmcd@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Autobuild-User(master): Jeremy Allison <jra@samba.org>
Autobuild-Date(master): Sat Aug 18 01:32:25 CEST 2018 on sn-devel-144
2018-08-17 17:30:16 +03:00
/*
* If log file was opened or created successfully , take over stderr to
* catch output into logs .
*/
if ( new_fd ! = - 1 ) {
2012-03-02 12:32:56 +04:00
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 ) {
2016-03-23 01:01:10 +03:00
ssize_t ret ;
do {
ret = write ( state . fd , msg , strlen ( msg ) ) ;
} while ( ret = = - 1 & & errno = = EINTR ) ;
2014-07-29 20:04:25 +04:00
}
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 .
2016-12-06 12:55:46 +03:00
Input : level - Debug level of the message ( not the system - wide debug
level . )
cls - Debuglevel class of the calling module .
location - 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 .
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 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 ;
}