2014-01-05 22:58:00 +00:00
# define CD_MAIN
# include "ausreg-cd.h"
# include <stdio.h>
# include <fcntl.h>
# include <signal.h>
# include <unistd.h>
2014-01-13 01:29:22 +00:00
bool cdHasTk ;
2014-01-18 20:35:18 +00:00
const char * cdOrTk = NULL ;
2014-01-05 22:58:00 +00:00
using namespace std ;
/*
* This is the shell for the Unix Client Server ( Cliever ) daemon .
2014-01-11 03:01:32 +00:00
* In this design , this " cliever " is more client than server and
* the main arch has the md as the thing the secondary name provder
* is using to talk to primary providers .
*
* It also contains a CLI for sending commands used in OTE testing
* to verify the EPP directives . This ruby swig binding of this
* is behind the final OTE test harness .
2014-01-05 22:58:00 +00:00
*
*/
void runCommander ( ) ;
void setSignals ( ) ;
void signal_handler ( int ) ;
void usage ( ) ;
using namespace boost : : interprocess ;
using namespace std ;
2014-01-17 17:26:02 +00:00
//RAII constructor/destructor
struct shm_remove
{
shm_remove ( ) { shared_memory_object : : remove ( " ausreg-cd-global " ) ; }
~ shm_remove ( ) { shared_memory_object : : remove ( " ausreg-cd-global " ) ; }
} remover ;
shared_memory_object shm ( create_only , " ausreg-cd-global " , read_write ) ;
2014-01-11 02:22:40 +00:00
void acClientServer ( ) { // AKA "Cliever"
2014-01-05 22:58:00 +00:00
int i , lfp ;
char str [ 10 ] ;
thisConfig - > daemonProcess = fork ( ) ;
if ( thisConfig - > daemonProcess < 0 ) {
puts ( " Can't initialize process! " ) ;
exit ( 1 ) ;
}
if ( thisConfig - > runCommander & & getpid ( ) = = thisConfig - > shellProcess )
{ setSignals ( ) ; runCommander ( ) ; }
setsid ( ) ; /* obtain a new process group */
i = open ( " /dev/null " , O_RDWR ) ; dup ( i ) ; dup ( i ) ; /* handle standard I/O */
umask ( 027 ) ; /* set newly created file permissions */
chdir ( RUNNING_DIR ) ; /* change running directory */
lfp = open ( CD_LOCK_FILE , O_RDWR | O_CREAT , 0640 ) ;
if ( lfp < 0 ) { puts ( " Can't open lockfile! " ) ; exit ( 1 ) ; }
if ( lockf ( lfp , F_TLOCK , 0 ) < 0 )
{ puts ( " Can't lock lockfile! " ) ; exit ( 0 ) ; }
2014-01-11 19:34:15 +00:00
shared_memory_object shm ( open_only , " ausreg-cd-global " , read_write ) ;
2014-01-11 02:22:40 +00:00
mapped_region acCDglobal ( shm , read_write ) ;
gm = ( ac_cd_global * ) acCDglobal . get_address ( ) ;
2014-01-11 19:34:15 +00:00
if ( strcmp ( gm - > id , " ausreg-cd " ) ) // Same deal
2014-01-05 22:58:00 +00:00
{ theseLogs . logN ( 0 , " Daemon couldn't identify global memory. Bye. " ) ; exit ( 1 ) ; }
gm - > daemon_pid = getpid ( ) ;
sprintf ( str , " %d " , getpid ( ) ) ;
2014-01-11 19:34:15 +00:00
theseLogs . logN ( 1 , " ausreg-cd running (%s) " , str ) ;
2014-01-05 22:58:00 +00:00
strcat ( str , " \n " ) ;
write ( lfp , str , strlen ( str ) ) ; /* record pid to lockfile */
setSignals ( ) ;
2014-01-11 19:34:15 +00:00
theseLogs . init ( " ausreg-cd " ) ;
2014-01-05 22:58:00 +00:00
theseLogs . logN ( 0 , CD_NAME " " CD_VERSION " compiled on " __DATE__ " @ " __TIME__ ) ;
theseLogs . logN ( 3 , " Cliever processing(%d) begins for devices on port %s to MD at %s. " , getpid ( ) , thisConfig - > telemetryPortStr . c_str ( ) , thisConfig - > mdAddress . c_str ( ) ) ;
try {
boost : : thread cliever ( runCliever ) ;
2014-01-11 19:34:15 +00:00
boost : : thread apiLayer ( runAPILayer ) ;
2014-01-05 22:58:00 +00:00
2014-01-13 01:29:22 +00:00
# ifdef XMLRPC_C
2014-01-11 21:55:55 +00:00
xmlrpc_c : : serverAbyss myAbyssServer (
thisConfig - > api_registry ,
thisConfig - > xmlrpcPort ,
thisConfig - > xmlrpcLogpath
) ;
# endif
2014-01-11 19:34:15 +00:00
if ( ! apiLayer . joinable ( ) | | ! cliever . joinable ( ) ) {
if ( ! apiLayer . joinable ( ) )
theseLogs . logN ( 0 , " Failed to start API layer, ausred-cd process will terminate. " ) ;
2014-01-05 22:58:00 +00:00
if ( ! cliever . joinable ( ) )
2014-01-11 19:34:15 +00:00
theseLogs . logN ( 0 , " Failed to start client-server, ausureg-cd process will terminate. " ) ;
2014-01-05 22:58:00 +00:00
}
else {
theseLogs . logN ( 0 , " Cliever started OK. " ) ;
2014-01-13 01:29:22 +00:00
# ifdef XMLRPC_C
2014-01-11 21:55:55 +00:00
theseLogs - > logN ( 2 , " %s %d " , " Accepting XMLRPC API Requests on Port " , thisConfig - > xmlrpcPort ) ;
myAbyssServer . run ( ) ;
# endif
apiLayer . join ( ) ;
2014-01-11 19:34:15 +00:00
theseLogs . logN ( 0 , " ausreg-cd EOJ. " ) ;
2014-01-05 22:58:00 +00:00
}
}
catch ( std : : exception & e )
{
theseLogs . logN ( 1 , " Exception: %s " , e . what ( ) ) ;
}
catch ( . . . ) {
theseLogs . logN ( 0 , " General fault. " ) ;
}
exit ( thisCliever - > rc ) ;
}
int main ( int const argc , const char * * const argv )
{
2014-01-18 20:35:18 +00:00
bool noParms = false ;
2014-01-05 22:58:00 +00:00
const char * exeName , * banner = " \n " CD_NAME " " CD_VERSION " compiled on " __DATE__ " @ " __TIME__ " (%d) \n " ;
2014-01-18 20:35:18 +00:00
int mthParm = 2 , rc = OK ;
2014-01-05 22:58:00 +00:00
thisCliever = NULL ;
2014-01-18 20:35:18 +00:00
cdOrTk = argv [ 0 ] ;
cdHasTk = strstr ( cdOrTk , " ausreg-cd " ) ? true : false ;
2014-01-05 22:58:00 +00:00
shm . truncate ( CD_GLOBAL_SIZE ) ;
2014-01-11 02:22:40 +00:00
mapped_region acCDglobal ( shm , read_write ) ;
memset ( acCDglobal . get_address ( ) , 0 , acCDglobal . get_size ( ) ) ;
gm = ( ac_cd_global * ) acCDglobal . get_address ( ) ;
2014-01-11 19:34:15 +00:00
strcpy ( gm - > id , " ausreg-cd " ) ;
2014-01-14 19:58:27 +00:00
strcmp ( gm - > id , " ausreg-cd " ) ; // Will segfault if there is a problem so catches are futile.
// But the signal trap will catch the fault.
2014-01-05 22:58:00 +00:00
thisConfig = new clientDaemonConfig ( ) ;
thisConfig - > shellProcess = getpid ( ) ;
strcpy ( thisConfig - > origCmd , argv [ 0 ] ) ;
2014-01-18 20:35:18 +00:00
if ( argc < 1 | | argc > 7 ) usage ( ) ;
if ( argc = = 1 | | * argv [ 1 ] = = ' ? ' )
{ noParms = true ;
thisConfig - > telemetryPort = 5000 ;
mthParm = 1 ;
}
else thisConfig - > telemetryPort = atoi ( argv [ 1 ] ) ;
2014-01-05 22:58:00 +00:00
if ( thisConfig - > telemetryPort < 1000 | | thisConfig - > telemetryPort > 65535 )
{
std : : cerr < < " The <telemetry-udp-port> value is invalid. \n " ;
exit ( 1 ) ;
}
2014-01-18 20:35:18 +00:00
if ( argc > 1 ) thisConfig - > telemetryPortStr = std : : string ( argv [ 1 ] ) ;
for ( ; mthParm < argc ; mthParm + + ) {
if ( * argv [ mthParm ] = = ' ? ' ) {
usage ( ) ;
}
else
if ( * argv [ mthParm ] = = ' * ' ) {
2014-01-05 22:58:00 +00:00
thisConfig - > runCommander = false ;
}
else
if ( ! strncmp ( argv [ mthParm ] , " device= " , 7 ) ) {
thisConfig - > deviceName = std : : string ( argv [ mthParm ] + 8 ) ;
}
else
if ( ! strncmp ( argv [ mthParm ] , " logs= " , 4 ) ) {
strcpy ( thisConfig - > logPath , argv [ mthParm ] + 5 ) ;
}
else
if ( ! strncmp ( argv [ mthParm ] , " mdIP= " , 4 ) ) {
thisConfig - > mdAddress = std : : string ( argv [ mthParm ] + 5 ) ;
}
else usage ( ) ;
}
if ( thisConfig - > runCommander ) printf ( banner , thisConfig - > shellProcess ) ;
2014-01-11 02:22:40 +00:00
acClientServer ( ) ;
2014-01-05 22:58:00 +00:00
while ( ! gm - > graceful ) sleep ( 2 ) ;
}
void runCommander ( ) {
char msg [ 128 ] ;
int i ;
mdCommander commander ;
2014-01-11 19:34:15 +00:00
theseLogs . init ( " ausreg-cd-ui " ) ;
2014-01-05 22:58:00 +00:00
theseLogs . logN ( 0 , " Interactive command processor started. " ) ;
commander . driver ( ) ;
if ( thisConfig - > terminateRequest ) {
theseLogs . logN ( 0 , " Interactive shutdown requested. " ) ;
2014-01-11 19:34:15 +00:00
puts ( " ausreg-cd operator issued terminate command. " ) ;
2014-01-05 22:58:00 +00:00
kill ( gm - > daemon_pid , SIGTERM ) ;
} else {
theseLogs . logN ( 0 , " Interactive command processor ended. " ) ;
2014-01-11 19:34:15 +00:00
sprintf ( msg , " Commander terminated, ausreg-cd continues (%d). " , gm - > daemon_pid ) ;
2014-01-05 22:58:00 +00:00
puts ( msg ) ;
}
theseLogs . logN ( 1 , " Closing out I/O for shell process (%d) " , thisConfig - > shellProcess ) ;
for ( i = getdtablesize ( ) ; i > = 0 ; - - i ) close ( i ) ; /* close all descriptors */
exit ( 0 ) ;
}
void setSignals ( ) {
signal ( SIGCHLD , SIG_IGN ) ; /* ignore child */
signal ( SIGTSTP , SIG_IGN ) ; /* ignore tty signals */
signal ( SIGTTOU , SIG_IGN ) ; // both input
signal ( SIGTTIN , SIG_IGN ) ; // and output
signal ( SIGSEGV , signal_handler ) ;
signal ( SIGUSR1 , signal_handler ) ; // commander log messages
signal ( SIGHUP , signal_handler ) ; /* catch hangup signal */
signal ( SIGTERM , signal_handler ) ; /* catch kill signal */
}
void signal_handler ( int sig )
2014-01-13 23:19:10 +00:00
{ int debug = 0 ;
2014-01-05 22:58:00 +00:00
switch ( sig ) {
case SIGSEGV :
2014-01-13 23:19:10 +00:00
debug = 1 ; // for breakpoint
theseLogs . logN ( 0 , " Segfault great that you can see this. " ) ;
2014-01-05 22:58:00 +00:00
break ;
case SIGUSR1 :
break ;
case SIGHUP :
2014-01-11 19:34:15 +00:00
theseLogs . logN ( 0 , " hangup signal caught, currently ausreg-cd ignores this. " ) ;
2014-01-05 22:58:00 +00:00
break ;
case SIGTERM :
2014-01-11 19:34:15 +00:00
theseLogs . logN ( 0 , " terminate signal caught, ausreg-cd will shutdown. " ) ;
2014-01-05 22:58:00 +00:00
cdShutdown termEvent ;
termEvent . send ( ) ;
break ;
}
}
void usage ( ) {
2014-01-18 20:35:18 +00:00
std : : cerr < < " Usage: " < < cdOrTk < < " <udp-port> ['*'] [device=TEST] [mdIP= " MD_DEFAULT_IP " ] [logs= \\ tmp] \n \n where \n \n "
" \t <udp-port> defaults to 5000, must be the first parameter, and must be 1000 or greater. \n "
2014-01-05 22:58:00 +00:00
" \t The other parameters are optional and non-positional and take the shown defaults. \n "
2014-01-14 19:58:27 +00:00
" \t '*', if present, indicates skip the command loop (string quotes may be required). \n \n " ;
2014-01-05 22:58:00 +00:00
exit ( 1 ) ;
}