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"
2021-10-28 11:05:19 +03:00
# include "system/network.h"
# include "system/time.h"
2014-09-08 10:32:46 +04:00
# 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"
2020-06-30 18:02:07 +03:00
# include <assert.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 .
*/
2019-04-18 01:23:22 +03:00
# define FORMAT_BUFR_SIZE 4096
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 07:19:32 +04:00
enum debug_logtype logtype ; /* The type of logging we are doing: eg stdout, file, stderr */
2019-02-06 14:39:03 +03:00
char prog_name [ 255 ] ;
2021-10-28 11:05:19 +03:00
char hostname [ HOST_NAME_MAX + 1 ] ;
2010-10-29 07:19:32 +04:00
bool reopening_logs ;
2011-02-24 08:14:03 +03:00
bool schedule_reopen_logs ;
struct debug_settings settings ;
2012-03-08 05:21:26 +04:00
debug_callback_fn callback ;
void * callback_private ;
2021-10-13 03:42:14 +03:00
char header_str [ 300 ] ;
2016-12-03 04:27:47 +03:00
char header_str_no_nl [ 300 ] ;
2021-10-13 03:42:14 +03:00
size_t hs_len ;
2021-10-14 03:00:20 +03:00
char msg_no_nl [ FORMAT_BUFR_SIZE ] ;
2011-02-24 08:14:03 +03:00
} state = {
. settings = {
. timestamp_logs = true
2011-04-01 07:55:37 +04:00
} ,
2011-02-24 08:14:03 +03:00
} ;
2010-10-29 07:19:32 +04:00
2018-12-13 00:21:57 +03:00
struct debug_class {
/*
* The debug loglevel of the class .
*/
int loglevel ;
2018-12-12 14:51:16 +03:00
/*
* An optional class specific logfile , may be NULL in which case the
* " global " logfile is used and fd is - 1.
*/
char * logfile ;
int fd ;
2020-11-23 18:04:03 +03:00
/* inode number of the logfile to detect logfile rotation */
ino_t ino ;
2018-12-13 00:21:57 +03:00
} ;
2022-06-16 08:26:08 +03:00
/*
* default_classname_table [ ] is read in from debug - classname - table . c
* so that test_logging . c can use it too .
*/
# include "lib/util/debug-classes/debug-classname-table.c"
2018-12-12 10:57:28 +03:00
/*
2018-12-13 00:19:06 +03:00
* This is to allow reading of dbgc_config before the debug
2018-12-12 10:57:28 +03:00
* system has been initialized .
*/
2018-12-13 00:49:15 +03:00
static struct debug_class debug_class_list_initial [ ARRAY_SIZE ( default_classname_table ) ] = {
2020-10-18 21:21:56 +03:00
[ DBGC_ALL ] = { . fd = 2 } ,
2018-12-13 00:49:15 +03:00
} ;
2018-12-12 10:57:28 +03:00
static size_t debug_num_classes = 0 ;
2018-12-13 00:21:57 +03:00
static struct debug_class * dbgc_config = debug_class_list_initial ;
2018-12-12 10:57:28 +03:00
static int current_msg_level = 0 ;
2018-12-13 00:22:44 +03:00
static int current_msg_class = 0 ;
2018-12-12 10:57:28 +03:00
2022-05-26 06:55:12 +03:00
/*
* DBG_DEV ( ) : when and how to user it .
*
* As a developer , you sometimes want verbose logging between point A and
* point B , where the relationship between these points is not easily defined
* in terms of the call stack .
*
* For example , you might be interested in what is going on in functions in
* lib / util / util_str . c in an ldap worker process after a particular query . If
* you use gdb , something will time out and you won ' t get the full
* conversation . If you add fprintf ( ) or DBG_ERR ( ) s to util_str . c , you ' ll get
* a massive flood , and there ' s a chance one will accidentally slip into a
* release and the whole world will flood . DBG_DEV is a solution .
*
* On start - up , DBG_DEV ( ) is switched OFF . Nothing is printed .
*
* 1. Add ` DBG_DEV ( " formatted msg %d, etc \n " , i ) ; ` where needed .
*
* 2. At each point you want to start debugging , add ` debug_developer_enable ( ) ` .
*
* 3. At each point you want debugging to stop , add ` debug_developer_disable ( ) ` .
*
* In DEVELOPER builds , the message will be printed at level 0 , as with
* DBG_ERR ( ) . In production builds , the macro resolves to nothing .
*
* The messages are printed with a " <function_name>:DEV:<pid>: " prefix .
*/
static bool debug_developer_is_enabled = false ;
bool debug_developer_enabled ( void )
{
return debug_developer_is_enabled ;
}
/*
* debug_developer_disable ( ) will turn DBG_DEV ( ) on in the current
* process and children .
*/
void debug_developer_enable ( void )
{
debug_developer_is_enabled = true ;
}
/*
* debug_developer_disable ( ) will make DBG_DEV ( ) do nothing in the current
* process ( and children ) .
*/
void debug_developer_disable ( void )
{
debug_developer_is_enabled = false ;
}
/*
* Within debug . c , DBG_DEV ( ) always writes to stderr , because some functions
* here will attempt infinite recursion with normal DEBUG macros .
*/
# ifdef DEVELOPER
# undef DBG_DEV
# define DBG_DEV(fmt, ...) \
( void ) ( ( debug_developer_enabled ( ) ) \
& & ( fprintf ( stderr , " %s:DEV:%d: " fmt " %s " , \
__func__ , getpid ( ) , # # __VA_ARGS__ , " " ) ) )
# endif
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 ;
2020-03-17 08:05:20 +03:00
if ( level < 0 | | ( size_t ) level > = ARRAY_SIZE ( priority_map ) )
2015-01-09 23:29:48 +03:00
priority = LOG_DEBUG ;
else
priority = priority_map [ level ] ;
return priority ;
}
# endif
2021-10-06 14:49:06 +03:00
/* -------------------------------------------------------------------------- **
* Produce a version of the given buffer without any trailing newlines .
*/
2021-10-14 03:08:38 +03:00
# if defined(HAVE_LIBSYSTEMD_JOURNAL) || defined(HAVE_LIBSYSTEMD) || \
defined ( HAVE_LTTNG_TRACEF ) | | defined ( HAVE_GPFS )
2021-10-06 14:49:06 +03:00
static void copy_no_nl ( char * out ,
size_t out_size ,
const char * in ,
size_t in_len )
{
size_t len ;
/*
* Some backends already add an extra newline , so also provide
* a buffer without the newline character .
*/
len = MIN ( in_len , out_size - 1 ) ;
if ( ( len > 0 ) & & ( in [ len - 1 ] = = ' \n ' ) ) {
len - - ;
}
memcpy ( out , in , len ) ;
out [ len ] = ' \0 ' ;
}
2021-09-23 11:13:30 +03:00
static void ensure_copy_no_nl ( char * out ,
size_t out_size ,
const char * in ,
size_t in_len )
{
/*
* Assume out is a static buffer that is reused as a cache .
* If it isn ' t empty then this has already been done with the
* same input .
*/
if ( out [ 0 ] ! = ' \0 ' ) {
return ;
}
copy_no_nl ( out , out_size , in , in_len ) ;
}
# endif
2015-01-09 23:49:13 +03:00
/* -------------------------------------------------------------------------- **
* Debug backends . When logging to DEBUG_FILE , send the log entries to
* all active backends .
*/
2021-10-14 03:00:20 +03:00
static void debug_file_log ( int msg_level , const char * msg , size_t msg_len )
2015-01-10 00:00:02 +03:00
{
2016-12-03 04:27:47 +03:00
struct iovec iov [ ] = {
{
. iov_base = discard_const ( state . header_str ) ,
. iov_len = state . hs_len ,
} ,
{
. iov_base = discard_const ( msg ) ,
2016-12-02 08:37:47 +03:00
. iov_len = msg_len ,
2016-12-03 04:27:47 +03:00
} ,
} ;
2016-03-23 01:01:10 +03:00
ssize_t ret ;
2018-12-12 14:51:16 +03:00
int fd ;
2016-03-23 01:01:10 +03:00
2015-01-10 00:00:02 +03:00
check_log_size ( ) ;
2018-12-12 14:51:16 +03:00
if ( dbgc_config [ current_msg_class ] . fd ! = - 1 ) {
fd = dbgc_config [ current_msg_class ] . fd ;
} else {
2018-12-13 00:49:15 +03:00
fd = dbgc_config [ DBGC_ALL ] . fd ;
2018-12-12 14:51:16 +03:00
}
2016-03-23 01:01:10 +03:00
do {
2016-12-03 04:27:47 +03:00
ret = writev ( fd , iov , ARRAY_SIZE ( iov ) ) ;
2016-03-23 01:01:10 +03:00
} 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 ) {
2019-02-06 14:39:03 +03:00
const char * ident = NULL ;
if ( ( prog_name ! = NULL ) & & ( prog_name [ 0 ] ! = ' \0 ' ) ) {
ident = prog_name ;
}
2015-03-23 05:30:31 +03:00
# ifdef LOG_DAEMON
2019-02-06 14:39:03 +03:00
openlog ( ident , LOG_PID , SYSLOG_FACILITY ) ;
2015-03-23 05:30:31 +03:00
# else
/* for old systems that have no facility codes. */
2019-02-06 14:39:03 +03:00
openlog ( ident , LOG_PID ) ;
2015-03-23 05:30:31 +03:00
# endif
return ;
}
if ( ! enabled & & previously_enabled ) {
closelog ( ) ;
}
}
2021-10-14 03:00:20 +03:00
static void debug_syslog_log ( int msg_level , const char * msg , size_t msg_len )
2015-03-23 05:30:31 +03:00
{
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 ;
2016-12-03 04:27:47 +03:00
if ( state . hs_len > 0 ) {
syslog ( priority , " %s " , state . header_str ) ;
}
2015-03-23 05:30:31 +03:00
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>
2021-10-14 03:00:20 +03:00
static void debug_systemd_log ( int msg_level , const char * msg , size_t msg_len )
2015-03-21 00:36:58 +03:00
{
2016-12-03 04:27:47 +03:00
if ( state . hs_len > 0 ) {
2021-09-23 11:13:30 +03:00
ensure_copy_no_nl ( state . header_str_no_nl ,
sizeof ( state . header_str_no_nl ) ,
state . header_str ,
state . hs_len ) ;
2016-12-03 04:27:47 +03:00
sd_journal_send ( " MESSAGE=%s " ,
state . header_str_no_nl ,
" PRIORITY=%d " ,
debug_level_to_priority ( msg_level ) ,
" LEVEL=%d " ,
msg_level ,
NULL ) ;
}
2021-10-14 03:08:38 +03:00
ensure_copy_no_nl ( state . msg_no_nl ,
sizeof ( state . msg_no_nl ) ,
msg , msg_len ) ;
2021-10-14 03:00:20 +03:00
sd_journal_send ( " MESSAGE=%s " , state . msg_no_nl ,
2015-03-21 00:36:58 +03:00
" 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>
2021-10-14 03:00:20 +03:00
static void debug_lttng_log ( int msg_level , const char * msg , size_t msg_len )
2015-01-10 02:17:08 +03:00
{
2016-12-03 04:27:47 +03:00
if ( state . hs_len > 0 ) {
2021-09-23 11:13:30 +03:00
ensure_copy_no_nl ( state . header_str_no_nl ,
sizeof ( state . header_str_no_nl ) ,
state . header_str ,
state . hs_len ) ;
2016-12-03 04:27:47 +03:00
tracef ( state . header_str_no_nl ) ;
}
2021-10-14 03:08:38 +03:00
ensure_copy_no_nl ( state . msg_no_nl ,
sizeof ( state . msg_no_nl ) ,
msg , msg_len ) ;
2021-10-14 03:00:20 +03:00
tracef ( state . msg_no_nl ) ;
2015-01-10 02:17:08 +03:00
}
# 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 ( ) ;
}
}
2021-10-14 03:00:20 +03:00
static void debug_gpfs_log ( int msg_level , const char * msg , size_t msg_len )
2015-02-20 02:32:44 +03:00
{
2016-12-03 04:27:47 +03:00
if ( state . hs_len > 0 ) {
2021-09-23 11:13:30 +03:00
ensure_copy_no_nl ( state . header_str_no_nl ,
sizeof ( state . header_str_no_nl ) ,
state . header_str ,
state . hs_len ) ;
2016-12-03 04:27:47 +03:00
gpfswrap_add_trace ( msg_level , state . header_str_no_nl ) ;
}
2021-10-14 03:08:38 +03:00
ensure_copy_no_nl ( state . msg_no_nl ,
sizeof ( state . msg_no_nl ) ,
msg , msg_len ) ;
2021-10-14 03:00:20 +03:00
gpfswrap_add_trace ( msg_level , state . msg_no_nl ) ;
2015-02-20 02:32:44 +03:00
}
# 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 ;
}
}
2021-10-14 03:00:20 +03:00
static void _debug_ringbuf_log ( int msg_level , const char * msg , size_t msg_len )
2017-01-07 16:36:24 +03:00
{
size_t allowed_size ;
if ( debug_ringbuf = = NULL ) {
return ;
}
/* Ensure the buffer is always \0 terminated */
allowed_size = debug_ringbuf_size - 1 ;
2021-10-06 15:02:10 +03:00
if ( msg_len > allowed_size ) {
2017-01-07 16:36:24 +03:00
return ;
}
2021-10-06 15:02:10 +03:00
if ( ( debug_ringbuf_ofs + msg_len ) < debug_ringbuf_ofs ) {
2017-01-07 16:36:24 +03:00
return ;
}
2021-10-06 15:02:10 +03:00
if ( ( debug_ringbuf_ofs + msg_len ) > allowed_size ) {
2017-01-07 16:36:24 +03:00
debug_ringbuf_ofs = 0 ;
}
2021-10-06 15:02:10 +03:00
memcpy ( debug_ringbuf + debug_ringbuf_ofs , msg , msg_len ) ;
debug_ringbuf_ofs + = msg_len ;
2017-01-07 16:36:24 +03:00
}
2021-10-14 03:00:20 +03:00
static void debug_ringbuf_log ( int msg_level , const char * msg , size_t msg_len )
2021-09-23 03:25:04 +03:00
{
2016-12-03 04:27:47 +03:00
if ( state . hs_len > 0 ) {
2016-12-02 08:37:47 +03:00
_debug_ringbuf_log ( msg_level , state . header_str , state . hs_len ) ;
2016-12-03 04:27:47 +03:00
}
2016-12-02 08:37:47 +03:00
_debug_ringbuf_log ( msg_level , msg , msg_len ) ;
2021-09-23 03:25:04 +03:00
}
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 ) ;
2016-12-02 08:37:47 +03:00
void ( * log ) ( int msg_level ,
const char * msg ,
2021-10-14 03:00:20 +03:00
size_t len ) ;
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 ;
}
}
2016-12-02 08:37:47 +03:00
static void debug_backends_log ( const char * msg , size_t msg_len , int msg_level )
2015-01-09 23:49:13 +03:00
{
2018-05-08 10:31:51 +03:00
size_t i ;
2015-01-09 23:49:13 +03:00
/*
2021-10-14 03:08:38 +03:00
* Some backends already add an extra newline , so initialize a
* buffer without the newline character . It will be filled by
* the first backend that needs it .
2015-01-09 23:49:13 +03:00
*/
2021-10-14 03:08:38 +03:00
state . msg_no_nl [ 0 ] = ' \0 ' ;
2015-01-09 23:49:13 +03:00
for ( i = 0 ; i < ARRAY_SIZE ( debug_backends ) ; i + + ) {
if ( msg_level < = debug_backends [ i ] . log_level ) {
2021-10-14 03:00:20 +03:00
debug_backends [ i ] . log ( msg_level , msg , msg_len ) ;
2015-01-09 23:49:13 +03:00
}
}
2016-12-03 04:27:47 +03:00
/* Only log the header once */
state . hs_len = 0 ;
2015-01-09 23:49:13 +03:00
}
2018-11-07 16:14:05 +03:00
int debuglevel_get_class ( size_t idx )
{
2018-12-13 00:21:57 +03:00
return dbgc_config [ idx ] . loglevel ;
2018-11-07 16:14:05 +03:00
}
void debuglevel_set_class ( size_t idx , int level )
{
2018-12-13 00:21:57 +03:00
dbgc_config [ idx ] . loglevel = level ;
2018-11-07 16:14:05 +03:00
}
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 ;
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
2018-12-13 00:19:06 +03:00
if ( dbgc_config ! = debug_class_list_initial ) {
TALLOC_FREE ( dbgc_config ) ;
2018-12-13 00:21:57 +03:00
dbgc_config = discard_const_p ( struct debug_class ,
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
{
2022-11-28 12:38:50 +03:00
char * buf = talloc_strdup ( 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 + + ) {
2022-11-28 12:38:50 +03:00
talloc_asprintf_addbuf ( & buf ,
" %s:%d%s " ,
classname_table [ i ] ,
dbgc_config [ i ] . loglevel ,
i = = ( debug_num_classes - 1 ) ? " \n " : " " ) ;
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
2019-05-24 16:32:09 +03:00
if ( classname = = NULL ) {
return - 1 ;
}
2001-02-12 19:18:02 +03:00
2002-07-15 14:35:28 +04:00
for ( i = 0 ; i < debug_num_classes ; i + + ) {
2019-05-24 16:32:09 +03:00
char * entry = classname_table [ i ] ;
if ( entry ! = NULL & & strcmp ( classname , entry ) = = 0 ) {
2001-02-12 19:18:02 +03:00
return i ;
2019-05-24 16:32:09 +03:00
}
2001-02-12 19:18:02 +03:00
}
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 ;
2018-12-13 00:21:57 +03:00
struct debug_class * new_class_list = NULL ;
2011-02-24 08:14:03 +03:00
char * * new_name_list ;
2011-03-04 04:23:16 +03:00
int default_level ;
2002-07-15 14:35:28 +04:00
2018-12-12 13:57:05 +03:00
if ( classname = = NULL ) {
2002-07-15 14:35:28 +04:00
return - 1 ;
2018-12-12 13:57:05 +03:00
}
2002-07-15 14:35:28 +04:00
/* check the init has yet been called */
debug_init ( ) ;
ndx = debug_lookup_classname_int ( classname ) ;
2018-12-12 13:57:05 +03:00
if ( ndx > = 0 ) {
2002-07-15 14:35:28 +04:00
return ndx ;
2018-12-12 13:57:05 +03:00
}
2002-07-15 14:35:28 +04:00
ndx = debug_num_classes ;
2018-12-13 00:19:06 +03:00
if ( dbgc_config = = 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 {
2018-12-13 00:19:06 +03:00
new_class_list = dbgc_config ;
2002-07-15 14:35:28 +04:00
}
2018-12-13 00:21:57 +03:00
default_level = dbgc_config [ DBGC_ALL ] . loglevel ;
2011-03-04 04:23:16 +03:00
2018-12-13 00:21:57 +03:00
new_class_list = talloc_realloc ( NULL ,
new_class_list ,
struct debug_class ,
ndx + 1 ) ;
2018-12-12 13:57:05 +03:00
if ( new_class_list = = NULL ) {
2002-07-15 14:35:28 +04:00
return - 1 ;
2018-12-12 13:57:05 +03:00
}
2018-12-13 00:19:06 +03:00
dbgc_config = new_class_list ;
2002-07-15 14:35:28 +04:00
2018-12-13 00:21:57 +03:00
dbgc_config [ ndx ] = ( struct debug_class ) {
. loglevel = default_level ,
2018-12-12 14:51:16 +03:00
. fd = - 1 ,
2018-12-13 00:21:57 +03:00
} ;
2011-02-24 08:14:03 +03:00
new_name_list = talloc_realloc ( NULL , classname_table , char * , ndx + 1 ) ;
2018-12-12 13:57:05 +03:00
if ( new_name_list = = NULL ) {
2002-07-15 14:35:28 +04:00
return - 1 ;
2018-12-12 13:57:05 +03:00
}
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 ) ;
2018-12-12 13:57:05 +03:00
if ( classname_table [ ndx ] = = NULL ) {
2002-07-15 14:35:28 +04:00
return - 1 ;
2018-12-12 13:57:05 +03:00
}
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
2019-05-24 16:32:09 +03:00
if ( classname = = NULL | | ! * classname )
2004-07-10 00:49:43 +04:00
return - 1 ;
2002-07-15 14:35:28 +04:00
ndx = debug_lookup_classname_int ( classname ) ;
if ( ndx ! = - 1 )
return ndx ;
2021-06-18 15:18:00 +03:00
DBG_WARNING ( " Unknown classname[%s] -> adding it... \n " , classname ) ;
2011-02-24 08:14:03 +03:00
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 ,
2018-12-13 00:21:57 +03:00
dbgc_config [ q ] . loglevel ) ) ;
2002-07-15 14:35:28 +04:00
}
}
2014-07-29 15:05:06 +04:00
static bool debug_parse_param ( char * param )
{
char * class_name ;
2018-12-12 15:11:26 +03:00
char * class_file = NULL ;
2014-07-29 15:05:06 +04:00
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 ;
}
2018-12-12 15:11:26 +03:00
class_level = strtok_r ( NULL , " @ \0 " , & saveptr ) ;
2014-07-29 15:05:06 +04:00
if ( class_level = = NULL ) {
return false ;
}
2018-12-12 15:11:26 +03:00
class_file = strtok_r ( NULL , " \0 " , & saveptr ) ;
2014-07-29 15:05:06 +04:00
ndx = debug_lookup_classname ( class_name ) ;
if ( ndx = = - 1 ) {
return false ;
}
2018-12-13 00:21:57 +03:00
dbgc_config [ ndx ] . loglevel = atoi ( class_level ) ;
2014-07-29 15:05:06 +04:00
2018-12-12 15:11:26 +03:00
if ( class_file = = NULL ) {
return true ;
}
TALLOC_FREE ( dbgc_config [ ndx ] . logfile ) ;
dbgc_config [ ndx ] . logfile = talloc_strdup ( NULL , class_file ) ;
if ( dbgc_config [ ndx ] . logfile = = NULL ) {
return false ;
}
2014-07-29 15:05:06 +04:00
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
2019-08-29 23:39:39 +03:00
Note : the 1 st param has no " name: " preceding 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 ] ) ) {
2018-12-13 00:21:57 +03:00
dbgc_config [ DBGC_ALL ] . loglevel = atoi ( tok ) ;
2014-07-29 22:01:31 +04:00
tok = strtok_r ( NULL , LIST_SEP , & saveptr ) ;
2004-07-10 00:49:43 +04:00
} else {
2018-12-13 00:21:57 +03:00
dbgc_config [ DBGC_ALL ] . loglevel = 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 + + ) {
2018-12-13 00:21:57 +03:00
dbgc_config [ i ] . loglevel = dbgc_config [ DBGC_ALL ] . loglevel ;
2018-12-12 15:09:03 +03:00
TALLOC_FREE ( dbgc_config [ i ] . logfile ) ;
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
}
2018-12-13 00:49:15 +03:00
dbgc_config [ DBGC_ALL ] . fd = 2 ;
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
}
2021-10-28 11:05:19 +03:00
static void ensure_hostname ( void )
{
int ret ;
if ( state . hostname [ 0 ] ! = ' \0 ' ) {
return ;
}
ret = gethostname ( state . hostname , sizeof ( state . hostname ) ) ;
if ( ret ! = 0 ) {
strlcpy ( state . hostname , " unknown " , sizeof ( state . hostname ) ) ;
return ;
}
/*
* Ensure NUL termination , since POSIX isn ' t clear about that .
*
* Don ' t worry about truncating at the first ' . ' or similar ,
* since this is usually not fully qualified . Trying to
* truncate opens up the multibyte character gates of hell .
*/
state . hostname [ sizeof ( state . hostname ) - 1 ] = ' \0 ' ;
}
void debug_set_hostname ( const char * name )
{
strlcpy ( state . hostname , name , sizeof ( state . hostname ) ) ;
}
2010-10-29 07:19:32 +04:00
/**
2022-05-26 06:50:23 +03:00
* Ensure debug logs are initialised .
*
* setup_logging ( ) is called to direct logging to the correct outputs , whether
* those be stderr , stdout , files , or syslog , and set the program name used in
* the logs . It can be called multiple times .
*
* There is an order of precedence to the log type . Once set to DEBUG_FILE , it
* cannot be reset DEFAULT_DEBUG_STDERR , but can be set to DEBUG_STDERR , after
* which DEBUG_FILE is unavailable ) . This makes it possible to override for
* debug to stderr on the command line , as the smb . conf cannot reset it back
* to file - based logging . See enum debug_logtype .
*
* @ param prog_name the program name . Directory path component will be
* ignored .
*
* @ param new_logtype the requested destination for the debug log ,
* as an enum debug_logtype .
*/
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 ;
}
2019-02-06 14:39:03 +03:00
strlcpy ( state . prog_name , prog_name , sizeof ( state . 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 ;
}
2018-12-13 00:49:15 +03:00
TALLOC_FREE ( dbgc_config [ DBGC_ALL ] . logfile ) ;
dbgc_config [ DBGC_ALL ] . logfile = talloc_strdup ( NULL , name ) ;
2021-11-08 21:41:50 +03:00
reopen_logs_internal ( ) ;
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
}
}
2021-01-08 10:31:24 +03:00
enum debug_logtype debug_get_log_type ( void )
{
return state . logtype ;
}
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 ;
}
}
2016-12-02 08:37:47 +03:00
static void debug_callback_log ( const char * msg , size_t msg_len , int msg_level )
2015-01-09 23:17:49 +03:00
{
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
2020-11-23 17:46:47 +03:00
static bool reopen_one_log ( struct debug_class * config )
2018-12-12 14:35:42 +03:00
{
2020-11-23 17:46:47 +03:00
int old_fd = config - > fd ;
const char * logfile = config - > logfile ;
2020-11-23 18:04:03 +03:00
struct stat st ;
2018-12-12 14:35:42 +03:00
int new_fd ;
2020-11-23 18:04:03 +03:00
int ret ;
2018-12-12 14:35:42 +03:00
2018-12-13 00:46:49 +03:00
if ( logfile = = NULL ) {
debug_close_fd ( old_fd ) ;
2020-11-23 17:46:47 +03:00
config - > fd = - 1 ;
2018-12-13 00:46:49 +03:00
return true ;
}
2018-12-12 14:35:42 +03:00
new_fd = open ( logfile , O_WRONLY | O_APPEND | O_CREAT , 0644 ) ;
if ( new_fd = = - 1 ) {
log_overflow = true ;
DBG_ERR ( " Unable to open new log file '%s': %s \n " ,
logfile , strerror ( errno ) ) ;
log_overflow = false ;
return false ;
}
debug_close_fd ( old_fd ) ;
smb_set_close_on_exec ( new_fd ) ;
2020-11-23 17:46:47 +03:00
config - > fd = new_fd ;
2018-12-12 14:35:42 +03:00
2020-11-23 18:04:03 +03:00
ret = fstat ( new_fd , & st ) ;
if ( ret ! = 0 ) {
log_overflow = true ;
DBG_ERR ( " Unable to fstat() new log file '%s': %s \n " ,
logfile , strerror ( errno ) ) ;
log_overflow = false ;
return false ;
}
config - > ino = st . st_ino ;
2018-12-12 14:35:42 +03:00
return true ;
}
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
{
2020-06-30 18:02:07 +03:00
struct debug_backend * b = NULL ;
2000-08-28 07:17:22 +04:00
mode_t oldumask ;
2018-12-13 00:49:15 +03:00
size_t i ;
2018-12-12 14:35:42 +03:00
bool ok ;
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 :
2018-12-13 00:49:15 +03:00
debug_close_fd ( dbgc_config [ DBGC_ALL ] . fd ) ;
dbgc_config [ DBGC_ALL ] . fd = 1 ;
2010-10-29 07:19:32 +04:00
return true ;
case DEBUG_DEFAULT_STDERR :
case DEBUG_STDERR :
2018-12-13 00:49:15 +03:00
debug_close_fd ( dbgc_config [ DBGC_ALL ] . fd ) ;
dbgc_config [ DBGC_ALL ] . fd = 2 ;
2010-10-29 07:19:32 +04:00
return true ;
2020-06-30 18:02:07 +03:00
case DEBUG_FILE :
b = debug_find_backend ( " file " ) ;
assert ( b ! = NULL ) ;
2020-04-22 14:53:42 +03:00
2020-06-30 18:03:05 +03:00
b - > log_level = MAX_DEBUG_LEVEL ;
2010-10-29 07:19:32 +04:00
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
2018-12-13 00:49:15 +03:00
for ( i = DBGC_ALL ; i < debug_num_classes ; i + + ) {
2020-02-13 18:44:38 +03:00
if ( dbgc_config [ i ] . logfile ! = NULL ) {
2018-12-13 00:49:15 +03:00
break ;
}
}
if ( i = = debug_num_classes ) {
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
2018-12-13 00:46:49 +03:00
for ( i = DBGC_ALL ; i < debug_num_classes ; i + + ) {
2020-11-23 17:46:47 +03:00
ok = reopen_one_log ( & dbgc_config [ i ] ) ;
2018-12-13 00:46:49 +03:00
if ( ! ok ) {
break ;
}
}
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 .
*/
2022-06-07 06:54:20 +03:00
if ( ! state . settings . debug_no_stderr_redirect & &
dbgc_config [ DBGC_ALL ] . fd > 0 ) {
2018-12-13 00:49:15 +03:00
if ( dup2 ( dbgc_config [ DBGC_ALL ] . fd , 2 ) = = - 1 ) {
2012-03-02 12:32:56 +04:00
/* 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 ;
2018-12-12 14:35:42 +03:00
return ok ;
2001-03-27 05:19:54 +04:00
}
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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2018-12-12 13:57:05 +03:00
bool need_to_check_log_size ( void )
2000-04-15 04:31:56 +04:00
{
int maxlog ;
2018-12-12 16:54:41 +03:00
size_t i ;
2000-04-15 04:31:56 +04:00
2018-12-12 13:57:05 +03:00
if ( debug_count < 100 ) {
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 ;
2018-12-12 16:54:41 +03:00
if ( maxlog < = 0 ) {
2000-04-15 04:31:56 +04:00
debug_count = 0 ;
2018-12-12 13:57:05 +03:00
return false ;
2000-04-15 04:31:56 +04:00
}
2018-12-12 16:54:41 +03:00
2018-12-13 00:49:15 +03:00
if ( dbgc_config [ DBGC_ALL ] . fd > 2 ) {
2018-12-12 16:54:41 +03:00
return true ;
}
for ( i = DBGC_ALL + 1 ; i < debug_num_classes ; i + + ) {
if ( dbgc_config [ i ] . fd ! = - 1 ) {
return true ;
}
}
debug_count = 0 ;
return false ;
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
2020-11-23 17:51:09 +03:00
static void do_one_check_log_size ( off_t maxlog , struct debug_class * config )
1999-12-13 16:27:58 +03:00
{
2020-11-23 17:51:09 +03:00
char name [ strlen ( config - > logfile ) + 5 ] ;
2011-02-24 08:14:03 +03:00
struct stat st ;
2018-12-12 14:45:11 +03:00
int ret ;
2020-11-23 18:04:03 +03:00
bool reopen = false ;
2018-12-12 14:45:11 +03:00
bool ok ;
if ( maxlog = = 0 ) {
return ;
}
2020-11-23 18:04:03 +03:00
ret = stat ( config - > logfile , & st ) ;
2018-12-12 14:45:11 +03:00
if ( ret ! = 0 ) {
return ;
}
2020-11-23 18:04:03 +03:00
if ( st . st_size > = maxlog ) {
reopen = true ;
}
if ( st . st_ino ! = config - > ino ) {
reopen = true ;
}
if ( ! reopen ) {
2018-12-12 14:45:11 +03:00
return ;
}
/* reopen_logs_internal() modifies *_fd */
( void ) reopen_logs_internal ( ) ;
2020-11-23 17:51:09 +03:00
if ( config - > fd < = 2 ) {
2018-12-12 14:45:11 +03:00
return ;
}
2020-11-23 17:51:09 +03:00
ret = fstat ( config - > fd , & st ) ;
2018-12-12 14:45:11 +03:00
if ( ret ! = 0 ) {
2020-11-23 18:04:03 +03:00
config - > ino = ( ino_t ) 0 ;
2018-12-12 14:45:11 +03:00
return ;
}
2020-11-23 18:04:03 +03:00
config - > ino = st . st_ino ;
2018-12-12 14:45:11 +03:00
if ( st . st_size < maxlog ) {
return ;
}
2020-11-23 17:51:09 +03:00
snprintf ( name , sizeof ( name ) , " %s.old " , config - > logfile ) ;
2018-12-12 14:45:11 +03:00
2020-11-23 17:51:09 +03:00
( void ) rename ( config - > logfile , name ) ;
2018-12-12 14:45:11 +03:00
ok = reopen_logs_internal ( ) ;
if ( ok ) {
return ;
}
/* We failed to reopen a log - continue using the old name. */
2020-11-23 17:51:09 +03:00
( void ) rename ( name , config - > logfile ) ;
2018-12-12 14:45:11 +03:00
}
static void do_check_log_size ( off_t maxlog )
{
2018-12-12 16:43:22 +03:00
size_t i ;
2018-12-13 00:49:15 +03:00
for ( i = DBGC_ALL ; i < debug_num_classes ; i + + ) {
2018-12-12 16:43:22 +03:00
if ( dbgc_config [ i ] . fd = = - 1 ) {
continue ;
}
if ( dbgc_config [ i ] . logfile = = NULL ) {
continue ;
}
2020-11-23 17:51:09 +03:00
do_one_check_log_size ( maxlog , & dbgc_config [ i ] ) ;
2018-12-12 16:43:22 +03:00
}
2018-12-12 14:45:11 +03:00
}
void check_log_size ( void )
{
off_t maxlog ;
2001-03-27 05:19:54 +04:00
2022-05-26 06:51:25 +03:00
if ( geteuid ( ) ! = 0 ) {
/*
* We need to be root to change the log file ( tests use a fake
* geteuid ( ) from third_party / uid_wrapper ) . Otherwise we skip
* this and let the main smbd loop or some other process do
* the work .
*/
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 ) {
2018-12-12 13:57:05 +03:00
( void ) reopen_logs_internal ( ) ;
2012-06-11 07:22:42 +04:00
}
2018-12-12 14:45:11 +03:00
do_check_log_size ( maxlog ) ;
1998-08-01 00:17:36 +04:00
2001-03-27 05:19:54 +04:00
/*
2018-12-13 00:49:15 +03:00
* Here ' s where we need to panic if dbgc_config [ DBGC_ALL ] . fd = = 0 or - 1
* ( invalid values )
2001-03-27 05:19:54 +04:00
*/
2000-04-15 04:31:56 +04:00
2018-12-13 00:49:15 +03:00
if ( dbgc_config [ DBGC_ALL ] . 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 ) ;
2018-12-13 00:49:15 +03:00
dbgc_config [ DBGC_ALL ] . fd = fd ;
DBG_ERR ( " check_log_size: open of debug file %s failed "
" - using console. \n " ,
dbgc_config [ DBGC_ALL ] . logfile ) ;
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 .
2016-12-03 04:27:47 +03:00
This is called by format_debug_text ( ) .
2004-07-10 00:49:43 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-01 00:17:36 +04:00
2016-12-02 08:29:56 +03:00
static void Debug1 ( const char * msg , size_t msg_len )
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 :
2016-12-02 08:37:47 +03:00
debug_callback_log ( msg , msg_len , 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 :
2018-12-13 00:49:15 +03:00
if ( dbgc_config [ DBGC_ALL ] . fd > 0 ) {
2016-03-23 01:01:10 +03:00
ssize_t ret ;
do {
2018-12-13 00:49:15 +03:00
ret = write ( dbgc_config [ DBGC_ALL ] . fd ,
msg ,
2016-12-02 08:29:56 +03:00
msg_len ) ;
2016-03-23 01:01:10 +03:00
} 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 :
2016-12-02 08:37:47 +03:00
debug_backends_log ( msg , msg_len , current_msg_level ) ;
2015-01-10 01:00:04 +03:00
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 ' ;
2016-12-02 08:29:56 +03:00
( void ) Debug1 ( format_bufr , format_pos ) ;
2004-07-10 00:49:43 +04:00
format_pos = 0 ;
}
2022-08-26 12:41:44 +03:00
/*
* If set ( by tevent_thread_call_depth_set ( ) ) to value > 0 , debug code will use
* it for the trace indentation .
*/
static size_t debug_call_depth = 0 ;
size_t * debug_call_depth_addr ( void )
{
return & debug_call_depth ;
}
2004-07-10 00:49:43 +04:00
/***************************************************************************
Format the debug message text .
Input : msg - Text to be added to the " current " debug message text .
Output : none .
Notes : The purpose of this is two - fold . First , each call to syslog ( )
( used by Debug1 ( ) , see above ) generates a new line of syslog
output . This is fixed by storing the partial lines until the
newline character is encountered . Second , printing the debug
message lines when a newline is encountered allows us to add
spaces , thus indenting the body of the message and making it
more readable .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void format_debug_text ( 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 ) {
2022-08-26 12:42:42 +03:00
/* Limit the maximum indentation to 20 levels */
size_t depth = MIN ( 20 , debug_call_depth ) ;
2004-07-10 00:49:43 +04:00
format_bufr [ 0 ] = format_bufr [ 1 ] = ' ' ;
format_pos = 2 ;
2022-08-26 12:42:42 +03:00
/*
* Indent by four spaces for each depth level ,
* but only if the current debug level is > = 8.
*/
if ( depth > 0 & & debuglevel_get ( ) > = 8 & &
format_pos + 4 * depth < FORMAT_BUFR_SIZE ) {
memset ( & format_bufr [ format_pos ] ,
' ' ,
4 * depth ) ;
format_pos + = 4 * depth ;
}
2004-07-10 00:49:43 +04:00
}
/* 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 ) {
2016-12-02 08:29:56 +03:00
const char cont [ ] = " +> \n " ;
2004-07-10 00:49:43 +04:00
bufr_print ( ) ;
2016-12-02 08:29:56 +03:00
( void ) Debug1 ( cont , sizeof ( cont ) - 1 ) ;
2004-07-10 00:49:43 +04:00
}
}
/* 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 ( ) ;
}
2019-04-26 14:40:58 +03:00
bool dbgsetclass ( int level , int cls )
{
/* Set current_msg_level. */
current_msg_level = level ;
/* Set current message class */
current_msg_class = cls ;
return true ;
}
2004-07-10 00:49:43 +04:00
/***************************************************************************
2016-12-03 04:27:47 +03:00
Put a Debug Header into header_str .
2004-07-10 00:49:43 +04:00
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-29 19:06:17 +04:00
struct timeval tv ;
struct timeval_buf tvbuf ;
2004-07-10 00:49:43 +04:00
2021-10-13 03:42:14 +03:00
/*
* This might be overkill , but if another early return is
* added later then initialising these avoids potential
* problems
*/
state . hs_len = 0 ;
state . header_str [ 0 ] = ' \0 ' ;
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
2019-04-26 14:40:58 +03:00
dbgsetclass ( level , cls ) ;
2018-12-13 00:22:44 +03: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 | |
2021-10-28 11:05:19 +03:00
state . settings . debug_prefix_timestamp | |
state . settings . debug_syslog_format ) ) {
2014-07-29 19:02:22 +04:00
return true ;
}
1999-12-13 16:27:58 +03:00
2014-07-29 19:26:22 +04:00
GetTimeOfDay ( & tv ) ;
2021-10-28 11:05:19 +03:00
if ( state . settings . debug_syslog_format ) {
if ( state . settings . debug_hires_timestamp ) {
timeval_str_buf ( & tv , true , true , & tvbuf ) ;
} else {
time_t t ;
struct tm * tm ;
t = ( time_t ) tv . tv_sec ;
tm = localtime ( & t ) ;
if ( tm ! = NULL ) {
size_t len ;
len = strftime ( tvbuf . buf ,
sizeof ( tvbuf . buf ) ,
" %b %e %T " ,
tm ) ;
if ( len = = 0 ) {
/* Trigger default time format below */
tm = NULL ;
}
}
if ( tm = = NULL ) {
snprintf ( tvbuf . buf ,
sizeof ( tvbuf . buf ) ,
" %ld seconds since the Epoch " , ( long ) t ) ;
}
}
ensure_hostname ( ) ;
state . hs_len = snprintf ( state . header_str ,
sizeof ( state . header_str ) ,
util: CID 1499409: Memory - corruptions (OVERLAPPING_COPY)
This is quite bizarre:
*** CID 1499409: Memory - corruptions (OVERLAPPING_COPY)
/lib/util/debug.c: 1742 in dbghdrclass()
1736 sizeof(tvbuf.buf),
1737 "%ld seconds since the Epoch", (long)t);
1738 }
1739 }
1740
1741 ensure_hostname();
>>> CID 1499409: Memory - corruptions (OVERLAPPING_COPY)
>>> In the call to function "snprintf", the object pointed to by argument "state.hostname" may overlap with the object pointed to by argument "state.header_str".
1742 state.hs_len = snprintf(state.header_str,
1743 sizeof(state.header_str),
1744 "%s %s %s[%u]: ",
1745 tvbuf.buf,
1746 state.hostname,
1747 state.prog_name,
Coverity doesn't explicitly say so but the only way this can happen is
if state.hostname is not NUL-terminated within its declared length.
ensure_hostname() and debug_set_hostname() ensure NUL-termination, but
the caching effect of ensure_hostname() probably stops Coverity from
being certain about anything.
Try making Coverity happy by using a precision to limit the number of
characters from hostname that can be used.
Signed-off-by: Martin Schwenke <martin@meltin.net>
Reviewed-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Autobuild-User(master): Martin Schwenke <martins@samba.org>
Autobuild-Date(master): Tue Feb 22 00:17:12 UTC 2022 on sn-devel-184
2022-02-18 04:02:50 +03:00
" %s %.*s %s[%u]: " ,
2021-10-28 11:05:19 +03:00
tvbuf . buf ,
util: CID 1499409: Memory - corruptions (OVERLAPPING_COPY)
This is quite bizarre:
*** CID 1499409: Memory - corruptions (OVERLAPPING_COPY)
/lib/util/debug.c: 1742 in dbghdrclass()
1736 sizeof(tvbuf.buf),
1737 "%ld seconds since the Epoch", (long)t);
1738 }
1739 }
1740
1741 ensure_hostname();
>>> CID 1499409: Memory - corruptions (OVERLAPPING_COPY)
>>> In the call to function "snprintf", the object pointed to by argument "state.hostname" may overlap with the object pointed to by argument "state.header_str".
1742 state.hs_len = snprintf(state.header_str,
1743 sizeof(state.header_str),
1744 "%s %s %s[%u]: ",
1745 tvbuf.buf,
1746 state.hostname,
1747 state.prog_name,
Coverity doesn't explicitly say so but the only way this can happen is
if state.hostname is not NUL-terminated within its declared length.
ensure_hostname() and debug_set_hostname() ensure NUL-termination, but
the caching effect of ensure_hostname() probably stops Coverity from
being certain about anything.
Try making Coverity happy by using a precision to limit the number of
characters from hostname that can be used.
Signed-off-by: Martin Schwenke <martin@meltin.net>
Reviewed-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Autobuild-User(master): Martin Schwenke <martins@samba.org>
Autobuild-Date(master): Tue Feb 22 00:17:12 UTC 2022 on sn-devel-184
2022-02-18 04:02:50 +03:00
( int ) ( sizeof ( state . hostname ) - 1 ) ,
2021-10-28 11:05:19 +03:00
state . hostname ,
state . prog_name ,
( unsigned int ) getpid ( ) ) ;
goto full ;
}
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
2021-10-13 03:42:14 +03:00
state . hs_len = snprintf ( state . header_str ,
sizeof ( state . header_str ) ,
" [%s, %2d " ,
tvbuf . buf ,
level ) ;
2021-10-13 12:40:34 +03:00
if ( state . hs_len > = sizeof ( state . header_str ) - 1 ) {
2014-07-30 13:22:21 +04:00
goto full ;
}
1999-12-13 16:27:58 +03:00
2018-12-13 00:21:57 +03:00
if ( unlikely ( dbgc_config [ cls ] . loglevel > = 10 ) ) {
2014-07-29 19:02:22 +04:00
verbose = true ;
}
2011-11-16 00:50:54 +04:00
2014-07-29 19:09:00 +04:00
if ( verbose | | state . settings . debug_pid ) {
2021-10-13 03:42:14 +03:00
state . hs_len + = snprintf ( state . header_str + state . hs_len ,
sizeof ( state . header_str ) - state . hs_len ,
" , pid=%u " ,
( unsigned int ) getpid ( ) ) ;
2021-10-13 12:40:34 +03:00
if ( state . hs_len > = sizeof ( state . header_str ) - 1 ) {
2014-07-30 13:22:21 +04:00
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 ) {
2021-10-13 03:42:14 +03:00
state . hs_len + = snprintf ( state . header_str + state . hs_len ,
sizeof ( state . header_str ) - state . hs_len ,
" , effective(%u, %u), real(%u, %u) " ,
( unsigned int ) geteuid ( ) ,
( unsigned int ) getegid ( ) ,
( unsigned int ) getuid ( ) ,
( unsigned int ) getgid ( ) ) ;
2021-10-13 12:40:34 +03:00
if ( state . hs_len > = sizeof ( state . header_str ) - 1 ) {
2014-07-30 13:22:21 +04:00
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 ) ) {
2021-10-13 03:42:14 +03:00
state . hs_len + = snprintf ( state . header_str + state . hs_len ,
sizeof ( state . header_str ) - state . hs_len ,
" , class=%s " ,
classname_table [ cls ] ) ;
2022-05-08 22:06:13 +03:00
if ( state . hs_len > = sizeof ( state . header_str ) - 1 ) {
goto full ;
}
2014-07-29 19:02:22 +04:00
}
2011-02-24 08:14:03 +03:00
2022-05-08 22:06:13 +03:00
if ( debug_traceid_get ( ) ! = 0 ) {
state . hs_len + = snprintf ( state . header_str + state . hs_len ,
sizeof ( state . header_str ) - state . hs_len ,
" , traceid=% " PRIu64 ,
debug_traceid_get ( ) ) ;
if ( state . hs_len > = sizeof ( state . header_str ) - 1 ) {
goto full ;
}
2014-07-30 13:22:21 +04:00
}
2022-05-08 22:06:13 +03:00
2022-08-26 12:42:42 +03:00
if ( debug_call_depth > 0 ) {
state . hs_len + = snprintf ( state . header_str + state . hs_len ,
sizeof ( state . header_str ) - state . hs_len ,
" , depth=%zu " ,
debug_call_depth ) ;
if ( state . hs_len > = sizeof ( state . header_str ) - 1 ) {
goto full ;
}
}
2021-10-13 04:06:13 +03:00
state . header_str [ state . hs_len ] = ' ] ' ;
state . hs_len + + ;
if ( state . hs_len < sizeof ( state . header_str ) - 1 ) {
state . header_str [ state . hs_len ] = ' ' ;
state . hs_len + + ;
}
state . header_str [ state . hs_len ] = ' \0 ' ;
2014-07-29 19:31:48 +04:00
if ( ! state . settings . debug_prefix_timestamp ) {
2021-10-13 03:42:14 +03:00
state . hs_len + = snprintf ( state . header_str + state . hs_len ,
sizeof ( state . header_str ) - state . hs_len ,
" %s(%s) \n " ,
location ,
func ) ;
if ( state . hs_len > = sizeof ( state . header_str ) ) {
2014-07-30 13:22:21 +04:00
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 :
2021-10-13 03:42:14 +03:00
/*
* Above code never overflows state . header_str and always
* NUL - terminates correctly . However , state . hs_len can point
* past the end of the buffer to indicate that truncation
* occurred , so fix it if necessary , since state . hs_len is
* expected to be used after return .
*/
if ( state . hs_len > = sizeof ( state . header_str ) ) {
state . hs_len = sizeof ( state . header_str ) - 1 ;
}
2021-09-23 11:13:30 +03:00
state . header_str_no_nl [ 0 ] = ' \0 ' ;
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 ;
}
2022-05-08 22:06:13 +03:00
static uint64_t debug_traceid = 0 ;
uint64_t debug_traceid_set ( uint64_t id )
{
2022-06-10 16:35:53 +03:00
uint64_t old_id = debug_traceid ;
debug_traceid = id ;
return old_id ;
2022-05-08 22:06:13 +03:00
}
uint64_t debug_traceid_get ( void )
{
2022-06-10 16:35:53 +03:00
return debug_traceid ;
2022-05-08 22:06:13 +03:00
}