diff options
author | Alberto Ruiz <alberto.ruiz@sun.com> | 2007-10-30 17:21:07 +0000 |
---|---|---|
committer | Alberto Ruiz <alberto.ruiz@sun.com> | 2007-10-30 17:21:07 +0000 |
commit | aadeffb3f0716ffd231d1146d050847e3be355ee (patch) | |
tree | 9f2ed61a84a37fce5f154498023b28d6bfbf69bf /apocd |
2007-30-10 Alberto Ruiz <alberto.ruiz@sun.com>
* Initial commit.
Diffstat (limited to 'apocd')
-rw-r--r-- | apocd/Makefile.am | 16 | ||||
-rw-r--r-- | apocd/apocd.c | 659 | ||||
-rw-r--r-- | apocd/apocd.h | 97 | ||||
-rw-r--r-- | apocd/config.h.in | 40 | ||||
-rw-r--r-- | apocd/linux.c | 178 | ||||
-rw-r--r-- | apocd/solaris.c | 178 | ||||
-rw-r--r-- | apocd/win32/apocdctl.c | 1393 |
7 files changed, 2561 insertions, 0 deletions
diff --git a/apocd/Makefile.am b/apocd/Makefile.am new file mode 100644 index 0000000..cd07fc2 --- /dev/null +++ b/apocd/Makefile.am @@ -0,0 +1,16 @@ +INCLUDES = \ + -I${top_builddir}/libapoc/ + +apocd_LDADD = ${top_builddir}/libapoc/libapoc.la -lapoc + +bindir = $(APOCD_DIR) +bin_PROGRAMS = apocd + +apocd_SOURCES = apocd.c + +if SOLARIS +apocd_SOURCES += solaris.c +else +apocd_SOURCES += linux.c +endif + diff --git a/apocd/apocd.c b/apocd/apocd.c new file mode 100644 index 0000000..f6c6505 --- /dev/null +++ b/apocd/apocd.c @@ -0,0 +1,659 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either + * the GNU General Public License Version 2 only ("GPL") or + * the Common Development and Distribution License("CDDL") + * (collectively, the "License"). You may not use this file + * except in compliance with the License. You can obtain a copy + * of the License at www.sun.com/CDDL or at COPYRIGHT. See the + * License for the specific language governing permissions and + * limitations under the License. When distributing the software, + * include this License Header Notice in each file and include + * the License file at /legal/license.txt. If applicable, add the + * following below the License Header, with the fields enclosed + * by brackets [] replaced by your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * If you wish your version of this file to be governed by + * only the CDDL or only the GPL Version 2, indicate your + * decision by adding "[Contributor] elects to include this + * software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice + * of license, a recipient has the option to distribute your + * version of this file under either the CDDL, the GPL Version + * 2 or to extend the choice of license to its licensees as + * provided above. However, if you add GPL Version 2 code and + * therefore, elected the GPL Version 2 license, then the + * option applies only if the new code is made subject to such + * option by the copyright holder. + */ + +#include "apocd.h" +#include "config.h" + +#include <papiUtils.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/uio.h> +#include <unistd.h> +#include <netinet/in.h> +#include <netdb.h> + +static int authenticate( PAPISocket inSocket ); +static Status daemonChangeDetect( void ); +static Status daemonReload( void ); +static Status daemonRequest( DaemonOp inOp, int inQuiet ); +static Status daemonRestart( void ); +static Status doOp( DaemonOp inOp ); +static int getDaemonAdminPort( void ); +static int getResponse( int inSocket, char * outResponse ); +static void invalidArg( const char * inArg ); +static Status javaStart( int inWait ); +static void putEnv( void ); +static int sendRequest( int inSocket, const unsigned char * inRequest ); +static DaemonOp stringToDaemonOp( const char * inString ); +static void usage( void ); + +static const char * sArgChangeDetect = "change-detect"; +static const char * sArgDisable = "disable"; +static const char * sArgEnable = "enable"; +static const char * sArgIsEnabled = "is-enabled"; +static const char * sArgReload = "reload"; +static const char * sArgRestart = "restart"; +static const char * sArgStart = "start"; +static const char * sArgStatus = "status"; +static const char * sArgStop = "stop"; +static const char * sArgsvcStart = "svcStart"; +static const char * sArgsvcStop = "svcStop"; + +int main( int inArgc, char ** inArgv ) +{ + Status theRC; + + if ( inArgc == 2 ) + { + DaemonOp theOp = stringToDaemonOp( inArgv[ 1 ] ); + if ( theOp == sOpUndefined ) + { + invalidArg( inArgv[ 1 ] ); + theRC = sErrorInvalidArg; + } + else + { + theRC = doOp( theOp ); + } + } + else + { + usage(); + theRC = sErrorInvalidArg; + } + return theRC; +} + +Status daemonStart( void ) +{ + Status theRC = daemonStatus( 1 ); + writeInitialMessage( sOpStart ); + if ( theRC == sStatusNotRunning ) + { +#ifndef LINUX + theRC = javaStart( 0 ); + if ( theRC == sStatusOK ) + { + theRC = daemonWaitStatus( sStatusOK, 30 ); + } +#else + if ( fork() == 0 ) + { + while ( 1 ) + { + theRC = javaStart( 1 ); + if ( theRC == sStatusOK ) + { + break; + } + if ( osDaemonShouldRestart() == 0 ) + { + theRC = sErrorGeneric; + break; + } + } + return theRC; + } + else + { + theRC = daemonWaitStatus( sStatusOK, 30 ); + } +#endif + } + writeFinalMessage( sOpStart, theRC ); + return theRC; +} + +Status daemonStatus( int inQuiet ) +{ + return daemonRequest( sOpStatus, inQuiet ) == sStatusOK ? + sStatusOK : sStatusNotRunning; +} + +Status daemonStop( void ) +{ + Status theRC; + writeInitialMessage( sOpStop ); + daemonRequest( sOpStop, 1 ); + theRC = + daemonWaitStatus( sStatusNotRunning, 20 ) == sStatusNotRunning ? + sStatusOK : sErrorGeneric; + writeFinalMessage( sOpStop, theRC ); + return theRC; +} + +Status daemonWaitStatus( Status inStatus, int inMaxIterations ) +{ + Status theRC; + int theIteration = 0; + + while ( ( theRC = daemonStatus( 1 ) ) != inStatus && + ++ theIteration <= inMaxIterations ) + { + papiSleep( 1 ); + } + return theRC; +} + +void writeInitialMessage( DaemonOp inOp ) +{ + if ( inOp == sOpChangeDetect ) + { + printf( "Requesting a Configuration Agent change detection ... " ); + } + else if ( inOp == sOpDisable ) + { + printf( "Disabling Configuration Agent ... "); + } + else if ( inOp == sOpEnable ) + { + printf( "Enabling Configuration Agent ... "); + } + else if ( inOp == sOpIsEnabled ) + { + printf( "Checking Configuration Agent enabled status ... " ); + } + else if ( inOp == sOpReload ) + { + printf( "Reloading Configuration Agent ... " ); + } + else if ( inOp == sOpStatus ) + { + printf( "Checking Configuration Agent status ... " ); + } + else if ( inOp == sOpStart ) + { + printf( "Starting Configuration Agent ... " ); + } + else if ( inOp == sOpStop ) + { + printf( "Stopping Configuration Agent ... " ); + } + fflush( stdout ); +} + +void writeAlreadyMessage(DaemonOp inOp) +{ + const char *theMessage = NULL ; + + switch (inOp) { + case sOpStart: + theMessage = "Already started" ; + break ; + case sOpStop: + theMessage = "Already stopped" ; + break ; + case sOpEnable: + theMessage = "Already enabled" ; + break ; + case sOpDisable: + theMessage = "Already disabled" ; + break ; + default: + break ; + } + if (theMessage != NULL) { + printf("%s\n", theMessage) ; + } +} + +void writeFinalMessage( DaemonOp inOp, Status inStatus ) +{ + if ( inStatus == sErrorAuthentication ) + { + printf( "Failed\n" ); + } + else if ( inOp == sOpIsEnabled ) + { + printf( "%s\n", inStatus == sStatusEnabled ? "Enabled" : "Not enabled"); + } + else if ( inOp == sOpStatus ) + { + printf( "%s\n", inStatus == sStatusOK ? "Running" : "Not running" ); + } + else if ( inOp == sOpStop ) + { + printf( inStatus == sStatusOK || inStatus == sErrorNotRunning ? + "OK\n" : "Failed\n" ); + } + else + { + printf( inStatus == sStatusOK ? "OK\n" : "Failed\n" ); + } + fflush( stdout ); +} + +int authenticate( PAPISocket inSocket ) +{ + static int sLocalCredentialsBufferSize = 21; + + int theRC = sErrorAuthentication; + char theChallenge[ BUFSIZ ]; + int theIndex = 0; + + theChallenge[ 0 ] = 0; + while ( recv( inSocket, &theChallenge[ theIndex ++ ], 1, 0 ) != -1 ) + { + if ( theChallenge[ theIndex - 1 ] == 0 ) + { + if ( theChallenge[ 0 ] != 0 ) + { + FILE * theFile = fopen( theChallenge, "r" ); + if ( theFile != 0 ) + { + char * theCredentials = + ( char * )malloc( sLocalCredentialsBufferSize ); + if ( theCredentials != 0 ) + { + if ( fgets( theCredentials, + sLocalCredentialsBufferSize, + theFile ) != 0 ) + { + if ( send( inSocket, + theCredentials, + sLocalCredentialsBufferSize - 1, + 0 ) == ( sLocalCredentialsBufferSize - 1 ) ) + { + char theResponse; + if ( getResponse(inSocket,&theResponse)!= -1 && + theResponse == 0 ) + { + theRC = sStatusOK; + } + } + } + free( ( void * )theCredentials ); + } + fclose( theFile ); + } + } + break; + } + } + return theRC; +} + +Status daemonChangeDetect( void ) +{ + return daemonRequest( sOpChangeDetect, 0 ); +} + +Status daemonReload( void ) +{ + return daemonRequest( sOpReload, 0 ); +} + +Status daemonRequest( DaemonOp inOp, int inQuiet ) +{ + Status theRC = sErrorNotRunning; + PAPISocket theSocket; + PAPIConnectResult theConnectResult = + getConnectedSocket( getDaemonAdminPort(), SOCK_STREAM, 0, &theSocket ); + if ( inQuiet == 0 ) + { + writeInitialMessage( inOp ); + } + if ( theConnectResult == PAPIConnectSuccess ) + { + if ( ( theRC = authenticate( theSocket ) ) == sStatusOK ) + { + unsigned char theOp = ( unsigned char )inOp; + if ( sendRequest( theSocket, &theOp ) != -1 ) + { + char theResponse; + if ( getResponse( theSocket, &theResponse ) == -1 ) + { + theRC = sErrorNotRunning; + } + else if ( theResponse == 0 ) + { + theRC = sStatusOK; + } + else + { + theRC = sErrorGeneric; + } + } + } + papiClose( theSocket ); + } + if ( inQuiet == 0 ) + { + writeFinalMessage( inOp, theRC ); + } + return theRC; +} + +Status daemonRestart( void ) +{ + Status theRC = osDaemonStop(); + if ( theRC == sStatusOK ) + { + theRC = osDaemonStart(); + } + return theRC; +} + +static int checkAlreadyDone(DaemonOp inOp) +{ + int retCode = 0 ; + + switch (inOp) { + case sOpStart: + if (daemonStatus(1) == sStatusRunning) { retCode = 1 ; } + break ; + case sOpStop: + if (daemonStatus(1) == sStatusNotRunning) { retCode = 1 ; } + break ; + case sOpEnable: + if (osDaemonIsEnabled(1) == sStatusEnabled) { retCode = 1 ; } + break ; + case sOpDisable: + if (osDaemonIsEnabled(1) == sStatusNotEnabled) { retCode = 1 ; } + break ; + default: + break ; + } + return retCode ; +} + +Status doOp( DaemonOp inOp ) +{ + Status theStatus = sErrorGeneric; + + if (checkAlreadyDone(inOp)) { + writeInitialMessage(inOp) ; + writeAlreadyMessage(inOp) ; + return sStatusOK ; + } + /* + * Non os specific operations + */ + if ( inOp == sOpChangeDetect ) + { + theStatus = daemonChangeDetect(); + } + else if ( inOp == sOpReload ) + { + theStatus = daemonReload(); + } + else if ( inOp == sOpRestart ) + { + theStatus = daemonRestart(); + } + else if ( inOp == sOpStatus ) + { + theStatus = daemonStatus( 0 ); + } + + /* + * os specific operations + */ + else if ( inOp == sOpDisable ) + { + theStatus = osDaemonDisable(); + } + else if ( inOp == sOpEnable ) + { + theStatus = osDaemonEnable(); + } + else if ( inOp == sOpIsEnabled ) + { + theStatus = osDaemonIsEnabled(0); + } + else if ( inOp == sOpStart ) + { + theStatus = osDaemonStart(); + } + else if ( inOp == sOpStop ) + { + theStatus = osDaemonStop(); + } + else if ( inOp == sOpSvcStart ) + { + theStatus = osDaemonSvcStart(); + } + else if ( inOp == sOpSvcStop ) + { + theStatus = osDaemonSvcStop(); + } + return theStatus; +} + +/* + * 6417539 - Need to use IANA registered port + * + * IANA has registered 3809 for us. We use a udp connection on this port to + * the daemon to ask what port is currently set as the admin port + */ +int getDaemonAdminPort( void ) +{ + static char sByte = 1; + static const char * sLocalHostName = "127.0.0.1"; + + int thePort = -1; + PAPISocket theSocket; + char thePortString[ 6 ]; + struct sockaddr_in theDaemonAddr; + struct hostent * theHostEnt; + int theCount; + + theHostEnt = gethostbyname( sLocalHostName ); + theDaemonAddr.sin_family = AF_INET; + theDaemonAddr.sin_port = htons( getDaemonPort() ); + theDaemonAddr.sin_addr = *( (struct in_addr * )theHostEnt->h_addr ); + memset( ( void * )&( theDaemonAddr.sin_zero ), 0, 8 ); + if ( ( theSocket = socket( AF_INET, SOCK_DGRAM, 0 ) ) != INVALID_SOCKET && + connect( theSocket, + ( struct sockaddr * )&theDaemonAddr, + sizeof( struct sockaddr ) ) == 0 && + send( theSocket, &sByte, 1, 0 ) == 1 && + ( theCount = recv( theSocket, thePortString, 6, 0 ) ) > 1 && + thePortString[ theCount - 1 ] == 0 ) + { + thePort = atoi( thePortString ); + } + papiClose( theSocket ); + return thePort; +} + +int getResponse( int inSocket, char * outResponse ) +{ + return recv( inSocket, + outResponse, + 1, + 0 ); +} + +void invalidArg( const char * inOp ) +{ + if ( inOp != 0 ) + { + fprintf( stderr, "Invalid argument '%s'\n", inOp ); + } + usage(); +} + +Status javaStart( int inWait ) +{ + static char * theFormat = + "java -Djava.library.path=%s%s%s -cp %s%sapocd.jar com.sun.apoc.daemon.apocd.Daemon %s %s"; + static char * theCommand = 0; + Status theRC = sStatusOK; + + putEnv(); + if ( theCommand == 0 ) + { + const char * theDaemonInstallDir = getDaemonInstallDir(); + const char * theDaemonLibraryDir = getDaemonLibraryDir(); + const char * theDaemonPropertiesDir = getDaemonPropertiesDir(); + theCommand = + ( char * )malloc( ( strlen( theDaemonInstallDir ) * 2 ) + + strlen( theDaemonLibraryDir ) + + strlen( PATHSEP ) + + strlen( DBJAVA_LIBDIR ) + + strlen( theDaemonPropertiesDir ) + + strlen( FILESEP ) + + ( strlen( theFormat ) + 6 )); + + if ( theCommand != 0 ) + { + sprintf( theCommand, + theFormat, + theDaemonLibraryDir, PATHSEP, + DBJAVA_LIBDIR, + theDaemonInstallDir, FILESEP, + theDaemonInstallDir, + theDaemonPropertiesDir ); + } + } + if ( theCommand != 0 ) + { + FILE * theStream = papiPopen( theCommand, "r" ); + if ( theStream == 0 ) + { + theRC = sErrorGeneric; + } + else if ( inWait == 1 ) + { + theRC = papiPclose( theStream ) == 0 ? sStatusOK : sErrorGeneric; + } + } + else + { + theRC = sErrorGeneric; + } + return theRC; +} + +void putEnv( void ) +{ + char * theJavaHome = getenv( "JAVA_HOME" ); + + if ( theJavaHome != 0 ) + { + char * theJavaPath = ( char * )malloc( strlen( theJavaHome ) + + 4 + + strlen( FILESEP ) ); + if ( theJavaPath != 0 ) + { + char * thePath = getenv( "PATH" ); + char * theNewPath; + sprintf( theJavaPath, "%s%sbin", theJavaHome, FILESEP ); + theNewPath = ( char * )malloc( strlen( theJavaPath ) + + strlen( PATHSEP ) + + strlen( thePath ) + + 6 ); + if ( theNewPath != 0 ) + { + sprintf( theNewPath, + "PATH=%s%s%s", + theJavaPath, + PATHSEP, + thePath ); + putenv( theNewPath ); + free( ( void * )theJavaPath ); + } + } + } + papiUmask( 022 ); +} + +int sendRequest( int inSocket, + const unsigned char * inRequest ) +{ + return send( inSocket, inRequest, 1, 0 ); +} + +DaemonOp stringToDaemonOp( const char * inString ) +{ + DaemonOp theDaemonOp = sOpUndefined; + if ( strcmp( inString, sArgChangeDetect ) == 0 ) + { + theDaemonOp = sOpChangeDetect; + } + else if ( strcmp( inString, sArgDisable ) == 0 ) + { + theDaemonOp = sOpDisable; + } + else if ( strcmp( inString, sArgEnable ) == 0 ) + { + theDaemonOp = sOpEnable; + } + else if ( strcmp( inString, sArgIsEnabled ) == 0 ) + { + theDaemonOp = sOpIsEnabled; + } + else if ( strcmp( inString, sArgReload ) == 0 ) + { + theDaemonOp = sOpReload; + } + else if ( strcmp( inString, sArgRestart ) == 0 ) + { + theDaemonOp = sOpRestart; + } + else if ( strcmp( inString, sArgStart ) == 0 ) + { + theDaemonOp = sOpStart; + } + else if ( strcmp( inString, sArgStatus ) == 0 ) + { + theDaemonOp = sOpStatus; + } + else if ( strcmp( inString, sArgStop ) == 0 ) + { + theDaemonOp = sOpStop; + } + else if ( strcmp( inString, sArgsvcStart ) == 0 ) + { + theDaemonOp = sOpSvcStart; + } + else if ( strcmp( inString, sArgsvcStop ) == 0 ) + { + theDaemonOp = sOpSvcStop; + } + return theDaemonOp; +} + +void usage( void ) +{ + fprintf( stderr, + "%s", + "Usage: apocd change-detect | disable | enable | is-enabled | reload | restart | start | status | stop\n" ); +} diff --git a/apocd/apocd.h b/apocd/apocd.h new file mode 100644 index 0000000..7f9747e --- /dev/null +++ b/apocd/apocd.h @@ -0,0 +1,97 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either + * the GNU General Public License Version 2 only ("GPL") or + * the Common Development and Distribution License("CDDL") + * (collectively, the "License"). You may not use this file + * except in compliance with the License. You can obtain a copy + * of the License at www.sun.com/CDDL or at COPYRIGHT. See the + * License for the specific language governing permissions and + * limitations under the License. When distributing the software, + * include this License Header Notice in each file and include + * the License file at /legal/license.txt. If applicable, add the + * following below the License Header, with the fields enclosed + * by brackets [] replaced by your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * If you wish your version of this file to be governed by + * only the CDDL or only the GPL Version 2, indicate your + * decision by adding "[Contributor] elects to include this + * software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice + * of license, a recipient has the option to distribute your + * version of this file under either the CDDL, the GPL Version + * 2 or to extend the choice of license to its licensees as + * provided above. However, if you add GPL Version 2 code and + * therefore, elected the GPL Version 2 license, then the + * option applies only if the new code is made subject to such + * option by the copyright holder. + */ + +#ifndef _APOCD_H_ +#define _APOCD_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum +{ + sOpUndefined, + sOpChangeDetect, + sOpDisable, + sOpEnable, + sDEPRECATED_OpInetdStart, + sOpIsEnabled, + sOpReload, + sOpRestart, + sOpStart, + sOpStatus, + sOpStop, + sOpSvcStart, + sOpSvcStop +} DaemonOp; + +typedef enum +{ + sStatusOK = 0, + sStatusEnabled = 0, + sStatusRunning = 0, + sErrorGeneric = 1, + sStatusNotEnabled = 1, + sErrorInvalidArg, + sStatusNotRunning, + sErrorNotRunning, + sErrorAuthentication +} Status; + +extern Status daemonStart( void ); +extern Status daemonStatus( int inQuiet ); +extern Status daemonStop( void ); +extern Status daemonWaitStatus( Status inStatus, int inMaxIterations ); + +extern Status osDaemonDisable( void ); +extern Status osDaemonEnable( void ); +extern Status osDaemonIsEnabled( int inQuiet ); +extern Status osDaemonStart( void ); +extern Status osDaemonStop( void ); +extern Status osDaemonSvcStart( void ); +extern Status osDaemonSvcStop( void ); +#ifdef LINUX +extern int osDaemonShouldRestart( void ); +#endif + +extern void writeInitialMessage( DaemonOp inOp ); +extern void writeFinalMessage( DaemonOp inOp, Status inStatus ); + + +#ifdef __cplusplus +} +#endif + +#endif /* APOCD_H_ */ diff --git a/apocd/config.h.in b/apocd/config.h.in new file mode 100644 index 0000000..e6c6da3 --- /dev/null +++ b/apocd/config.h.in @@ -0,0 +1,40 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either + * the GNU General Public License Version 2 only ("GPL") or + * the Common Development and Distribution License("CDDL") + * (collectively, the "License"). You may not use this file + * except in compliance with the License. You can obtain a copy + * of the License at www.sun.com/CDDL or at COPYRIGHT. See the + * License for the specific language governing permissions and + * limitations under the License. When distributing the software, + * include this License Header Notice in each file and include + * the License file at /legal/license.txt. If applicable, add the + * following below the License Header, with the fields enclosed + * by brackets [] replaced by your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * If you wish your version of this file to be governed by + * only the CDDL or only the GPL Version 2, indicate your + * decision by adding "[Contributor] elects to include this + * software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice + * of license, a recipient has the option to distribute your + * version of this file under either the CDDL, the GPL Version + * 2 or to extend the choice of license to its licensees as + * provided above. However, if you add GPL Version 2 code and + * therefore, elected the GPL Version 2 license, then the + * option applies only if the new code is made subject to such + * option by the copyright holder. + */ + +#ifndef _HAVE_CONFIG_H +#define _HAVE_CONFIG_H +#define BDBJDK "@BDBJDK@" +#define DBJAVA_LIBDIR "@DBJAVA_LIBDIR@" +#endif diff --git a/apocd/linux.c b/apocd/linux.c new file mode 100644 index 0000000..f3b7752 --- /dev/null +++ b/apocd/linux.c @@ -0,0 +1,178 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either + * the GNU General Public License Version 2 only ("GPL") or + * the Common Development and Distribution License("CDDL") + * (collectively, the "License"). You may not use this file + * except in compliance with the License. You can obtain a copy + * of the License at www.sun.com/CDDL or at COPYRIGHT. See the + * License for the specific language governing permissions and + * limitations under the License. When distributing the software, + * include this License Header Notice in each file and include + * the License file at /legal/license.txt. If applicable, add the + * following below the License Header, with the fields enclosed + * by brackets [] replaced by your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * If you wish your version of this file to be governed by + * only the CDDL or only the GPL Version 2, indicate your + * decision by adding "[Contributor] elects to include this + * software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice + * of license, a recipient has the option to distribute your + * version of this file under either the CDDL, the GPL Version + * 2 or to extend the choice of license to its licensees as + * provided above. However, if you add GPL Version 2 code and + * therefore, elected the GPL Version 2 license, then the + * option applies only if the new code is made subject to such + * option by the copyright holder. + */ + +#include "apocd.h" + +#include <papiUtils.h> + +#include <stdio.h> +#include <sys/types.h> +#include <time.h> +#include <syslog.h> + +#define SCRIPT_DISABLE "#!/bin/sh\n \ +/sbin/chkconfig apocd off\n \ +exit $?\n" + +#define SCRIPT_ENABLE "#!/bin/sh\n \ +/sbin/chkconfig apocd on\n \ +exit $?\n" + +#define SCRIPT_ISENABLED "#!/bin/sh\n \ +/sbin/chkconfig -c apocd\n \ +exit $?\n" + +static int execute( const char * inCommand ); + +Status osDaemonDisable( void ) +{ + Status theRC; + writeInitialMessage( sOpDisable ); + theRC = execute( SCRIPT_DISABLE ) == 0 ? sStatusOK : sErrorGeneric; + writeFinalMessage( sOpDisable, theRC ); + if ( theRC == sStatusOK && daemonStatus( 1 ) == sStatusOK ) + { + theRC = daemonStop(); + } + return theRC; +} + +Status osDaemonEnable( void ) +{ + Status theRC; + writeInitialMessage( sOpEnable ); + theRC = execute( SCRIPT_ENABLE ) == 0 ? sStatusOK : sErrorGeneric; + writeFinalMessage( sOpEnable, theRC ); + if ( theRC == sStatusOK && daemonStatus( 1 ) != sStatusOK ) + { + theRC = daemonStart(); + } + return theRC; +} + +Status osDaemonIsEnabled( inQuiet ) +{ + Status theRC; + if (inQuiet == 0) { writeInitialMessage( sOpIsEnabled ); } + theRC = execute( SCRIPT_ISENABLED ) == 0 ? + sStatusEnabled : sStatusNotEnabled; + if (inQuiet == 0) { writeFinalMessage( sOpIsEnabled, theRC ); } + return theRC; +} + +int osDaemonShouldRestart( void ) +{ + static int sFailureIndex = 0; + static time_t sFailureTimes[ 4 ]; + time_t theFailureTime = time( 0 ); + int bShouldRestart = 1; + + if ( sFailureIndex == 4 ) + { + if ( theFailureTime - sFailureTimes[ 0 ] < 60 ) + { + bShouldRestart = 0; + } + else + { + sFailureTimes[ 0 ] = sFailureTimes[ 1 ]; + sFailureTimes[ 1 ] = sFailureTimes[ 2 ]; + sFailureTimes[ 2 ] = sFailureTimes[ 3 ]; + sFailureTimes[ 3 ] = theFailureTime; + } + } + else + { + sFailureTimes[ sFailureIndex ++ ] = theFailureTime; + } + if ( bShouldRestart == 0 ) + { + syslog( LOG_WARNING, "Too many Configuration Agent failures in the last 60 seconds. Not restarting." ); + } + return bShouldRestart; +} + +Status osDaemonStart( void ) +{ + return daemonStart(); +} + +Status osDaemonStop( void ) +{ + return daemonStop(); +} + +Status osDaemonSvcStart( void ) +{ + close( 0 ); close( 1 ); close( 2 ); + return daemonStart(); +} + +Status osDaemonSvcStop( void ) +{ + return daemonStop(); +} + + +int execute( const char * inCommand ) +{ + int theRC = -1; + char * theFileName = tmpnam( 0 ); + FILE * theFile = fopen( theFileName, "w" ); + + if ( theFile != 0 ) + { + char theBuf[ BUFSIZ ]; + + fprintf( theFile, "%s", inCommand ); + fclose( theFile ); + chmod( theFileName, 0700 ); + + theFile = papiPopen( theFileName, "r" ); + if ( theFile != 0 ) + { + while ( 1 ) + { + if ( fgets( theBuf, BUFSIZ, theFile ) == 0 ) + { + break; + } + } + theRC = papiPclose( theFile ); + unlink( theFileName ); + } + } + return theRC; +} diff --git a/apocd/solaris.c b/apocd/solaris.c new file mode 100644 index 0000000..4552a49 --- /dev/null +++ b/apocd/solaris.c @@ -0,0 +1,178 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either + * the GNU General Public License Version 2 only ("GPL") or + * the Common Development and Distribution License("CDDL") + * (collectively, the "License"). You may not use this file + * except in compliance with the License. You can obtain a copy + * of the License at www.sun.com/CDDL or at COPYRIGHT. See the + * License for the specific language governing permissions and + * limitations under the License. When distributing the software, + * include this License Header Notice in each file and include + * the License file at /legal/license.txt. If applicable, add the + * following below the License Header, with the fields enclosed + * by brackets [] replaced by your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * If you wish your version of this file to be governed by + * only the CDDL or only the GPL Version 2, indicate your + * decision by adding "[Contributor] elects to include this + * software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice + * of license, a recipient has the option to distribute your + * version of this file under either the CDDL, the GPL Version + * 2 or to extend the choice of license to its licensees as + * provided above. However, if you add GPL Version 2 code and + * therefore, elected the GPL Version 2 license, then the + * option applies only if the new code is made subject to such + * option by the copyright holder. + */ + +#include "apocd.h" + +#include <libscf.h> +#include <stdlib.h> +#include <string.h> + +static const char * sInstanceName = "svc:/network/apocd/udp:default"; + +static Status osEnabler( int inEnable, int inOneTime, int inQuiet ); + +Status osDaemonDisable( void ) +{ + return osEnabler( 0, 0, 0 ); +} + +Status osDaemonEnable( void ) +{ + return osEnabler( 1, 0, 0 ); +} + +Status osDaemonIsEnabled( int inQuiet ) +{ + Status isEnabled = sStatusNotEnabled; + scf_handle_t * theHandle = scf_handle_create( SCF_VERSION ); + if (inQuiet == 0) { writeInitialMessage( sOpIsEnabled ); } + if ( theHandle != 0 ) + { + if ( scf_handle_bind( theHandle ) == 0 ) + { + scf_instance_t * theInstance = scf_instance_create( theHandle ); + if ( theInstance != 0 ) + { + if ( scf_handle_decode_fmri( + theHandle, + sInstanceName, + 0, + 0, + theInstance, + 0, + 0, + SCF_DECODE_FMRI_EXACT ) != -1 ) + { + scf_handle_t * theInstanceHandle = + scf_instance_handle( theInstance ); + if ( theInstanceHandle != 0 ) + { + uint8_t theEnabled; + scf_propertygroup_t * theGroup = + scf_pg_create( theInstanceHandle ); + scf_property_t * theProp = + scf_property_create( theInstanceHandle ); + scf_value_t * theValue = + scf_value_create( theInstanceHandle ); + if ( theGroup != 0 && theProp != 0 && theValue != 0 ) + { + if ( scf_instance_get_pg( theInstance, + SCF_PG_GENERAL, + theGroup ) == 0 && + scf_pg_get_property( theGroup, + SCF_PROPERTY_ENABLED, + theProp ) == 0 && + scf_property_get_value( theProp, + theValue ) == 0 && + scf_value_get_boolean( theValue, + &theEnabled ) == 0 ) + { + isEnabled = theEnabled == 1 ? + sStatusEnabled : sStatusNotEnabled; + } + } + scf_pg_destroy( theGroup ); + scf_property_destroy( theProp ); + scf_value_destroy( theValue ); + } + } + scf_instance_destroy( theInstance ); + } + } + scf_handle_destroy( theHandle ); + } + if (inQuiet == 0) { writeFinalMessage( sOpIsEnabled, isEnabled ); } + return isEnabled; +} + +Status osDaemonStart( void ) +{ + Status theRC; + writeInitialMessage( sOpStart ); + osEnabler( 1, 1, 1 ); + theRC = daemonWaitStatus( sStatusOK, 30 ); + writeFinalMessage( sOpStart, theRC ); + return theRC; +} + +Status osDaemonStop( void ) +{ + Status theRC; + writeInitialMessage( sOpStop ); + osEnabler( 0, 1, 1 ); + theRC = daemonWaitStatus( sStatusNotRunning, 20 ) == sStatusNotRunning ? + sStatusOK : sErrorGeneric; + writeFinalMessage( sOpStop, theRC ); + return theRC; +} + +Status osDaemonSvcStart( void ) +{ + return daemonStart(); +} + +Status osDaemonSvcStop( void ) +{ + return daemonStop(); +} + +Status osEnabler( int inEnable, int inOneTime, int inQuiet ) +{ + Status theStatus; + DaemonOp theOp = inEnable == 1 ? sOpEnable : sOpDisable; + int theFlags = inOneTime == 1 ? SMF_TEMPORARY : 0; + + if ( inQuiet == 0 ) + { + writeInitialMessage( theOp ); + } + if ( theOp == sOpEnable ) + { + theStatus = + smf_enable_instance( sInstanceName, theFlags ) == SCF_SUCCESS ? + sStatusOK : sErrorGeneric; + } + else + { + theStatus = + smf_disable_instance( sInstanceName, theFlags ) == SCF_SUCCESS ? + sStatusOK : sErrorGeneric; + } + if ( inQuiet == 0 ) + { + writeFinalMessage( theOp, theStatus ); + } + return theStatus; +} diff --git a/apocd/win32/apocdctl.c b/apocd/win32/apocdctl.c new file mode 100644 index 0000000..3081284 --- /dev/null +++ b/apocd/win32/apocdctl.c @@ -0,0 +1,1393 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either + * the GNU General Public License Version 2 only ("GPL") or + * the Common Development and Distribution License("CDDL") + * (collectively, the "License"). You may not use this file + * except in compliance with the License. You can obtain a copy + * of the License at www.sun.com/CDDL or at COPYRIGHT. See the + * License for the specific language governing permissions and + * limitations under the License. When distributing the software, + * include this License Header Notice in each file and include + * the License file at /legal/license.txt. If applicable, add the + * following below the License Header, with the fields enclosed + * by brackets [] replaced by your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * If you wish your version of this file to be governed by + * only the CDDL or only the GPL Version 2, indicate your + * decision by adding "[Contributor] elects to include this + * software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice + * of license, a recipient has the option to distribute your + * version of this file under either the CDDL, the GPL Version + * 2 or to extend the choice of license to its licensees as + * provided above. However, if you add GPL Version 2 code and + * therefore, elected the GPL Version 2 license, then the + * option applies only if the new code is made subject to such + * option by the copyright holder. + */ + +#include <papi/papiUtils.h> + +#include <stdlib.h> +#include <stdio.h> + +#ifndef WNT +#include <sys/socket.h> +#include <netdb.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <inttypes.h> +#include <strings.h> +#include <string.h> +#include <stdio.h> +#include <errno.h> +#include <unistd.h> +#include <signal.h> +#include <sys/stat.h> +#endif + +typedef unsigned char daemonOp; + +static int authenticate( PAPISocket inSocket ); + +static int doDisable( int inQuite ); + +static int doEnable( void ); + +static int doGeneric( daemonOp inOp, int inQuiet ); + +static int doIsEnabled( void ); + +static int doOp( daemonOp inOp ); + +static int doServiceOp( void * inService, int inOp ); + +#ifndef WNT +static int doStart( int inQuite ); +#else +static int doStart( int inQuite, HANDLE * outHandle ); +#endif + +static int doStop( void ); + +static int doRestart( void ); + +static void * getService( void ); + +static int getResponse( int inSocket, char * outResponse ); + +static void invalidArg( const char * inArg ); + +static void putEnv( void ); + +static int sendRequest( int inSocket, + const unsigned char * inRequest ); + +static daemonOp stringToDaemonOp( const char * inString ); + +static void usage( void ); + +static void writeInitialMessage( daemonOp inOp ); + +static void writeFinalMessage( daemonOp inOp, int inStatus ); + +#ifndef WNT + +static int doInetdDisable( void ); + +static int doInetdEnable( void ); + +static int doInetdStart( void ); + +static pid_t getPid( void ); + +static const char * getPidFile( void ); + +static int isInetdRunning( void ); + +static void killPid( void ); + +static void putPid( void ); + +static const char * sPidFile = ".pid"; + +#ifdef LINUX + +#define SCRIPT_DISABLE "#!/bin/sh\n \ +if [ -f /etc/inetd.conf ] ; then\n \ + grep -v apocd /etc/inetd.conf > /tmp/inetd.conf\n \ + cp /tmp/inetd.conf /etc/inetd.conf\n \ + rm -f /tmp/inetd.conf\n \ + /etc/init.d/inetd status > /dev/null 2>&1\n \ + if [ $? -eq 0 ] ; then\n \ + /etc/init.d/inetd restart\n \ + fi\n \ +fi\n \ +exit 0\n" + +#define SCRIPT_ENABLE "#!/bin/sh\n \ +if [ -f /etc/inetd.conf ] ; then\n \ + grep -v apocd /etc/inetd.conf > /tmp/inetd.conf\n \ + cp /tmp/inetd.conf /etc/inetd.conf\n \ + rm -f /tmp/inetd.conf\n \ + echo \"apocd dgram udp wait root /usr/lib/apoc/apocd apocd inetdStart\" >> /etc/inetd.conf\n\ + /etc/init.d/inetd status > /dev/null 2>&1\n \ + if [ $? -eq 0 ] ; then\n \ + /etc/init.d/inetd restart\n \ + fi\n \ +fi\n \ +exit 0\n" + +#else + +#define SCRIPT_DISABLE "#!/bin/sh\n \ +if [ -f /etc/inetd.conf ] ; then\n \ + grep -v apocd /etc/inetd.conf > /tmp/inetd.conf\n \ + cp /tmp/inetd.conf /etc/inetd.conf\n \ + rm -f /tmp/inetd.conf\n \ + pkill -HUP inetd > /dev/null 2>&1\n \ +fi\n \ +exit 0\n" + +#define SCRIPT_ENABLE "#!/bin/sh\n \ +if [ -f /etc/inetd.conf ] ; then\n \ + grep -v apocd /etc/inetd.conf > /tmp/inetd.conf\n \ + cp /tmp/inetd.conf /etc/inetd.conf\n \ + rm -f /tmp/inetd.conf\n \ + echo \"apocd dgram udp wait root /usr/lib/apoc/apocd apocd inetdStart\" >> /etc/inetd.conf\n\ + pkill -HUP inetd > /dev/null 2>&1\n \ +fi\n \ +exit 0\n" + +#endif + +#else + +#include <windows.h> + +typedef WINADVAPI BOOL ( WINAPI *ChangeServiceConfig2Func )( SC_HANDLE, DWORD, LPVOID ); + +typedef WINADVAPI BOOL ( WINAPI *CloseServiceHandleFunc )( SC_HANDLE ); + +typedef WINADVAPI BOOL ( WINAPI *ControlServiceFunc )( SC_HANDLE, DWORD, LPSERVICE_STATUS ); + +typedef WINADVAPI SC_HANDLE ( WINAPI *CreateServiceFunc )( SC_HANDLE, + LPCTSTR, + LPCTSTR, + DWORD, + DWORD, + DWORD, + DWORD, + LPCTSTR, + LPCTSTR, + LPDWORD, + LPCTSTR, + LPCTSTR, + LPCTSTR ); + +typedef WINADVAPI BOOL ( WINAPI *DeleteServiceFunc )( SC_HANDLE ); + +typedef WINADVAPI SC_HANDLE ( WINAPI *OpenSCManagerFunc )( LPCTSTR, LPCTSTR, DWORD ); + +typedef WINADVAPI SC_HANDLE ( WINAPI *OpenServiceFunc )( SC_HANDLE, LPCTSTR, DWORD ); + +typedef WINADVAPI BOOL ( WINAPI *SetServiceStatusFunc )( SERVICE_STATUS_HANDLE, LPSERVICE_STATUS ); + +typedef WINADVAPI SERVICE_STATUS_HANDLE ( WINAPI *RegisterServiceCtrlHandlerFunc )( LPCTSTR, LPHANDLER_FUNCTION ); + +typedef WINADVAPI BOOL ( WINAPI *StartServiceFunc )( SC_HANDLE, DWORD, LPCTSTR * ); + +typedef WINADVAPI BOOL ( WINAPI *StartServiceCtrlDispatcherFunc )( CONST LPSERVICE_TABLE_ENTRY ); + +ChangeServiceConfig2Func fChangeServiceConfig2; +CloseServiceHandleFunc fCloseServiceHandle; +ControlServiceFunc fControlService; +CreateServiceFunc fCreateService; +DeleteServiceFunc fDeleteService; +OpenSCManagerFunc fOpenSCManager; +OpenServiceFunc fOpenService; +RegisterServiceCtrlHandlerFunc fRegisterServiceCtrlHandler; +SetServiceStatusFunc fSetServiceStatus; +StartServiceFunc fStartService; +StartServiceCtrlDispatcherFunc fStartServiceCtrlDispatcher; + +static int doRegistryDisable( void ); + +static int doRegistryEnable( void ); + +static int doServiceDisable( void ); + +static int doServiceEnable( void ); + +static DWORD getServiceStatus( void ); + +static int loadServiceFuncs( void ); + +static void serviceCtrlHandler( DWORD inOpCode ); + +static void serviceMain( DWORD inArgc, LPTSTR * inArgv ); + +static void serviceRestartLoop( HANDLE inHandle ); + +static void setServiceStatus( DWORD inStatus ); + +static const char * sServiceProgram = "apocd.exe"; + +static const char * sServiceName = "apocd"; + +static const char * sServiceDisplayName = "Configuration Agent"; + +static const char * sServiceDescription = "Maintains locally cached policy data"; + +SERVICE_STATUS_HANDLE gServiceStatusHandle; + +SERVICE_STATUS gServiceStatus; + +PAPIMutex * gServiceStatusMutex; + +#endif + +static const char * sArgChangeDetect = "change-detect"; +static const char * sArgDisable = "disable"; +static const char * sArgEnable = "enable"; +static const char * sArgInetdStart = "inetdStart"; +static const char * sArgIsEnabled = "is-enabled"; +static const char * sArgReload = "reload"; +static const char * sArgRestart = "restart"; +static const char * sArgStart = "start"; +static const char * sArgStatus = "status"; +static const char * sArgStop = "stop"; + +static unsigned char sOpUndefined = 0; +static unsigned char sOpChangeDetect = 1; +static unsigned char sOpDisable = 2; +static unsigned char sOpEnable = 3; +static unsigned char sOpInetdStart = 4; +static unsigned char sOpIsEnabled = 5; +static unsigned char sOpReload = 6; +static unsigned char sOpRestart = 7; +static unsigned char sOpStart = 8; +static unsigned char sOpStatus = 9; +static unsigned char sOpStop = 10; + +static int sStatusOK = 0; +static int sStatusEnabled = 0; +static int sErrorGeneric = 1; +static int sStatusNotEnabled = 1; +static int sErrorInvalidArg = 2; +static int sStatusNotRunning = 3; +static int sStatusEnabledWithWarning = 4; +static int sErrorNotRunning = 7; +static int sErrorAuthentication = 8; + +static int sLocalCredentialsBufferSize = 21; + +int main( int inArgc, char ** inArgv ) +{ + int theRC; + int newerThanWindows98 = 0; + +#ifdef WNT + if ( isNewerThanWindows98() == 1 ) + { + newerThanWindows98 = 1; + loadServiceFuncs(); + gServiceStatusMutex = newMutex(); + } + if ( inArgc == 1 && newerThanWindows98 == 1 ) + { + SERVICE_TABLE_ENTRY theServiceTable[] = + { + { ( char *)sServiceName, ( LPSERVICE_MAIN_FUNCTION )serviceMain }, + { NULL, NULL } + }; + fStartServiceCtrlDispatcher( theServiceTable ); + } +#endif + + if ( inArgc == 2 ) + { + daemonOp theOp = stringToDaemonOp( inArgv[ 1 ] ); + if ( theOp == sOpUndefined ) + { + invalidArg( inArgv[ 1 ] ); + theRC = sErrorInvalidArg; + } + else + { + theRC = doOp( theOp ); + } + } + else + { + usage(); + theRC = sErrorInvalidArg; + } + return theRC; +} + +int authenticate( PAPISocket inSocket ) +{ + int theRC = sErrorAuthentication; + char theChallenge[ BUFSIZ ]; + int theIndex = 0; + + theChallenge[ 0 ] = 0; + while ( recv( inSocket, &theChallenge[ theIndex ++ ], 1, 0 ) != -1 ) + { + if ( theChallenge[ theIndex - 1 ] == 0 ) + { + if ( theChallenge[ 0 ] != 0 ) + { + FILE * theFile = fopen( theChallenge, "r" ); + if ( theFile != 0 ) + { + char * theCredentials = + ( char * )malloc( sLocalCredentialsBufferSize ); + if ( theCredentials != 0 ) + { + if ( fgets( theCredentials, + sLocalCredentialsBufferSize, + theFile ) != 0 ) + { + if ( send( inSocket, + theCredentials, + sLocalCredentialsBufferSize - 1, + 0 ) == ( sLocalCredentialsBufferSize - 1 ) ) + { + char theResponse; + if ( getResponse(inSocket,&theResponse)!= -1 && + theResponse == 0 ) + { + theRC = sStatusOK; + } + } + } + free( ( void * )theCredentials ); + } + fclose( theFile ); +#ifdef WNT + remove( theChallenge ); +#endif + } + } + break; + } + } + return theRC; +} + +int doGeneric( daemonOp inOp, int inQuiet ) +{ + int theRC; + PAPISocket theSocket; + PAPIConnectResult theConnectResult = + getConnectedSocket( getDaemonAdminPort(), SOCK_STREAM, 0, &theSocket ); + + if ( inQuiet != 1 ) + { + writeInitialMessage( inOp ); + } + if ( theConnectResult == PAPIConnectSuccess ) + { + if ( ( theRC = authenticate( theSocket ) ) == sStatusOK ) + { + if ( ( theRC = sendRequest( theSocket, &inOp ) ) != -1 ) + { + char theResponse; + theRC = getResponse( theSocket, &theResponse ); + } + if ( theRC == -1 ) + { + theRC = inOp == sOpStatus ? + sStatusNotRunning : sErrorNotRunning; + } + else + { + theRC = sStatusOK; + } + } + papiClose( theSocket ); + } + else + { + theRC = sStatusNotRunning; + } + if ( inQuiet != 1 ) + { + writeFinalMessage( inOp, theRC ); + } + return theRC; +} + +int doIsEnabled() +{ + int theRC = isDaemonEnabled() == 1 ? sStatusEnabled : sStatusNotEnabled; + writeInitialMessage( sOpIsEnabled ); + writeFinalMessage( sOpIsEnabled, theRC ); + return theRC; +} + +int doOp( daemonOp inOp ) +{ + int theRC; + + if ( inOp == sOpDisable ) + { + theRC = doDisable( 0 ); + } + else if ( inOp == sOpEnable ) + { + theRC = doEnable(); + } +#ifndef WNT + else if ( inOp == sOpInetdStart ) + { + theRC = doInetdStart(); + } +#endif + else if ( inOp == sOpIsEnabled ) + { + theRC = doIsEnabled(); + } + else if ( inOp == sOpStart || inOp == sOpStop || inOp == sOpRestart ) + { + void * theService = getService(); + if ( theService != 0 ) + { + theRC = doServiceOp( theService, inOp ); + } + else + { + if ( inOp == sOpStart ) + { +#ifndef WNT + theRC = doStart( 0 ); +#else + theRC = doStart( 0, 0 ); +#endif + } + else if ( inOp == sOpStop ) + { + theRC = doStop(); + } + else if ( inOp == sOpRestart ) + { + theRC = doRestart(); + } + } + } + else + { + theRC = doGeneric( inOp, 0 ); + } + return theRC; +} + +int doServiceOp( void * inService, int inOp ) +{ + int theRC = sStatusOK; +#ifdef WNT + if ( inOp == sOpStop || inOp == sOpRestart ) + { + SERVICE_STATUS theServiceStatus; + BOOL theStatus; + + writeInitialMessage( sOpStop ); + theStatus = + fControlService( inService, SERVICE_CONTROL_STOP, &theServiceStatus ); + if ( theStatus == 0 && + GetLastError() != ERROR_SERVICE_NOT_ACTIVE ) + { + theRC = sErrorGeneric; + } + writeFinalMessage( sOpStop, theRC ); + } + if ( inOp == sOpStart || ( inOp == sOpRestart && theRC == sStatusOK ) ) + { + BOOL theStatus; + + writeInitialMessage( sOpStart ); + theStatus = fStartService( inService, 0, NULL ); + if ( theStatus == 0 && + GetLastError() != ERROR_SERVICE_ALREADY_RUNNING ) + { + theRC = sErrorGeneric; + } + writeFinalMessage( sOpStart, theRC ); + } +#endif + return theRC; +} + +#ifndef WNT +int doStart( int inQuiet ) +#else +int doStart( int inQuiet, HANDLE * outHandle ) +#endif +{ + static char * theFormat = + "java -Djava.library.path=%s -cp %s%sapocd.jar%s%s%sdb.jar%s%s%sldapjdk.jar%s%s%sspi.jar com.sun.apoc.daemon.apocd.Daemon %s %s"; + static char * theCommand = 0; + int theRC = sStatusOK; + + if ( inQuiet != 1 ) + { + writeInitialMessage( sOpStart ); + } + if ( isDaemonEnabled() == 1 ) + { + putEnv(); + if ( theCommand == 0 ) + { + const char * theDaemonInstallDir = getDaemonInstallDir(); + const char * theDaemonLibraryDir = getDaemonLibraryDir(); + const char * theDaemonPropertiesDir = getDaemonPropertiesDir(); + theCommand = + ( char * )malloc( ( strlen( theDaemonInstallDir ) * 5 ) + + strlen( theDaemonLibraryDir ) + + strlen( theDaemonPropertiesDir ) + + ( strlen( FILESEP ) * 4 ) + + ( strlen( PATHSEP ) * 3 ) + + strlen( theFormat ) + 1 ); + if ( theCommand != 0 ) + { + sprintf( theCommand, + theFormat, + theDaemonLibraryDir, + theDaemonInstallDir, FILESEP, PATHSEP, + theDaemonInstallDir, FILESEP, PATHSEP, + theDaemonInstallDir, FILESEP, PATHSEP, + theDaemonInstallDir, FILESEP, + theDaemonInstallDir, + theDaemonPropertiesDir ); + } + } + if ( theCommand != 0 ) + { +#ifndef WNT + if ( papiPopen( theCommand, "w" ) == 0 ) + { + theRC = sErrorGeneric; + } +#else + STARTUPINFO theStartupInfo; + PROCESS_INFORMATION theProcessInfo; + + + ZeroMemory( &theStartupInfo, sizeof( theStartupInfo ) ); + theStartupInfo.dwFlags = STARTF_USESHOWWINDOW; + theStartupInfo.wShowWindow = SW_HIDE; + theStartupInfo.cb = sizeof( theStartupInfo ); + ZeroMemory( &theProcessInfo, sizeof( theProcessInfo ) ); + if ( CreateProcess( 0, + theCommand, + 0, + 0, + FALSE, + 0, + 0, + 0, + &theStartupInfo, + &theProcessInfo ) == 0 ) + { + theRC = sErrorGeneric; + } + else if ( outHandle != 0 ) + { + *outHandle = theProcessInfo.hProcess; + } +#endif + } + else + { + theRC = sErrorGeneric; + } + } + else + { + theRC = sErrorGeneric; + } + if ( inQuiet != 1 ) + { + writeFinalMessage( sOpStart, theRC ); + } + return theRC; +} + +int doStop( void ) +{ + int theRC; + writeInitialMessage( sOpStop ); + theRC = doGeneric( sOpStatus, 1 ); + if ( theRC != sErrorAuthentication ) + { + if ( theRC == sStatusNotRunning ) + { + theRC = sStatusOK; + } + else + { + theRC = doGeneric( sOpStop, 1 ); + } + } + writeFinalMessage( sOpStop, theRC ); +#ifndef WNT + if ( theRC == sStatusOK ) + { + killPid(); + } +#endif + return theRC; +} + +void * getService( void ) +{ +#ifndef WNT + return 0; +#else + if ( isNewerThanWindows98() == 0 ) + { + return 0; + } + else + { + SC_HANDLE theService = NULL; + SC_HANDLE theServiceManager = + fOpenSCManager( 0, 0, SC_MANAGER_ALL_ACCESS ); + if ( theServiceManager != NULL ) + { + theService = fOpenService( theServiceManager, + sServiceName, + GENERIC_EXECUTE ); + } + return theService; + } +#endif +} + +int doRestart( void ) +{ + doGeneric( sOpStop, 0 ); +#ifndef WNT + return doStart( 0 ); +#else + return doStart( 0, 0 ); +#endif +} + +int getResponse( int inSocket, char * outResponse ) +{ + return recv( inSocket, + outResponse, + 1, + 0 ); +} + +void invalidArg( const char * inOp ) +{ + if ( inOp != 0 ) + { + fprintf( stderr, "Invalid argument '%s'\n", inOp ); + } + usage(); +} + +void putEnv( void ) +{ + char * theJavaHome = getenv( "JAVA_HOME" ); + + if ( theJavaHome != 0 ) + { + char * theJavaPath = ( char * )malloc( strlen( theJavaHome ) + + 4 + + strlen( FILESEP ) ); + if ( theJavaPath != 0 ) + { + char * thePath = getenv( "PATH" ); + char * theNewPath; + sprintf( theJavaPath, "%s%sbin", theJavaHome, FILESEP ); + theNewPath = ( char * )malloc( strlen( theJavaPath ) + + strlen( PATHSEP ) + + strlen( thePath ) + + 6 ); + if ( theNewPath != 0 ) + { + sprintf( theNewPath, + "PATH=%s%s%s", + theJavaPath, + PATHSEP, + thePath ); + putenv( theNewPath ); + free( ( void * )theJavaPath ); + } + } + } + papiUmask( 022 ); +} + +int sendRequest( int inSocket, + const unsigned char * inRequest ) +{ + return send( inSocket, inRequest, 1, 0 ); +} + +daemonOp stringToDaemonOp( const char * inString ) +{ + daemonOp theDaemonOp = sOpUndefined; + if ( strcmp( inString, sArgChangeDetect ) == 0 ) + { + theDaemonOp = sOpChangeDetect; + } + else if ( strcmp( inString, sArgDisable ) == 0 ) + { + theDaemonOp = sOpDisable; + } + else if ( strcmp( inString, sArgEnable ) == 0 ) + { + theDaemonOp = sOpEnable; + } + else if ( strcmp( inString, sArgInetdStart ) == 0 ) + { + theDaemonOp = sOpInetdStart; + } + else if ( strcmp( inString, sArgIsEnabled ) == 0 ) + { + theDaemonOp = sOpIsEnabled; + } + else if ( strcmp( inString, sArgReload ) == 0 ) + { + theDaemonOp = sOpReload; + } + else + if ( strcmp( inString, sArgRestart ) == 0 ) + { + theDaemonOp = sOpRestart; + } + else + if ( strcmp( inString, sArgStart ) == 0 ) + { + theDaemonOp = sOpStart; + } + else if ( strcmp( inString, sArgStatus ) == 0 ) + { + theDaemonOp = sOpStatus; + } + else + if ( strcmp( inString, sArgStop ) == 0 ) + { + theDaemonOp = sOpStop; + } + return theDaemonOp; +} + +void usage( void ) +{ + fprintf( stderr, + "%s", + "Usage: apocdctl change-detect | disable | enable | is-enabled | reload | restart | start | status | stop\n" ); +} + +void writeInitialMessage( daemonOp inOp ) +{ + if ( inOp == sOpChangeDetect ) + { + printf( "Requesting a Configuration Agent change detection ... " ); + } + else if ( inOp == sOpDisable ) + { + printf( "Disabling Configuration Agent ... "); + } + else if ( inOp == sOpEnable ) + { + printf( "Enabling Configuration Agent ... "); + } + else if ( inOp == sOpIsEnabled ) + { + printf( "Checking Configuration Agent enabled status ... " ); + } + else if ( inOp == sOpReload ) + { + printf( "Reloading Configuration Agent ... " ); + } + else if ( inOp == sOpStatus ) + { + printf( "Checking Configuration Agent status ... " ); + } + else if ( inOp == sOpStart ) + { + printf( "Starting Configuration Agent ... " ); + } + else if ( inOp == sOpStop ) + { + printf( "Stopping Configuration Agent ... " ); + } +} + +void writeFinalMessage( daemonOp inOp, int inStatus ) +{ + if ( inStatus == sErrorAuthentication ) + { + printf( "Failed\n" ); + } + else if ( inOp == sOpIsEnabled ) + { + printf( "%s\n", inStatus == sStatusEnabled ? "Enabled" : "Not enabled"); + } + else if ( inOp == sOpStatus ) + { + printf( "%s\n", inStatus == sStatusOK ? "Running" : "Not running" ); + } + else if ( inOp == sOpStop ) + { + printf( inStatus == sStatusOK || inStatus == sErrorNotRunning ? + "OK\n" : "Failed\n" ); + } + else + { + printf( inStatus == sStatusOK ? "OK\n" : "Failed\n" ); + } +} + +#ifndef WNT + +int doDisable( int inQuite ) +{ + int theRC; + if ( inQuite != 1 ) + { + writeInitialMessage( sOpDisable ); + } +#ifdef SOLARIS + if ( haveService() != 0 ) + { + theRC = doServiceDisable(); + } + else + { + theRC = doInetdDisable(); + } +#else + theRC = doInetdDisable(); +#endif + if ( inQuite != 1 ) + { + writeFinalMessage( sOpDisable, theRC ); + } + doStop(); + return theRC; +} + +int doInetdDisable() +{ + char * theFileName = tmpnam( 0 ); + FILE * theFile; + int theRC = sErrorGeneric; + + theFile = fopen( theFileName, "w" ); + if ( theFile != 0 ) + { + FILE * theStream; + char theBuf[ BUFSIZ ]; + + fprintf( theFile, "%s", SCRIPT_DISABLE ); + fclose( theFile ); + chmod( theFileName, 0700 ); + theStream = papiPopen( theFileName, "r" ); + if ( theStream != 0 ) + { + while ( 1 ) + { + if ( fgets( theBuf, BUFSIZ, theStream ) == 0 ) + { + break; + } + } + theRC = papiPclose( theStream ); + } + unlink( theFileName ); + } + return theRC; +} + +int doEnable( void ) +{ + int theRC; + + writeInitialMessage( sOpEnable ); +#ifdef SOLARIS + if ( haveService() != 0 ) + { + theRC = doServiceEnable(); + } + else + { + theRC = doInetdEnable(); + } +#else + theRC = doInetdEnable(); +#endif + writeFinalMessage( sOpEnable, theRC ); + if ( theRC == sStatusOK && isInetdRunning() != 1 ) + { + fprintf( stderr, + "%s\n", + "Warning: inetd is not running and must be started if you want the" ); + fprintf( stderr, + "%s\n", + " Configuration Agent to start automatically." ); + theRC = sStatusEnabledWithWarning; + } + return theRC; +} + +int doInetdEnable( void ) +{ + char * theFileName = tmpnam( 0 ); + FILE * theFile; + int theRC = sErrorGeneric; + + theFile = fopen( theFileName, "w" ); + if ( theFile != 0 ) + { + FILE * theStream; + char theBuf[ BUFSIZ ]; + + fprintf( theFile, "%s", SCRIPT_ENABLE ); + fclose( theFile ); + chmod( theFileName, 0700 ); + theStream = papiPopen( theFileName, "r" ); + if ( theStream != 0 ) + { + while ( 1 ) + { + if ( fgets( theBuf, BUFSIZ, theStream ) == 0 ) + { + break; + } + } + theRC = papiPclose( theStream ); + } + unlink( theFileName ); + } + return theRC; +} + +int doInetdStart( void ) +{ + if ( doStart( 1 ) == sStatusOK ) + { + putPid(); + while ( 1 ) + { + getchar(); + } + } + return 0; +} + +pid_t getPid( void ) +{ + pid_t thePid = 0; + const char * thePidFile = getPidFile(); + if ( thePidFile != 0 ) + { + FILE * thePidStream = fopen( thePidFile, "r" ); + if ( thePidStream != 0 ) + { + fscanf( thePidStream, "%d", &thePid ); + fclose( thePidStream ); + } + free( ( void * )thePidFile ); + } + return thePid; +} + +const char * getPidFile( void ) +{ + const char * thePidDir = getDaemonInstallDir(); + char * thePidFile = + ( char * )malloc( strlen( thePidDir ) + + ( 2 * strlen( FILESEP ) ) + + strlen( sPidFile ) + + 4 ); + if ( thePidFile != 0 ) + { + sprintf( thePidFile, + "%s%s%s", + thePidDir, + FILESEP, + sPidFile ); + } + return thePidFile; +} + +int isInetdRunning( void ) +{ + int theRC = 0; + static const char * theCommand = "/bin/ps -e | /bin/grep inetd "; + FILE * theStream = papiPopen( theCommand, "r" ); + + if ( theStream != 0 ) + { + char theBuffer[ BUFSIZ ]; + + while ( fgets( theBuffer, BUFSIZ, theStream ) != 0 ){} + theRC = papiPclose( theStream ) == 0 ? 1 : 0; + } + return theRC; +} + +void killPid( void ) +{ + pid_t thePid = getPid(); + if ( thePid > 0 ) + { + kill( thePid, SIGINT ); + } + unlink( getPidFile() ); +} + +void putPid( void ) +{ + const char * thePidFile = getPidFile(); + if ( thePidFile != 0 ) + { + FILE * thePidStream = fopen( thePidFile, "w" ); + if ( thePidStream != 0 ) + { + chmod( thePidFile, 0600 ); + fprintf( thePidStream, "%d", getpid() ); + fclose( thePidStream ); + } + free( ( void * )thePidFile ); + } +} + +#else + +int doDisable( int inQuiet ) +{ + int theRC; + int newerThanWindows98 = isNewerThanWindows98(); + + if ( newerThanWindows98 == 1 ) + { + doServiceOp( getService(), sOpStop ); + theRC = doServiceDisable(); + } + else + { + theRC = doRegistryDisable(); + doStop(); + } + return theRC; +} + +int doRegistryDisable( void ) +{ + int theRC; + LONG theStatus; + + writeInitialMessage( sOpDisable ); + theStatus = RegDeleteKey( HKEY_LOCAL_MACHINE, APOCENABLEDKEY ); + theRC = theStatus == ERROR_SUCCESS || theStatus == ERROR_FILE_NOT_FOUND ? + sStatusOK : sErrorGeneric; + writeFinalMessage( sOpDisable, theRC ); + return theRC; +} + +int doServiceDisable( void ) +{ + int theRC = sErrorGeneric; + SC_HANDLE theServiceManager; + + if ( isNewerThanWindows98() == 1 ) + { + theServiceManager = fOpenSCManager( 0, 0, SC_MANAGER_ALL_ACCESS ); + writeInitialMessage( sOpDisable ); + if ( theServiceManager != 0 ) + { + SC_HANDLE theService = fOpenService( theServiceManager, + sServiceName, + DELETE ); + if ( theService != 0 ) + { + if ( fDeleteService( theService ) == TRUE || + GetLastError() == ERROR_SERVICE_MARKED_FOR_DELETE ) + { + theRC = sStatusOK; + } + fCloseServiceHandle( theService ); + } + else + { + if ( GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST ) + { + theRC = sStatusOK; + } + } + fCloseServiceHandle( theServiceManager ); + } + else + { + theRC = sStatusOK; + } + } + writeFinalMessage( sOpDisable, theRC ); + return theRC; +} + +int doEnable( void ) +{ + int theRC; + int newerThanWindows98 = isNewerThanWindows98(); + + writeInitialMessage( sOpEnable ); + theRC = newerThanWindows98 == 1 ? + doServiceEnable() : doRegistryEnable(); + writeFinalMessage( sOpEnable, theRC ); + + if ( newerThanWindows98 == 1 && theRC == sStatusOK ) + { + theRC = doServiceOp( getService(), sOpStart ); + } + return theRC; +} + +int doServiceEnable( void ) +{ + int theRC = sErrorGeneric; + char * theDaemonInstallDir = getDaemonInstallDir(); + char * theServiceProgram = + ( char * )malloc( strlen( theDaemonInstallDir ) + + strlen( FILESEP ) + + strlen( sServiceProgram ) + + 1 ); + if ( theServiceProgram != 0 ) + { + SC_HANDLE theServiceManager; + char * theCP = ( char * )theDaemonInstallDir + + strlen( theDaemonInstallDir ) - 1; + while ( theCP-- != theDaemonInstallDir ) + { + if ( *theCP == '\\' ) + { + *( ++theCP ) = 0; + break; + } + } + sprintf( theServiceProgram, + "%sbin%s%s", + theDaemonInstallDir, + FILESEP, + sServiceProgram ); + theServiceManager = fOpenSCManager( 0, 0, SC_MANAGER_ALL_ACCESS ); + if ( theServiceManager != 0 ) + { + SC_HANDLE theService = + fCreateService( theServiceManager, + sServiceName, + sServiceDisplayName, + SERVICE_ALL_ACCESS, + SERVICE_WIN32_OWN_PROCESS, + SERVICE_AUTO_START, + SERVICE_ERROR_NORMAL, + theServiceProgram, + 0, + 0, + 0, + 0, + 0 ); + if ( theService != 0 ) + { + fChangeServiceConfig2( theService, + SERVICE_CONFIG_DESCRIPTION, + ( LPVOID )&sServiceDescription ); + theRC = sStatusOK; + fCloseServiceHandle( theService ); + } + else + { + if ( GetLastError() == ERROR_SERVICE_EXISTS ) + { + theRC = sStatusOK; + } + } + fCloseServiceHandle( theServiceManager ); + } + free( ( void * )theServiceProgram ); + } + return theRC; +} + +int doRegistryEnable( void ) +{ + int theRC = sErrorGeneric; + HKEY theKey; + DWORD theDisposition; + + if ( RegCreateKeyEx( HKEY_LOCAL_MACHINE, + APOCENABLEDKEY, + 0, + 0, + 0, + KEY_WRITE, + 0, + &theKey, + &theDisposition ) == ERROR_SUCCESS ) + { + RegCloseKey( theKey ); + theRC = sStatusOK; + } + return theRC; +} + +DWORD getServiceStatus( void ) +{ + DWORD theStatus = -1; + if ( lockMutex( gServiceStatusMutex ) == 0 ) + { + theStatus = gServiceStatus.dwCurrentState; + unlockMutex( gServiceStatusMutex ); + } + return theStatus; +} + +int loadServiceFuncs( void ) +{ + HMODULE theModule = GetModuleHandle( "advapi32" ); + if ( theModule != NULL ) + { + fChangeServiceConfig2 = + ( ChangeServiceConfig2Func )GetProcAddress( + theModule, "ChangeServiceConfig2A" ); + fCloseServiceHandle = + ( CloseServiceHandleFunc )GetProcAddress( + theModule, "CloseServiceHandle" ); + fControlService = + ( ControlServiceFunc )GetProcAddress( + theModule, "ControlService" ); + fCreateService = + ( CreateServiceFunc )GetProcAddress( + theModule, "CreateServiceA" ); + fDeleteService = + ( DeleteServiceFunc )GetProcAddress( + theModule, "DeleteService" ); + fOpenSCManager = + ( OpenSCManagerFunc )GetProcAddress( + theModule, "OpenSCManagerA" ); + fOpenService = + ( OpenServiceFunc )GetProcAddress( + theModule, "OpenServiceA" ); + fRegisterServiceCtrlHandler = + ( RegisterServiceCtrlHandlerFunc )GetProcAddress( + theModule, "RegisterServiceCtrlHandlerA" ); + fSetServiceStatus = + ( SetServiceStatusFunc )GetProcAddress( + theModule, "SetServiceStatus" ); + fStartService = + ( StartServiceFunc )GetProcAddress( + theModule, "StartServiceA" ); + fStartServiceCtrlDispatcher = + ( StartServiceCtrlDispatcherFunc )GetProcAddress( + theModule, "StartServiceCtrlDispatcherA" ); + } + return 1; +} + +void serviceCtrlHandler( DWORD inOpcode ) +{ + switch( inOpcode ) + { + case SERVICE_CONTROL_STOP: + case SERVICE_CONTROL_SHUTDOWN: + setServiceStatus( SERVICE_STOPPED ); + doGeneric( sOpStop, 1 ); + break; + + case SERVICE_CONTROL_INTERROGATE: + setServiceStatus( doGeneric( sOpStatus, 1 ) == 0 ? + SERVICE_RUNNING : SERVICE_STOPPED ); + break; + + default: + break; + } + gServiceStatus.dwWin32ExitCode = NO_ERROR; + gServiceStatus.dwCheckPoint = 0; + gServiceStatus.dwWaitHint = 0; + fSetServiceStatus( gServiceStatusHandle, &gServiceStatus ); +} + +void serviceMain( DWORD inArgc, LPTSTR * inArgv ) +{ + HANDLE theHandle; + gServiceStatusHandle = + fRegisterServiceCtrlHandler( + sServiceName, + ( LPHANDLER_FUNCTION )serviceCtrlHandler ); + + gServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + setServiceStatus( SERVICE_START_PENDING ); + gServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | + SERVICE_ACCEPT_SHUTDOWN; + gServiceStatus.dwWin32ExitCode = 0; + gServiceStatus.dwServiceSpecificExitCode = 0; + gServiceStatus.dwCheckPoint = 0; + gServiceStatus.dwWaitHint = 0; + fSetServiceStatus( gServiceStatusHandle, &gServiceStatus ); + + if ( doStart( 1, &theHandle ) == 0 ) + { + setServiceStatus( SERVICE_RUNNING ); + gServiceStatus.dwWin32ExitCode = NO_ERROR; + gServiceStatus.dwCheckPoint = 0; + gServiceStatus.dwWaitHint = 0; + fSetServiceStatus( gServiceStatusHandle, &gServiceStatus ); + serviceRestartLoop( theHandle ); + } + else + { + setServiceStatus( SERVICE_STOPPED ); + gServiceStatus.dwWin32ExitCode = ERROR_GEN_FAILURE; + gServiceStatus.dwCheckPoint = 0; + gServiceStatus.dwWaitHint = 0; + fSetServiceStatus( gServiceStatusHandle, &gServiceStatus ); + } +} + +void serviceRestartLoop( HANDLE inHandle ) +{ + while ( 1 ) + { + WaitForSingleObject( inHandle, INFINITE ); + Sleep( 5000 ); + if ( getServiceStatus() == SERVICE_RUNNING ) + { + doStart( 1, &inHandle ); + } + else + { + break; + } + } +} + +void setServiceStatus( DWORD inStatus ) +{ + if ( lockMutex( gServiceStatusMutex ) == 0 ) + { + gServiceStatus.dwCurrentState = inStatus; + unlockMutex( gServiceStatusMutex ); + } +} + +#endif |