2008-01-16 14:03:01 +03:00
/*
ctdb logging code
Copyright ( C ) Andrew Tridgell 2008
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 3 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , see < http : //www.gnu.org/licenses/>.
*/
# include "includes.h"
2010-05-20 09:48:30 +04:00
# include "../include/ctdb_client.h"
2008-01-16 14:03:01 +03:00
# include "../include/ctdb_private.h"
# include "system/syslog.h"
# include "system/time.h"
# include "system/filesys.h"
2014-08-19 06:15:31 +04:00
# include "lib/util/debug.h"
2008-01-16 14:03:01 +03:00
2009-10-30 10:53:17 +03:00
struct syslog_message {
uint32_t level ;
uint32_t len ;
char message [ 1 ] ;
} ;
2009-11-16 07:17:32 +03:00
struct ctdb_syslog_state {
int syslog_fd ;
int fd [ 2 ] ;
} ;
static int syslogd_is_started = 0 ;
/* called when child is finished
* this is for the syslog daemon , we can not use DEBUG here
*/
static void ctdb_syslog_handler ( struct event_context * ev , struct fd_event * fde ,
uint16_t flags , void * p )
{
struct ctdb_syslog_state * state = talloc_get_type ( p , struct ctdb_syslog_state ) ;
int count ;
char str [ 65536 ] ;
struct syslog_message * msg ;
if ( state = = NULL ) {
return ;
}
count = recv ( state - > syslog_fd , str , sizeof ( str ) , 0 ) ;
if ( count < sizeof ( struct syslog_message ) ) {
return ;
}
msg = ( struct syslog_message * ) str ;
2013-11-11 05:39:27 +04:00
if ( msg - > len > = ( sizeof ( str ) - offsetof ( struct syslog_message , message ) ) ) {
msg - > len = ( sizeof ( str ) - 1 ) - offsetof ( struct syslog_message , message ) ;
}
msg - > message [ msg - > len ] = ' \0 ' ;
2009-11-16 07:17:32 +03:00
syslog ( msg - > level , " %s " , msg - > message ) ;
}
2013-04-15 14:50:42 +04:00
/* called when the pipe from the main daemon has closed
2009-11-16 07:17:32 +03:00
* this is for the syslog daemon , we can not use DEBUG here
*/
static void ctdb_syslog_terminate_handler ( struct event_context * ev , struct fd_event * fde ,
uint16_t flags , void * p )
{
syslog ( LOG_ERR , " Shutting down SYSLOG daemon with pid:%d " , ( int ) getpid ( ) ) ;
_exit ( 0 ) ;
}
2009-10-30 10:53:17 +03:00
/*
* this is for the syslog daemon , we can not use DEBUG here
*/
int start_syslog_daemon ( struct ctdb_context * ctdb )
{
struct sockaddr_in syslog_sin ;
2009-11-16 07:17:32 +03:00
struct ctdb_syslog_state * state ;
2010-08-18 03:46:31 +04:00
struct tevent_fd * fde ;
2013-06-17 09:14:53 +04:00
int startup_fd [ 2 ] ;
int ret = - 1 ;
2009-10-30 10:53:17 +03:00
2009-11-16 07:17:32 +03:00
state = talloc ( ctdb , struct ctdb_syslog_state ) ;
CTDB_NO_MEMORY ( ctdb , state ) ;
if ( pipe ( state - > fd ) ! = 0 ) {
printf ( " Failed to create syslog pipe \n " ) ;
talloc_free ( state ) ;
return - 1 ;
}
2013-06-17 09:14:53 +04:00
if ( pipe ( startup_fd ) ! = 0 ) {
printf ( " Failed to create syslog startup pipe \n " ) ;
close ( state - > fd [ 0 ] ) ;
close ( state - > fd [ 1 ] ) ;
talloc_free ( state ) ;
return - 1 ;
}
2011-01-10 05:57:49 +03:00
ctdb - > syslogd_pid = ctdb_fork ( ctdb ) ;
2009-11-16 07:17:32 +03:00
if ( ctdb - > syslogd_pid = = ( pid_t ) - 1 ) {
2009-10-30 10:53:17 +03:00
printf ( " Failed to create syslog child process \n " ) ;
2009-11-16 07:17:32 +03:00
close ( state - > fd [ 0 ] ) ;
close ( state - > fd [ 1 ] ) ;
2013-06-17 09:14:53 +04:00
close ( startup_fd [ 0 ] ) ;
close ( startup_fd [ 1 ] ) ;
2009-11-16 07:17:32 +03:00
talloc_free ( state ) ;
2009-10-30 10:53:17 +03:00
return - 1 ;
}
2009-11-16 07:17:32 +03:00
if ( ctdb - > syslogd_pid ! = 0 ) {
2013-06-17 09:14:53 +04:00
ssize_t n ;
int dummy ;
2009-11-16 07:17:32 +03:00
DEBUG ( DEBUG_ERR , ( " Starting SYSLOG child process with pid:%d \n " , ( int ) ctdb - > syslogd_pid ) ) ;
close ( state - > fd [ 1 ] ) ;
set_close_on_exec ( state - > fd [ 0 ] ) ;
2013-06-17 09:14:53 +04:00
close ( startup_fd [ 1 ] ) ;
2014-07-30 15:03:53 +04:00
n = sys_read ( startup_fd [ 0 ] , & dummy , sizeof ( dummy ) ) ;
2013-06-17 09:14:53 +04:00
close ( startup_fd [ 0 ] ) ;
if ( n < sizeof ( dummy ) ) {
return - 1 ;
}
syslogd_is_started = 1 ;
2009-10-30 10:53:17 +03:00
return 0 ;
}
2010-07-19 13:59:09 +04:00
debug_extra = talloc_asprintf ( NULL , " syslogd: " ) ;
2009-11-17 04:07:10 +03:00
talloc_free ( ctdb - > ev ) ;
ctdb - > ev = event_context_init ( NULL ) ;
2009-11-16 07:17:32 +03:00
syslog ( LOG_ERR , " Starting SYSLOG daemon with pid:%d " , ( int ) getpid ( ) ) ;
2013-07-09 06:32:53 +04:00
ctdb_set_process_name ( " ctdb_syslogd " ) ;
2009-11-16 07:17:32 +03:00
close ( state - > fd [ 0 ] ) ;
2013-06-17 09:14:53 +04:00
close ( startup_fd [ 0 ] ) ;
2009-12-17 15:04:27 +03:00
set_close_on_exec ( state - > fd [ 1 ] ) ;
2013-06-17 09:14:53 +04:00
set_close_on_exec ( startup_fd [ 1 ] ) ;
2010-08-18 03:46:31 +04:00
fde = event_add_fd ( ctdb - > ev , state , state - > fd [ 1 ] , EVENT_FD_READ ,
2009-11-16 07:17:32 +03:00
ctdb_syslog_terminate_handler , state ) ;
2010-08-18 03:46:31 +04:00
tevent_fd_set_auto_close ( fde ) ;
2009-11-16 07:17:32 +03:00
state - > syslog_fd = socket ( AF_INET , SOCK_DGRAM , IPPROTO_UDP ) ;
if ( state - > syslog_fd = = - 1 ) {
2009-10-30 10:53:17 +03:00
printf ( " Failed to create syslog socket \n " ) ;
2013-06-17 09:14:53 +04:00
close ( startup_fd [ 1 ] ) ;
return ret ;
2009-10-30 10:53:17 +03:00
}
2009-12-17 15:04:27 +03:00
set_close_on_exec ( state - > syslog_fd ) ;
2009-10-30 10:53:17 +03:00
syslog_sin . sin_family = AF_INET ;
syslog_sin . sin_port = htons ( CTDB_PORT ) ;
syslog_sin . sin_addr . s_addr = htonl ( INADDR_LOOPBACK ) ;
2011-11-25 19:40:52 +04:00
if ( bind ( state - > syslog_fd , ( struct sockaddr * ) & syslog_sin ,
sizeof ( syslog_sin ) ) = = - 1 )
{
2009-10-30 10:53:17 +03:00
printf ( " syslog daemon failed to bind to socket. errno:%d(%s) \n " , errno , strerror ( errno ) ) ;
2013-06-17 09:14:53 +04:00
close ( startup_fd [ 1 ] ) ;
2009-10-30 10:53:17 +03:00
_exit ( 10 ) ;
}
2010-08-18 03:46:31 +04:00
fde = event_add_fd ( ctdb - > ev , state , state - > syslog_fd , EVENT_FD_READ ,
2009-11-16 07:17:32 +03:00
ctdb_syslog_handler , state ) ;
2010-08-18 03:46:31 +04:00
tevent_fd_set_auto_close ( fde ) ;
2009-10-30 10:53:17 +03:00
2013-06-17 09:14:53 +04:00
/* Tell parent that we're up */
ret = 0 ;
2014-07-30 15:03:53 +04:00
sys_write ( startup_fd [ 1 ] , & ret , sizeof ( ret ) ) ;
2013-06-17 09:14:53 +04:00
close ( startup_fd [ 1 ] ) ;
2009-11-16 07:17:32 +03:00
event_loop_wait ( ctdb - > ev ) ;
/* this should not happen */
2009-10-30 10:53:17 +03:00
_exit ( 10 ) ;
}
2008-01-16 14:03:01 +03:00
struct ctdb_log_state {
2011-08-26 03:39:25 +04:00
const char * prefix ;
2008-01-16 14:03:01 +03:00
int fd , pfd ;
char buf [ 1024 ] ;
uint16_t buf_used ;
bool use_syslog ;
2009-12-08 05:14:30 +03:00
void ( * logfn ) ( const char * , uint16_t , void * ) ;
void * logfn_private ;
2008-01-16 14:03:01 +03:00
} ;
2009-09-15 13:33:35 +04:00
/* we need this global to keep the DEBUG() syntax */
2008-01-16 14:03:01 +03:00
static struct ctdb_log_state * log_state ;
/*
syslog logging function
*/
2014-08-19 06:15:31 +04:00
static void ctdb_syslog_log ( void * private_ptr , int dbglevel , const char * s )
2008-01-16 14:03:01 +03:00
{
2009-10-30 10:53:17 +03:00
struct syslog_message * msg ;
2008-02-04 09:44:24 +03:00
int level = LOG_DEBUG ;
2014-08-19 06:15:31 +04:00
int len ;
2009-10-30 10:53:17 +03:00
int syslog_fd ;
struct sockaddr_in syslog_sin ;
2014-08-19 06:15:31 +04:00
switch ( dbglevel ) {
2008-02-04 09:44:24 +03:00
case DEBUG_ERR :
level = LOG_ERR ;
break ;
case DEBUG_WARNING :
level = LOG_WARNING ;
break ;
case DEBUG_NOTICE :
level = LOG_NOTICE ;
break ;
case DEBUG_INFO :
level = LOG_INFO ;
break ;
default :
level = LOG_DEBUG ;
break ;
}
2009-10-30 10:53:17 +03:00
2010-07-19 13:59:09 +04:00
len = offsetof ( struct syslog_message , message ) + strlen ( debug_extra ) + strlen ( s ) + 1 ;
2009-10-30 10:53:17 +03:00
msg = malloc ( len ) ;
if ( msg = = NULL ) {
return ;
}
msg - > level = level ;
2010-07-19 13:59:09 +04:00
msg - > len = strlen ( debug_extra ) + strlen ( s ) ;
strcpy ( msg - > message , debug_extra ) ;
strcat ( msg - > message , s ) ;
2009-10-30 10:53:17 +03:00
2009-10-30 11:39:11 +03:00
if ( syslogd_is_started = = 0 ) {
syslog ( msg - > level , " %s " , msg - > message ) ;
} else {
syslog_fd = socket ( AF_INET , SOCK_DGRAM , IPPROTO_UDP ) ;
if ( syslog_fd = = - 1 ) {
printf ( " Failed to create syslog socket \n " ) ;
free ( msg ) ;
return ;
}
2009-10-30 10:53:17 +03:00
2009-10-30 11:39:11 +03:00
syslog_sin . sin_family = AF_INET ;
syslog_sin . sin_port = htons ( CTDB_PORT ) ;
2011-11-25 19:41:59 +04:00
syslog_sin . sin_addr . s_addr = htonl ( INADDR_LOOPBACK ) ;
2009-10-30 11:39:11 +03:00
2014-08-19 06:15:31 +04:00
( void ) sendto ( syslog_fd , msg , len , 0 ,
( struct sockaddr * ) & syslog_sin ,
sizeof ( syslog_sin ) ) ;
2009-10-30 11:39:11 +03:00
/* no point in checking here since we cant log an error */
2009-10-30 10:53:17 +03:00
2009-10-30 11:39:11 +03:00
close ( syslog_fd ) ;
}
2009-10-30 10:53:17 +03:00
free ( msg ) ;
2008-01-16 14:03:01 +03:00
}
/*
log file logging function
*/
2014-08-19 06:15:31 +04:00
static void ctdb_logfile_log ( void * private_ptr , int dbglevel , const char * s )
2008-01-16 14:03:01 +03:00
{
struct timeval t ;
struct tm * tm ;
char tbuf [ 100 ] ;
2008-01-29 06:31:51 +03:00
char * s2 = NULL ;
2009-05-20 14:08:13 +04:00
int ret ;
2008-01-16 14:03:01 +03:00
t = timeval_current ( ) ;
tm = localtime ( & t . tv_sec ) ;
strftime ( tbuf , sizeof ( tbuf ) - 1 , " %Y/%m/%d %H:%M:%S " , tm ) ;
2014-10-15 13:04:45 +04:00
ret = asprintf ( & s2 , " %s.%06u [%s%5u]: %s \n " ,
2010-07-19 13:59:09 +04:00
tbuf , ( unsigned ) t . tv_usec ,
debug_extra , ( unsigned ) getpid ( ) , s ) ;
2009-05-20 14:08:13 +04:00
if ( ret = = - 1 ) {
2009-05-21 05:49:16 +04:00
const char * errstr = " asprintf failed \n " ;
2014-07-30 15:03:53 +04:00
sys_write ( log_state - > fd , errstr , strlen ( errstr ) ) ;
2009-05-20 14:08:13 +04:00
return ;
}
2008-01-29 06:31:51 +03:00
if ( s2 ) {
2014-07-30 15:03:53 +04:00
sys_write ( log_state - > fd , s2 , strlen ( s2 ) ) ;
2009-05-20 14:08:13 +04:00
free ( s2 ) ;
2008-01-29 06:31:51 +03:00
}
2008-01-16 14:03:01 +03:00
}
/*
choose the logfile location
*/
2014-10-16 13:03:51 +04:00
int ctdb_set_logfile ( TALLOC_CTX * mem_ctx , const char * logfile , bool use_syslog )
2008-01-16 14:03:01 +03:00
{
2014-08-19 06:15:31 +04:00
debug_callback_fn callback ;
2009-05-20 14:08:13 +04:00
int ret ;
2009-10-30 10:53:17 +03:00
2014-10-16 13:03:51 +04:00
log_state = talloc_zero ( mem_ctx , struct ctdb_log_state ) ;
2014-08-08 05:50:37 +04:00
if ( log_state = = NULL ) {
2009-05-20 13:47:34 +04:00
printf ( " talloc_zero failed \n " ) ;
abort ( ) ;
}
2008-01-16 14:03:01 +03:00
if ( use_syslog ) {
2014-08-19 06:15:31 +04:00
callback = ctdb_syslog_log ;
2014-08-08 05:50:37 +04:00
log_state - > use_syslog = true ;
2008-01-16 14:03:01 +03:00
} else if ( logfile = = NULL | | strcmp ( logfile , " - " ) = = 0 ) {
2014-08-19 06:15:31 +04:00
callback = ctdb_logfile_log ;
2014-08-08 05:50:37 +04:00
log_state - > fd = 1 ;
2008-01-16 14:03:01 +03:00
/* also catch stderr of subcommands to stdout */
2009-05-20 14:08:13 +04:00
ret = dup2 ( 1 , 2 ) ;
if ( ret = = - 1 ) {
printf ( " dup2 failed: %s \n " , strerror ( errno ) ) ;
abort ( ) ;
}
2008-01-16 14:03:01 +03:00
} else {
2014-08-19 06:15:31 +04:00
callback = ctdb_logfile_log ;
2008-01-16 14:03:01 +03:00
2014-08-08 05:50:37 +04:00
log_state - > fd = open ( logfile , O_WRONLY | O_APPEND | O_CREAT , 0666 ) ;
if ( log_state - > fd = = - 1 ) {
2009-05-20 13:47:34 +04:00
printf ( " Failed to open logfile %s \n " , logfile ) ;
2008-01-16 14:03:01 +03:00
abort ( ) ;
}
}
2014-08-19 06:15:31 +04:00
debug_set_callback ( NULL , callback ) ;
2008-01-16 14:03:01 +03:00
return 0 ;
}
2009-12-08 05:14:30 +03:00
/* Note that do_debug always uses the global log state. */
static void write_to_log ( struct ctdb_log_state * log ,
const char * buf , unsigned int len )
{
2014-09-24 11:12:56 +04:00
if ( script_log_level < = DEBUGLEVEL ) {
2011-08-26 03:39:25 +04:00
if ( log ! = NULL & & log - > prefix ! = NULL ) {
2014-08-19 06:15:31 +04:00
dbgtext ( " %s: %*.*s \n " , log - > prefix , len , len , buf ) ;
2011-08-26 03:39:25 +04:00
} else {
2014-08-19 06:15:31 +04:00
dbgtext ( " %*.*s \n " , len , len , buf ) ;
2011-08-26 03:39:25 +04:00
}
2009-12-08 05:14:30 +03:00
/* log it in the eventsystem as well */
2013-11-11 05:39:27 +04:00
if ( log & & log - > logfn ) {
2009-12-08 05:14:30 +03:00
log - > logfn ( log - > buf , len , log - > logfn_private ) ;
2013-11-11 05:39:27 +04:00
}
2009-12-08 05:14:30 +03:00
}
}
2008-01-16 14:03:01 +03:00
/*
called when log data comes in from a child process
*/
2014-08-08 05:42:51 +04:00
static void ctdb_child_log_handler ( struct event_context * ev ,
struct fd_event * fde ,
uint16_t flags , void * private )
2008-01-16 14:03:01 +03:00
{
2009-12-07 17:01:29 +03:00
struct ctdb_log_state * log = talloc_get_type ( private , struct ctdb_log_state ) ;
2008-01-16 14:03:01 +03:00
char * p ;
2008-07-23 09:25:52 +04:00
int n ;
2008-01-16 14:03:01 +03:00
if ( ! ( flags & EVENT_FD_READ ) ) {
return ;
}
2011-08-26 03:39:25 +04:00
2014-07-30 15:03:53 +04:00
n = sys_read ( log - > pfd , & log - > buf [ log - > buf_used ] ,
2009-12-07 17:01:29 +03:00
sizeof ( log - > buf ) - log - > buf_used ) ;
2008-07-23 09:25:52 +04:00
if ( n > 0 ) {
2009-12-07 17:01:29 +03:00
log - > buf_used + = n ;
2009-12-15 02:23:58 +03:00
} else if ( n = = 0 ) {
2009-12-15 11:04:52 +03:00
if ( log ! = log_state ) {
talloc_free ( log ) ;
}
2009-12-15 02:23:58 +03:00
return ;
2008-01-16 14:03:01 +03:00
}
2009-12-07 17:01:29 +03:00
while ( log - > buf_used > 0 & &
( p = memchr ( log - > buf , ' \n ' , log - > buf_used ) ) ! = NULL ) {
int n1 = ( p - log - > buf ) + 1 ;
2008-07-23 09:25:52 +04:00
int n2 = n1 - 1 ;
/* swallow \r from child processes */
2009-12-07 17:01:29 +03:00
if ( n2 > 0 & & log - > buf [ n2 - 1 ] = = ' \r ' ) {
2008-07-23 09:25:52 +04:00
n2 - - ;
2008-01-16 15:06:37 +03:00
}
2009-12-08 05:14:30 +03:00
write_to_log ( log , log - > buf , n2 ) ;
2009-12-07 17:01:29 +03:00
memmove ( log - > buf , p + 1 , sizeof ( log - > buf ) - n1 ) ;
log - > buf_used - = n1 ;
2008-01-16 14:03:01 +03:00
}
2008-07-23 09:25:52 +04:00
/* the buffer could have completely filled - unfortunately we have
no choice but to dump it out straight away */
2009-12-07 17:01:29 +03:00
if ( log - > buf_used = = sizeof ( log - > buf ) ) {
2009-12-08 05:14:30 +03:00
write_to_log ( log , log - > buf , log - > buf_used ) ;
2009-12-07 17:01:29 +03:00
log - > buf_used = 0 ;
2008-01-16 14:40:01 +03:00
}
2008-01-16 14:03:01 +03:00
}
2009-12-08 05:14:30 +03:00
static int log_context_destructor ( struct ctdb_log_state * log )
{
/* Flush buffer in case it wasn't \n-terminated. */
if ( log - > buf_used > 0 ) {
write_to_log ( log , log - > buf , log - > buf_used ) ;
}
return 0 ;
}
2013-12-16 08:39:29 +04:00
/*
* vfork + exec , redirecting child output to logging and specified callback .
*/
struct ctdb_log_state * ctdb_vfork_with_logging ( TALLOC_CTX * mem_ctx ,
struct ctdb_context * ctdb ,
const char * log_prefix ,
const char * helper ,
int helper_argc ,
const char * * helper_argv ,
void ( * logfn ) ( const char * , uint16_t , void * ) ,
void * logfn_private , pid_t * pid )
{
int p [ 2 ] ;
struct ctdb_log_state * log ;
struct tevent_fd * fde ;
char * * argv ;
int i ;
log = talloc_zero ( mem_ctx , struct ctdb_log_state ) ;
CTDB_NO_MEMORY_NULL ( ctdb , log ) ;
log - > prefix = log_prefix ;
log - > logfn = logfn ;
log - > logfn_private = logfn_private ;
if ( pipe ( p ) ! = 0 ) {
DEBUG ( DEBUG_ERR , ( __location__ " Failed to setup pipe for child logging \n " ) ) ;
goto free_log ;
}
argv = talloc_array ( mem_ctx , char * , helper_argc + 2 ) ;
if ( argv = = NULL ) {
DEBUG ( DEBUG_ERR , ( __location__ " Failed to allocate memory for helper \n " ) ) ;
goto free_log ;
}
argv [ 0 ] = discard_const ( helper ) ;
argv [ 1 ] = talloc_asprintf ( argv , " %d " , p [ 1 ] ) ;
if ( argv [ 1 ] = = NULL ) {
DEBUG ( DEBUG_ERR , ( __location__ " Failed to allocate memory for helper \n " ) ) ;
talloc_free ( argv ) ;
goto free_log ;
}
for ( i = 0 ; i < helper_argc ; i + + ) {
argv [ i + 2 ] = discard_const ( helper_argv [ i ] ) ;
}
* pid = vfork ( ) ;
if ( * pid = = 0 ) {
execv ( helper , argv ) ;
_exit ( 1 ) ;
}
close ( p [ 1 ] ) ;
if ( * pid < 0 ) {
DEBUG ( DEBUG_ERR , ( __location__ " vfork failed for helper process \n " ) ) ;
close ( p [ 0 ] ) ;
goto free_log ;
}
ctdb_track_child ( ctdb , * pid ) ;
log - > pfd = p [ 0 ] ;
set_close_on_exec ( log - > pfd ) ;
talloc_set_destructor ( log , log_context_destructor ) ;
fde = tevent_add_fd ( ctdb - > ev , log , log - > pfd , EVENT_FD_READ ,
2014-08-08 05:42:51 +04:00
ctdb_child_log_handler , log ) ;
2013-12-16 08:39:29 +04:00
tevent_fd_set_auto_close ( fde ) ;
return log ;
free_log :
talloc_free ( log ) ;
return NULL ;
}
2008-01-16 14:03:01 +03:00
/*
setup for logging of child process stdout
*/
int ctdb_set_child_logging ( struct ctdb_context * ctdb )
{
int p [ 2 ] ;
2010-01-07 15:29:09 +03:00
int old_stdout , old_stderr ;
2010-08-18 03:46:31 +04:00
struct tevent_fd * fde ;
2008-01-16 14:03:01 +03:00
2014-08-08 05:50:37 +04:00
if ( log_state - > fd = = STDOUT_FILENO ) {
2008-01-16 14:03:01 +03:00
/* not needed for stdout logging */
return 0 ;
}
/* setup a pipe to catch IO from subprocesses */
if ( pipe ( p ) ! = 0 ) {
2008-02-04 12:07:15 +03:00
DEBUG ( DEBUG_ERR , ( __location__ " Failed to setup for child logging pipe \n " ) ) ;
2008-01-16 14:03:01 +03:00
return - 1 ;
}
2010-01-07 15:29:09 +03:00
/* We'll fail if stderr/stdout not already open; it's simpler. */
old_stdout = dup ( STDOUT_FILENO ) ;
old_stderr = dup ( STDERR_FILENO ) ;
2011-08-10 19:53:56 +04:00
if ( old_stdout < 0 | | old_stderr < 0 ) {
DEBUG ( DEBUG_ERR , ( " Failed to dup stdout/stderr for child logging \n " ) ) ;
return - 1 ;
}
2010-01-07 15:29:09 +03:00
if ( dup2 ( p [ 1 ] , STDOUT_FILENO ) < 0 | | dup2 ( p [ 1 ] , STDERR_FILENO ) < 0 ) {
int saved_errno = errno ;
dup2 ( old_stdout , STDOUT_FILENO ) ;
dup2 ( old_stderr , STDERR_FILENO ) ;
close ( old_stdout ) ;
close ( old_stderr ) ;
close ( p [ 0 ] ) ;
close ( p [ 1 ] ) ;
errno = saved_errno ;
printf ( __location__ " dup2 failed: %s \n " ,
strerror ( errno ) ) ;
return - 1 ;
}
close ( p [ 1 ] ) ;
close ( old_stdout ) ;
close ( old_stderr ) ;
2014-08-08 05:50:37 +04:00
fde = event_add_fd ( ctdb - > ev , log_state , p [ 0 ] ,
EVENT_FD_READ , ctdb_child_log_handler , log_state ) ;
2010-08-18 03:46:31 +04:00
tevent_fd_set_auto_close ( fde ) ;
2014-08-08 05:50:37 +04:00
log_state - > pfd = p [ 0 ] ;
2008-01-16 14:03:01 +03:00
2010-02-03 22:37:41 +03:00
DEBUG ( DEBUG_DEBUG , ( __location__ " Created PIPE FD:%d for logging \n " , p [ 0 ] ) ) ;
2009-10-15 04:24:54 +04:00
2008-01-16 14:03:01 +03:00
return 0 ;
}
2009-11-18 04:44:18 +03:00
2010-09-22 04:59:01 +04:00
/*
* set up a log handler to catch logging from TEVENT
*/
static void ctdb_tevent_logging ( void * private_data ,
enum tevent_debug_level level ,
const char * fmt ,
va_list ap )
{
2012-09-28 03:39:12 +04:00
enum debug_level lvl = DEBUG_CRIT ;
2010-09-22 04:59:01 +04:00
switch ( level ) {
case TEVENT_DEBUG_FATAL :
2012-09-28 03:39:12 +04:00
lvl = DEBUG_CRIT ;
2010-09-22 04:59:01 +04:00
break ;
case TEVENT_DEBUG_ERROR :
lvl = DEBUG_ERR ;
break ;
case TEVENT_DEBUG_WARNING :
lvl = DEBUG_WARNING ;
break ;
case TEVENT_DEBUG_TRACE :
lvl = DEBUG_DEBUG ;
break ;
}
2014-09-24 11:12:56 +04:00
if ( lvl < = DEBUGLEVEL ) {
2014-08-19 06:15:31 +04:00
dbgtext ( fmt , ap ) ;
2010-09-22 04:59:01 +04:00
}
}
int ctdb_init_tevent_logging ( struct ctdb_context * ctdb )
{
int ret ;
ret = tevent_set_debug ( ctdb - > ev ,
ctdb_tevent_logging ,
ctdb ) ;
return ret ;
}