2013-12-16 15:40:01 +11:00
/*
ctdb event script helper
Copyright ( C ) Amitay Isaacs 2013
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/>.
*/
2015-10-26 16:50:46 +11:00
# include "replace.h"
2013-12-16 15:40:01 +11:00
# include "system/filesys.h"
2015-10-26 16:50:46 +11:00
# include "system/network.h"
# include "system/wait.h"
# include <talloc.h>
2014-06-06 16:46:15 +10:00
# include "ctdb_private.h"
2015-10-26 16:50:46 +11:00
2015-10-23 14:11:53 +11:00
# include "common/system.h"
2013-12-16 15:40:01 +11:00
static char * progname = NULL ;
/* CTDB sends SIGTERM, when process must die */
static void sigterm ( int sig )
{
pid_t pid ;
/* all the child processes are running in the same process group */
pid = getpgrp ( ) ;
if ( pid = = - 1 ) {
kill ( - getpid ( ) , SIGKILL ) ;
} else {
kill ( - pid , SIGKILL ) ;
}
_exit ( 0 ) ;
}
static int check_executable ( const char * path )
{
struct stat st ;
if ( stat ( path , & st ) ! = 0 ) {
fprintf ( stderr , " Failed to access '%s' - %s \n " ,
path , strerror ( errno ) ) ;
return errno ;
}
if ( ! ( st . st_mode & S_IXUSR ) ) {
return ENOEXEC ;
}
return 0 ;
}
static void usage ( void )
{
fprintf ( stderr , " \n " ) ;
fprintf ( stderr , " Usage: %s <log-fd> <output-fd> <script_path> <event> [<args>] \n " ,
progname ) ;
}
int main ( int argc , char * argv [ ] )
{
int log_fd , write_fd ;
pid_t pid ;
2014-11-13 11:02:26 +11:00
int status , output , ret ;
2013-12-16 15:40:01 +11:00
progname = argv [ 0 ] ;
if ( argc < 5 ) {
usage ( ) ;
exit ( 1 ) ;
}
2014-06-06 16:49:13 +10:00
reset_scheduler ( ) ;
2013-12-16 15:40:01 +11:00
log_fd = atoi ( argv [ 1 ] ) ;
write_fd = atoi ( argv [ 2 ] ) ;
set_close_on_exec ( write_fd ) ;
close ( STDOUT_FILENO ) ;
close ( STDERR_FILENO ) ;
dup2 ( log_fd , STDOUT_FILENO ) ;
dup2 ( log_fd , STDERR_FILENO ) ;
close ( log_fd ) ;
if ( setpgid ( 0 , 0 ) ! = 0 ) {
fprintf ( stderr , " Failed to create process group for event script - %s \n " ,
strerror ( errno ) ) ;
exit ( 1 ) ;
}
signal ( SIGTERM , sigterm ) ;
pid = fork ( ) ;
if ( pid < 0 ) {
2014-11-13 11:02:26 +11:00
int save_errno = errno ;
2013-12-16 15:40:01 +11:00
fprintf ( stderr , " Failed to fork - %s \n " , strerror ( errno ) ) ;
2014-11-13 11:02:26 +11:00
sys_write ( write_fd , & save_errno , sizeof ( save_errno ) ) ;
exit ( 1 ) ;
2013-12-16 15:40:01 +11:00
}
if ( pid = = 0 ) {
2014-11-13 11:02:26 +11:00
ret = check_executable ( argv [ 3 ] ) ;
if ( ret ! = 0 ) {
_exit ( ret ) ;
}
ret = execv ( argv [ 3 ] , & argv [ 3 ] ) ;
if ( ret ! = 0 ) {
int save_errno = errno ;
2013-12-16 15:40:01 +11:00
fprintf ( stderr , " Error executing '%s' - %s \n " ,
2014-11-13 11:02:26 +11:00
argv [ 3 ] , strerror ( save_errno ) ) ;
2013-12-16 15:40:01 +11:00
}
2014-11-13 11:02:26 +11:00
/* This should never happen */
_exit ( ENOEXEC ) ;
2013-12-16 15:40:01 +11:00
}
2014-11-13 11:02:26 +11:00
ret = waitpid ( pid , & status , 0 ) ;
if ( ret = = - 1 ) {
output = - errno ;
fprintf ( stderr , " waitpid() failed - %s \n " , strerror ( errno ) ) ;
sys_write ( write_fd , & output , sizeof ( output ) ) ;
exit ( 1 ) ;
}
2013-12-16 15:40:01 +11:00
if ( WIFEXITED ( status ) ) {
2015-07-21 16:37:04 +10:00
output = WEXITSTATUS ( status ) ;
/* Only errors should be returned as -ve values */
if ( output = = ENOENT | | output = = ENOEXEC ) {
output = - output ;
}
2014-11-13 11:02:26 +11:00
sys_write ( write_fd , & output , sizeof ( output ) ) ;
exit ( 0 ) ;
}
if ( WIFSIGNALED ( status ) ) {
output = - EINTR ;
fprintf ( stderr , " Process terminated with signal - %d \n " ,
WTERMSIG ( status ) ) ;
2014-07-30 21:03:53 +10:00
sys_write ( write_fd , & output , sizeof ( output ) ) ;
2014-11-13 11:02:26 +11:00
exit ( 0 ) ;
2013-12-16 15:40:01 +11:00
}
2014-11-13 11:02:26 +11:00
fprintf ( stderr , " waitpid() status=%d \n " , status ) ;
2013-12-16 15:40:01 +11:00
exit ( 1 ) ;
}