diff options
Diffstat (limited to 'libapoc')
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; + } +} |