summaryrefslogtreecommitdiff
path: root/libapoc
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 /libapoc
2007-30-10 Alberto Ruiz <alberto.ruiz@sun.com>
* Initial commit.
Diffstat (limited to 'libapoc')
-rw-r--r--libapoc/Makefile.am39
-rw-r--r--libapoc/config.h.in41
-rw-r--r--libapoc/papi.c128
-rw-r--r--libapoc/papi.h146
-rw-r--r--libapoc/papiConnection.c747
-rw-r--r--libapoc/papiConnection.h117
-rw-r--r--libapoc/papiDaemon.c516
-rw-r--r--libapoc/papiDaemon.h91
-rw-r--r--libapoc/papiDatabase.c285
-rw-r--r--libapoc/papiDatabase.h88
-rw-r--r--libapoc/papiEntityList.c92
-rw-r--r--libapoc/papiEntityList.h56
-rw-r--r--libapoc/papiInternal.c227
-rw-r--r--libapoc/papiInternal.h81
-rw-r--r--libapoc/papiLayerList.c104
-rw-r--r--libapoc/papiLayerList.h55
-rw-r--r--libapoc/papiListenerList.c131
-rw-r--r--libapoc/papiListenerList.h66
-rw-r--r--libapoc/papiMessage.c293
-rw-r--r--libapoc/papiMessage.h125
-rw-r--r--libapoc/papiPort.c457
-rw-r--r--libapoc/papiSAXParserContext.c182
-rw-r--r--libapoc/papiSAXParserContext.h74
-rw-r--r--libapoc/papiStringList.c176
-rw-r--r--libapoc/papiStringList.h61
-rw-r--r--libapoc/papiTypes.h96
-rw-r--r--libapoc/papiUtils.c662
-rw-r--r--libapoc/papiUtils.h167
-rw-r--r--libapoc/papitool.c521
-rw-r--r--libapoc/w32/Makefile55
-rw-r--r--libapoc/w32/Makefile.old110
-rwxr-xr-xlibapoc/w32/papiPort.c624
32 files changed, 6613 insertions, 0 deletions
diff --git a/libapoc/Makefile.am b/libapoc/Makefile.am
new file mode 100644
index 0000000..1da0d20
--- /dev/null
+++ b/libapoc/Makefile.am
@@ -0,0 +1,39 @@
+lib_LTLIBRARIES = libapoc.la
+
+libapocdir = $(includedir)/apoc/papi
+
+libapoc_HEADERS = \
+ papi.h \
+ papiTypes.h
+
+libapoc_la_LDFLAGS = -version-info "1:0:0"
+
+libapoc_la_SOURCES = \
+ papi.c \
+ papi.h \
+ papiConnection.h \
+ papiConnection.c \
+ papiDaemon.h \
+ papiDaemon.c \
+ papiDatabase.c \
+ papiDatabase.h \
+ papiInternal.c \
+ papiInternal.h \
+ papiLayerList.c \
+ papiLayerList.h \
+ papiListenerList.c \
+ papiListenerList.h \
+ papiMessage.c \
+ papiMessage.h \
+ papiSAXParserContext.c \
+ papiSAXParserContext.h \
+ papiStringList.c \
+ papiStringList.h \
+ papiEntityList.c \
+ papiEntityList.h \
+ papiUtils.c \
+ papiUtils.h \
+ papiPort.c \
+ papiTypes.h
+
+
diff --git a/libapoc/config.h.in b/libapoc/config.h.in
new file mode 100644
index 0000000..74120a7
--- /dev/null
+++ b/libapoc/config.h.in
@@ -0,0 +1,41 @@
+/*
+ * 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 APOC_INSTALLDIR "@APOCDIR@"
+#define APOC_LIBRARYDIR "@EXPANDED_LIBDIR@"
+#define APOC_PROPDIR "@EXPANDED_SYSCONFDIR@"
+#endif
diff --git a/libapoc/papi.c b/libapoc/papi.c
new file mode 100644
index 0000000..23e4c8f
--- /dev/null
+++ b/libapoc/papi.c
@@ -0,0 +1,128 @@
+/*
+ * 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.h"
+#include "papiInternal.h"
+
+
+PAPI * papiInitialise( const char * inEntityId,
+ PAPIStatus * outStatus )
+{
+ return papiInitialiseWithListener( inEntityId, 0, 0, outStatus );
+}
+
+PAPI * papiInitialiseWithListener( const char * inEntityId,
+ PAPIConnectionListener inListener,
+ void * inUserData,
+ PAPIStatus * outStatus )
+{
+ PAPIEntityList theEntity ;
+
+ theEntity.entityType = PAPIEntityUser;
+ theEntity.entityId = inEntityId;
+ theEntity.next = 0;
+ return initialise( &theEntity, inListener, inUserData, outStatus);
+}
+
+void papiDeinitialise( PAPI * inPAPI, PAPIStatus * outStatus )
+{
+ deinitialise( inPAPI, outStatus );
+}
+
+PAPILayerList * papiReadComponentLayers( const PAPI * inPAPI,
+ const char * inComponentName,
+ PAPIStatus * outStatus )
+{
+ return readComponentLayers( inPAPI, inComponentName, outStatus );
+}
+
+PAPIStringList * papiListComponentNames( const PAPI * inPAPI,
+ const char * inFilter,
+ PAPIStatus * outStatus )
+{
+ return listComponentNames( inPAPI, inFilter, outStatus );
+}
+
+void papiSetOffline( const PAPI * inPAPI,
+ const char * inComponentName,
+ int inOffline,
+ PAPIStatus * outStatus )
+{
+ if ( outStatus != 0 )
+ {
+ *outStatus = PAPISuccess;
+ }
+}
+
+int papiIsOffline( const PAPI * inPAPI,
+ const char * inComponentName,
+ int * outIsOffline,
+ PAPIStatus * outStatus )
+{
+ if ( outStatus != 0 )
+ {
+ *outStatus = PAPISuccess;
+ }
+ return 0;
+}
+
+PAPIListenerId papiAddListener( const PAPI * inPAPI,
+ const char * inComponentName,
+ PAPIListener inListener,
+ void * inUserData,
+ PAPIStatus * outStatus )
+{
+ return addListener( inPAPI,
+ inComponentName,
+ inListener,
+ inUserData,
+ outStatus );
+}
+
+void papiRemoveListener( const PAPI * inPAPI,
+ PAPIListenerId inListenerId,
+ PAPIStatus * outStatus )
+{
+ removeListener( inPAPI, inListenerId, outStatus );
+}
+
+void papiFreeLayerList( PAPILayerList * inList )
+{
+ deleteLayerList( inList );
+}
+
+void papiFreeStringList( PAPIStringList * inList )
+{
+ deleteStringList( inList );
+}
diff --git a/libapoc/papi.h b/libapoc/papi.h
new file mode 100644
index 0000000..0addec9
--- /dev/null
+++ b/libapoc/papi.h
@@ -0,0 +1,146 @@
+/*
+ * 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.
+ */
+/* papi.h - Policy Access API */
+
+#ifndef PAPI_H_
+#define PAPI_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "papiTypes.h"
+
+#ifdef WIN32
+#ifdef PAPI_EXPORTS
+#define PAPI_API __declspec(dllexport)
+#else
+#define PAPI_API __declspec(dllimport)
+#endif
+#else
+#define PAPI_API
+#endif
+
+/* Main PAPI functions */
+
+/*
+ * Obtain a new PAPI handle for the specified entity
+ * Specifying inEntityId=NULL will result in the entity id being calculated
+ * from the current user id.
+ */
+PAPI_API PAPI * papiInitialise( const char * inEntityId,
+ PAPIStatus * outStatus );
+
+/*
+ * Same as papiInitialise with the additional possibility of specifying
+ * a listener function which will be called in the event of a daemon connect or
+ * disconnect.
+ */
+PAPI_API PAPI * papiInitialiseWithListener( const char * inEntityId,
+ PAPIConnectionListener inListener,
+ void * inUserData,
+ PAPIStatus * outStatus );
+
+/*
+ * Invalidate and free all resoures associated with a PAPI handle
+ * previously returned by papiInitialise()
+ */
+PAPI_API void papiDeinitialise( PAPI * inPAPI, PAPIStatus * outStatus );
+
+/*
+ * Retrieve all layers for a specified component
+ * Returns a PAPILayerList ( See papiTypes.h ) ordered according to mergepath
+ *
+ * The caller must "free" the returned PAPILayerList using papiFreeLayerList()
+ */
+PAPI_API PAPILayerList * papiReadComponentLayers( const PAPI * inPAPI,
+ const char * inComponentName,
+ PAPIStatus * outStatus );
+
+/*
+ * List all available components which comply with the specified filter
+ * Returns a PAPIStringList ( See papiTypes.h )
+ *
+ * The caller must "free" the returned PAPIStringList using papiFreeStringList()
+ *
+ * TBD: specify the supported filter syntax
+ */
+PAPI_API PAPIStringList * papiListComponentNames( const PAPI * inPAPI,
+ const char * inFilter,
+ PAPIStatus * outStatus );
+
+/*
+ * Mark the specified component as offline or online
+ */
+PAPI_API void papiSetOffline( const PAPI * inPAPI,
+ const char * inComponentName,
+ int inOffline,
+ PAPIStatus * outStatus );
+
+/*
+ * Query the online/offline status of a specified component
+ */
+PAPI_API int papiIsOffline( const PAPI * inPAPI,
+ const char * inComponentName,
+ int * outIsOffline,
+ PAPIStatus * outStatus );
+
+/*
+ * Add a listener for changes to the specified component
+ */
+PAPI_API PAPIListenerId papiAddListener( const PAPI * inPAPI,
+ const char * inComponentName,
+ PAPIListener inListener,
+ void * inUserData,
+ PAPIStatus * outStatus );
+
+/*
+ * Remove a listener previously added by papiAddListener()
+ */
+PAPI_API void papiRemoveListener( const PAPI * inPAPI,
+ PAPIListenerId inListenerId,
+ PAPIStatus * outStatus );
+
+/*
+ * Free all resources associated with the specified list
+ */
+PAPI_API void papiFreeLayerList( PAPILayerList * inList );
+PAPI_API void papiFreeStringList( PAPIStringList * inList );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PAPI_H_ */
diff --git a/libapoc/papiConnection.c b/libapoc/papiConnection.c
new file mode 100644
index 0000000..7eb4b6e
--- /dev/null
+++ b/libapoc/papiConnection.c
@@ -0,0 +1,747 @@
+/*
+ * 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 "papiConnection.h"
+#include "papiSAXParserContext.h"
+#include "papiStringList.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <errno.h>
+#ifndef WNT
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif
+
+typedef struct NotificationThreadArg
+{
+ PAPIListener mListener;
+ PAPIEvent * mEvent;
+ void * mUserData;
+} NotificationThreadArg;
+
+static PAPIConnection * allocConnection (
+ PAPIConnectionListener inListener,
+ void * inUserDat,
+ PAPIListener inInternalListener,
+ void * inInternalListenerData,
+ PAPISocket inFD,
+ PAPIStatus * outStatus );
+
+static int daemonConnect( int inRetryCount );
+
+static void createNotificationThread( PAPIListener inListener,
+ PAPIEventType inType,
+ const char * inComponentName,
+ void * inUserData );
+
+static PAPIListenerThreadStatus getListenerThreadStatus(
+ PAPIConnection *inConnection );
+
+static PAPIMessage * getResponse( PAPIConnection *inConnection,
+ PAPIStatus * outStatus );
+
+static PAPIMessage * getResponseMessage( PAPIConnection *inConnection,
+ PAPIStatus * outStatus );
+
+static void handleSASLAuth( PAPIConnection *inConnection,
+ PAPIMessage * inChallenge );
+
+static int haveMessage( PAPIConnection *inConnection );
+
+static void * listener( void * inConnection );
+
+static void * notifier( void * inNotificationThreadArg );
+
+static void sendInternalNotification( PAPIConnection *inConnection,
+ PAPIMessage * inMessage );
+
+static void sendNotification( PAPIConnection *inConnection,
+ PAPIMessage * theMessage );
+
+static void setListenerThreadStatus( PAPIConnection *inConnection,
+ PAPIListenerThreadStatus inStatus );
+
+static void startListeningThread( PAPIConnection *inConnection,
+ PAPIStatus * outStatus );
+
+static void stopListeningThread( PAPIConnection *inConnection,
+ PAPIStatus * outStatus );
+
+static void takeFive( void );
+
+static int sDefaultDaemonPort = 38900;
+
+PAPIListenerId connectionAddListener( PAPIConnection * inConnection,
+ const char * inComponentName,
+ PAPIListener inListener,
+ void * inUserData,
+ PAPIStatus * outStatus )
+{
+ PAPIListenerId theListenerId = 0;
+ *outStatus = PAPISuccess;
+ if ( lockMutex( inConnection->mListenersMutex ) == 0 )
+ {
+ theListenerId = addListenerList( &( inConnection->mListeners ),
+ inComponentName,
+ inListener,
+ inUserData );
+ *outStatus = theListenerId == 0 ?
+ PAPIOutOfMemoryFailure :
+ PAPISuccess;
+ unlockMutex( inConnection->mListenersMutex );
+ }
+ else
+ {
+ *outStatus = PAPIUnknownFailure;
+ }
+ return theListenerId;
+}
+
+void connectionRemoveListener( PAPIConnection * inConnection,
+ PAPIListenerId inListenerId,
+ PAPIStatus * outStatus )
+{
+ *outStatus = PAPISuccess;
+ if ( lockMutex( inConnection->mListenersMutex ) == 0 )
+ {
+ removeListenerList( & ( inConnection->mListeners ),
+ ( PAPIListenerList * )inListenerId );
+ unlockMutex( inConnection->mListenersMutex );
+ }
+ else
+ {
+ *outStatus = PAPIUnknownFailure;
+ }
+}
+
+void connectionSetSASLAuthHandler( PAPIConnection * inConnection,
+ PAPIAuthHandler inHandler,
+ void * inHandlerUserData )
+{
+ inConnection->mAuthHandler = inHandler;
+ inConnection->mAuthHandlerUserData->mUserData = inHandlerUserData;
+}
+
+void deleteConnection( PAPIConnection * inConnection )
+{
+ if ( inConnection != 0 )
+ {
+ PAPIStatus theStatus;
+ stopListeningThread( inConnection, &theStatus );
+ deleteListenerList( inConnection->mListeners );
+ deleteMutex( inConnection->mListenersMutex );
+ deleteMutex( inConnection->mSavedMessageMutex );
+ deleteMutex( inConnection->mListenerThreadStatusMutex );
+ deleteMutex( inConnection->mConnectionStateChangeMutex );
+ if ( inConnection->mAuthHandlerUserData != 0 )
+ {
+ free( ( void * )inConnection->mAuthHandlerUserData );
+ }
+ free( ( void * )inConnection );
+ }
+}
+
+PAPIConnection * newConnection( PAPIConnectionListener inConnectionListener,
+ void * inUserData,
+ PAPIListener inInternalListener,
+ void * inInternalListenerData,
+ PAPIStatus * outStatus )
+{
+ PAPIStatus theStatus;
+ PAPIConnection * theConnection = 0;
+ int theSocket = daemonConnect( 10 );
+
+ if ( theSocket == INVALID_SOCKET )
+ {
+ *outStatus = PAPIConnectionFailure;
+ }
+ else
+ {
+ *outStatus = PAPISuccess;
+ }
+ if ( *outStatus == PAPISuccess || isDaemonEnabled() == 1 )
+ {
+ theConnection = allocConnection( inConnectionListener,
+ inUserData,
+ inInternalListener,
+ inInternalListenerData,
+ theSocket,
+ &theStatus );
+ if ( theStatus == PAPISuccess )
+ {
+ startListeningThread( theConnection, &theStatus );
+ }
+ if ( theStatus != PAPISuccess )
+ {
+ deleteConnection( theConnection );
+ theConnection = 0;
+ *outStatus = theStatus;
+ }
+ }
+ return theConnection;
+}
+
+int readBytes( PAPIConnection * inConnection, char * inBuffer, int inLen )
+{
+ int theTotalByteCount = 0;
+ while ( inLen > 0 )
+ {
+ int theByteCount = -1;
+ if ( haveMessage( inConnection ) != -1 )
+ {
+ theByteCount =
+ recv(inConnection->mFD, inBuffer + theTotalByteCount, inLen, 0);
+ if ( theByteCount == -1 && errno == EINTR )
+ {
+ theByteCount = 0;
+ }
+ }
+ if ( theByteCount == SOCKET_ERROR )
+ {
+ theTotalByteCount = -1;
+ break;
+ }
+ else
+ {
+ inLen -= theByteCount;
+ theTotalByteCount += theByteCount;
+ }
+ }
+ return theTotalByteCount;
+}
+
+int readContentLength( PAPIConnection * inConnection )
+{
+ char theBuffer[ 15 ];
+ int theIndex;
+ int theContentLength = -1;
+ if ( readBytes( inConnection, theBuffer, 15 ) != 15 )
+ {
+ return -1;
+ }
+ if ( strncmp( theBuffer,
+ CONTENTLENGTH,
+ sizeof( CONTENTLENGTH ) - 1 ) != 0)
+ {
+ return -1;
+ }
+ theIndex = 0;
+ while ( readBytes( inConnection, theBuffer + theIndex, 1 ) == 1 )
+ {
+ if ( theBuffer[ theIndex ] == '\n' )
+ {
+ theBuffer[ theIndex - 1 ] = 0;
+ theContentLength = atoi( theBuffer );
+ break;
+ }
+ theIndex ++;
+ }
+ return theContentLength;
+}
+
+PAPIMessage * sendRequest( PAPIConnection * inConnection,
+ PAPIMessage * inRequestMessage,
+ PAPIStatus * outStatus )
+{
+ int theContentLength;
+ char theContentLengthString[ MAX_CONTENT_LENGTH_SIZE ];
+ char * theRequest;
+ PAPIMessage * theResponse = 0;
+
+ *outStatus = PAPISuccess;
+
+ if ( inConnection == 0 || inConnection->mFD == INVALID_SOCKET )
+ {
+ *outStatus = PAPIConnectionFailure;
+ return 0;
+ }
+
+ theRequest = messageToString( inRequestMessage );
+ if ( theRequest != 0 && ( theContentLength = strlen( theRequest ) ) > 0 )
+ {
+ char * theBuf;
+ int theSize;
+ snprintf( theContentLengthString,
+ MAX_CONTENT_LENGTH_SIZE,
+ "%s%d\r\n",
+ CONTENTLENGTH,
+ theContentLength );
+
+ deleteMessage( inConnection->mSavedMessage );
+ inConnection->mSavedMessage = 0;
+ theSize = strlen( theContentLengthString ) + theContentLength + 1;
+ theBuf = ( char * )malloc( theSize );
+ if ( theBuf == 0 )
+ {
+ *outStatus = PAPIOutOfMemoryFailure;
+ free( ( void * )theRequest );
+ return 0;
+ }
+ snprintf( theBuf, theSize, "%s%s", theContentLengthString, theRequest );
+ if ( send( inConnection->mFD,
+ ( void * )theBuf,
+ theSize - 1,
+ 0 ) == SOCKET_ERROR )
+ {
+ *outStatus = PAPIConnectionFailure;
+ free( ( void * )theBuf );
+ free( ( void * )theRequest );
+ return 0;
+ }
+ free( ( void * )theBuf );
+ free( ( void * )theRequest );
+ theResponse = getResponse( inConnection, outStatus );
+ }
+ else
+ {
+ free( ( void * )theRequest );
+ }
+ return theResponse;
+}
+
+void setBlocking( PAPIConnection * inConnection, int inIsBlocking )
+{
+ inConnection->mFDPollTimeout = inIsBlocking == 1 ?
+ -1 : getTransactionTimeout();
+}
+
+PAPIConnection* allocConnection( PAPIConnectionListener inConnectionListener,
+ void * inUserData,
+ PAPIListener inInternalListener,
+ void * inInternalListenerData,
+ PAPISocket inSocket,
+ PAPIStatus * outStatus )
+{
+ PAPIConnection * theConnection =
+ ( PAPIConnection * )malloc( sizeof( PAPIConnection ) );
+ if ( theConnection != 0 )
+ {
+ theConnection->mFD = inSocket;
+ theConnection->mFDPollTimeout = getTransactionTimeout();
+ theConnection->mListeners = 0;
+ theConnection->mSavedMessage = 0;
+ theConnection->mListenerThreadStatus = NOT_RUNNING;
+ theConnection->mConnectionListener = inConnectionListener;
+ theConnection->mUserData = inUserData;
+ theConnection->mListenersMutex = newMutex();
+ theConnection->mSavedMessageMutex = newMutex();
+ theConnection->mListenerThreadStatusMutex= newMutex();
+ theConnection->mConnectionStateChangeMutex= newMutex();
+ theConnection->mInternalListener = inInternalListener;
+ theConnection->mInternalListenerData = inInternalListenerData;
+ theConnection->mAuthHandler = 0;
+ theConnection->mAuthHandlerUserData =
+ ( PAPIAuthHandlerData * )malloc( sizeof( PAPIAuthHandlerData ) );
+ *outStatus = PAPISuccess;
+ }
+ else
+ {
+ *outStatus = PAPIOutOfMemoryFailure;
+ }
+ return theConnection;
+}
+
+PAPISocket daemonConnect( int inRetryCount )
+{
+ int thePort = getDaemonPort();
+ PAPISocket theSocket;
+ PAPIConnectResult theRC =
+ getConnectedSocket( thePort, SOCK_STREAM, 0, &theSocket );
+
+ if ( theRC == PAPIConnectRejected ||
+ ( theRC == PAPIConnectFailed && startDaemon() == 0 ) )
+ {
+ theRC =
+ getConnectedSocket( thePort, SOCK_STREAM, inRetryCount, &theSocket);
+ }
+ return theSocket;
+}
+
+void createNotificationThread( PAPIListener inListener,
+ PAPIEventType inType,
+ const char * inComponentName,
+ void * inUserData )
+{
+ NotificationThreadArg * theArg =
+ ( NotificationThreadArg * )malloc( sizeof( NotificationThreadArg ) );
+ if ( theArg != 0 )
+ {
+ theArg->mEvent = ( PAPIEvent * )malloc( sizeof( PAPIEvent ) );
+ if ( theArg->mEvent != 0 )
+ {
+ theArg->mEvent->eventType = inType;
+ theArg->mEvent->componentName = strdup( inComponentName );
+ theArg->mListener = inListener;
+ theArg->mUserData = inUserData;
+
+ createThread( notifier, ( void *)theArg );
+ }
+ }
+}
+
+PAPIListenerThreadStatus getListenerThreadStatus(
+ PAPIConnection * inConnection )
+{
+ PAPIListenerThreadStatus theListenerThreadStatus = NOT_RUNNING;
+ if ( lockMutex( inConnection->mListenerThreadStatusMutex ) == 0 )
+ {
+ theListenerThreadStatus = inConnection->mListenerThreadStatus;
+ unlockMutex( inConnection->mListenerThreadStatusMutex );
+ }
+ return theListenerThreadStatus;
+}
+
+PAPIMessage * getResponse( PAPIConnection * inConnection,
+ PAPIStatus * outStatus )
+{
+ PAPIMessage * theResponse = 0;
+ *outStatus = PAPISuccess;
+ while ( theResponse == 0 && inConnection->mFD != INVALID_SOCKET )
+ {
+ if ( lockMutex( inConnection->mSavedMessageMutex ) == 0 )
+ {
+ theResponse = inConnection->mSavedMessage;
+ inConnection->mSavedMessage = 0;
+ unlockMutex( inConnection->mSavedMessageMutex );
+ }
+ takeFive();
+ }
+ if ( theResponse == 0 || inConnection->mFD == INVALID_SOCKET )
+ {
+ *outStatus = PAPIConnectionFailure;
+ }
+ return theResponse;
+}
+
+PAPIMessage * getResponseMessage( PAPIConnection * inConnection,
+ PAPIStatus * outStatus )
+{
+ PAPISAXUserData theUserData;
+ PAPISAXParserContext theSAXParserContext;
+ PAPIMessage * theResponse = 0;
+
+ theUserData.mMessage = 0;
+ theSAXParserContext =
+ newSAXParserContext( inConnection, &theUserData );
+ if ( parse( theSAXParserContext ) != 0 )
+ {
+ if ( inConnection->mFD == INVALID_SOCKET )
+ {
+ *outStatus = PAPIConnectionFailure;
+ }
+ else
+ {
+ *outStatus = PAPIUnknownFailure;
+ }
+ }
+ deleteSAXParserContext( theSAXParserContext );
+ return theUserData.mMessage;
+}
+
+void handleSASLAuth( PAPIConnection * inConnection, PAPIMessage * inChallenge )
+{
+ PAPIAuthHandler theHandler = inConnection->mAuthHandler;
+ PAPIAuthHandlerData * theData = inConnection->mAuthHandlerUserData;
+ theData->mChallenge = inChallenge;
+ /* avoid calling handler repeatedly during sasl auth */
+ inConnection->mAuthHandler = 0;
+ createThread( theHandler, theData );
+}
+
+int haveMessage( PAPIConnection * inConnection )
+{
+ int bHaveMessage = 0;
+ int theRC;
+
+ theRC = socketPoll( inConnection->mFD, inConnection->mFDPollTimeout );
+ if ( theRC == 1 )
+ {
+ char theByte;
+ if ( recv( inConnection->mFD, &theByte, 1, MSG_PEEK ) != 1 )
+ {
+ if ( errno != EINTR )
+ {
+ bHaveMessage = -1;
+ }
+ }
+ else
+ {
+ bHaveMessage = 1;
+ }
+ }
+ else
+ {
+ bHaveMessage = -1;
+ }
+ return bHaveMessage;
+}
+
+void * listener( void * inConnection )
+{
+#ifndef WNT
+ sigset_t theSigset;
+#endif
+ PAPIConnection * theConnection = ( PAPIConnection * )inConnection;
+
+#ifndef WNT
+ sigemptyset( &theSigset );
+ sigaddset( &theSigset, SIGHUP );
+ pthread_sigmask( SIG_BLOCK, &theSigset, 0 );
+#endif
+ setListenerThreadStatus( inConnection, RUNNING );
+ while ( getListenerThreadStatus( inConnection ) == RUNNING )
+ {
+ PAPIStatus theStatus;
+ PAPIMessage * theMessage;
+ if ( theConnection->mFD != INVALID_SOCKET )
+ {
+ int bHaveMessage = haveMessage( theConnection );
+ if ( bHaveMessage == 0 )
+ {
+ continue;
+ }
+ else if ( bHaveMessage == -1 )
+ {
+ papiClose( theConnection->mFD );
+ theConnection->mFD = INVALID_SOCKET;
+ if ( lockMutex( theConnection->mConnectionStateChangeMutex )
+ == 0 )
+ {
+ theConnection->mConnectionListener( PAPIDisconnected,
+ theConnection->mUserData );
+ unlockMutex( theConnection->mConnectionStateChangeMutex );
+ }
+ if ( isDaemonEnabled() != 1 )
+ {
+ break;
+ }
+ continue;
+ }
+ theMessage = getResponseMessage( theConnection, &theStatus );
+ if ( theMessage != 0 )
+ {
+ if ( theMessage->mName == PAPImodifyNotification ||
+ theMessage->mName == PAPIaddNotification ||
+ theMessage->mName == PAPIremoveNotification )
+ {
+ sendInternalNotification( theConnection, theMessage );
+ sendNotification( theConnection, theMessage );
+ deleteMessage( theMessage );
+ }
+ else if ( theMessage->mName == PAPIRespSuccessContinueSASLAuth&&
+ theConnection->mAuthHandler != 0 )
+ {
+ handleSASLAuth( theConnection, theMessage );
+ }
+ else
+ {
+ if ( lockMutex( theConnection->mSavedMessageMutex ) == 0 )
+ {
+ theConnection->mSavedMessage = theMessage;
+ unlockMutex( theConnection->mSavedMessageMutex );
+ }
+ }
+ }
+ }
+ else
+ {
+ if ( lockMutex( theConnection->mConnectionStateChangeMutex ) == 0 )
+ {
+ theConnection->mFD = daemonConnect( 1 );
+ setBlocking( theConnection, 0 );
+ if ( theConnection->mFD != INVALID_SOCKET )
+ {
+ theConnection->mConnectionListener( PAPIConnected,
+ theConnection->mUserData );
+ }
+ unlockMutex( theConnection->mConnectionStateChangeMutex );
+ if ( theConnection->mFD == INVALID_SOCKET )
+ {
+ papiSleep( 10 );
+ }
+ }
+ }
+ }
+ setListenerThreadStatus( inConnection, NOT_RUNNING );
+ return 0;
+}
+
+void * notifier( void * inArg )
+{
+ NotificationThreadArg * theArg = ( NotificationThreadArg * )inArg;
+ theArg->mListener( theArg->mEvent, theArg->mUserData );
+ free( ( void *)theArg->mEvent->componentName );
+ free( ( void *)theArg->mEvent );
+ free( ( void *)theArg );
+ return 0;
+}
+
+void sendInternalNotification( PAPIConnection * inConnection,
+ PAPIMessage * inMessage )
+{
+ PAPIMessageName theName = inMessage->mName;
+ if ( theName == PAPIaddNotification || theName == PAPIremoveNotification )
+ {
+ PAPIStringList * theComponentNames =
+ getParamValue( inMessage, PAPIParamComponentName );
+ PAPIStringList * theTmpList = theComponentNames;
+ while ( theTmpList != 0 )
+ {
+ PAPIEvent theEvent;
+ theEvent.eventType =
+ theName == PAPIaddNotification ?
+ PAPIComponentAdd : PAPIComponentRemove;
+ theEvent.componentName = theTmpList->data;
+ inConnection->mInternalListener(
+ &theEvent,
+ inConnection->mInternalListenerData );
+ theTmpList = theTmpList->next;
+ }
+ deleteStringList( theComponentNames );
+ }
+}
+
+void sendNotification( PAPIConnection * inConnection, PAPIMessage * inMessage )
+{
+ PAPIStringList * theComponentNames =
+ getParamValue( inMessage, PAPIParamComponentName );
+ PAPIStringList * theTmpList = theComponentNames;
+ while ( theComponentNames != 0 )
+ {
+ PAPIListenerList * theListenerList;
+
+ if ( lockMutex( inConnection->mListenersMutex ) == 0 )
+ {
+ theListenerList = inConnection->mListeners;
+ while ( theListenerList != 0 )
+ {
+ int theLen = strlen( theListenerList->mComponentName );
+ if ( strcmp( theListenerList->mComponentName,
+ theComponentNames->data ) == 0 ||
+ ( theListenerList->mComponentName[ theLen - 1 ] == '.' &&
+ strncmp( theListenerList->mComponentName,
+ theComponentNames->data,
+ theLen ) == 0 ) )
+ {
+ PAPIEventType theEventType;
+ switch( inMessage->mName )
+ {
+ case PAPImodifyNotification:
+ theEventType = PAPIComponentModify;
+ break;
+
+ case PAPIaddNotification:
+ theEventType = PAPIComponentAdd;
+ break;
+
+ case PAPIremoveNotification:
+ theEventType = PAPIComponentRemove;
+ break;
+ }
+ createNotificationThread( theListenerList->mListener,
+ theEventType,
+ theComponentNames->data,
+ theListenerList->mUserData);
+ }
+ theListenerList = theListenerList->mNext;
+ }
+ theComponentNames = theComponentNames->next;
+ unlockMutex( inConnection->mListenersMutex );
+ }
+ }
+ deleteStringList( theTmpList );
+}
+
+void setListenerThreadStatus( PAPIConnection * inConnection,
+ PAPIListenerThreadStatus inStatus )
+{
+ if ( lockMutex(inConnection->mListenerThreadStatusMutex ) == 0 )
+ {
+ inConnection->mListenerThreadStatus = inStatus;
+ unlockMutex( inConnection->mListenerThreadStatusMutex );
+ }
+}
+
+void startListeningThread( PAPIConnection * inConnection,
+ PAPIStatus * outStatus )
+{
+ inConnection->mListenerThread = createThread( listener, inConnection );
+ if ( inConnection->mListenerThread != 0 )
+ {
+ *outStatus = PAPISuccess;
+ }
+ else
+ {
+ *outStatus = PAPIUnknownFailure;
+ }
+}
+
+void stopListeningThread( PAPIConnection * inConnection, PAPIStatus * outStatus)
+{
+ *outStatus = PAPISuccess;
+ if ( getListenerThreadStatus( inConnection ) == RUNNING )
+ {
+ if ( lockMutex( inConnection->mListenersMutex ) == 0 )
+ {
+ destroyThread( inConnection->mListenerThread );
+ papiClose( inConnection->mFD );
+ unlockMutex( inConnection->mListenersMutex );
+ }
+ else
+ {
+ *outStatus = PAPIUnknownFailure;
+ }
+ }
+}
+
+void takeFive( void )
+{
+#ifndef WNT
+
+ struct timespec theTimeout;
+
+ theTimeout.tv_sec = 0;
+ theTimeout.tv_nsec = 5000000;
+ nanosleep( &theTimeout, NULL);
+
+#else
+
+ Sleep( 50 );
+
+#endif
+}
diff --git a/libapoc/papiConnection.h b/libapoc/papiConnection.h
new file mode 100644
index 0000000..b973806
--- /dev/null
+++ b/libapoc/papiConnection.h
@@ -0,0 +1,117 @@
+/*
+ * 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 PAPICONNECTION_H_
+#define PAPICONNECTION_H_
+
+#include "papiListenerList.h"
+#include "papiMessage.h"
+#include "papiUtils.h"
+#include "papiTypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum { NOT_RUNNING, EXITING, RUNNING } PAPIListenerThreadStatus;
+
+typedef struct PAPIAuthHandlerData
+{
+ void * mUserData;
+ PAPIMessage * mChallenge;
+} PAPIAuthHandlerData;
+
+typedef void * ( *PAPIAuthHandler )( void * inAuthData );
+
+typedef struct PAPIConnection
+{
+ PAPISocket mFD;
+ int mFDPollTimeout;
+ PAPIListenerList * mListeners;
+ PAPIMutex * mListenersMutex;
+ PAPIMessage * mSavedMessage;
+ PAPIMutex * mSavedMessageMutex;
+ PAPIThread mListenerThread;
+ PAPIListenerThreadStatus mListenerThreadStatus;
+ PAPIMutex * mListenerThreadStatusMutex;
+ PAPIConnectionListener mConnectionListener;
+ PAPIMutex * mConnectionStateChangeMutex;
+ void * mUserData;
+ PAPIListener mInternalListener;
+ void * mInternalListenerData;
+ PAPIAuthHandler mAuthHandler;
+ PAPIAuthHandlerData * mAuthHandlerUserData;
+} PAPIConnection;
+
+PAPIListenerId connectionAddListener( PAPIConnection * inConnection,
+ const char * inComponentName,
+ PAPIListener inListener,
+ void * inUserData,
+ PAPIStatus * outStatus );
+
+void connectionRemoveListener( PAPIConnection * inConnection,
+ PAPIListenerId inListenerId,
+ PAPIStatus * outStatus );
+
+void connectionSetSASLAuthHandler( PAPIConnection * inConnection,
+ PAPIAuthHandler inAuthHandler,
+ void * inUserData );
+
+void deleteConnection ( PAPIConnection * inConnection );
+
+
+PAPIConnection * newConnection( PAPIConnectionListener inConnectionListener,
+ void * inUserData,
+ PAPIListener inInternalListener,
+ void * inInternalListenerData,
+ PAPIStatus * outStatus );
+
+int readBytes( PAPIConnection * inConnection,
+ char * inBuffer,
+ int inLen );
+
+int readContentLength( PAPIConnection * inConnection );
+
+PAPIMessage * sendRequest( PAPIConnection * inConnection,
+ PAPIMessage * inRequest,
+ PAPIStatus * outStatus );
+
+void setBlocking( PAPIConnection * inConnection,
+ int inIsBlocking );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PAPICONNECTION_H_ */
diff --git a/libapoc/papiDaemon.c b/libapoc/papiDaemon.c
new file mode 100644
index 0000000..841ee19
--- /dev/null
+++ b/libapoc/papiDaemon.c
@@ -0,0 +1,516 @@
+/*
+ * 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 "papiDaemon.h"
+#include "papiMessage.h"
+#include "papiUtils.h"
+#include "papiEntityList.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static PAPIMessage * createCreateSessionRequest(
+ const char * inUserId,
+ const PAPIEntityList * inEntityId,
+ const char * inCredentials );
+
+static void createSession( PAPIDaemon * inDaemon,
+ PAPIStatus * outStatus );
+
+static void daemonReaddListener( PAPIDaemon * inDaemon,
+ const char * inComponentName,
+ PAPIStatus * outStatus );
+
+static void destroySession( PAPIDaemon * inDaemon );
+
+static const char * getLocalCreds( const char * inLocalChallengeFile,
+ PAPIStatus * outStatus );
+
+static void * saslAuthHandler( void * inData );
+
+static int sLocalCredentialsBufferSize = 21;
+
+PAPIListenerId daemonAddListener( PAPIDaemon * inDaemon,
+ const char * inComponentName,
+ PAPIListener inListener,
+ void * inUserData,
+ PAPIStatus * outStatus )
+{
+ PAPIListenerId theListenerId = 0;
+ daemonReaddListener( inDaemon, inComponentName, outStatus );
+ if ( *outStatus == PAPISuccess )
+ {
+ theListenerId = connectionAddListener( inDaemon->mConnection,
+ inComponentName,
+ inListener,
+ inUserData,
+ outStatus );
+ }
+ return theListenerId;
+}
+
+PAPIStringList * daemonList( PAPIDaemon * inDaemon, PAPIStatus * outStatus )
+{
+ PAPIStringList * theList = 0;
+ if ( inDaemon->mSessionId != 0 )
+ {
+ PAPIMessage * theRequest;
+ PAPIMessage * theResponse;
+
+ theRequest = newMessage( PAPIReqList );
+ if ( theRequest == 0 )
+ {
+ *outStatus = PAPIOutOfMemoryFailure;
+ return 0;
+ }
+ addParam( theRequest, PAPIParamSessionId, inDaemon->mSessionId );
+ theResponse = sendRequest( inDaemon->mConnection,theRequest,outStatus );
+ if ( theResponse != 0 )
+ {
+ theList = getParamValue( theResponse, PAPIParamComponentName );
+ }
+
+ deleteMessage( theRequest );
+ deleteMessage( theResponse );
+ }
+ return theList;
+}
+
+PAPIStringList * daemonRead( PAPIDaemon * inDaemon,
+ const char * inComponentName,
+ PAPIStatus * outStatus )
+{
+ PAPIStringList * theLayers = 0;
+ if ( inDaemon->mSessionId != 0 )
+ {
+ PAPIMessage * theRequest;
+ PAPIMessage * theResponse;
+
+ theRequest = newMessage( PAPIReqRead );
+ if ( theRequest == 0 )
+ {
+ *outStatus = PAPIOutOfMemoryFailure;
+ return 0;
+ }
+ addParam( theRequest, PAPIParamSessionId, inDaemon->mSessionId );
+ addParam( theRequest, PAPIParamComponentName, inComponentName );
+ theResponse = sendRequest( inDaemon->mConnection,theRequest,outStatus );
+ if ( theResponse != 0 )
+ {
+ theLayers = getParamValue( theResponse, PAPIParamLayer );
+ }
+
+ deleteMessage( theRequest );
+ deleteMessage( theResponse );
+ }
+ return theLayers;
+}
+
+void daemonReconnect( PAPIDaemon * inDaemon,
+ PAPIStatus * outStatus )
+{
+ setBlocking( inDaemon->mConnection, 0 );
+ createSession( inDaemon, outStatus );
+ if ( *outStatus == PAPISuccess )
+ {
+ PAPIListenerList * theList = inDaemon->mConnection->mListeners;
+ setBlocking( inDaemon->mConnection, 1 );
+ while ( theList != 0 )
+ {
+ daemonReaddListener( inDaemon, theList->mComponentName, outStatus);
+ theList = theList->mNext;
+ }
+ }
+}
+
+void daemonRemoveListener( PAPIDaemon * inDaemon,
+ PAPIListenerId inListenerId,
+ PAPIStatus * outStatus )
+{
+ *outStatus = PAPISuccess;
+ if ( inDaemon->mSessionId != 0 && inListenerId != 0 )
+ {
+ PAPIMessage * theRequest;
+ PAPIMessage * theResponse;
+ PAPIListenerList * theListenerList =
+ ( PAPIListenerList * )inListenerId;
+ const char * theComponentName = theListenerList->mComponentName;
+
+ if ( theComponentName == 0 )
+ {
+ return;
+ }
+
+ theRequest = newMessage( PAPIReqRemoveListener );
+ if ( theRequest == 0 )
+ {
+ *outStatus = PAPIOutOfMemoryFailure;
+ return;
+ }
+ addParam( theRequest, PAPIParamSessionId, inDaemon->mSessionId );
+ addParam( theRequest, PAPIParamComponentName, theComponentName );
+ theResponse = sendRequest( inDaemon->mConnection,theRequest,outStatus );
+ deleteMessage( theRequest );
+ deleteMessage( theResponse );
+
+ if ( *outStatus == PAPISuccess )
+ {
+ connectionRemoveListener( inDaemon->mConnection,
+ inListenerId,
+ outStatus );
+ }
+ }
+}
+
+void deleteDaemon( PAPIDaemon * inDaemon )
+{
+ if ( inDaemon != 0 )
+ {
+ if ( inDaemon->mUserId != 0 )
+ {
+ free( ( void *)inDaemon->mUserId );
+ }
+ if ( inDaemon->mEntities != 0 )
+ {
+ papiFreeEntityList( inDaemon->mEntities );
+ }
+ if ( inDaemon->mSessionId != 0 )
+ {
+ destroySession( inDaemon );
+ free( ( void * )inDaemon->mSessionId );
+ }
+ deleteConnection( inDaemon->mConnection );
+ free( inDaemon );
+ }
+}
+
+static void fillDaemonEntities( PAPIDaemon * inDaemon )
+{
+ PAPIEntityList *theEntity = inDaemon->mEntities;
+
+ while ( theEntity != 0 )
+ {
+ switch ( theEntity->entityType )
+ {
+ case PAPIEntityUser:
+ if ( theEntity->entityId == 0 )
+ {
+ theEntity->entityId = strdup(inDaemon->mUserId);
+ }
+ break ;
+ default:
+ break ;
+ }
+ theEntity = theEntity->next;
+ }
+}
+
+PAPIDaemon * newDaemon( const PAPIEntityList * inEntities,
+ PAPIConnectionListener inListener,
+ void * inUserData,
+ PAPIListener inInternalListener,
+ void * inInternalListenerData,
+ PAPIStatus * outStatus )
+{
+ PAPIDaemon * theDaemon = ( PAPIDaemon *)malloc( sizeof( PAPIDaemon ) );
+ if ( theDaemon == 0 )
+ {
+ *outStatus = PAPIOutOfMemoryFailure;
+ return 0;
+ }
+ memset( theDaemon, 0, sizeof( PAPIDaemon ) );
+ theDaemon->mUserId = getUserName();
+ if ( theDaemon->mUserId == 0 )
+ {
+ *outStatus = PAPIUnknownFailure;
+ deleteDaemon( theDaemon );
+ return 0;
+ }
+ if ( inEntities != 0 )
+ {
+ theDaemon->mEntities = papiCopyEntityList( inEntities );
+ if ( theDaemon->mEntities == 0 )
+ {
+ *outStatus = PAPIOutOfMemoryFailure;
+ deleteDaemon( theDaemon );
+ return 0;
+ }
+ fillDaemonEntities( theDaemon );
+ }
+
+
+ theDaemon->mConnection = newConnection( inListener,
+ inUserData,
+ inInternalListener,
+ inInternalListenerData,
+ outStatus );
+ if ( *outStatus == PAPISuccess )
+ {
+ daemonReconnect( theDaemon, outStatus );
+ }
+ if ( *outStatus != PAPISuccess && *outStatus != PAPIConnectionFailure )
+ {
+ deleteDaemon( theDaemon );
+ theDaemon = 0;
+ }
+ return theDaemon;
+}
+
+PAPIMessage * createCreateSessionRequest( const char * inUserId,
+ const PAPIEntityList * inEntities,
+ const char * inCredentials )
+{
+ PAPIMessage * theRequest = newMessage( PAPIReqCreateSessionExt );
+ if ( theRequest != 0 )
+ {
+ const PAPIEntityList * entity = inEntities;
+
+ addParam( theRequest, PAPIParamUserId, inUserId );
+ addParam( theRequest, PAPIParamCredentials, inCredentials );
+ while ( entity != 0 )
+ {
+ addParam( theRequest, PAPIParamEntityType,
+ getEntityTypeString( entity->entityType ) );
+ addParam( theRequest, PAPIParamEntityId, entity->entityId );
+ entity = entity->next;
+ }
+ }
+ return theRequest;
+}
+
+void createSession( PAPIDaemon * inDaemon,
+ PAPIStatus * outStatus )
+{
+ int shouldContinue = 1;
+ char * theCreds = 0;
+ void * theSASLContext = 0;
+
+ connectionSetSASLAuthHandler( inDaemon->mConnection, 0, 0 );
+ while ( shouldContinue == 1 )
+ {
+ PAPIMessage * theResponse;
+ PAPIMessage * theRequest =
+ createCreateSessionRequest( inDaemon->mUserId,
+ inDaemon->mEntities,
+ theCreds );
+ if ( theCreds != 0 )
+ {
+ free( ( void * )theCreds );
+ }
+ if ( theRequest == 0 )
+ {
+ *outStatus = PAPIOutOfMemoryFailure;
+ connectionSetSASLAuthHandler( inDaemon->mConnection,
+ saslAuthHandler,
+ inDaemon );
+ return;
+ }
+ theResponse = sendRequest(inDaemon->mConnection, theRequest, outStatus);
+ deleteMessage( theRequest );
+ if ( *outStatus == PAPISuccess )
+ {
+ PAPIStringList * theValues;
+ switch( theResponse->mName )
+ {
+ case PAPIRespSuccess:
+ theValues = getParamValue( theResponse, PAPIParamSessionId);
+ if ( theValues != 0 )
+ {
+ inDaemon->mSessionId = strdup( theValues->data );
+ deleteStringList( theValues );
+ }
+ shouldContinue = 0;
+ break;
+
+ case PAPIRespSuccessContinueLocalAuth:
+ case PAPIRespSuccessContinueSASLAuth:
+ theValues = getParamValue( theResponse, PAPIParamMessage );
+ if ( theValues != 0 )
+ {
+ theCreds =
+ theResponse->mName == PAPIRespSuccessContinueLocalAuth?
+ ( char * )getLocalCreds( theValues->data,
+ outStatus ) :
+ ( char * )getSASLCreds( theValues->data,
+ outStatus );
+ if ( *outStatus != PAPISuccess )
+ {
+ theCreds = 0;
+ *outStatus = PAPISuccess;
+ }
+ deleteStringList( theValues );
+ }
+ else
+ {
+ *outStatus = PAPIUnknownFailure;
+ shouldContinue = 0;
+ }
+ break;
+
+ case PAPIRespConnectionFailure:
+ case PAPIRespAuthenticationFailure:
+ *outStatus = PAPISuccess;
+ shouldContinue = 0;
+ break;
+
+ default:
+ *outStatus = PAPIUnknownFailure;
+ shouldContinue = 0;
+ break;
+ }
+ }
+ else
+ {
+ shouldContinue = 0;
+ }
+ deleteMessage( theResponse );
+ }
+ connectionSetSASLAuthHandler( inDaemon->mConnection,
+ saslAuthHandler,
+ inDaemon );
+}
+
+void daemonReaddListener( PAPIDaemon * inDaemon,
+ const char * inComponentName,
+ PAPIStatus * outStatus )
+{
+ if ( inDaemon->mSessionId != 0 )
+ {
+ PAPIMessage * theRequest;
+ PAPIMessage * theResponse;
+
+ theRequest = newMessage( PAPIReqAddListener );
+ if ( theRequest == 0 )
+ {
+ *outStatus = PAPIOutOfMemoryFailure;
+ return;
+ }
+ addParam( theRequest, PAPIParamSessionId, inDaemon->mSessionId );
+ addParam( theRequest, PAPIParamComponentName, inComponentName );
+ theResponse = sendRequest( inDaemon->mConnection,theRequest,outStatus );
+ deleteMessage( theRequest );
+ deleteMessage( theResponse );
+ }
+ else
+ {
+ *outStatus = PAPIAuthenticationFailure;
+ }
+}
+
+void destroySession( PAPIDaemon * inDaemon )
+{
+ if ( inDaemon->mSessionId != 0 )
+ {
+ PAPIMessage * theRequest;
+ PAPIMessage * theResponse;
+ PAPIStatus theStatus;
+
+ theRequest = newMessage( PAPIReqDestroySession );
+ if ( theRequest == 0 )
+ {
+ return;
+ }
+ addParam( theRequest, PAPIParamSessionId, inDaemon->mSessionId );
+ theResponse = sendRequest( inDaemon->mConnection,theRequest,&theStatus);
+ deleteMessage( theRequest );
+ deleteMessage( theResponse );
+ }
+}
+
+const char * getLocalCreds( const char * inLocalChallengeFile,
+ PAPIStatus * outStatus )
+{
+ char * theCredentials = ( char * )malloc( sLocalCredentialsBufferSize );
+ if ( theCredentials == 0 )
+ {
+ *outStatus = PAPIOutOfMemoryFailure;
+ return theCredentials;
+ }
+ if ( inLocalChallengeFile != 0 )
+ {
+ FILE * theFile = fopen( inLocalChallengeFile, "r" );
+ if ( theFile != 0 )
+ {
+ fgets( theCredentials,
+ sLocalCredentialsBufferSize,
+ theFile );
+ fclose( theFile );
+ }
+ else
+ {
+ *outStatus = PAPIUnknownFailure;
+ }
+ }
+ else
+ {
+ *outStatus = PAPIUnknownFailure;
+ }
+ return theCredentials;
+}
+
+void * saslAuthHandler( void * inData )
+{
+ PAPIAuthHandlerData * theData = ( PAPIAuthHandlerData * )inData;
+ PAPIDaemon * theDaemon = ( PAPIDaemon * )theData->mUserData;
+ PAPIStringList * theValues = getParamValue( theData->mChallenge,
+ PAPIParamMessage );
+ deleteMessage( theData->mChallenge );
+ if ( theValues != 0 )
+ {
+ PAPIStatus theStatus;
+ const char * theCreds =
+ getSASLCreds( theValues->data, &theStatus );
+ PAPIMessage * theRequest =
+ createCreateSessionRequest( theDaemon->mUserId,
+ theDaemon->mEntities,
+ theCreds );
+ deleteStringList( theValues );
+ if ( theCreds != 0 )
+ {
+ free( ( void * )theCreds );
+ }
+ if ( theRequest != 0 )
+ {
+ PAPIMessage * theResponse =
+ sendRequest( theDaemon->mConnection, theRequest,&theStatus);
+ deleteMessage( theResponse );
+ deleteMessage( theRequest );
+ }
+ }
+ connectionSetSASLAuthHandler( theDaemon->mConnection,
+ saslAuthHandler,
+ theDaemon );
+ return 0;
+}
diff --git a/libapoc/papiDaemon.h b/libapoc/papiDaemon.h
new file mode 100644
index 0000000..b7732b8
--- /dev/null
+++ b/libapoc/papiDaemon.h
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+/* papiDaemon.h */
+
+#ifndef PAPIDAEMON_H_
+#define PAPIDAEMON_H_
+
+#include "papiConnection.h"
+#include "papiTypes.h"
+#include "papiInternal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct PAPIDaemon
+{
+ const char * mUserId;
+ PAPIEntityList * mEntities;
+ PAPIConnection * mConnection;
+ const char * mSessionId;
+ PAPIConnectionListener mConnectionListener;
+ void * mUserData;
+} PAPIDaemon;
+
+PAPIListenerId daemonAddListener( PAPIDaemon * inDaemon,
+ const char * inComponentName,
+ PAPIListener inListener,
+ void * inUserData,
+ PAPIStatus * outStatus );
+
+PAPIStringList *daemonList( PAPIDaemon * inDaemon,
+ PAPIStatus * outStatus );
+
+PAPIStringList *daemonRead( PAPIDaemon * inDaemon,
+ const char * inComponentName,
+ PAPIStatus * outStatus );
+
+void daemonReconnect( PAPIDaemon * inDaemon,
+ PAPIStatus * outStatus );
+
+void daemonRemoveListener( PAPIDaemon * inDaemon,
+ PAPIListenerId inListenerId,
+ PAPIStatus * outStatus );
+
+void deleteDaemon( PAPIDaemon * inDaemon );
+
+PAPIDaemon * newDaemon( const PAPIEntityList * inEntities,
+ PAPIConnectionListener inListener,
+ void * inUserData,
+ PAPIListener inInternalListener,
+ void * inInternalListenerData,
+ PAPIStatus * outStatus );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PAPIDAEMON_H_ */
diff --git a/libapoc/papiDatabase.c b/libapoc/papiDatabase.c
new file mode 100644
index 0000000..dad61e6
--- /dev/null
+++ b/libapoc/papiDatabase.c
@@ -0,0 +1,285 @@
+/*
+ * 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 "papiDatabase.h"
+#include "papiInternal.h"
+#include "papiUtils.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static void connectionListener( PAPIConnectionState inState,
+ void * inUserData);
+
+static int componentExists( PAPIDatabase * inDatabase,
+ const char * inComponentName );
+
+static void componentsListener( const PAPIEvent * inEvent,
+ void * inUserData );
+
+static void * onConnect( void * inDatabase );
+
+static void * onDisconnect( void * inDatabase );
+
+#define TIMESTAMPSIZE 16
+
+
+PAPIListenerId addListenerToDatabase( PAPIDatabase * inDatabase,
+ const char * inComponentName,
+ PAPIListener inListener,
+ void * inUserData,
+ PAPIStatus * outStatus )
+{
+ return daemonAddListener( inDatabase->mDaemon,
+ inComponentName,
+ inListener,
+ inUserData,
+ outStatus );
+}
+
+void deleteDatabase( PAPIDatabase * inDatabase )
+{
+ if ( inDatabase != 0 )
+ {
+ deleteStringList( inDatabase->mComponents );
+ deleteMutex( inDatabase->mComponentsMutex );
+ if ( inDatabase->mDaemon != 0 )
+ {
+ deleteDaemon( inDatabase->mDaemon );
+ }
+ deleteMutex( inDatabase->mConnectionStateMutex );
+ free( ( void *)inDatabase );
+ }
+}
+
+PAPIConnectionState getConnectionState( PAPIDatabase * inDatabase )
+{
+ PAPIConnectionState theState = PAPIDisconnected;
+ if ( lockMutex( inDatabase->mConnectionStateMutex ) == 0 )
+ {
+ theState = inDatabase->mConnectionState;
+ unlockMutex( inDatabase->mConnectionStateMutex );
+ }
+ return theState;
+}
+
+PAPILayerList * readLayersFromDatabase( PAPIDatabase * inDatabase,
+ const char * inComponentName,
+ PAPIStatus * outStatus )
+{
+ PAPILayerList * theLayerList = 0;
+ if ( componentExists( inDatabase, inComponentName ) != 0 )
+ {
+ PAPIStringList * theTmpList =
+ daemonRead( inDatabase->mDaemon, inComponentName, outStatus );
+ PAPIStringList * theList = theTmpList;
+ while ( theTmpList != 0 )
+ {
+ if ( theTmpList->data != 0 &&
+ strlen( theTmpList->data ) >= TIMESTAMPSIZE )
+ {
+ char theTimestamp[ TIMESTAMPSIZE ];
+ snprintf( theTimestamp, TIMESTAMPSIZE, "%s", theTmpList->data);
+#ifdef WNT
+ theTimestamp[ TIMESTAMPSIZE - 1 ] = 0;
+#endif
+ addLayerList( &theLayerList,
+ theTmpList->data + TIMESTAMPSIZE - 1,
+ theTimestamp );
+ theTmpList = theTmpList->next;
+ }
+ }
+ deleteStringList( theList );
+ }
+ else
+ {
+ *outStatus = PAPINoSuchComponentFailure;
+ }
+ return theLayerList;
+}
+
+PAPIStringList * readNamesFromDatabase( PAPIDatabase * inDatabase,
+ const char * inFilter )
+{
+ PAPIStringList * theList = 0;
+ if ( lockMutex( inDatabase->mComponentsMutex ) == 0 )
+ {
+ theList = copyStringList( inDatabase->mComponents );
+ unlockMutex( inDatabase->mComponentsMutex );
+ }
+ return theList;
+}
+
+void removeListenerFromDatabase( PAPIDatabase * inDatabase,
+ PAPIListenerId inListenerId,
+ PAPIStatus * outStatus )
+{
+ daemonRemoveListener( inDatabase->mDaemon, inListenerId, outStatus );
+}
+
+PAPIDatabase * newDatabase( const PAPIEntityList * inEntities,
+ PAPIConnectionListener inConnectionListener,
+ void * inUserData,
+ PAPIStatus * outStatus )
+{
+ PAPIDatabase * theDatabase =
+ ( PAPIDatabase *)malloc( sizeof( PAPIDatabase ) );
+
+ if ( theDatabase == 0 )
+ {
+ *outStatus = PAPIOutOfMemoryFailure;
+ return 0;
+ }
+ memset( theDatabase, 0, sizeof( PAPIDatabase ) );
+ theDatabase->mConnectionListener = inConnectionListener;
+ theDatabase->mUserData = inUserData;
+ theDatabase->mConnectionState = PAPIDisconnected;
+ theDatabase->mConnectionStateMutex = newMutex();
+ if ( lockMutex( theDatabase->mConnectionStateMutex ) == 0 )
+ {
+ theDatabase->mDaemon = newDaemon( inEntities,
+ connectionListener,
+ theDatabase,
+ componentsListener,
+ theDatabase,
+ outStatus );
+ if ( *outStatus != PAPISuccess &&
+ ( *outStatus != PAPIConnectionFailure || isDaemonEnabled() == 0 ) )
+ {
+ unlockMutex( theDatabase->mConnectionStateMutex );
+ deleteDatabase( theDatabase );
+ theDatabase = 0;
+ }
+ else
+ {
+ if ( *outStatus == PAPISuccess )
+ {
+ theDatabase->mComponents =
+ daemonList( theDatabase->mDaemon, outStatus );
+ theDatabase->mConnectionState = PAPIConnected;
+ }
+ theDatabase->mComponentsMutex = newMutex();
+ unlockMutex( theDatabase->mConnectionStateMutex );
+ }
+ }
+ return theDatabase;
+}
+
+void connectionListener( PAPIConnectionState inState, void * inUserData )
+{
+ createThread( inState == PAPIConnected ? onConnect : onDisconnect,
+ inUserData );
+}
+
+int componentExists( PAPIDatabase * inDatabase, const char * inComponentName )
+{
+ int haveComponent = 0;
+ if ( lockMutex( inDatabase->mComponentsMutex ) == 0 )
+ {
+ haveComponent =
+ containsString( inDatabase->mComponents, inComponentName );
+ unlockMutex( inDatabase->mComponentsMutex );
+ }
+ return haveComponent;
+}
+
+void componentsListener( const PAPIEvent * inEvent, void * inUserData )
+{
+ PAPIDatabase * theDatabase = ( PAPIDatabase * )inUserData;
+ if ( lockMutex( theDatabase->mComponentsMutex ) == 0 )
+ {
+ if ( inEvent->eventType == PAPIComponentAdd )
+ {
+ addStringList( &theDatabase->mComponents,
+ ( const char * )inEvent->componentName );
+ }
+ else
+ {
+ deleteStringList(
+ removeStringList( &theDatabase->mComponents,
+ ( const char * )inEvent->componentName ) );
+ }
+ unlockMutex( theDatabase->mComponentsMutex );
+ }
+}
+
+void * onConnect( void * inDatabase )
+{
+ PAPIStatus theStatus;
+ PAPIDatabase * theDatabase = ( PAPIDatabase * )inDatabase;
+ if ( lockMutex( theDatabase->mConnectionStateMutex ) == 0 )
+ {
+ daemonReconnect( theDatabase->mDaemon,
+ &theStatus );
+ if ( theStatus == PAPISuccess )
+ {
+ theDatabase->mConnectionState = PAPIConnected;
+ if ( lockMutex( theDatabase->mComponentsMutex ) == 0 )
+ {
+ deleteStringList( theDatabase->mComponents );
+ theDatabase->mComponents =
+ daemonList( theDatabase->mDaemon, &theStatus );
+ unlockMutex( theDatabase->mComponentsMutex );
+ }
+ unlockMutex( theDatabase->mConnectionStateMutex );
+ if ( theDatabase->mConnectionListener != 0 )
+ {
+ theDatabase->mConnectionListener( PAPIConnected,
+ theDatabase->mUserData );
+ }
+ }
+ else
+ {
+ unlockMutex( theDatabase->mConnectionStateMutex );
+ }
+ }
+ return 0;
+}
+
+void * onDisconnect( void * inDatabase )
+{
+ PAPIDatabase * theDatabase = ( PAPIDatabase * )inDatabase;
+ if ( lockMutex( theDatabase->mConnectionStateMutex ) == 0 )
+ {
+ theDatabase->mConnectionState = PAPIDisconnected;
+ unlockMutex( theDatabase->mConnectionStateMutex );
+ if ( theDatabase->mConnectionListener != 0 )
+ {
+ theDatabase->mConnectionListener( PAPIDisconnected,
+ theDatabase->mUserData );
+ }
+ }
+ return 0;
+}
diff --git a/libapoc/papiDatabase.h b/libapoc/papiDatabase.h
new file mode 100644
index 0000000..e8e3b86
--- /dev/null
+++ b/libapoc/papiDatabase.h
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+/* papiDatabase.h */
+
+#ifndef PAPIDATABASE_H_
+#define PAPIDATABASE_H_
+
+#include "papiTypes.h"
+#include "papiDaemon.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct PAPIDatabase
+{
+ PAPIStringList * mComponents;
+ PAPIMutex * mComponentsMutex;
+ PAPIDaemon * mDaemon;
+ PAPIConnectionState mConnectionState;
+ PAPIMutex * mConnectionStateMutex;
+ PAPIConnectionListener mConnectionListener;
+ void * mUserData;
+} PAPIDatabase;
+
+PAPIListenerId addListenerToDatabase( PAPIDatabase * inDatabase,
+ const char * inComponentName,
+ PAPIListener inListener,
+ void * inUserData,
+ PAPIStatus * outStatus );
+
+void deleteDatabase( PAPIDatabase * inDatabase );
+
+PAPIConnectionState getConnectionState( PAPIDatabase * inDatabase );
+
+PAPILayerList * readLayersFromDatabase( PAPIDatabase * inDatabase,
+ const char * inComponentName,
+ PAPIStatus * outStatus );
+
+PAPIStringList * readNamesFromDatabase( PAPIDatabase * inDatabase,
+ const char * inFilter );
+
+void removeListenerFromDatabase( PAPIDatabase * inDatabase,
+ PAPIListenerId inListenerId,
+ PAPIStatus * outStatus );
+
+PAPIDatabase * newDatabase( const PAPIEntityList * inEntities,
+ PAPIConnectionListener inConnectionListener,
+ void * inUserData,
+ PAPIStatus * outStatus );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PAPIDATABASE_H_ */
diff --git a/libapoc/papiEntityList.c b/libapoc/papiEntityList.c
new file mode 100644
index 0000000..3a2249a
--- /dev/null
+++ b/libapoc/papiEntityList.c
@@ -0,0 +1,92 @@
+/*
+ * 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 "papiEntityList.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+PAPIEntityList *papiAddEntityItem(PAPIEntityList *aEntities,
+ PAPIEntityType aEntityType,
+ const char *aEntityId)
+{
+ PAPIEntityList *retCode = aEntities ;
+
+ if (aEntityId != NULL)
+ {
+ PAPIEntityList *last = retCode ;
+ PAPIEntityList *newItem = malloc(sizeof(PAPIEntityList)) ;
+
+ newItem->entityType = aEntityType ;
+ newItem->entityId = strdup(aEntityId) ;
+ newItem->next = NULL ;
+ while (last != NULL && last->next != NULL) { last = last->next ; }
+ if (last != NULL) { last->next = newItem ; }
+ else { retCode = newItem ; }
+ }
+ return retCode ;
+}
+
+PAPIEntityList *papiCopyEntityList(const PAPIEntityList *aEntities)
+{
+ PAPIEntityList *retCode = NULL ;
+
+ if (aEntities != NULL)
+ {
+ retCode = malloc(sizeof(PAPIEntityList)) ;
+ retCode->entityType = aEntities->entityType ;
+ if (aEntities->entityId != NULL)
+ {
+ retCode->entityId = strdup(aEntities->entityId) ;
+ }
+ else { retCode->entityId = NULL ; }
+ retCode->next = papiCopyEntityList(aEntities->next) ;
+ }
+ return retCode ;
+}
+
+void papiFreeEntityList(PAPIEntityList *aEntities)
+{
+ if (aEntities != NULL)
+ {
+ if (aEntities->entityId != NULL)
+ {
+ free((void *) aEntities->entityId) ;
+ }
+ if (aEntities->next != NULL) { papiFreeEntityList(aEntities->next) ; }
+ free(aEntities) ;
+ }
+}
+
diff --git a/libapoc/papiEntityList.h b/libapoc/papiEntityList.h
new file mode 100644
index 0000000..6a8b207
--- /dev/null
+++ b/libapoc/papiEntityList.h
@@ -0,0 +1,56 @@
+/*
+ * 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 PAPI_ENTITY_LIST_H_
+#define PAPI_ENTITY_LIST_H_
+
+/* Recognised entity types. */
+typedef enum { PAPIEntityHost = 0,
+ PAPIEntityUser } PAPIEntityType;
+
+typedef struct PAPIEntityList
+{
+ PAPIEntityType entityType;
+ const char * entityId;
+ struct PAPIEntityList * next;
+} PAPIEntityList;
+
+PAPIEntityList * papiAddEntityItem( PAPIEntityList * inEntities,
+ PAPIEntityType inEntityType,
+ const char * inEntityId );
+void papiFreeEntityList( PAPIEntityList * inEntities );
+PAPIEntityList *papiCopyEntityList(const PAPIEntityList *aEntities) ;
+
+#endif /* PAPI_ENTITY_LIST_H_ */
diff --git a/libapoc/papiInternal.c b/libapoc/papiInternal.c
new file mode 100644
index 0000000..c2c08e6
--- /dev/null
+++ b/libapoc/papiInternal.c
@@ -0,0 +1,227 @@
+/*
+ * 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.h"
+#include "papiDatabase.h"
+
+static PAPIMutex * gMutex = 0;
+
+static int lock( void )
+{
+ int theRC = -1;
+ if ( gMutex == 0 )
+ {
+ gMutex = newMutex();
+ }
+ if ( gMutex != 0 )
+ {
+ theRC = lockMutex( gMutex );
+ }
+ return theRC;
+}
+
+static int unlock( void )
+{
+ int theRC = -1;
+ if ( gMutex != 0 )
+ {
+ theRC = unlockMutex( gMutex );
+ }
+ return theRC;
+}
+
+PAPIListenerId addListener( const PAPI * inPAPI,
+ const char * inComponentName,
+ PAPIListener inListener,
+ void * inUserData,
+ PAPIStatus * outStatus )
+{
+ PAPIStatus theStatus;
+ PAPIDatabase * theDatabase = ( PAPIDatabase * )inPAPI;
+ PAPIListenerId theListenerId;
+
+ if ( theDatabase != 0 && inComponentName != 0 && inListener != 0 )
+ {
+ if ( getConnectionState( theDatabase ) == PAPIDisconnected )
+ {
+ theStatus = PAPIConnectionFailure;
+ }
+ else if ( lock() == 0 )
+ {
+ theListenerId = addListenerToDatabase( theDatabase,
+ inComponentName,
+ inListener,
+ inUserData,
+ &theStatus );
+ unlock();
+ }
+ }
+ else
+ {
+ theStatus = PAPIInvalidArg;
+ }
+ if ( outStatus != 0 )
+ {
+ *outStatus = theStatus;
+ }
+ return theListenerId;
+}
+
+void deinitialise( PAPI * inPAPI, PAPIStatus * outStatus )
+{
+ if ( lock() == 0 )
+ {
+ deleteDatabase( ( PAPIDatabase * )inPAPI );
+ unlock();
+ }
+ if ( outStatus != 0 )
+ {
+ *outStatus = PAPISuccess;
+ }
+}
+
+PAPI * initialise( const PAPIEntityList * inEntities,
+ PAPIConnectionListener inConnectionListener,
+ void * inUserData,
+ PAPIStatus * outStatus )
+{
+ PAPIStatus theStatus;
+ PAPI * thePAPI = 0;
+ if ( lock() == 0 )
+ {
+ thePAPI = ( PAPI *)newDatabase( inEntities,
+ inConnectionListener,
+ inUserData,
+ &theStatus );
+ unlock();
+ }
+ if ( outStatus != 0 )
+ {
+ *outStatus = theStatus;
+ }
+ return thePAPI;
+}
+
+PAPIStringList * listComponentNames( const PAPI * inPAPI,
+ const char * inFilter,
+ PAPIStatus * outStatus )
+{
+ PAPIStatus theStatus;
+ PAPIDatabase * theDatabase = ( PAPIDatabase * )inPAPI;
+ PAPIStringList * theNames = 0;
+ if ( theDatabase != 0 )
+ {
+ if ( getConnectionState( theDatabase ) == PAPIDisconnected )
+ {
+ theStatus = PAPIConnectionFailure;
+ }
+ else if ( lock() == 0 )
+ {
+ theNames = readNamesFromDatabase( theDatabase, inFilter );
+ theStatus = PAPISuccess;
+ unlock();
+ }
+ }
+ else
+ {
+ theStatus = PAPIInvalidArg;
+ }
+ if ( outStatus != 0 )
+ {
+ *outStatus = theStatus;
+ }
+ return theNames;
+}
+
+PAPILayerList * readComponentLayers( const PAPI * inPAPI,
+ const char * inComponentName,
+ PAPIStatus * outStatus )
+{
+ PAPIStatus theStatus;
+ PAPIDatabase * theDatabase = ( PAPIDatabase * )inPAPI;
+ PAPILayerList * theLayers = 0;
+
+ if ( theDatabase != 0 && inComponentName != 0 )
+ {
+ if ( getConnectionState( theDatabase ) == PAPIDisconnected )
+ {
+ theStatus = PAPIConnectionFailure;
+ }
+ else if ( lock() == 0 )
+ {
+ theLayers = readLayersFromDatabase( theDatabase,
+ inComponentName,
+ &theStatus );
+ unlock();
+ }
+ }
+ else
+ {
+ theStatus = PAPIInvalidArg;
+ }
+ if ( outStatus != 0 )
+ {
+ *outStatus = theStatus;
+ }
+ return theLayers;
+}
+
+void removeListener( const PAPI * inPAPI,
+ PAPIListenerId inListenerId,
+ PAPIStatus * outStatus )
+{
+ PAPIStatus theStatus;
+ PAPIDatabase * theDatabase = ( PAPIDatabase * )inPAPI;
+
+ if ( theDatabase != 0 && inListenerId != 0 )
+ {
+ if ( getConnectionState( theDatabase ) == PAPIDisconnected )
+ {
+ theStatus = PAPIConnectionFailure;
+ }
+ else if ( lock() == 0 )
+ {
+ removeListenerFromDatabase( theDatabase, inListenerId, &theStatus );
+ unlock();
+ }
+ }
+ else
+ {
+ theStatus = PAPIInvalidArg;
+ }
+ if ( outStatus != 0 )
+ {
+ *outStatus = theStatus;
+ }
+}
diff --git a/libapoc/papiInternal.h b/libapoc/papiInternal.h
new file mode 100644
index 0000000..0b36c17
--- /dev/null
+++ b/libapoc/papiInternal.h
@@ -0,0 +1,81 @@
+/*
+ * 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 PAPIINTERNAL_H_
+#define PAPIINTERNAL_H_
+
+#include "papi.h"
+#include "papiLayerList.h"
+#include "papiStringList.h"
+#include "papiEntityList.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+PAPIListenerId addListener( const PAPI * inPAPI,
+ const char * inComponentName,
+ PAPIListener inListener,
+ void * inUserData,
+ PAPIStatus * outStatus );
+
+void deinitialise( PAPI * inPAPI,
+ PAPIStatus * outStatus );
+
+PAPI * initialise( const PAPIEntityList * inEntities,
+ PAPIConnectionListener inConnectionListener,
+ void * inUserData,
+ PAPIStatus * outStatus );
+
+PAPIStringList * listComponentNames( const PAPI * inPAPI,
+ const char * inFilter,
+ PAPIStatus * outStatus );
+
+
+
+PAPILayerList * readComponentLayers( const PAPI * inPAPI,
+ const char * inComponentName,
+ PAPIStatus * outStatus );
+
+
+
+void removeListener( const PAPI * inPAPI,
+ PAPIListenerId inListenerId,
+ PAPIStatus * outStatus );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PAPIINTERNAL_H_ */
diff --git a/libapoc/papiLayerList.c b/libapoc/papiLayerList.c
new file mode 100644
index 0000000..3cb6def
--- /dev/null
+++ b/libapoc/papiLayerList.c
@@ -0,0 +1,104 @@
+/*
+ * 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 "papiLayerList.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+static PAPILayerList * newLayerList( void );
+
+PAPILayerList * addLayerList( PAPILayerList ** ioPrevious,
+ const char * inData,
+ const char * inTimestamp )
+{
+ PAPILayerList * theLayerList = ioPrevious[ 0 ];
+
+ if ( inData != 0 )
+ {
+ if ( ( theLayerList = newLayerList() ) != 0 )
+ {
+ theLayerList->data = ( unsigned char * )strdup( inData );
+ theLayerList->size = strlen( inData );
+ theLayerList->timestamp = strdup( inTimestamp );
+ if ( ioPrevious[ 0 ] == 0 )
+ {
+ ioPrevious[ 0 ] = theLayerList;
+ }
+ else
+ {
+ PAPILayerList * theTmpList = ioPrevious[ 0 ];
+ while ( theTmpList->next != 0 )
+ {
+ theTmpList = theTmpList->next;
+ }
+ theTmpList->next = theLayerList;
+ }
+ }
+ }
+ return theLayerList;
+}
+
+void deleteLayerList( PAPILayerList * inLayerList )
+{
+ if ( inLayerList != 0 )
+ {
+ if ( inLayerList->next != 0 )
+ {
+ deleteLayerList( inLayerList->next );
+ }
+ if ( inLayerList->data != 0 )
+ {
+ free( ( void *)inLayerList->data );
+ }
+ if ( inLayerList->timestamp != 0 )
+ {
+ free( ( void *)inLayerList->timestamp );
+ }
+ free( inLayerList );
+ }
+}
+
+PAPILayerList * newLayerList( void )
+{
+ PAPILayerList * theLayerList =
+ ( PAPILayerList * )malloc( sizeof( PAPILayerList ) );
+ if ( theLayerList != 0 )
+ {
+ theLayerList->data = 0;
+ theLayerList->size = 0;
+ theLayerList->next = 0;
+ }
+ return theLayerList;
+}
diff --git a/libapoc/papiLayerList.h b/libapoc/papiLayerList.h
new file mode 100644
index 0000000..55fb938
--- /dev/null
+++ b/libapoc/papiLayerList.h
@@ -0,0 +1,55 @@
+/*
+ * 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 PAPILAYERLIST_H_
+#define PAPILAYERLIST_H_
+
+#include "papiTypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+PAPILayerList * addLayerList( PAPILayerList ** ioPreviousList,
+ const char * inData,
+ const char * inTimestamp );
+
+void deleteLayerList( PAPILayerList * inLayerList );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PAPILAYERLIST_H_ */
diff --git a/libapoc/papiListenerList.c b/libapoc/papiListenerList.c
new file mode 100644
index 0000000..d7d6222
--- /dev/null
+++ b/libapoc/papiListenerList.c
@@ -0,0 +1,131 @@
+/*
+ * 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 "papiListenerList.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+static PAPIListenerList * newListenerList( void );
+
+PAPIListenerList * addListenerList( PAPIListenerList ** ioPrevious,
+ const char * inComponentName,
+ PAPIListener inListener,
+ void * inUserData )
+{
+ PAPIListenerList * theListenerList = ioPrevious[ 0 ];
+
+ if ( inComponentName != 0 && inListener != 0 )
+ {
+ if ( ( theListenerList = newListenerList() ) != 0 )
+ {
+ theListenerList->mComponentName = strdup( inComponentName );
+ theListenerList->mListener = inListener;
+ theListenerList->mUserData = inUserData;
+ if ( ioPrevious[ 0 ] == 0 )
+ {
+ ioPrevious[ 0 ] = theListenerList;
+ }
+ else
+ {
+ PAPIListenerList * theTmpList = ioPrevious[ 0 ];
+ while ( theTmpList->mNext != 0 )
+ {
+ theTmpList = theTmpList->mNext;
+ }
+ theTmpList->mNext = theListenerList;
+ }
+ }
+ }
+ return theListenerList;
+}
+
+void removeListenerList( PAPIListenerList ** ioPreviousList,
+ PAPIListenerList * inList )
+{
+ if ( inList != 0 && ioPreviousList != 0 )
+ {
+ PAPIListenerList * thePreviousList = 0;
+ PAPIListenerList * theNextList = ioPreviousList[ 0 ];
+ while ( theNextList != 0 )
+ {
+ if ( theNextList == inList )
+ {
+ if ( theNextList == ioPreviousList[ 0 ] )
+ {
+ ioPreviousList[ 0 ] = ioPreviousList[ 0 ]->mNext;
+ }
+ else
+ {
+ thePreviousList->mNext = theNextList->mNext;
+ }
+ inList->mNext = 0;
+ deleteListenerList( inList );
+ break;
+ }
+ thePreviousList = theNextList;
+ theNextList = theNextList->mNext;
+ }
+ }
+}
+
+void deleteListenerList( PAPIListenerList * inListenerList )
+{
+ if ( inListenerList != 0 )
+ {
+ if ( inListenerList->mNext != 0 )
+ {
+ deleteListenerList( inListenerList->mNext );
+ }
+ if ( inListenerList->mComponentName != 0 )
+ {
+ free( ( void *)inListenerList->mComponentName );
+ }
+ free( inListenerList );
+ }
+}
+
+PAPIListenerList * newListenerList( void )
+{
+ PAPIListenerList * theListenerList =
+ ( PAPIListenerList * )malloc( sizeof( PAPIListenerList ) );
+ if ( theListenerList != 0 )
+ {
+ theListenerList->mComponentName = 0;
+ theListenerList->mListener = 0;
+ theListenerList->mUserData = 0;
+ theListenerList->mNext = 0;
+ }
+ return theListenerList;
+}
diff --git a/libapoc/papiListenerList.h b/libapoc/papiListenerList.h
new file mode 100644
index 0000000..120b0c3
--- /dev/null
+++ b/libapoc/papiListenerList.h
@@ -0,0 +1,66 @@
+/*
+ * 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 PAPILISTENERLIST_H_
+#define PAPILISTENERLIST_H_
+
+#include "papiTypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct PAPIListenerList
+{
+ const char * mComponentName;
+ PAPIListener mListener;
+ void * mUserData;
+ struct PAPIListenerList * mNext;
+} PAPIListenerList;
+
+PAPIListenerList * addListenerList( PAPIListenerList ** ioPreviousList,
+ const char * inComponentName,
+ PAPIListener inListener,
+ void * inUserData );
+
+void removeListenerList( PAPIListenerList ** ioPreviousList,
+ PAPIListenerList * inList );
+
+void deleteListenerList( PAPIListenerList * inListenerList );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PAPILISTENERLIST_H_ */
diff --git a/libapoc/papiMessage.c b/libapoc/papiMessage.c
new file mode 100644
index 0000000..da95ef8
--- /dev/null
+++ b/libapoc/papiMessage.c
@@ -0,0 +1,293 @@
+/*
+ * 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 <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "papiMessage.h"
+#include "papiInternal.h"
+
+static PAPIParamNameList * newParamNameList( PAPIParamName inParamName );
+
+static void deleteParamNameList( PAPIParamNameList * inParamNameList );
+
+static PAPIParamNameList * addParamNameList( PAPIParamNameList **ioPreviousList,
+ PAPIParamName inParamName );
+
+static const char *sMessageNames[] =
+{
+ "success",
+ "invalidRequest",
+ "connectionFailure",
+ "authenticationFailure",
+ "invalidSessionId",
+ "noSuchComponent",
+ "successContinueLocalAuth",
+ "successContinueSASLAuth",
+
+ "addNotification",
+ "removeNotification",
+ "modifyNotification",
+
+ "createSession",
+ "read",
+ "list",
+ "destroySession",
+ "addListener",
+ "removeListener",
+ "createSessionExt"
+};
+
+static const char *sParamNames[] =
+{
+ "sessionId",
+ "userId",
+ "entityId",
+ "credentials",
+ "componentName",
+ "clientData",
+ "message",
+ "layer",
+ "entityType"
+};
+
+/* Must be aligned with PAPIEntityType enumeration in papiTypes.h AND
+ must be the same strings as the SOURCE ones in
+ spi/environment/EnvironmentConstants. */
+static const char *sEntityTypes[] =
+{
+ "HOST",
+ "USER"
+};
+
+PAPIMessage * newMessage( PAPIMessageName inMessageName )
+{
+ PAPIMessage * theMessage = ( PAPIMessage * )malloc( sizeof( PAPIMessage ) );
+ if ( theMessage != 0 )
+ {
+ theMessage->mName = inMessageName;
+ theMessage->mParamNames = 0;
+ theMessage->mParamValues = 0;
+ }
+ return theMessage;
+}
+
+void deleteMessage( PAPIMessage * inMessage )
+{
+ if ( inMessage != 0 )
+ {
+ deleteParamNameList( inMessage->mParamNames );
+ deleteStringList( inMessage->mParamValues );
+ free( ( void * )inMessage );
+ }
+}
+
+void addParam( PAPIMessage * inMessage,
+ PAPIParamName inParamName,
+ const char * inParamValue )
+{
+ if ( inMessage != 0 )
+ {
+ addParamNameList( &inMessage->mParamNames, inParamName );
+ addStringList( &inMessage->mParamValues, inParamValue );
+ }
+}
+
+char * messageToString( PAPIMessage * inMessage )
+{
+ int theStringSize;
+ char * theString = 0;
+ if ( inMessage != 0 )
+ {
+ PAPIParamNameList * theNameList = inMessage->mParamNames;
+ PAPIStringList * theValueList = inMessage->mParamValues;
+ theStringSize =
+ ( 2 * strlen( sMessageNames[ ( int )inMessage->mName ] ) ) + 5;
+ while ( theNameList != 0 )
+ {
+ theStringSize +=
+ ( 2 * strlen( sParamNames[ ( int )theNameList->mName ] ) ) + 5;
+ if ( theValueList->data != 0 )
+ {
+ theStringSize += strlen( theValueList->data );
+ }
+ theNameList = theNameList->mNext;
+ theValueList = theValueList->next;
+ }
+
+
+ if ( theStringSize > 0 )
+ {
+ theNameList = inMessage->mParamNames;
+ theValueList = inMessage->mParamValues;
+ theString = ( char * )malloc( theStringSize + 1 );
+ theString[ 0 ] = 0;
+
+ sprintf( theString, "<%s>", sMessageNames[( int )inMessage->mName]);
+ while ( theNameList != 0 )
+ {
+ strcat( theString, "<" );
+ strcat( theString, sParamNames[ ( int )theNameList->mName ] );
+ strcat( theString, ">" );
+
+ if ( theValueList->data != 0 )
+ {
+ strcat( theString, theValueList->data );
+ }
+
+ strcat( theString, "</" );
+ strcat( theString, sParamNames[ ( int )theNameList->mName] );
+ strcat( theString, ">" );
+
+ theNameList = theNameList->mNext;
+ theValueList = theValueList->next;
+ }
+ strcat( theString, "</" );
+ strcat( theString, sMessageNames[ ( int )inMessage->mName ] );
+ strcat( theString, ">" );
+ }
+ }
+ return theString;
+}
+
+PAPIStringList * getParamValue( PAPIMessage * inMessage,
+ PAPIParamName inParamName )
+{
+ PAPIStringList * theValue = 0;
+ if ( inMessage != 0 )
+ {
+ PAPIParamNameList * theNames = inMessage->mParamNames;
+ PAPIStringList * theValues = inMessage->mParamValues;
+ while ( theNames != 0 )
+ {
+ if ( theNames->mName == inParamName )
+ {
+ addStringList( &theValue, theValues->data );
+ }
+ theNames = theNames->mNext;
+ theValues = theValues->next;
+ }
+ }
+ return theValue;
+}
+
+PAPIParamNameList * newParamNameList( PAPIParamName inParamName )
+{
+ PAPIParamNameList * theList =
+ ( PAPIParamNameList * )malloc( sizeof( PAPIParamNameList ) );
+ if ( theList != 0 )
+ {
+ theList->mName = inParamName;
+ theList->mNext = 0;
+ }
+ return theList;
+}
+
+PAPIMessageName stringToMessageName( const char * inMessageName )
+{
+ PAPIMessageName theName = PAPIMessageNameUnused;
+ if ( inMessageName != 0 )
+ {
+ int theIndex;
+ for ( theIndex = 0; theIndex < PAPIMessageNameUnused; theIndex ++ )
+ {
+ if ( strcmp( inMessageName, sMessageNames[ theIndex ] ) == 0 )
+ {
+ theName = ( PAPIMessageName )theIndex;
+ break;
+ }
+ }
+ }
+ return theName;
+}
+
+PAPIParamName stringToParamName( const char * inParamName )
+{
+ PAPIParamName theName = PAPIParamNameUnused;
+ if ( inParamName != 0 )
+ {
+ int theIndex;
+ for ( theIndex = 0; theIndex < PAPIParamNameUnused; theIndex ++ )
+ {
+ if ( strcmp( inParamName, sParamNames[ theIndex ] ) == 0 )
+ {
+ theName = ( PAPIParamName )theIndex;
+ break;
+ }
+ }
+ }
+ return theName;
+}
+
+static void deleteParamNameList( PAPIParamNameList * inParamNameList )
+{
+ if ( inParamNameList != 0 )
+ {
+ if ( inParamNameList->mNext != 0 )
+ {
+ deleteParamNameList( inParamNameList->mNext );
+ }
+ free( ( void * )inParamNameList );
+ }
+}
+
+static PAPIParamNameList * addParamNameList( PAPIParamNameList **ioPrevious,
+ PAPIParamName inParamName )
+{
+ PAPIParamNameList * theList = newParamNameList( inParamName );
+ if ( theList != 0 )
+ {
+ if ( ioPrevious[ 0 ] == 0 )
+ {
+ ioPrevious[ 0 ] = theList;
+ }
+ else
+ {
+ PAPIParamNameList * theTmpList = ioPrevious[ 0 ];
+ while ( theTmpList->mNext != 0 )
+ {
+ theTmpList = theTmpList->mNext;
+ }
+ theTmpList->mNext = theList;
+ }
+ }
+ return theList;
+}
+
+const char * getEntityTypeString( PAPIEntityType inType )
+{
+ return sEntityTypes[ inType ];
+}
+
diff --git a/libapoc/papiMessage.h b/libapoc/papiMessage.h
new file mode 100644
index 0000000..988ee99
--- /dev/null
+++ b/libapoc/papiMessage.h
@@ -0,0 +1,125 @@
+/*
+ * 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 PAPIMESSAGE_H_
+#define PAPIMESSAGE_H_
+
+#include "papiTypes.h"
+#include "papiEntityList.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum
+{
+ PAPIRespSuccess = 0,
+ PAPIRespInvalidRequest,
+ PAPIRespConnectionFailure,
+ PAPIRespAuthenticationFailure,
+ PAPIRespInvalidSessionId,
+ PAPIRespNoSuchComponent,
+ PAPIRespSuccessContinueLocalAuth,
+ PAPIRespSuccessContinueSASLAuth,
+
+ PAPIaddNotification,
+ PAPIremoveNotification,
+ PAPImodifyNotification,
+
+ PAPIReqCreateSession,
+ PAPIReqRead,
+ PAPIReqList,
+ PAPIReqDestroySession,
+ PAPIReqAddListener,
+ PAPIReqRemoveListener,
+ PAPIReqCreateSessionExt,
+
+ PAPIMessageNameUnused
+
+} PAPIMessageName;
+
+typedef enum
+{
+ PAPIParamSessionId = 0,
+ PAPIParamUserId,
+ PAPIParamEntityId,
+ PAPIParamCredentials,
+ PAPIParamComponentName,
+ PAPIParamClientData,
+ PAPIParamMessage,
+ PAPIParamLayer,
+ PAPIParamEntityType,
+ PAPIParamNameUnused
+} PAPIParamName;
+
+typedef struct PAPIParamNameList
+{
+ PAPIParamName mName;
+ struct PAPIParamNameList * mNext;
+} PAPIParamNameList;
+
+typedef struct PAPIMessage
+{
+ PAPIMessageName mName;
+ PAPIParamNameList * mParamNames;
+ PAPIStringList * mParamValues;
+} PAPIMessage;
+
+PAPIMessage * newMessage( PAPIMessageName inMessageName );
+
+void deleteMessage( PAPIMessage * inMessage );
+
+void addParam( PAPIMessage * inMessage,
+ PAPIParamName inParamName,
+ const char * inParamValue );
+
+PAPIStringList *getParamValue( PAPIMessage * inMessage,
+ PAPIParamName inParamName );
+
+char * messageToString( PAPIMessage * inMessage );
+
+PAPIMessageName stringToMessageName( const char * inMessageName );
+PAPIParamName stringToParamName( const char * inParamName );
+
+const char *getEntityTypeString( PAPIEntityType inType );
+
+#define CONTENTLENGTH "CONTENT-LENGTH:"
+#define MAX_CONTENT_LENGTH_SIZE 23
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PAPIMESSAGE_H_ */
diff --git a/libapoc/papiPort.c b/libapoc/papiPort.c
new file mode 100644
index 0000000..f19926e
--- /dev/null
+++ b/libapoc/papiPort.c
@@ -0,0 +1,457 @@
+/*
+ * 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 "papiUtils.h"
+#include "config.h"
+
+#include <gssapi.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <poll.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#ifdef SOLARIS
+#include <libscf.h>
+#endif
+
+static void initGSSAPIContext( const char * inServiceName,
+ gss_ctx_id_t * outContext,
+ gss_buffer_desc * outToken,
+ PAPIStatus * outStatus );
+
+static int isDaemonInitdEnabled( void );
+
+static void writeGSSAPIAuthId( gss_ctx_id_t * outContext,
+ gss_buffer_desc * outToken,
+ PAPIStatus * outStatus );
+
+const char * getGSSAPISrcName( gss_ctx_id_t * inContext );
+
+static void getTargetService( const char * inServiceName,
+ gss_name_t * outService,
+ PAPIStatus * outStatus );
+
+static void encodeGSSAPITokens( gss_buffer_desc * inBuffers,
+ int inBufferCnt,
+ char ** outB64 );
+
+static const char * sInstallDir = APOC_INSTALLDIR;
+static const char * sLibraryDir = APOC_LIBRARYDIR;
+static const char * sPropertiesDir = APOC_PROPDIR;
+
+
+PAPIThread createThread( PAPIThreadFunc inThreadFunc, void * inArg )
+{
+ pthread_attr_t theAttr;
+ pthread_t * theThread = ( pthread_t * )malloc( sizeof( pthread_t ) );
+
+ pthread_attr_init( &theAttr );
+ pthread_attr_setdetachstate( &theAttr, PTHREAD_CREATE_DETACHED );
+ if ( pthread_create( theThread, &theAttr, inThreadFunc, inArg ) != 0 )
+ {
+ free( ( void * )theThread );
+ theThread = 0;
+ }
+ return theThread;
+}
+
+void destroyThread( PAPIThread inThread )
+{
+ pthread_cancel( *inThread );
+}
+
+void deleteMutex( PAPIMutex * inMutex )
+{
+ if ( inMutex != 0 )
+ {
+ pthread_mutex_destroy( inMutex );
+ free( ( void * )inMutex );
+ }
+}
+
+const char * getSASLCreds( const char * inServiceName, PAPIStatus * outStatus )
+{
+ char * theCredentials = 0;
+ gss_ctx_id_t theContextHandle = GSS_C_NO_CONTEXT;
+ gss_buffer_desc theOutputTokens[ 3 ];
+
+ theOutputTokens[ 0 ].length =
+ theOutputTokens[ 1 ].length =
+ theOutputTokens[ 2 ].length = 0;
+ initGSSAPIContext( inServiceName,
+ &theContextHandle,
+ &theOutputTokens[ 0 ],
+ outStatus );
+ if ( *outStatus == PAPISuccess )
+ {
+ writeGSSAPIAuthId( &theContextHandle, &theOutputTokens[ 2 ],outStatus );
+ if ( *outStatus == PAPISuccess )
+ {
+ OM_uint32 theMinorStatus;
+ encodeGSSAPITokens( theOutputTokens,
+ 3,
+ &theCredentials );
+ gss_release_buffer( &theMinorStatus, &theOutputTokens[ 0 ] );
+ gss_release_buffer( &theMinorStatus, &theOutputTokens[ 2 ] );
+ gss_delete_sec_context( &theMinorStatus,
+ &theContextHandle,
+ 0 );
+ }
+ }
+ return theCredentials;
+}
+
+const char * getInstallDir( void )
+{
+ return sInstallDir;
+}
+
+const char * getLibraryDir( void )
+{
+ return sLibraryDir;
+}
+
+const char * getPropertiesDir( void )
+{
+ return sPropertiesDir;
+}
+
+const char * getUserName( void )
+{
+/*
+ * no longer using cuserid here as it truncates user name at 8 characters
+ */
+ struct passwd * thePasswd = getpwuid( geteuid() );
+ return thePasswd != 0 && thePasswd->pw_name != 0 ?
+ strdup( thePasswd->pw_name ) : 0;
+}
+
+int isDaemonEnabled( void )
+{
+ int isDaemonEnabled = 0;
+#ifdef SOLARIS
+ isDaemonEnabled = isServiceEnabled();
+#else
+ isDaemonEnabled = isDaemonInitdEnabled();
+#endif
+ return isDaemonEnabled;
+}
+
+#ifdef SOLARIS
+int isServiceEnabled( void )
+{
+ static const char * sInstanceName = "svc:/network/apocd/udp:default";
+ int isServiceEnabled = 0;
+ char * theState = smf_get_state( sInstanceName );
+ if ( theState != 0 )
+ {
+ if ( strcmp( theState, SCF_STATE_STRING_DISABLED ) != 0 )
+ {
+ isServiceEnabled = 1;
+ }
+ free( ( void * )theState );
+ }
+ return isServiceEnabled;
+}
+#else
+int isDaemonInitdEnabled( void )
+{
+ static char * theCommand = "/sbin/chkconfig -c apocd";
+ FILE * theStream;
+ int theRC = 0;
+
+ theStream = papiPopen( theCommand, "w" );
+ if ( theStream != 0 )
+ {
+ theRC = papiPclose( theStream ) == 0 ? 1 : 0;
+ }
+
+ return theRC;
+}
+#endif
+
+int lockMutex( PAPIMutex * inMutex )
+{
+ return pthread_mutex_lock( inMutex );
+}
+
+PAPIMutex * newMutex( void )
+{
+ pthread_mutex_t * theMutex =
+ ( pthread_mutex_t * )malloc( sizeof( pthread_mutex_t ) );
+ if ( theMutex != 0 )
+ {
+ pthread_mutex_init( theMutex, 0 );
+ }
+ return theMutex;
+}
+
+int socketPoll( PAPISocket inSocket, int inMillis )
+{
+ struct pollfd thePollFD;
+ int theRC;
+
+ thePollFD.fd = inSocket;
+ thePollFD.events = POLLIN;
+ theRC = poll( &thePollFD, 1, inMillis );
+ if ( theRC == 1 && thePollFD.revents & POLLIN != POLLIN )
+ {
+ theRC = 0;
+ }
+ else if ( theRC == -1 && thePollFD.revents & POLLHUP == POLLHUP )
+ {
+ theRC = 0;
+ }
+
+ return theRC;
+}
+
+int startDaemon( void )
+{
+ int theRC = 1;
+
+ /*
+ * apoc2.0: daemon startup via inetd no longer supported
+ *
+ if ( isDaemonEnabled() == 1 )
+ {
+ int theSocket = getConnectedSocket( getDaemonPort(), SOCK_DGRAM, 0 );
+ if ( theSocket != INVALID_SOCKET )
+ {
+ if ( send( theSocket, ( void *)"\n", 1, 0 ) != -1 )
+ {
+ theRC = 0;
+ }
+ close( theSocket );
+ }
+ }
+ */
+ return theRC;
+}
+
+int unlockMutex( PAPIMutex * inMutex )
+{
+ return pthread_mutex_unlock( inMutex );
+}
+
+void encodeGSSAPITokens( gss_buffer_desc * inBuffers,
+ int inBufferCnt,
+ char ** outB64Buffer )
+{
+ void * theBuffer;
+ char * theTmpPtr;
+ int theBufferSize = 0;
+ int theIndex;
+
+ for ( theIndex = 0; theIndex < inBufferCnt; ++ theIndex )
+ {
+ theBufferSize += inBuffers[ theIndex ].length + 5;
+ }
+
+ theBuffer = malloc( theBufferSize );
+ theTmpPtr = ( char *)theBuffer;
+ for ( theIndex = 0; theIndex < inBufferCnt; ++ theIndex )
+ {
+ /* Write the token size */
+ snprintf( theTmpPtr, 6, "%05d", inBuffers[ theIndex ].length );
+ theTmpPtr += 5;
+
+ /* Write the token */
+ memcpy( ( void *)theTmpPtr,
+ inBuffers[ theIndex ].value,
+ inBuffers[ theIndex ].length);
+ theTmpPtr += inBuffers[ theIndex ].length;
+ }
+ base64_encode( theBuffer, theBufferSize, outB64Buffer );
+ free( ( void *)theBuffer );
+}
+
+void initGSSAPIContext( const char * inServiceName,
+ gss_ctx_id_t * outContext,
+ gss_buffer_desc * outToken,
+ PAPIStatus * outStatus )
+{
+ gss_name_t theServiceName;
+
+ getTargetService( inServiceName, &theServiceName, outStatus );
+ if ( *outStatus == PAPISuccess )
+ {
+ OM_uint32 theMajorStatus;
+ OM_uint32 theMinorStatus;
+ gss_buffer_desc theServiceNameBuf;
+ OM_uint32 theReqFlags = GSS_C_DELEG_FLAG;
+ OM_uint32 theRetFlags;
+ gss_OID theMech;
+#ifdef SOLARIS
+ gss_OID_desc theMechArr =
+ { 9, "\052\206\110\206\367\022\001\002\002"};
+ theMech = &theMechArr;
+#else
+ theMech = GSS_KRB5_MECHANISM;
+#endif
+
+ outToken->length = 0;
+ theMajorStatus = gss_init_sec_context( &theMinorStatus,
+ GSS_C_NO_CREDENTIAL,
+ outContext,
+ theServiceName,
+ GSS_C_NO_OID,
+ 0,
+ 0,
+ NULL,
+ GSS_C_NO_BUFFER,
+ 0,
+ outToken,
+ &theRetFlags,
+ 0 );
+ if ( theMajorStatus == GSS_S_COMPLETE )
+ {
+ *outStatus = PAPISuccess;
+ }
+ else
+ {
+ *outStatus = PAPIAuthenticationFailure;
+ }
+ }
+}
+
+const char * getGSSAPISrcName( gss_ctx_id_t * inContext )
+{
+ char * theGSSAPISrcName = 0;
+ OM_uint32 theMajorStatus;
+ OM_uint32 theMinorStatus;
+ gss_name_t theSrcName;
+
+ theMajorStatus = gss_inquire_context( &theMinorStatus,
+ *inContext,
+ &theSrcName,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0 );
+ if ( theMajorStatus == GSS_S_COMPLETE )
+ {
+ gss_buffer_desc theSrcNameBuffer;
+ theMajorStatus = gss_display_name( &theMinorStatus,
+ theSrcName,
+ &theSrcNameBuffer,
+ 0 );
+ if ( theMajorStatus == GSS_S_COMPLETE )
+ {
+ int theSize = theSrcNameBuffer.length + 1;
+ theGSSAPISrcName = ( char * )malloc( theSize );
+ if ( theGSSAPISrcName != 0 )
+ {
+ snprintf( theGSSAPISrcName,
+ theSize,
+ "%s",
+ ( char *)theSrcNameBuffer.value );
+ }
+ gss_release_buffer( &theMinorStatus, &theSrcNameBuffer );
+ }
+ }
+ return theGSSAPISrcName;
+}
+
+void getTargetService( const char * inServiceName,
+ gss_name_t * outServiceName,
+ PAPIStatus * outStatus )
+{
+ if ( inServiceName != 0 )
+ {
+ OM_uint32 theMajorStatus;
+ OM_uint32 theMinorStatus;
+ gss_buffer_desc theServiceNameBuf;
+ OM_uint32 theReqFlags = GSS_C_DELEG_FLAG;
+ OM_uint32 theRetFlags;
+
+ theServiceNameBuf.length = strlen( inServiceName );
+ theServiceNameBuf.value = ( char * )inServiceName;
+ theMajorStatus =
+ gss_import_name( &theMinorStatus,
+ &theServiceNameBuf,
+ GSS_C_NO_OID,
+ outServiceName );
+ *outStatus = theMajorStatus == GSS_S_COMPLETE ?
+ PAPISuccess : PAPIAuthenticationFailure;
+ }
+}
+
+void writeGSSAPIAuthId( gss_ctx_id_t * inContext,
+ gss_buffer_desc * outToken,
+ PAPIStatus * outStatus )
+{
+ /*
+ * We no longer write the ldap authorisation id as LDAP servers
+ * can't agree on the format.
+ * See 6275775
+ */
+ OM_uint32 theMajorStatus;
+ OM_uint32 theMinorStatus;
+ gss_buffer_desc theAuthzIdBuffer;
+ int theConfState;
+
+ *outStatus = PAPIAuthenticationFailure;
+ theAuthzIdBuffer.length = 4;
+ theAuthzIdBuffer.value = malloc( theAuthzIdBuffer.length );
+ if ( theAuthzIdBuffer.value != 0 )
+ {
+ char * theCP = ( char *)theAuthzIdBuffer.value;
+ /* security layer */
+ theCP[ 0 ] = ( char )1;
+ /* message size */
+ theCP[ 1 ] = ( char )1;
+ theCP[ 2 ] = theCP[ 3 ] = ( char )0;
+
+ theMajorStatus = gss_wrap( &theMinorStatus,
+ *inContext,
+ 0,
+ GSS_C_QOP_DEFAULT,
+ &theAuthzIdBuffer,
+ &theConfState,
+ outToken );
+ free( theAuthzIdBuffer.value );
+ if ( theMajorStatus == GSS_S_COMPLETE )
+ {
+ *outStatus = PAPISuccess;
+ }
+ }
+}
diff --git a/libapoc/papiSAXParserContext.c b/libapoc/papiSAXParserContext.c
new file mode 100644
index 0000000..edf60dc
--- /dev/null
+++ b/libapoc/papiSAXParserContext.c
@@ -0,0 +1,182 @@
+/*
+ * 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 <stdlib.h>
+
+#include "papiSAXParserContext.h"
+
+static int saxReader( void * inIOContext, char * inBuffer, int inLen );
+
+static int saxCloser( void * inIOContext );
+
+static void papiStartElement( void * inUserData,
+ const xmlChar * inName,
+ const xmlChar ** inAttrs );
+static void papiCharacters( void * inUserData,
+ const xmlChar * inChars,
+ int inLen );
+
+static xmlSAXHandler sSAXHandler =
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ papiStartElement,
+ 0,
+ 0,
+ papiCharacters,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 1
+ };
+
+PAPISAXParserContext newSAXParserContext( PAPIConnection * inConnection,
+ PAPISAXUserData * inUserData )
+{
+ PAPISAXParserContext theSAXParserContext;
+ PAPISAXIOContext * theIOContext =
+ ( PAPISAXIOContext * )malloc( sizeof( PAPISAXIOContext ) );
+ if ( theIOContext != 0 )
+ {
+ theIOContext->mContentLength = -1;
+ theIOContext->mConnection = inConnection;
+
+ theSAXParserContext =
+ xmlCreateIOParserCtxt( &sSAXHandler,
+ ( void *) inUserData,
+ saxReader,
+ saxCloser,
+ ( void *)theIOContext,
+ XML_CHAR_ENCODING_NONE );
+
+ }
+ return theSAXParserContext;
+}
+
+void deleteSAXParserContext( PAPISAXParserContext inParserContext )
+{
+ xmlFreeParserCtxt( inParserContext );
+}
+
+int parse( PAPISAXParserContext inParserContext )
+{
+ return xmlParseDocument( inParserContext );
+}
+
+void papiStartElement( void * inUserData,
+ const xmlChar * inName,
+ const xmlChar ** inAttrs )
+{
+ PAPISAXUserData * theUserData = ( PAPISAXUserData * )inUserData;
+ if ( theUserData != 0 && theUserData->mMessage == 0 )
+ {
+ theUserData->mMessage = newMessage(
+ stringToMessageName( ( const char * )inName ) );
+ }
+ else
+ {
+ theUserData->mCurrentParamName =
+ stringToParamName( ( const char * )inName );
+ }
+}
+
+void papiCharacters( void * inUserData,
+ const xmlChar * inChars,
+ int inLen )
+{
+ PAPISAXUserData * theUserData = ( PAPISAXUserData * )inUserData;
+ if ( theUserData != 0 && theUserData->mMessage != 0 )
+ {
+ char * theValue = ( char * )malloc( inLen + 1 );
+ if ( theValue != 0 )
+ {
+ snprintf( theValue, inLen + 1, "%s", inChars );
+ theValue[ inLen ] = 0;
+ addParam( theUserData->mMessage,
+ theUserData->mCurrentParamName,
+ theValue );
+ free( ( void *)theValue );
+ theUserData->mCurrentParamName = PAPIParamNameUnused;
+ }
+ }
+}
+
+int saxReader( void * inIOContext, char * inBuffer, int inLen )
+{
+ int theByteCount = EOF;
+ PAPISAXIOContext * theIOContext = ( PAPISAXIOContext * )inIOContext;
+
+ if ( theIOContext->mContentLength == -1 )
+ {
+ theIOContext->mContentLength =
+ readContentLength( theIOContext->mConnection );
+ }
+ if ( theIOContext->mContentLength > 0 )
+ {
+ int theLen = inLen < theIOContext->mContentLength ?
+ inLen : theIOContext->mContentLength;
+ theByteCount = readBytes( theIOContext->mConnection,
+ ( void *)inBuffer,
+ theLen );
+ if ( theByteCount > 0 )
+ {
+ theIOContext->mContentLength -= theByteCount;
+ }
+ }
+ return theByteCount == -1 ? 0 : theByteCount;
+}
+
+int saxCloser( void * inIOContext )
+{
+ free( inIOContext );
+ return 0;
+}
diff --git a/libapoc/papiSAXParserContext.h b/libapoc/papiSAXParserContext.h
new file mode 100644
index 0000000..b36bf99
--- /dev/null
+++ b/libapoc/papiSAXParserContext.h
@@ -0,0 +1,74 @@
+/*
+ * 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 PAPISAXPARSERCONTEXT_H_
+#define PAPISAXPARSERCONTEXT_H_
+
+#include <libxml/parser.h>
+
+#include "papiConnection.h"
+#include "papiMessage.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef xmlParserCtxtPtr PAPISAXParserContext;
+
+typedef struct PAPISAXIOContext
+{
+ int mContentLength;
+ PAPIConnection * mConnection;
+} PAPISAXIOContext;
+
+typedef struct PAPISAXUserData
+{
+ PAPIMessage * mMessage;
+ PAPIParamName mCurrentParamName;
+} PAPISAXUserData;
+
+PAPISAXParserContext newSAXParserContext( PAPIConnection * inFD,
+ PAPISAXUserData * inUserData );
+
+void deleteSAXParserContext( PAPISAXParserContext inParserContext );
+
+int parse( PAPISAXParserContext inParserContext );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PAPISAXPARSERCONTEXT_H_ */
diff --git a/libapoc/papiStringList.c b/libapoc/papiStringList.c
new file mode 100644
index 0000000..d992af6
--- /dev/null
+++ b/libapoc/papiStringList.c
@@ -0,0 +1,176 @@
+/*
+ * 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 "papiStringList.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+static PAPIStringList * newStringList( void );
+
+PAPIStringList * addStringList( PAPIStringList ** ioPrevious,
+ const char * inData )
+{
+ PAPIStringList * theStringList = newStringList();
+ if ( theStringList != 0 )
+ {
+ theStringList->data = inData == 0 ? 0 : strdup( inData );
+ if ( ioPrevious[ 0 ] == 0 )
+ {
+ ioPrevious[ 0 ] = theStringList;
+ }
+ else
+ {
+ PAPIStringList * theTmpList = ioPrevious[ 0 ];
+ while ( theTmpList->next != 0 )
+ {
+ theTmpList = theTmpList->next;
+ }
+ theTmpList->next = theStringList;
+ }
+ }
+ return theStringList;
+}
+
+int containsString( PAPIStringList * inList, const char * inString )
+{
+ int isContained = 0;
+ if ( inList != 0 && inString != 0 )
+ {
+ while ( inList != 0 )
+ {
+ if ( strcmp( inList->data, inString ) == 0 )
+ {
+ isContained = 1;
+ break;
+ }
+ inList = inList->next;
+ }
+ }
+ return isContained;
+}
+
+PAPIStringList * copyStringList( PAPIStringList * inList )
+{
+ PAPIStringList * theList = 0;
+ while ( inList != 0 )
+ {
+ addStringList( &theList, inList->data );
+ inList = inList->next;
+ }
+ return theList;
+}
+
+void deleteStringList( PAPIStringList * inStringList )
+{
+ if ( inStringList != 0 )
+ {
+ if ( inStringList->next != 0 )
+ {
+ deleteStringList( inStringList->next );
+ }
+ if ( inStringList->data != 0 )
+ {
+ free( ( void *)inStringList->data );
+ }
+ free( inStringList );
+ }
+}
+
+PAPIStringList * removeStringList( PAPIStringList ** ioStringList,
+ const char * inString )
+{
+ PAPIStringList * theList = 0;
+ if ( ioStringList != 0 && inString != 0 )
+ {
+ theList = ioStringList[ 0 ];
+ if ( theList != 0 )
+ {
+ PAPIStringList * thePrevList = theList;
+ while ( theList != 0 )
+ {
+ if ( strcmp( theList->data, inString ) == 0 )
+ {
+ if ( theList == ioStringList[ 0 ] )
+ {
+ ioStringList[ 0 ] = ioStringList[ 0 ]->next;
+ }
+ else
+ {
+ thePrevList->next = theList->next;
+ }
+ theList->next = 0;
+ break;
+ }
+ thePrevList = theList;
+ theList = theList->next;
+ }
+ }
+ }
+ return theList;
+}
+
+PAPIStringList * strToStringList( const char * inString )
+{
+ PAPIStringList * theList = 0;
+ if ( inString != 0 )
+ {
+ PAPIStringList * theTmpList;
+ const char * theString = strdup( inString );
+ char * theToken = strtok( ( char *)theString, " " );
+ while ( theToken != 0 )
+ {
+ theTmpList = addStringList( &theList, theToken );
+ if ( theList == 0 )
+ {
+ theList = theTmpList;
+ }
+ theToken = strtok( NULL, " " );
+ }
+ free( ( void * )theString );
+ }
+ return theList;
+}
+
+PAPIStringList * newStringList( void )
+{
+ PAPIStringList * theStringList =
+ ( PAPIStringList * )malloc( sizeof( PAPIStringList ) );
+ if ( theStringList != 0 )
+ {
+ theStringList->data = 0;
+ theStringList->next = 0;
+ }
+ return theStringList;
+}
diff --git a/libapoc/papiStringList.h b/libapoc/papiStringList.h
new file mode 100644
index 0000000..52f2526
--- /dev/null
+++ b/libapoc/papiStringList.h
@@ -0,0 +1,61 @@
+/*
+ * 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 PAPISTRINGLIST_H_
+#define PAPISTRINGLIST_H_
+
+#include "papiTypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+PAPIStringList * addStringList( PAPIStringList ** ioPreviousList,
+ const char * inData );
+
+int containsString( PAPIStringList * inList, const char * inString );
+
+PAPIStringList * copyStringList( PAPIStringList * inList );
+
+void deleteStringList( PAPIStringList * inStringList );
+
+PAPIStringList * removeStringList( PAPIStringList ** ioStringList, const char * inString );
+
+PAPIStringList * strToStringList( const char * inString );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PAPISTRINGLIST_H_ */
diff --git a/libapoc/papiTypes.h b/libapoc/papiTypes.h
new file mode 100644
index 0000000..f324476
--- /dev/null
+++ b/libapoc/papiTypes.h
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ */
+/* papiTypes.h - Policy Access API types */
+
+#ifndef PAPITYPES_H_
+#define PAPITYPES_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* opaque PAPI session handle */
+typedef struct PAPI PAPI;
+
+/* Status returned by PAPI functions */
+typedef enum { PAPISuccess = 0,
+ PAPIConnectionFailure,
+ PAPIAuthenticationFailure,
+ PAPINoSuchComponentFailure,
+ PAPILDBFailure,
+ PAPIInvalidArg,
+ PAPIOutOfMemoryFailure,
+ PAPIUnknownFailure } PAPIStatus;
+
+/* Notification stuff */
+typedef enum { PAPIComponentAdd,
+ PAPIComponentModify,
+ PAPIComponentRemove } PAPIEventType;
+
+typedef struct {
+ PAPIEventType eventType;
+ const char * componentName;
+} PAPIEvent;
+
+typedef void ( *PAPIListener )( const PAPIEvent * inEvent, void * inUserData );
+
+typedef void * PAPIListenerId;
+
+/* Connection state stuff */
+typedef enum { PAPIConnected, PAPIDisconnected } PAPIConnectionState;
+
+typedef void ( *PAPIConnectionListener )( PAPIConnectionState inState,
+ void * inUserData );
+
+/* Layer stuff */
+typedef struct PAPILayerList
+{
+ const unsigned char * data;
+ int size;
+ const char * timestamp;
+ struct PAPILayerList * next;
+} PAPILayerList;
+
+typedef struct PAPIStringList
+{
+ const char * data;
+ struct PAPIStringList * next;
+} PAPIStringList;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PAPITYPES_H_ */
diff --git a/libapoc/papiUtils.c b/libapoc/papiUtils.c
new file mode 100644
index 0000000..df30a13
--- /dev/null
+++ b/libapoc/papiUtils.c
@@ -0,0 +1,662 @@
+/*
+ * 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 "papiUtils.h"
+
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#ifndef WNT
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#endif
+
+typedef struct PAPIConfigList
+{
+ int mName;
+ const char * mValue;
+ struct PAPIConfigList * mNext;
+} PAPIConfigList;
+
+typedef enum
+{
+ PAPIDaemonInstallDir = 0,
+ PAPIDaemonPort,
+ PAPIDaemonDataDir,
+ PAPITransactionTimeout,
+ PAPIUnknown
+} PAPIConfigName;
+
+static PAPIConfigList * addConfigList( PAPIConfigList ** inPrevious,
+ int inName,
+ char * inValue) ;
+
+static void deleteConfigList( PAPIConfigList * inList );
+
+static unsigned char findNextPair( FILE * inFile,
+ int * outName,
+ char ** outValue );
+
+static int mapToName( const char * inName );
+
+static void loadConfig( void );
+
+static void loadConfigFile( const char * inFileName,
+ PAPIConfigList ** inoutList );
+
+static int configLock( void );
+
+static PAPIConfigList * newConfigList( void );
+
+static int skipComments( FILE * inFile );
+
+static int configUnlock( void );
+
+static int papiConnect( PAPISocket inSocket,
+ struct sockaddr * inRemote );
+
+static const char * sDaemonInstallDir = 0;
+static const char * sDaemonLibraryDir = 0;
+static const char * sDaemonPropertiesDir = 0;
+static int sDaemonPort = -1;
+static const char * sDataDir = 0;
+static int sTransactionTimeout = -1;
+
+static int sDefaultDaemonPort = 3809;
+static int sDefaultTransactionTimeout = 10000;
+static int sMinimumTransactionTimeout = 1000;
+
+static PAPIMutex * sConfigMutex = 0;
+
+
+static const char sB64[ 64 ] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+#define ISWHITESPACE(inChar) ((inChar) == ' ' || (inChar) == '\t')
+#define ISRETURN(inChar) ((inChar) == '\r' || (inChar) == '\n')
+
+int base64_encode( const void * inBuffer,
+ int inBufferSize,
+ char ** outB64Buffer )
+{
+ char *s, *p;
+ int i;
+ int c;
+ const unsigned char *q;
+
+ p = s = (char *) malloc( inBufferSize * 4 / 3 + 4);
+ if (p == NULL)
+ return -1;
+ q = (const unsigned char *) inBuffer;
+ i = 0;
+ for (i = 0; i < inBufferSize;) {
+ c = q[i++];
+ c *= 256;
+ if (i < inBufferSize)
+ c += q[i];
+ i++;
+ c *= 256;
+ if (i < inBufferSize)
+ c += q[i];
+ i++;
+ p[0] = ( char )sB64[(c & 0x00fc0000) >> 18];
+ p[1] = ( char )sB64[(c & 0x0003f000) >> 12];
+ p[2] = ( char )sB64[(c & 0x00000fc0) >> 6];
+ p[3] = ( char )sB64[(c & 0x0000003f) >> 0];
+ if (i > inBufferSize)
+ p[3] = '=';
+ if (i > inBufferSize + 1)
+ p[2] = '=';
+ p += 4;
+ }
+ *p = 0;
+ *outB64Buffer = s;
+ return strlen(s);
+}
+
+const char * getDaemonDataDir( void )
+{
+ if ( configLock() == 0 )
+ {
+ if ( sDataDir == 0 )
+ {
+ loadConfig();
+ }
+ configUnlock();
+ }
+ return sDataDir;
+}
+
+const char * getDaemonInstallDir( void )
+{
+ if ( sDaemonInstallDir == 0 )
+ {
+ sDaemonInstallDir = getInstallDir();
+ }
+ return sDaemonInstallDir;
+}
+
+const char * getDaemonLibraryDir( void )
+{
+ if ( sDaemonLibraryDir == 0 )
+ {
+ sDaemonLibraryDir = getLibraryDir();
+ }
+ return sDaemonLibraryDir;
+}
+
+const char * getDaemonPropertiesDir( void )
+{
+ if ( sDaemonPropertiesDir == 0 )
+ {
+ sDaemonPropertiesDir = getPropertiesDir();
+ }
+ return sDaemonPropertiesDir;
+}
+
+int getDaemonPort( void )
+{
+ if ( configLock() == 0 )
+ {
+ if ( sDaemonPort == -1 )
+ {
+ loadConfig();
+ if ( sDaemonPort == -1 )
+ {
+ sDaemonPort = sDefaultDaemonPort;
+ }
+ }
+ configUnlock();
+ }
+ return sDaemonPort;
+}
+
+const char * getTimestamp( void )
+{
+ char * theTimestamp = 0;
+ time_t theTime = time( 0 );
+ struct tm * theGMTime = gmtime( &theTime );
+ if ( theTime != 0 )
+ {
+ theTimestamp = ( char * )malloc( 16 );
+ if ( theTimestamp != 0 )
+ {
+ snprintf( theTimestamp,
+ 16,
+ "%d%.2d%.2d%.2d%.2d%.2dZ",
+ theGMTime->tm_year + 1900,
+ theGMTime->tm_mon + 1,
+ theGMTime->tm_mday,
+ theGMTime->tm_hour,
+ theGMTime->tm_min,
+ theGMTime->tm_sec );
+ }
+ }
+ return theTimestamp;
+}
+
+int getTransactionTimeout( void )
+{
+ if ( configLock() == 0 )
+ {
+ if ( sTransactionTimeout == -1 )
+ {
+ loadConfig();
+ if ( sTransactionTimeout == -1 )
+ {
+ sTransactionTimeout = sDefaultTransactionTimeout;
+ }
+ else
+ if ( sTransactionTimeout < sMinimumTransactionTimeout )
+ {
+ sTransactionTimeout = sMinimumTransactionTimeout;
+ }
+ }
+ configUnlock();
+ }
+ return sTransactionTimeout;
+}
+
+PAPIConfigList * addConfigList( PAPIConfigList ** inPrevious,
+ int inName,
+ char * inValue)
+{
+ PAPIConfigList * theConfigList = newConfigList();
+ if ( theConfigList != 0 )
+ {
+ theConfigList->mName = inName;
+ theConfigList->mValue = inValue ;
+ theConfigList->mNext = 0;
+ if ( inPrevious[ 0 ] == 0 )
+ {
+ inPrevious[ 0 ] = theConfigList;
+ }
+ else
+ {
+ PAPIConfigList * theTmpList = inPrevious[ 0 ];
+ while ( theTmpList->mNext != 0 )
+ {
+ theTmpList = theTmpList->mNext;
+ }
+ theTmpList->mNext = theConfigList;
+ }
+ }
+ return theConfigList;
+}
+
+void deleteConfigList( PAPIConfigList * inList )
+{
+ if ( inList != 0 )
+ {
+ if ( inList->mNext != 0 )
+ {
+ deleteConfigList( inList->mNext );
+ }
+ if ( inList->mValue )
+ {
+ free( ( void * )inList->mValue );
+ }
+ free( inList );
+ }
+}
+
+unsigned char findNextPair(FILE *inFile, int *outName, char **outValue)
+{
+ char theString [1024] ;
+ int theChar = -1 ;
+ int theStringLength = 0 ;
+
+ *outName = PAPIUnknown ;
+ *outValue = 0 ;
+ /* Get rid of comments */
+ theChar = skipComments(inFile) ;
+ /* Find name */
+ while (theChar != EOF)
+ {
+ /* Skip initial whitespace */
+ if (theStringLength == 0 && ISWHITESPACE(theChar)) { continue ; }
+ if (theChar == '\\')
+ { /* Drop escape character */
+ theChar = fgetc(inFile) ;
+ }
+ else if (theChar == '=')
+ { /* Skip initial whitespace for possible value */
+ do { theChar = fgetc(inFile) ; } while (ISWHITESPACE(theChar)) ;
+ break ;
+ }
+ /* If we encounter a line break, something's wrong */
+ if (ISRETURN(theChar))
+ {
+ theStringLength = 0 ;
+ break ;
+ }
+ /* Else copy into the current string */
+ theString [theStringLength ++] = theChar ;
+ theChar = fgetc(inFile) ;
+ }
+ /* Remove trailing whitespace */
+ while (theStringLength != 0 &&
+ ISWHITESPACE(theString [theStringLength - 1]))
+ {
+ -- theStringLength ;
+ }
+ /* Terminate string */
+ theString [theStringLength] = 0 ;
+ *outName = mapToName(theString) ;
+ if (*outName == PAPIUnknown)
+ { /* If uncomprehensible name, move to next line */
+ while (!ISRETURN(theChar) && theChar != EOF)
+ {
+ theChar = fgetc(inFile) ;
+ }
+ return theChar != EOF ;
+ }
+ theStringLength = 0 ;
+ /* Find corresponding value */
+ while (theChar != EOF)
+ {
+ /* Skip initial whitespace */
+ if (theStringLength == 0 && ISWHITESPACE(theChar)) { continue ; }
+ if (theChar == '\\')
+ { /* Drop escape character */
+ theChar = fgetc(inFile) ;
+ }
+ if (ISRETURN(theChar))
+ { /* If end of line is reached, remove trailing whitespace */
+ while (theStringLength != 0 &&
+ ISWHITESPACE(theString [theStringLength - 1]))
+ {
+ -- theStringLength ;
+ }
+ break ;
+ }
+ /* Else copy into the current string */
+ theString [theStringLength ++] = theChar ;
+ theChar = fgetc(inFile) ;
+ }
+ /* Terminate and duplicate value */
+ theString [theStringLength] = 0 ;
+ *outValue = strdup(theString) ;
+ return theChar != EOF ;
+}
+
+PAPIConnectResult getConnectedSocket(
+ int inPort, int inType, int inRetryCount, PAPISocket * outSocket )
+{
+ static char sRejected = 0;
+ static char sAccepted = 1;
+ static const char * sLocalHostName = "127.0.0.1";
+ PAPIConnectResult theResult;
+ PAPISocket theSocket;
+ struct sockaddr_in theDaemonAddr;
+ struct hostent * theHostEnt;
+ int bResue = 1;
+#ifdef WNT
+ static int isWSAInitialised = 0;
+ WSADATA theWSAData;
+
+ if ( isWSAInitialised == 0 )
+ {
+ WSAStartup( MAKEWORD( 2, 2 ), &theWSAData );
+ isWSAInitialised = 1;
+ }
+#endif
+
+ *outSocket = INVALID_SOCKET;
+
+ theHostEnt = gethostbyname( sLocalHostName );
+ theDaemonAddr.sin_family = AF_INET;
+ theDaemonAddr.sin_port = htons( inPort );
+ theDaemonAddr.sin_addr = *( (struct in_addr * )theHostEnt->h_addr );
+
+ do
+ {
+ memset( ( void * )&( theDaemonAddr.sin_zero ), 0, 8 );
+ theResult = PAPIConnectFailed;
+ if ( ( theSocket = socket( AF_INET, inType, 0 ) ) != INVALID_SOCKET &&
+ papiConnect( theSocket,
+ ( struct sockaddr * )&theDaemonAddr ) == 0 )
+ {
+ char theInitialByte;
+ if ( socketPoll( theSocket, getTransactionTimeout() ) != 1 ||
+ recv( theSocket, &theInitialByte, 1, 0 ) != 1 ||
+ ( theInitialByte != sAccepted && theInitialByte != sRejected ))
+ {
+ papiClose( theSocket );
+ theResult = PAPIConnectWrongService;
+ break;
+ }
+ else
+ {
+ theResult = theInitialByte == sAccepted ?
+ PAPIConnectSuccess : PAPIConnectRejected;
+ if ( theResult == PAPIConnectSuccess )
+ {
+ *outSocket = theSocket;
+ break;
+ }
+ }
+ }
+ papiClose( theSocket );
+ if ( inRetryCount > 0 )
+ {
+ papiSleep( 1 );
+ }
+ } while ( --inRetryCount > 0 );
+ return theResult;
+}
+
+int mapToName(const char *inName)
+{
+ if (strcmp(inName, "DaemonPort") == 0)
+ { return PAPIDaemonPort ; }
+ else if (strcmp(inName, "DataDir") == 0)
+ { return PAPIDaemonDataDir ; }
+ else if (strcmp(inName, "DaemonInstallDir") == 0)
+ { return PAPIDaemonInstallDir ; }
+ else if (strcmp(inName, "TransactionTimeout") == 0)
+ { return PAPITransactionTimeout ; }
+ else return PAPIUnknown ;
+}
+
+void loadConfig( void )
+{
+ static const char * sPropertiesFile = "/apocd.properties";
+ static const char * sOsPropertiesFile = "/os.properties" ;
+ PAPIConfigList * theConfigList = 0 ;
+ PAPIConfigList * theTmpList = 0 ;
+ char * thePropertiesFileName = 0;
+ int theSize;
+ int prefixLength;
+
+ if ( sDaemonPropertiesDir == 0 )
+ {
+ sDaemonPropertiesDir = getPropertiesDir();
+ }
+ prefixLength = strlen( sDaemonPropertiesDir );
+ theSize = prefixLength + strlen( sPropertiesFile ) + 1;
+ thePropertiesFileName = ( char * )malloc( theSize );
+ snprintf( thePropertiesFileName,
+ theSize,
+ "%s%s",
+ sDaemonPropertiesDir,
+ sPropertiesFile );
+ loadConfigFile( thePropertiesFileName, &theConfigList );
+ free( ( void * )thePropertiesFileName );
+
+ theSize = prefixLength + strlen( sOsPropertiesFile ) + 1;
+ thePropertiesFileName = ( char * )malloc( theSize );
+ snprintf( thePropertiesFileName,
+ theSize,
+ "%s%s",
+ sDaemonPropertiesDir,
+ sOsPropertiesFile );
+ loadConfigFile( thePropertiesFileName, &theConfigList );
+ free( ( void *)thePropertiesFileName );
+
+ theTmpList = theConfigList;
+ while ( theTmpList != 0 )
+ {
+ switch( theTmpList->mName )
+ {
+ case PAPIDaemonPort:
+ sDaemonPort = atoi( theTmpList->mValue );
+ break;
+
+ case PAPIDaemonDataDir:
+#ifndef WNT
+ sDataDir = strdup( theTmpList->mValue );
+#else
+ sDataDir = convertDataDir( theTmpList->mValue );
+#endif
+ break;
+
+ case PAPITransactionTimeout:
+ sTransactionTimeout = 1000 * atoi( theTmpList->mValue );
+ break;
+
+ default:
+ break;
+ }
+ theTmpList = theTmpList->mNext;
+ }
+ deleteConfigList( theConfigList );
+}
+
+void loadConfigFile(const char *inFileName, PAPIConfigList **inoutConfigList)
+{
+ FILE *theFile = 0 ;
+ int theName = 0 ;
+ char *theValue = 0 ;
+
+ if (inoutConfigList == 0 || inFileName == 0) { return ; }
+ theFile = fopen(inFileName, "r") ;
+ if (theFile == 0) { return ; }
+ while (findNextPair(theFile, &theName, &theValue))
+ {
+ if (theName != PAPIUnknown)
+ {
+ addConfigList(inoutConfigList, theName, theValue) ;
+ }
+ }
+ fclose(theFile) ;
+}
+
+int configLock( void )
+{
+ int theRC = -1;
+ if ( sConfigMutex == 0 )
+ {
+ sConfigMutex = newMutex();
+ }
+ if ( sConfigMutex != 0 )
+ {
+ theRC = lockMutex( sConfigMutex );
+ }
+ return theRC;
+}
+
+PAPIConfigList * newConfigList( void )
+{
+ PAPIConfigList * theConfigList =
+ ( PAPIConfigList * )malloc( sizeof( PAPIConfigList ) );
+ if ( theConfigList != 0 )
+ {
+ theConfigList->mName = PAPIUnknown;
+ theConfigList->mValue = 0;
+ theConfigList->mNext = 0;
+ }
+ return theConfigList;
+}
+
+int skipComments(FILE *inFile)
+{
+ int theChar = -1 ;
+
+ do
+ {
+ theChar = fgetc(inFile) ;
+ if (ISRETURN(theChar) || ISWHITESPACE(theChar)) { continue ; }
+ if (theChar == '/')
+ {
+ theChar = fgetc(inFile) ;
+ if (theChar != '*') { ungetc(theChar, inFile) ; }
+ else
+ {
+ do
+ {
+ theChar = fgetc(inFile) ;
+ if (theChar == '*')
+ {
+ theChar = fgetc(inFile) ;
+ if (theChar == '/') { break ; }
+ }
+ } while (theChar != EOF) ;
+ }
+ }
+ else
+ {
+ ungetc(theChar, inFile) ;
+ break ;
+ }
+ } while (theChar != EOF) ;
+ return fgetc(inFile) ;
+}
+
+int configUnlock( void )
+{
+ int theRC = -1;
+ if ( sConfigMutex != 0 )
+ {
+ theRC = unlockMutex( sConfigMutex );
+ }
+ return theRC;
+}
+
+static int papiConnect( PAPISocket inSocket, struct sockaddr * inRemote )
+{
+ int theRC = -1;
+ int bReuse = 1;
+ int theSocketFlags;
+ if ( setsockopt( inSocket,
+ SOL_SOCKET,
+ SO_REUSEADDR,
+ &bReuse,
+ sizeof( bReuse ) ) == -1 )
+ {
+ return theRC;
+ }
+#ifdef SOLARIS
+ theSocketFlags = fcntl( inSocket, F_GETFL, 0);
+ if ( theSocketFlags >= 0 &&
+ fcntl( inSocket, F_SETFL, theSocketFlags | O_NONBLOCK ) != -1 )
+ {
+ theRC = connect( inSocket, inRemote, sizeof( struct sockaddr ) );
+ fcntl( inSocket, F_SETFL, theSocketFlags );
+ }
+#else
+ theRC = connect( inSocket, inRemote, sizeof( struct sockaddr ) );
+#endif
+ if ( theRC == 0 )
+ {
+ /*
+ * Nasty problem on Linux where connecting to daemon port sometimes
+ * works even when daemon is not listening. The following is an
+ * attempt to detect this
+ */
+ struct sockaddr_in theLocal;
+ socklen_t theSize = sizeof( theLocal );
+ if ( getsockname( inSocket,
+ ( struct sockaddr * )&theLocal,
+ &theSize ) == 0 )
+ {
+ if ( ntohs( theLocal.sin_port ) ==
+ ntohs( ( ( struct sockaddr_in * )&inRemote )->sin_port ) )
+ {
+ theRC = -1;
+ }
+ }
+ else
+ {
+ theRC = -1;
+ }
+ }
+ return theRC;
+}
diff --git a/libapoc/papiUtils.h b/libapoc/papiUtils.h
new file mode 100644
index 0000000..118e48d
--- /dev/null
+++ b/libapoc/papiUtils.h
@@ -0,0 +1,167 @@
+/*
+ * 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 PAPIUTILS_H_
+#define PAPIUTILS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "papiTypes.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+typedef enum
+{
+ PAPIConnectSuccess,
+ PAPIConnectRejected,
+ PAPIConnectFailed,
+ PAPIConnectWrongService
+} PAPIConnectResult;
+
+#ifndef WNT
+#include <pthread.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+typedef pthread_mutex_t PAPIMutex;
+typedef int PAPISocket;
+typedef pthread_t * PAPIThread;
+
+#define FILESEP "/"
+#define PATHSEP ":"
+#define papiClose close
+#define papiSleep sleep
+#define papiPclose pclose
+#define papiPopen popen
+#define papiUmask umask
+#define INVALID_SOCKET -1
+#define SOCKET_ERROR -1
+
+#ifdef SOLARIS
+int isServiceEnabled( void );
+#endif
+
+#else
+#include <windows.h>
+#include <io.h>
+#include <stdio.h>
+
+typedef CRITICAL_SECTION PAPIMutex;
+typedef SOCKET PAPISocket;
+typedef HANDLE PAPIThread;
+typedef int socklen_t;
+
+#define FILESEP "\\\\"
+#define PATHSEP ";"
+#define snprintf _snprintf
+#define papiClose closesocket
+#define papiSleep( inSeconds ) Sleep( inSeconds * 1000 )
+#define papiPclose _pclose
+#define papiPopen _popen
+#define papiUmask _umask
+
+#define APOCENABLEDKEY "Software\\Sun Microsystems\\apoc\\1.0\\Enabled"
+
+#define APOCSERVICENAME "apocd"
+
+const char * convertDataDir( const char * inDir );
+
+int isNewerThanWindows98( void );
+
+#endif
+
+
+typedef void * ( *PAPIThreadFunc )( void * inArg );
+
+int base64_encode( const void * inBuffer,
+ int inBufferSize,
+ char ** outB64Buffer );
+
+PAPIThread createThread( PAPIThreadFunc inThreadFunc,
+ void * inArg );
+
+void destroyThread( PAPIThread inThread );
+
+void deleteMutex( PAPIMutex * inMutex );
+
+PAPIConnectResult getConnectedSocket( int inPort,
+ int inType,
+ int inRetryCount,
+ PAPISocket * outSocket );
+
+const char * getDaemonDataDir( void );
+
+const char * getDaemonInstallDir(void );
+
+const char * getDaemonLibraryDir(void );
+
+const char * getDaemonPropertiesDir(void );
+
+int getDaemonPort( void );
+
+const char * getInstallDir( void );
+
+const char * getLibraryDir( void );
+
+const char * getPropertiesDir( void );
+
+const char * getSASLCreds( const char * inServiceName,
+ PAPIStatus * outStatus );
+
+const char * getTimestamp( void );
+
+int getTransactionTimeout( void );
+
+const char * getUserName( void );
+
+int isDaemonEnabled( void );
+
+int lockMutex( PAPIMutex * inMutex );
+
+int socketPoll( PAPISocket inSocket,
+ int inMillis );
+
+int startDaemon( void );
+
+PAPIMutex * newMutex( void );
+
+int unlockMutex( PAPIMutex * inMutex );
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PAPIUTILS_H_ */
diff --git a/libapoc/papitool.c b/libapoc/papitool.c
new file mode 100644
index 0000000..cfaec0e
--- /dev/null
+++ b/libapoc/papitool.c
@@ -0,0 +1,521 @@
+/*
+ * 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/papi.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+
+char const * g_appname;
+const char * g_entity = NULL;
+
+void show_version(FILE * target);
+
+void show_error(char const * fmt, char const * param);
+void usage(char const * fmt, char const * param);
+void list_usage();
+void show_usage();
+void offline_usage();
+
+void test_connect_avail(int argc, char * const argv[]);
+void list_components(int argc, char * const argv[]);
+void show_components(int argc, char * const argv[]);
+void do_offline(int argc, char * const argv[]);
+
+int match(const char * input, const char * command)
+{
+ if (!input || !*input) return 0;
+
+ return !strncmp(input,command,strlen(input));
+}
+
+int main(int argc, char * argv[])
+{
+ int argindex = 1;
+ int subargc;
+ char * const * subargv;
+
+ if (argv[0] == NULL)
+ g_appname = "[papitool]";
+ else if ( (g_appname = strrchr(argv[0],'/')) != NULL )
+ ++g_appname;
+ else
+ g_appname = argv[0];
+
+ if (argc <= argindex) usage("Too few arguments: %s", "Missing Command");
+
+ /* parse options */
+ if (!strcmp(argv[argindex], "--version") ||
+ !strcmp(argv[argindex], "-V") )
+ {
+ show_version(stdout);
+ if (argc == ++argindex) exit(0);
+ }
+
+ if ( !strcmp(argv[argindex], "-e") ||
+ (!strcmp(argv[argindex], "-Ve") && (show_version(stdout),1)) )
+ {
+ ++argindex;
+ if (argc <= argindex) usage("Too few arguments: %s", "Missing Entity and Command");
+
+ g_entity = argv[argindex++];
+
+ if (argc <= argindex) usage("Too few arguments: %s", "Missing Command");
+ }
+
+ /* do help command/options */
+ if (!strcmp(argv[argindex], "help") ||
+ !strcmp(argv[argindex], "--help") ||
+ !strcmp(argv[argindex], "-h") ||
+ !strcmp(argv[argindex], "-?") )
+ {
+ usage(NULL,NULL);
+ }
+
+ /* end of options */
+ subargc = argc - argindex;
+ subargv = argv + argindex;
+
+ if (match(subargv[0],"test"))
+ test_connect_avail(subargc,subargv);
+
+ else if (match(subargv[0],"list"))
+ list_components(subargc,subargv);
+
+ else if (match(subargv[0],"show"))
+ show_components(subargc,subargv);
+
+ else if (match(subargv[0],"offline"))
+ do_offline(subargc,subargv);
+
+ else
+ usage("Unknown command: '%s'",subargv[0]);
+
+ return 0;
+}
+
+/* PAPI helper functions */
+
+void checkPapiError(PAPIStatus error)
+{
+ const char * errmsg;
+ switch (error)
+ {
+ case PAPISuccess:
+ return;
+
+ case PAPIConnectionFailure:
+ errmsg = "PAPI: Connection Failure for entity %s";
+ break;
+
+ case PAPIAuthenticationFailure:
+ errmsg = "PAPI: Authentication Failure for entity %s";
+ break;
+
+
+ case PAPINoSuchComponentFailure:
+ errmsg = "PAPI: No such component";
+ break;
+
+ case PAPILDBFailure:
+ errmsg = "PAPI: Database (LDB) Failure";
+ break;
+
+ case PAPIInvalidArg:
+ errmsg = "PAPI: Invalid Argument";
+ break;
+
+ case PAPIOutOfMemoryFailure:
+ errmsg = "PAPI: Out of Memory";
+ break;
+
+ case PAPIUnknownFailure:
+ errmsg = "PAPI: Unspecified Failure";
+ break;
+
+ default:
+ errmsg = "PAPI: Unknown PAPI error code";
+ break;
+ }
+ const char * entity = g_entity ? g_entity : "<default entity>";
+
+ show_error(errmsg,entity);
+ fprintf(stderr,"\nTerminating\n");
+
+ exit(-error);
+}
+
+PAPI * initPapi()
+{
+ PAPIStatus error = PAPISuccess;
+ PAPI * result = papiInitialise(g_entity,&error);
+
+ checkPapiError(error);
+ return result;
+}
+
+void exitPapi(PAPI * papi)
+{
+ PAPIStatus error = PAPISuccess;
+
+ papiDeinitialise(papi,&error);
+
+ checkPapiError(error);
+}
+
+/* connection test function */
+
+void describe_test_usage()
+{
+ fprintf(stderr,"\n\n\t%s [options] t[est]", g_appname);
+ fputs( "\n\t\t- Test if a PAPI connection can be established"
+ , stderr);
+}
+
+void test_connect_avail(int argc, char * const argv[])
+{
+ PAPI * papi;
+
+ papi = initPapi();
+
+ fprintf(stderr,"\nOK. PAPI connection was established successfully");
+ if (g_entity)
+ fprintf(stderr," for entity '%s'", g_entity);
+ else
+ fprintf(stderr," for the current user");
+ fputs("\n",stderr);
+
+ exitPapi(papi);
+}
+
+/* list components function */
+
+void describe_list_usage()
+{
+ fprintf(stderr,"\n\n\t%s [options] l[ist] [filter]", g_appname);
+ fputs( "\n\t\t- List components that match a filter"
+ , stderr);
+}
+
+void list_components(int argc, char * const argv[])
+{
+ PAPI * papi;
+ PAPIStatus error = PAPISuccess;
+ PAPIStringList * components;
+ PAPIStringList * component;
+ const char * filter;
+ int count = 0;
+
+ if (argc > 2)
+ {
+ show_error("Too many arguments for 'list' command",NULL);
+ list_usage();
+ }
+
+ if (argc < 2)
+ filter = NULL;
+ else
+ filter = argv[1];
+
+ papi = initPapi();
+
+ components = papiListComponentNames(papi,filter,&error);
+
+ if (error == PAPINoSuchComponentFailure)
+ {
+ fprintf(stderr,"\nNo Component for filter '%s'\n",filter ? filter : "<null>");
+ goto done;
+ }
+
+ checkPapiError(error);
+
+ for (component = components; component; component=component->next)
+ {
+ ++count;
+ if (component->data)
+ printf("%s\n",component->data);
+ else
+ fprintf(stderr, "### Data for component #%d is NULL ###\n",count);
+ }
+ fprintf(stderr,"\n\n%d component(s) found.\n",count );
+
+ papiFreeStringList(components);
+
+done:
+ exitPapi(papi);
+}
+
+/* show component data function */
+
+void describe_show_usage()
+{
+ fprintf(stderr,"\n\n\t%s [options] s[how] (all|time|count|<N>) <component> ...", g_appname);
+
+ fputs( "\n\t\t- Show data for component(s)."
+ "\n\t\t Supported operations:"
+ "\n\t\t all - show entire contents for all layers of each component"
+ "\n\t\t time - show layer count and timestamp for each component"
+ "\n\t\t count - show layer count for each component"
+ "\n\t\t <N> - show Nth layer of component (works best with a single component)"
+ , stderr);
+}
+
+enum {
+ SHOW_FULL = -1,
+ SHOW_TIME = -2,
+ SHOW_COUNT = -3
+};
+
+void dump_layer(PAPILayerList * layer, FILE * tofile)
+{
+ fputs("\n",tofile);
+ if (layer && layer->data && layer->size>0)
+ {
+ size_t size = layer->size, read;
+ const unsigned char * data = layer->data;
+
+ while (size > 0)
+ {
+ read = fwrite(data,1,size,tofile);
+
+ if (read == 0)
+ {
+ fputs("\n### ERROR ###",tofile);
+ show_error("Error writing output: %s", strerror(errno));
+ break;
+ }
+
+ size -= read;
+ data += read;
+ }
+ }
+ else
+ fputs("### No data for this layer ###",tofile);
+
+ fputs("\n",tofile);
+}
+
+void dump_component(const char * component, PAPILayerList * layers, int op)
+{
+ PAPILayerList * layer;
+ int count = 0;
+
+ if (op >= SHOW_FULL)
+ printf("\n========== Start of data for component '%s' ==================", component);
+ else
+ printf("\nComponent '%s':", component);
+
+ for (layer = layers; layer; layer=layer->next)
+ {
+ ++count;
+
+ if (op == SHOW_FULL || op == SHOW_TIME)
+ printf("\n- Layer #%d: Timestamp = %s\t***",
+ count, layer->timestamp ? layer->timestamp : "<null>");
+
+ if (op == SHOW_FULL || op == count)
+ dump_layer(layer,stdout);
+ }
+
+ if (op >= SHOW_FULL)
+ printf("========== End of data for component '%s' ====================", component);
+
+ printf("\n\t%d layer(s)\n",count);
+}
+
+void show_components(int argc, char * const argv[])
+{
+ PAPI * papi;
+ PAPIStatus error = PAPISuccess;
+ const char * component;
+ int argindex = 1;
+ int op;
+
+ if (argc < 3)
+ {
+ show_error("Not enough arguments for 'show' command",NULL);
+ show_usage();
+ }
+
+ if (match(argv[argindex],"all"))
+ op = SHOW_FULL;
+
+ else if (match(argv[argindex],"time"))
+ op = SHOW_TIME;
+
+ else if (match(argv[argindex],"count"))
+ op = SHOW_COUNT;
+
+ else
+ op = atoi(argv[argindex]);
+
+ if (op == 0)
+ {
+ show_error("Invalid operation '%s' for 'show' command",argv[argindex]);
+ show_usage();
+ }
+
+ papi = initPapi();
+
+ while ( (component = argv[++argindex]) != NULL )
+ {
+ PAPILayerList * layers = papiReadComponentLayers(papi,component,&error);
+
+ if (error == PAPINoSuchComponentFailure)
+ {
+ printf("\nNo Such Component '%s'\n",component);
+ continue;
+ }
+
+ checkPapiError(error);
+
+ dump_component(component,layers,op);
+
+ papiFreeLayerList(layers);
+ }
+
+ exitPapi(papi);
+}
+
+/* offline status function */
+
+void describe_offline_usage()
+{
+ fprintf(stderr,"\n\n\t%s [options] o[ffline] (show|add|drop|+|-) <component> ...", g_appname);
+
+ fputs( "\n\t\t- Show or change offline status for component(s)."
+ "\n\t\t Supported operations:"
+ "\n\t\t show - show current offline status for each component"
+ "\n\t\t add - mark each component for offline availability (alias '+')"
+ "\n\t\t drop - mark each component as not availabile offline (alias '-')"
+ , stderr);
+ fputs("\n\t*** NOT YET IMPLEMENTED ***",stderr);
+}
+
+void do_offline(int argc, char * const argv[])
+{
+ PAPI * papi;
+ PAPIStatus error = PAPISuccess;
+
+ offline_usage();
+
+ papi = initPapi();
+ exitPapi(papi);
+}
+
+/* usage reporting */
+
+void show_version(FILE * file)
+{
+ const char * version = "0.1";
+ const char * author = "Joerg Barfurth";
+ fprintf(file,"\n%s - PAPI dumper tool for APOC",g_appname);
+ fprintf(file,"\nVersion: %s\tBuild time: %s",version,__TIME__);
+ fprintf(file,"\nAuthor: %s",author);
+ fprintf(file,"\nCopyright (C) 2003 Sun Microsystems,Inc.\n");
+}
+
+void pre_usage()
+{
+ show_version(stderr);
+ fprintf(stderr,"\nUsage: ");
+}
+
+void post_usage(int exitcode)
+{
+ fprintf(stderr,"\n\nOptions:");
+ fprintf(stderr,"\n\t-V / --version\t- display information about this tool");
+ fprintf(stderr,"\n\t-e <entity>\t- use entity id <entity>");
+ fprintf(stderr,"\n");
+
+ exit(exitcode);
+}
+
+void describe_help_usage()
+{
+ fprintf(stderr,"\n\n\t%s [options] help\n\t\t- show this help screen", g_appname);
+}
+
+void show_error(char const * fmt, char const * param)
+{
+ fprintf(stderr,"### %s Error: ", g_appname);
+ fprintf(stderr,fmt,param);
+}
+
+void usage(char const * fmt, char const * param)
+{
+ if (fmt)
+ show_error(fmt,param);
+
+ pre_usage();
+
+ describe_test_usage();
+ describe_list_usage();
+ describe_show_usage();
+ describe_offline_usage();
+ describe_help_usage();
+
+ post_usage(fmt?1:0);
+}
+
+void list_usage()
+{
+ pre_usage();
+
+ describe_list_usage();
+
+ post_usage(2);
+}
+
+void show_usage()
+{
+ pre_usage();
+
+ describe_show_usage();
+
+ post_usage(3);
+}
+
+void offline_usage()
+{
+ pre_usage();
+
+ describe_offline_usage();
+
+ post_usage(4);
+}
+
+
diff --git a/libapoc/w32/Makefile b/libapoc/w32/Makefile
new file mode 100644
index 0000000..1d4d88a
--- /dev/null
+++ b/libapoc/w32/Makefile
@@ -0,0 +1,55 @@
+#
+#*******************************************************************************
+#* $RCSfile: Makefile,v $
+#*
+#* Description:
+#*
+#* Last change: $Date: 2007/04/20 15:01:50 $ $Revision: 1.3 $
+#*
+#* Copyright 2003 Sun Microsystems, Inc. All rights reserved. Use of this
+#* product is subject to license terms.
+#*
+#*******************************************************************************
+#
+
+
+PRJ=../../..
+
+include $(PRJ)/Makefile.common
+
+ifdef WNT
+
+APOCSOURCES = papiPort.c
+APOCOBJS = $(APOCSOURCES:%.c=$(OBJDIR)/%.o)
+APOCINCLUDES = -I../.. $(GSSINCLUDES) $(INCLUDES)
+
+all: apoc
+
+clean: apocclean
+
+apoc: mkdirs $(APOCOBJS)
+
+apocclean:
+ rm -f $(APOCOBJS)
+
+mkdirs:
+ $(mkoutdirs)
+
+$(OBJDIR)/%.o: %.c
+ $(CC) $(CFLAGSSO) $(APOCINCLUDES) -c $*.c -Fo$(OBJDIR)/$*.o -Fd$(OBJDIR)/$*.pdb
+
+else
+
+apoc:
+
+all:
+
+clean:
+
+apoc:
+
+apocclean:
+
+mkdirs:
+
+endif
diff --git a/libapoc/w32/Makefile.old b/libapoc/w32/Makefile.old
new file mode 100644
index 0000000..c75f42e
--- /dev/null
+++ b/libapoc/w32/Makefile.old
@@ -0,0 +1,110 @@
+#
+#*******************************************************************************
+#* $RCSfile: Makefile,v $
+#*
+#* Description:
+#*
+#* Last change: $Date: 2006/06/27 09:08:56 $ $Revision: 1.9 $
+#*
+#* Copyright 2003 Sun Microsystems, Inc. All rights reserved. Use of this
+#* product is subject to license terms.
+#*
+#*******************************************************************************
+#
+
+
+PRJ=../..
+
+include $(PRJ)/Makefile.common
+
+APOCSOURCES = \
+ papi.c \
+ papiConnection.c \
+ papiDaemon.c \
+ papiDatabase.c \
+ papiInternal.c \
+ papiLayerList.c \
+ papiListenerList.c \
+ papiMessage.c \
+ papiSAXParserContext.c \
+ papiStringList.c \
+ papiEntityList.c \
+ papiUtils.c
+APOCOBJS = $(APOCSOURCES:%.c=$(OBJDIR)/%.o) $(OBJDIR)/papiPort.o
+LIBAPOC = $(LIBDIR)/$(SOPREFIX)apoc$(SOSUFFIX)
+APOCINCLUDES = $(LIBXML2INCLUDES) $(INCLUDES)
+APOCLIBS = $(LIBXML2LIBS) $(GSSLIBS) $(LIBS)
+ifdef SOLARIS
+APOCLIBS += -lscf
+endif
+
+
+APOCJAVASOURCE = papiJava.c
+APOCJAVAOBJS = $(APOCJAVASOURCE:%.c=$(OBJDIR)/%.o)
+LIBAPOCJAVA = $(LIBDIR)/$(SOPREFIX)apoc_java$(SOSUFFIX)
+ifdef UNX
+APOCJAVALIBS = -L$(LIBDIR) -lapoc $(LIBS)
+else
+APOCJAVALIBS = apoc.lib $(LIBS)
+endif
+
+
+APOCWRAPSOURCE = papiWrap.c
+APOCWRAPOBJS = $(APOCWRAPSOURCE:%.c=$(OBJDIR)/%.o)
+LIBAPOCWRAP = $(LIBDIR)/$(SOPREFIX)apocwrap$(SOSUFFIX)
+ifdef UNX
+APOCWRAPLIBS = -L$(LIBDIR) -lapoc $(LIBS) -lrt
+else
+APOCWRAPLIBS = apoc.lib $(LIBS)
+endif
+
+all: apoc apoc-adapter-java
+
+clean: apocclean apoc-adapter-javaclean
+
+apoc: mkdirs $(LIBAPOC)
+
+$(LIBAPOC): $(APOCOBJS)
+ifdef UNX
+ $(CC) $(LDFLAGSSO) -o $(LIBAPOC) $(APOCOBJS) $(APOCLIBS) -ldl
+else
+ $(LINK) $(LDFLAGSSO) $(APOCOBJS) /OUT:$(LIBAPOC) $(APOCLIBS)
+endif
+
+apocclean:
+ rm -f $(APOCOBJS) $(LIBAPOC)
+
+apoc-adapter-java: $(LIBAPOCJAVA)
+
+$(LIBAPOCJAVA): $(APOCJAVAOBJS)
+ifdef UNX
+ $(CC) $(LDFLAGSSO) -o$(LIBAPOCJAVA) $(APOCJAVAOBJS) $(APOCJAVALIBS)
+else
+ $(LINK) $(LDFLAGSSO) $(APOCJAVAOBJS) /OUT:$(LIBAPOCJAVA) $(APOCJAVALIBS)
+endif
+
+apoc-adapter-javaclean:
+ rm -f $(APOCJAVAOBJS) $(LIBAPOCJAVA)
+
+
+apocwrap: $(LIBAPOCWRAP)
+
+$(LIBAPOCWRAP): $(APOCWRAPOBJS)
+ifdef UNX
+ $(CC) $(LDFLAGSSO) -o$(LIBAPOCWRAP) $(APOCWRAPOBJS) $(APOCWRAPLIBS)
+else
+ $(LINK) $(LDFLAGSSO) $(APOCWRAPOBJS) /OUT:$(LIBAPOCWRAP) $(APOCWRAPLIBS)
+endif
+
+apocwrapclean:
+ rm -f $(APOCWRAPOBJS) $(LIBAPOCWRAP)
+
+mkdirs:
+ $(mkoutdirs)
+
+$(OBJDIR)/%.o: %.c
+ifdef UNX
+ $(CC) $(CFLAGSSO) $(APOCINCLUDES) -c $*.c -o $(OBJDIR)/$*.o
+else
+ $(CC) $(CFLAGSSO) -DPAPI_EXPORTS $(APOCINCLUDES) -c $*.c -Fo$(OBJDIR)/$*.o -Fd$(OBJDIR)/$*.pdb
+endif
diff --git a/libapoc/w32/papiPort.c b/libapoc/w32/papiPort.c
new file mode 100755
index 0000000..6383f02
--- /dev/null
+++ b/libapoc/w32/papiPort.c
@@ -0,0 +1,624 @@
+/*
+ * 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 "papiUtils.h"
+
+#include <lmcons.h>
+#define SECURITY_WIN32
+#include <security.h>
+#include <sspi.h>
+#include <ntsecapi.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <shlobj.h>
+
+typedef WINADVAPI SC_HANDLE ( WINAPI *OpenSCManagerFunc )
+ ( LPCTSTR, LPCTSTR, DWORD );
+
+typedef WINADVAPI BOOL ( WINAPI * EnumServicesStatusFunc )
+ ( SC_HANDLE, DWORD, DWORD, LPENUM_SERVICE_STATUS, DWORD, LPDWORD, LPDWORD,
+ LPDWORD );
+
+static PSecurityFunctionTable getSecurityInterface( int * outMaxTokenSize );
+
+static int isRegistryEnabled( void );
+
+static int isServiceEnabled( void );
+
+static int loadServiceFuncs( void );
+
+static void writeGSSAPIAuthId(
+ PSecurityFunctionTable inSecurityInterface,
+ CredHandle * inCredentials,
+ CtxtHandle * inContext,
+ SecBuffer * outBuffer,
+ PAPIStatus * outStatus );
+
+static void encodeGSSAPITokens( SecBuffer * inBuffers,
+ int inBufferCount,
+ char ** outB64Buffer );
+
+#define INSTALLDIR "\\Sun\\apoc\\lib"
+
+const char * convertDataDir( const char * inDataDir )
+{
+ char * theDataDir = 0;
+ if ( inDataDir != 0 )
+ {
+ theDataDir = ( char * )malloc( strlen( inDataDir ) + 1 );
+ if ( theDataDir != 0 )
+ {
+ char * theToken = strtok( inDataDir, "\\" );
+ theDataDir[ 0 ] = 0;
+ while ( theToken != 0 )
+ {
+ strcat( theDataDir, theToken );
+ theToken = strtok( 0, "\\" );
+ if ( theToken != 0 )
+ {
+ strcat( theDataDir, "\\" );
+ }
+ }
+ }
+ }
+ return theDataDir;
+}
+
+int createThread( PAPIThreadFunc inThreadFunc,
+ void * inArg )
+{
+ int theThreadId;
+ HANDLE theThread =
+ CreateThread( NULL,
+ 0,
+ ( LPTHREAD_START_ROUTINE )inThreadFunc,
+ inArg,
+ 0,
+ ( LPDWORD )&theThreadId );
+ return theThread != 0 ? 0 : -1;
+}
+
+const char * getInstallDir( void )
+{
+ static char * sInstallDir = 0;
+ if ( sInstallDir == 0 )
+ {
+ char theProgramFiles[ MAX_PATH ];
+ if ( SHGetFolderPath( NULL,
+ CSIDL_PROGRAM_FILES,
+ NULL,
+ SHGFP_TYPE_CURRENT,
+ ( LPTSTR )&theProgramFiles ) == S_OK )
+ {
+ char theShortPath[ MAX_PATH ];
+ DWORD theSize = MAX_PATH;
+ theSize =GetShortPathName( theProgramFiles, &theShortPath, theSize);
+ sInstallDir = malloc( theSize +
+ strlen( INSTALLDIR ) +
+ 1 );
+ if ( sInstallDir != 0 )
+ {
+ sprintf( sInstallDir, "%s%s", theShortPath, INSTALLDIR );
+ }
+ }
+ }
+ return sInstallDir;
+}
+
+const char * getLibraryDir( void )
+{
+ return getInstallDir();
+}
+
+const char * getPropertiesDir( void )
+{
+ return getInstallDir();
+}
+
+int isNewerThanWindows98( void )
+{
+ if ( GetVersion() < 0x80000000 )
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+PAPIMutex * newMutex( void )
+{
+ PAPIMutex * theMutex =
+ ( PAPIMutex * )malloc( sizeof( PAPIMutex ) );
+ if ( theMutex != 0 )
+ {
+ InitializeCriticalSection( theMutex );
+ }
+ return theMutex;
+}
+
+void deleteMutex( PAPIMutex * inMutex )
+{
+ if ( inMutex != 0 )
+ {
+ DeleteCriticalSection( inMutex );
+ free( ( void *)inMutex );
+ }
+}
+
+const char * getSASLCreds( const char * inServiceName, PAPIStatus * outStatus )
+{
+ char * theCredentials;
+ static int sMaxTokenSize;
+ PSecurityFunctionTable theSecurityInterface =
+ getSecurityInterface( &sMaxTokenSize );
+
+ *outStatus = PAPIAuthenticationFailure;
+ if ( theSecurityInterface != 0 )
+ {
+ if ( inServiceName != 0 )
+ {
+ CredHandle theCredHandle;
+ TimeStamp theCredLifetime;
+ SECURITY_STATUS theStatus =
+ ( theSecurityInterface->AcquireCredentialsHandle )
+ (
+ 0,
+ "Kerberos",
+ SECPKG_CRED_OUTBOUND,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ &theCredHandle,
+ &theCredLifetime
+ );
+ if ( theStatus == SEC_E_OK )
+ {
+ CtxtHandle theContextHandle;
+ SecBufferDesc theOutBufferDesc;
+ SecBuffer theOutBuffer[ 3 ];
+ ULONG theAttrs;
+
+ theOutBuffer[ 1 ].cbBuffer =
+ theOutBuffer[ 2 ].cbBuffer = 0;
+ theOutBufferDesc.ulVersion = SECBUFFER_VERSION;
+ theOutBufferDesc.cBuffers = 1;
+ theOutBufferDesc.pBuffers = &theOutBuffer[ 0 ];
+ theOutBuffer[ 0 ].BufferType = SECBUFFER_TOKEN;
+ theOutBuffer[ 0 ].cbBuffer = sMaxTokenSize;
+ theOutBuffer[ 0 ].pvBuffer =
+ ( PBYTE )malloc( sMaxTokenSize );
+
+ theStatus =
+ ( theSecurityInterface->InitializeSecurityContext )
+ (
+ &theCredHandle,
+ NULL,
+ ( SEC_CHAR * )inServiceName,
+ ISC_REQ_DELEGATE,
+ 0,
+ SECURITY_NATIVE_DREP,
+ NULL,
+ 0,
+ &theContextHandle,
+ &theOutBufferDesc,
+ &theAttrs,
+ &theCredLifetime
+ );
+ if ( theStatus == SEC_E_OK ||
+ theStatus == SEC_I_CONTINUE_NEEDED ||
+ theStatus == SEC_I_COMPLETE_NEEDED ||
+ theStatus == SEC_I_COMPLETE_AND_CONTINUE )
+ {
+ writeGSSAPIAuthId( theSecurityInterface,
+ &theCredHandle,
+ &theContextHandle,
+ &theOutBuffer[ 2 ],
+ outStatus );
+ if ( *outStatus == PAPISuccess )
+ {
+ encodeGSSAPITokens( theOutBuffer,
+ 3,
+ &theCredentials );
+ }
+ FreeContextBuffer( &theContextHandle );
+ }
+ FreeCredentialsHandle( &theCredHandle );
+ }
+ }
+ }
+ return theCredentials;
+}
+
+const char * getUserName( void )
+{
+ DWORD theBufferSize = UNLEN + 1;
+ LPTSTR theBuffer = ( LPTSTR )malloc( ( size_t )theBufferSize );
+
+ GetUserName( theBuffer, &theBufferSize );
+ return theBuffer;
+}
+
+int isDaemonEnabled( void )
+{
+ return isNewerThanWindows98() == 1 ?
+ isServiceEnabled() : isRegistryEnabled();
+}
+
+int lockMutex( PAPIMutex * inMutex )
+{
+ int theRC = -1;
+ if ( inMutex != 0 )
+ {
+ EnterCriticalSection( inMutex );
+ theRC = 0;
+ }
+ return theRC;
+}
+
+int socketPoll( PAPISocket inSocket, int inMillis )
+{
+ fd_set theReadSet;
+
+ FD_ZERO( &theReadSet );
+ FD_SET( inSocket, &theReadSet );
+ if ( inMillis != -1 )
+ {
+ struct timeval theTimeout;
+ theTimeout.tv_sec = 0;
+ theTimeout.tv_usec = inMillis * 1000;
+ return select( 1, &theReadSet, 0, 0, &theTimeout );
+ }
+ else
+ {
+ return select( 1, &theReadSet, 0, 0, 0 );
+ }
+}
+
+int startDaemon( void )
+{
+ int theRC = 1;
+ static const char * theFormat = "%s%sbin%sapocd start";
+ static char * theCommand = 0;
+
+ if ( isNewerThanWindows98() == 0 && isDaemonEnabled() == 1 )
+ {
+ if ( theCommand == 0 )
+ {
+ const char * theDaemonInstallDir = getDaemonInstallDir();
+ char * theCP = ( char * )theDaemonInstallDir +
+ strlen( theDaemonInstallDir ) - 1;
+ while ( theCP-- != theDaemonInstallDir )
+ {
+ if ( *theCP == '\\' )
+ {
+ *theCP = 0;
+ break;
+ }
+ }
+ theCommand =
+ ( char * )malloc( strlen( theDaemonInstallDir ) +
+ ( strlen( FILESEP ) * 2 ) +
+ strlen( theFormat ) + 1 );
+ if ( theCommand != 0 )
+ {
+ sprintf( theCommand,
+ theFormat,
+ theDaemonInstallDir,
+ FILESEP,
+ FILESEP );
+ }
+ }
+ if ( theCommand != 0 )
+ {
+ 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,
+ DETACHED_PROCESS,
+ 0,
+ 0,
+ &theStartupInfo,
+ &theProcessInfo ) != 0 )
+ {
+ theRC = 0;
+ CloseHandle( theProcessInfo.hProcess );
+ CloseHandle( theProcessInfo.hThread );
+ }
+ }
+ }
+ return theRC;
+}
+
+int unlockMutex( PAPIMutex * inMutex )
+{
+ int theRC = -1;
+ if ( inMutex != 0 )
+ {
+ LeaveCriticalSection( inMutex );
+ theRC = 0;
+ }
+ return theRC;
+}
+
+void encodeGSSAPITokens( SecBuffer * inBuffers,
+ int inBufferCount,
+ char ** outB64Buffer )
+{
+ void * theBuffer;
+ char * theTmpPtr;
+ int theBufferSize = 0;
+ int theIndex;
+
+ for ( theIndex = 0; theIndex < inBufferCount; ++ theIndex )
+ {
+ theBufferSize += inBuffers[ theIndex ].cbBuffer + 5;
+ }
+
+ theBuffer = malloc( theBufferSize );
+ theTmpPtr = ( char *)theBuffer;
+ for ( theIndex = 0; theIndex < inBufferCount; ++ theIndex )
+ {
+ /* Write the token size */
+ snprintf( theTmpPtr, 6, "%05d", inBuffers[ theIndex ].cbBuffer );
+ theTmpPtr[ 5 ] = 0;
+ theTmpPtr += 5;
+
+ /* Write the token */
+ memcpy( ( void *)theTmpPtr,
+ inBuffers[ theIndex ].pvBuffer,
+ inBuffers[ theIndex ].cbBuffer );
+ theTmpPtr += inBuffers[ theIndex ].cbBuffer;
+ }
+ base64_encode( theBuffer, theBufferSize, outB64Buffer );
+ free( ( void * )theBuffer );
+}
+
+PSecurityFunctionTable getSecurityInterface( int * outMaxTokenSize )
+{
+ static PSecurityFunctionTable theSecurityInterface = 0;
+ static int isInitialised = 0;
+
+ if ( isInitialised == 0 )
+ {
+ isInitialised = 1;
+ theSecurityInterface = InitSecurityInterface();
+ if ( theSecurityInterface != 0 )
+ {
+ PSecPkgInfo thePkgInfo;
+ if ( ( theSecurityInterface->QuerySecurityPackageInfo )
+ (
+ "Kerberos",
+ &thePkgInfo
+ ) != SEC_E_OK )
+ {
+ theSecurityInterface = 0;
+ }
+ *outMaxTokenSize = thePkgInfo->cbMaxToken;
+ }
+ }
+ return theSecurityInterface;
+}
+
+int isRegistryEnabled( void )
+{
+ int theRC = 0;
+ HKEY theKey;
+ if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
+ APOCENABLEDKEY,
+ 0,
+ KEY_QUERY_VALUE,
+ &theKey ) == ERROR_SUCCESS )
+ {
+ RegCloseKey( theKey );
+ theRC = 1;
+ }
+ return theRC;
+}
+
+int isServiceEnabled( void )
+{
+ int theRC = 0;
+ HMODULE theModule = GetModuleHandle( "advapi32" );
+
+ if ( theModule != 0 )
+ {
+ OpenSCManagerFunc fOpenSCManager =
+ ( OpenSCManagerFunc )GetProcAddress( theModule, "OpenSCManagerA" );
+ EnumServicesStatusFunc fEnumServicesStatus =
+ ( EnumServicesStatusFunc )GetProcAddress( theModule,
+ "EnumServicesStatusA" );
+ if ( fOpenSCManager != 0 && fEnumServicesStatus != 0 )
+ {
+ SC_HANDLE theSCManager =
+ fOpenSCManager( 0, 0, SC_MANAGER_ENUMERATE_SERVICE );
+ if ( theSCManager != 0 )
+ {
+ DWORD theBytes;
+ DWORD theCount;
+ DWORD theHandle = 0;
+
+ if ( fEnumServicesStatus(
+ theSCManager,
+ SERVICE_WIN32,
+ SERVICE_STATE_ALL,
+ 0,
+ 0,
+ &theBytes,
+ &theCount,
+ &theHandle ) == 0 &&
+ GetLastError() == ERROR_MORE_DATA &&
+ theBytes > 0 )
+ {
+ ENUM_SERVICE_STATUS * theServices =
+ ( ENUM_SERVICE_STATUS * )malloc( theBytes );
+ if ( theServices != 0 )
+ {
+ DWORD theIndex;
+
+ fEnumServicesStatus(
+ theSCManager,
+ SERVICE_WIN32,
+ SERVICE_STATE_ALL,
+ theServices,
+ theBytes,
+ &theBytes,
+ &theCount,
+ &theHandle );
+ for ( theIndex = 0; theIndex < theCount; ++ theIndex )
+ {
+ if ( strcmp( theServices[ theIndex ].lpServiceName,
+ APOCSERVICENAME ) == 0 )
+ {
+ theRC = 1;
+ break;
+ }
+ }
+ }
+ }
+ CloseServiceHandle( theSCManager );
+ }
+ }
+ }
+ return theRC;
+}
+
+void writeGSSAPIAuthId( PSecurityFunctionTable inSecurityInterface,
+ CredHandle * inCredentials,
+ CtxtHandle * inContext,
+ SecBuffer * outBuffer,
+ PAPIStatus * outStatus )
+{
+ SecPkgContext_Sizes theContextSizes;
+ SecPkgContext_Names theSourceName;
+ SECURITY_STATUS theStatus =
+ ( inSecurityInterface->QueryCredentialsAttributes )
+ (
+ inCredentials,
+ SECPKG_CRED_ATTR_NAMES,
+ ( PVOID )&theSourceName
+ );
+ *outStatus = PAPIAuthenticationFailure;
+ if ( theStatus == SEC_E_OK )
+ {
+ theStatus = ( inSecurityInterface->QueryContextAttributes )
+ (
+ inContext,
+ SECPKG_ATTR_SIZES,
+ ( PVOID )&theContextSizes
+ );
+ if ( theStatus == SEC_E_OK )
+ {
+ SecBufferDesc theBufferDesc;
+ SecBuffer theBuffers[ 3 ];
+ int theSourceNameSize = strlen(theSourceName.sUserName);
+ char * theCP;
+ BYTE * theOutput =
+ ( PBYTE )malloc( theContextSizes.cbSecurityTrailer +
+ theSourceNameSize +
+ 4 +
+ sizeof( DWORD ) );
+
+ theBufferDesc.ulVersion = SECBUFFER_VERSION;
+ theBufferDesc.cBuffers = 3;
+ theBufferDesc.pBuffers = theBuffers;
+
+ theBuffers[ 0 ].cbBuffer = theContextSizes.cbSecurityTrailer;
+ theBuffers[ 0 ].BufferType = SECBUFFER_TOKEN;
+ theBuffers[ 0 ].pvBuffer = theOutput + sizeof( DWORD );
+
+
+ theBuffers[ 1 ].cbBuffer = theSourceNameSize + 4;
+ theBuffers[ 1 ].BufferType = SECBUFFER_DATA;
+ theBuffers[ 1 ].pvBuffer = malloc( theBuffers[ 1 ].cbBuffer );
+ theCP = ( char * )theBuffers[ 1 ].pvBuffer;
+ theCP[ 0 ] = 1;
+ theCP[ 1 ] = theCP[ 2 ] = theCP[ 3 ] = ( char )0;
+ memcpy( theCP + 4,
+ theSourceName.sUserName,
+ theSourceNameSize );
+
+ theBuffers[ 2 ].cbBuffer = theContextSizes.cbBlockSize;
+ theBuffers[ 2 ].BufferType = SECBUFFER_PADDING;
+ theBuffers[ 2 ].pvBuffer = malloc( theBuffers[ 2 ].cbBuffer );
+
+ theStatus = inSecurityInterface->EncryptMessage( inContext,
+ KERB_WRAP_NO_ENCRYPT,
+ &theBufferDesc,
+ 0 );
+ if ( theStatus == SEC_E_OK )
+ {
+ outBuffer->cbBuffer = theBuffers[ 0 ].cbBuffer +
+ theBuffers[ 1 ].cbBuffer +
+ theBuffers[ 2 ].cbBuffer;
+ outBuffer->pvBuffer = malloc( outBuffer->cbBuffer );
+ if ( outBuffer->pvBuffer != 0 )
+ {
+ theCP = ( char * )outBuffer->pvBuffer;
+ memcpy( theCP,
+ theBuffers[ 0 ].pvBuffer,
+ theBuffers[ 0 ].cbBuffer );
+ memcpy( theCP + theBuffers[ 0 ].cbBuffer,
+ theBuffers[ 1 ].pvBuffer,
+ theBuffers[ 1 ].cbBuffer );
+ memcpy( theCP +
+ theBuffers[ 0 ].cbBuffer +
+ theBuffers[ 1 ].cbBuffer,
+ theBuffers[ 2 ].pvBuffer,
+ theBuffers[ 2 ].cbBuffer );
+ *outStatus = PAPISuccess;
+ }
+ else
+ {
+ *outStatus = PAPIOutOfMemoryFailure;
+ }
+ }
+ }
+ }
+ else
+ {
+ *outStatus = PAPIAuthenticationFailure;
+ }
+}