summaryrefslogtreecommitdiff
path: root/apocd
diff options
context:
space:
mode:
authorAlberto Ruiz <alberto.ruiz@sun.com>2007-10-30 17:21:07 +0000
committerAlberto Ruiz <alberto.ruiz@sun.com>2007-10-30 17:21:07 +0000
commitaadeffb3f0716ffd231d1146d050847e3be355ee (patch)
tree9f2ed61a84a37fce5f154498023b28d6bfbf69bf /apocd
2007-30-10 Alberto Ruiz <alberto.ruiz@sun.com>
* Initial commit.
Diffstat (limited to 'apocd')
-rw-r--r--apocd/Makefile.am16
-rw-r--r--apocd/apocd.c659
-rw-r--r--apocd/apocd.h97
-rw-r--r--apocd/config.h.in40
-rw-r--r--apocd/linux.c178
-rw-r--r--apocd/solaris.c178
-rw-r--r--apocd/win32/apocdctl.c1393
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