summaryrefslogtreecommitdiff
path: root/usr/src/lib/libkmsagent/common/SYSCommon.c
diff options
context:
space:
mode:
authorJohn Sonnenschein <johns@joyent.com>2012-05-17 18:26:57 +0000
committerJohn Sonnenschein <johns@joyent.com>2012-05-17 18:26:57 +0000
commit04b244dd661c24b510ac22936decfc0972d202d3 (patch)
tree3ebfef98afc303fddf3415d6fba64e8682f495e8 /usr/src/lib/libkmsagent/common/SYSCommon.c
parenteac250589e41f1b705e1b7427b02b3379aac9f9e (diff)
parenta69187741b83640a90dd8586195456dd50c016a8 (diff)
downloadillumos-joyent-20120517.tar.gz
Merge git.joyent.com:illumos-joyent20120517
Diffstat (limited to 'usr/src/lib/libkmsagent/common/SYSCommon.c')
-rw-r--r--usr/src/lib/libkmsagent/common/SYSCommon.c2307
1 files changed, 0 insertions, 2307 deletions
diff --git a/usr/src/lib/libkmsagent/common/SYSCommon.c b/usr/src/lib/libkmsagent/common/SYSCommon.c
deleted file mode 100644
index dd418fec4b..0000000000
--- a/usr/src/lib/libkmsagent/common/SYSCommon.c
+++ /dev/null
@@ -1,2307 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- */
-
-/*---------------------------------------------------------------------------
- * Module: SYSCommon.c
- *-------------------------------------------------------------------------*/
-
-#include <stdio.h>
-#include "SYSCommon.h"
-#include <time.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <signal.h>
-
-#ifndef WIN32
-#include <unistd.h>
-#endif
-
-#ifdef WIN32
-#include <io.h>
-#include <stdlib.h> /* for malloc, calloc, and free */
-#elif defined K_LINUX_PLATFORM
-#include <unistd.h> /* it includes usleep(us) */
-#include <sys/time.h>
-#include <fts.h>
-#else
-/*
- * Directory traversal code is not yet available for Solaris.
- * If such code will need to be written, then it will probably use ftw.h.
- */
-#endif
-
-#ifdef K_SOLARIS_PLATFORM
-/* For K_AdjustLocalClock */
-#include <unistd.h>
-/* For K_SetRootPassword */
-#define __EXTENSIONS__ /* to expose flockfile and friends in stdio.h */
-#include <errno.h>
-#include <libgen.h>
-#include <malloc.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <strings.h>
-#include <stropts.h>
-#include <unistd.h>
-#include <termio.h>
-#include <security/pam_appl.h>
-#include <widec.h>
-#endif
-
-#ifdef K_LINUX_PLATFORM
-extern int pthread_mutexattr_settype __P ((pthread_mutexattr_t *__attr,
- int __kind));
-#endif
-
-#ifdef K_HPUX_PLATFORM
-int64 atoll(const char *str)
-{
- int64 tmp = 0;
- sscanf(str, "%lld", &tmp);
- return tmp;
-}
-
-#endif
-
-
-/*---------------------------------------------------------------------------
- * Function: K_CreateThread
- *
- * Description:
- * Thread creation function "CreateThread" takes a thread function
- * and its parameter to create a thread. It also has a Boolean
- * parameter to indicate if the thread is detached or joinable.
- * A new thread's handle is returned through the output parameter.
- *
- * Input
- * -----
- * i_pFunc Function pointer of the thread function
- * i_pvData The point of the parameter passed to the thread function
- * i_bIsDetached The thread is detached or not
- * (Note: It is not supported on Win32)
- *
- * Output
- * ------
- * o_pNewThread The Thread handle
- *
- * Return value Error code
- *
- *--------------------------------------------------------------------------*/
-
-int K_CreateThread(K_ThreadFunc i_pFunc,
- void *i_pvData,
- int i_bIsDetached,
- K_THREAD_HANDLE *o_pNewThread)
-{
- int iOK = K_SYS_OK;
- int iReturn = 0;
-
-#ifdef WIN32
-
- {
- unsigned id;
-
- *o_pNewThread = (HANDLE)_beginthreadex(NULL,
- 0,
- (int (_stdcall *) (void *vpData))i_pFunc,
- i_pvData,
- 0,
- &id);
-
-
- if(*o_pNewThread == 0)
- {
-#ifdef SYS_DEBUG
- printf(" (%s, %d): error creating pthread, error = %d\n",
- __FILE__, __LINE__, iReturn);
-#endif
- return K_SYS_ERR_CREATE_THREAD;
- }
-
- return K_SYS_OK;
- }
-
-#else
- pthread_attr_t attr;
-
- iReturn = pthread_attr_init(&attr);
-
- if ( iReturn == 0 )
- {
- iReturn = pthread_attr_setdetachstate(&attr, (i_bIsDetached) ?
- PTHREAD_CREATE_DETACHED :
- PTHREAD_CREATE_JOINABLE);
- }
-
-#ifdef UNIX
- if ( iReturn == 0 )
- {
- iReturn = pthread_attr_setstacksize(&attr, 1024*1024);
- }
-#endif
-
- if ( iReturn == 0 )
- {
- iReturn = pthread_create(o_pNewThread, &attr, (void *(*)(void *)) i_pFunc, i_pvData);
- }
-
- if ( iReturn == 0 )
- {
- iReturn = pthread_attr_destroy(&attr);
- }
-
- // TODO: Log error?
- if ( iReturn )
- {
-#ifdef SYS_DEBUG
- printf(" (%s, %d): error creating pthread, error = %d\n",
- __FILE__, __LINE__, iReturn);
-#endif
-
- iOK = K_SYS_ERR_CREATE_THREAD;
- }
-
- return iOK;
-#endif
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: K_JoinThread
- *
- * Description:
- * Thread joining function is called when the current thread
- * waits another thread to terminate.
- *
- * Input
- * -----
- * i_hThread The thread handle of the to-be-joined thread
- *
- * Output
- * ------
- * (none)
- *
- * Return value Error code
- *
- *--------------------------------------------------------------------------*/
-
-int K_JoinThread(K_THREAD_HANDLE i_hThread)
-{
- int iOK = K_SYS_OK;
-#ifdef WIN32
-
- WaitForSingleObject(i_hThread, INFINITE);
-
-#else
- {
- int iReturn;
- iReturn = pthread_join(i_hThread, NULL);
-
- if ( iReturn )
- {
-
-#ifdef SYS_DEBUG
- printf(" (%s, %d): error creating pthread, error = %d\n",
- __FILE__, __LINE__, iReturn);
-#endif
- iOK = K_SYS_ERR_JOIN_THREAD;
- }
- }
-
-#endif
- return iOK;
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: K_GetCurrentThreadId
- *
- * Description:
- * Returns the thread ID of the current thread.
- *
- * Input
- * -----
- * (none)
- *
- * Output
- * ------
- * (none)
- *
- * Return value The thread ID
- *
- *--------------------------------------------------------------------------*/
-
-int K_GetCurrentThreadId()
-{
-#ifdef WIN32
- return GetCurrentThreadId();
-#else
- return pthread_self();
-#endif
-
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: K_CreateMutex
- *
- * Description:
- * The mutex creation function creates a mutex according to the given
- * mutex type, and returns the mutex handle to the output parameter.
- *
- * Input
- * -----
- * i_bIsRecursive Indication whether the mutex can be entered recursively
- *
- * Output
- * ------
- * o_phandle the handle pointer to the mutex
- *
- * Return value Error Code
- *
- *--------------------------------------------------------------------------*/
-
-int K_CreateMutex( K_MUTEX_HANDLE *o_phandle )
-{
- int iOK = K_SYS_OK;
- BOOL bIsRecursive = 1; // this used to be an input -- but why do we want this to be optional?
-
-#ifdef WIN32
- {
- *o_phandle = (WIN32Mutex *)malloc(sizeof(WIN32Mutex));
- if(*o_phandle == NULL)
- {
- return K_SYS_ERR_NO_MEMORY;
- }
- (*o_phandle)->m_bIsRecursive = bIsRecursive;
- if(bIsRecursive)
- {
- InitializeCriticalSection(&((*o_phandle)->m_stCriticalSection));
- }
- else
- {
- (*o_phandle)->m_handle = CreateMutex(NULL, FALSE, NULL);
- }
-
- }
-#else
- {
- int iType;
- pthread_mutexattr_t attr;
-
- if ( pthread_mutexattr_init(&attr) )
- {
- return K_SYS_ERR_COND;
- }
-
- if(bIsRecursive)
- {
- iType =
-#ifdef K_LINUX_PLATFORM
- PTHREAD_MUTEX_RECURSIVE_NP;
-#else
- PTHREAD_MUTEX_RECURSIVE;
-#endif
-
- if ( pthread_mutexattr_settype(&attr, iType) )
- {
- return K_SYS_ERR_COND;
- }
- }
-
- *o_phandle = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
- if(*o_phandle == NULL)
- {
- return K_SYS_ERR_NO_MEMORY;
- }
-
- if ( pthread_mutex_init(*o_phandle, &attr) )
- {
- return K_SYS_ERR_COND;
- }
-
- if ( pthread_mutexattr_destroy(&attr) )
- {
- return K_SYS_ERR_COND;
- }
- }
-#endif
-
- return iOK;
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: K_LockMutex
- *
- * Description:
- * K_LockMutex is used to lock the mutex, and K_UnlockMutex is
- * used to unlock it.
- *
- * Input
- * -----
- * i_handle the mutex handle
- *
- * Output
- * ------
- * (none)
- *
- * Return value Error Code
- *
- *--------------------------------------------------------------------------*/
-
-int K_LockMutex(K_MUTEX_HANDLE i_handle)
-{
- int iOK = K_SYS_OK;
-#ifdef WIN32
-
- if(i_handle->m_bIsRecursive)
- {
- EnterCriticalSection(&(i_handle->m_stCriticalSection));
- }
- else
- {
- WaitForSingleObject(i_handle->m_handle, INFINITE);
- }
-
-#else
-
- if ( pthread_mutex_lock(i_handle) )
- {
- return K_SYS_ERR_COND;
- }
-
-#endif
- return iOK; // TODO: better error handling
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: K_UnlockMutex
- *
- * Description:
- * K_UnlockMutex is used to unlock the lock.
- *
- * Input
- * -----
- * i_handle the mutex handle
- *
- * Output
- * ------
- * (none)
- *
- * Return value Error Code
- *
- *--------------------------------------------------------------------------*/
-
-int K_UnlockMutex(K_MUTEX_HANDLE i_handle)
-{
- int iOK = K_SYS_OK;
-
-#ifdef WIN32
- if(i_handle->m_bIsRecursive)
- {
- LeaveCriticalSection(&(i_handle->m_stCriticalSection));
- }
- else
- {
- ReleaseMutex(i_handle->m_handle);
- }
-
-#else
-
- if ( pthread_mutex_unlock(i_handle) )
- {
- return K_SYS_ERR_COND;
- }
-#endif
-
- return iOK; // TODO: better error handling
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: K_DestroyMutex
- *
- * Description:
- * When a mutex is no longer needed, K_DestroyMutex must be called
- * to destroy it.
- *
- * Input
- * -----
- * i_handle the mutex handle
- * Output
- * ------
- * (none)
- *
- * Return value Error Code
- *
- *--------------------------------------------------------------------------*/
-
-int K_DestroyMutex(K_MUTEX_HANDLE i_handle)
-{
-
- int iOK = K_SYS_OK;
-
-#ifdef WIN32
-
- if(i_handle->m_bIsRecursive)
- {
- DeleteCriticalSection(&(i_handle->m_stCriticalSection));
- }
- else
- {
- CloseHandle(i_handle->m_handle);
- }
- free(i_handle);
-
-#else
- pthread_mutex_destroy(i_handle);
- free(i_handle);
-#endif
- return iOK; // TODO: better error handling
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: K_InitConditionalVariable
- *
- * Description:
- * This function initializes a conditional variable. Upon successful
- * completion, the new condition variable is returned via the condition
- * parameter, and 0 is returned. Otherwise, an error code is returned.
- *
- * Input
- * -----
- * i_pCond the pointer to the conditional variable which is to be
- * initialized
- *
- * Output
- * ------
- * (none)
- *
- * Return value Error Code
- *
- *--------------------------------------------------------------------------*/
-
-int K_InitConditionalVariable (K_ConditionalVariable * i_pCond)
-{
- int iOK = K_SYS_OK;
-#ifdef WIN32
-
- i_pCond->m_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- i_pCond->m_hMutex = CreateMutex(NULL, FALSE, NULL);
- i_pCond->m_iSignalAll = 0;
- i_pCond->m_iNumWaiting = 0;
-
-#else
-
- if ( pthread_cond_init(i_pCond, NULL) )
- {
- return K_SYS_ERR_COND;
- }
-
-#endif
-
- return iOK;
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: K_DestroyConditionalVariable
- *
- * Description:
- * This function destroys a conditional variable. Upon successful
- * completion, the condition variable is destroyed, and 0 is returned.
- * Otherwise, an error code is returned.
- * After deletion of the condition variable, the condition parameter
- * is not valid until it is initialized again by a call to the
- * K_InitConditionalVariable subroutine.
- *
- * Input
- * -----
- * i_pCond the pointer to the conditional variable which is to be
- * destroyed
- * Output
- * ------
- * (none)
- *
- * Return value Error Code
- *
- *--------------------------------------------------------------------------*/
-
-int K_DestroyConditionalVariable(K_ConditionalVariable * i_pCond)
-{
- int iOK = K_SYS_OK;
-#ifdef WIN32
- CloseHandle(i_pCond->m_hMutex);
- CloseHandle(i_pCond->m_hEvent);
-#else
-
- if ( pthread_cond_destroy(i_pCond) )
- {
- return K_SYS_ERR_COND;
- }
-
-#endif
- return iOK;
-
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: K_WaitConditionalVariable
- *
- * Description:
- * This function is used to block on a condition variable.
- * They are called with mutex locked by the calling thread or undefined
- * behaviour will result.
- *
- * Input
- * -----
- * i_pCond the pointer to the conditional variable
- * i_handle the companion mutex handle
- *
- * Output
- * ------
- * (none)
- *
- * Return value Error Code
- *
- *--------------------------------------------------------------------------*/
-
-int K_WaitConditionalVariable(K_ConditionalVariable * i_pCond,
- K_MUTEX_HANDLE i_handle)
-{
-
- int iOK = K_SYS_OK;
-#ifdef WIN32
- DWORD res;
-
- while (1)
- {
- iOK = WaitForSingleObject(i_pCond->m_hMutex, INFINITE);
- if (iOK != WAIT_OBJECT_0)
- {
- return K_SYS_ERR_COND;
- }
- i_pCond->m_iNumWaiting++;
- ReleaseMutex(i_pCond->m_hMutex);
-
- K_UnlockMutex(i_handle);
- res = WaitForSingleObject(i_pCond->m_hEvent, INFINITE);
- i_pCond->m_iNumWaiting--;
-
- if (res != WAIT_OBJECT_0)
- {
- ReleaseMutex(i_pCond->m_hMutex);
- return K_SYS_ERR_COND;
- }
-
- if (i_pCond->m_iSignalAll)
- {
- if (i_pCond->m_iNumWaiting == 0)
- {
- ResetEvent(i_pCond->m_hEvent);
- }
- break;
- }
-
- if (i_pCond->m_iSignalled)
- {
- i_pCond->m_iSignalled = 0;
- ResetEvent(i_pCond->m_hEvent);
- break;
- }
- ReleaseMutex(i_pCond->m_hMutex);
- }
-
- K_LockMutex(i_handle);
-
- return K_SYS_OK;
-#else
-
- if ( pthread_cond_wait(i_pCond, i_handle) )
- {
- return K_SYS_ERR_COND;
- }
-
-#endif
- return iOK; // TODO: better error handling
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: K_SignalConditionalVariable
- *
- * Description:
- * This function is used to restart one of the threads that are waiting on
- * the condition variable. If no threads are waiting on it, nothing happens.
- * If several threads are waiting on it, exactly one is restarted.
- *
- * Input
- * -----
- * i_pCond the pointer to the conditional variable
- *
- * Output
- * ------
- * (none)
- *
- * Return value Error Code
- *
- *--------------------------------------------------------------------------*/
-
-int K_SignalConditionalVariable(K_ConditionalVariable * i_pCond)
-{
- int iOK = K_SYS_OK;
-#ifdef WIN32
-
- int iReturn;
-
- iReturn = WaitForSingleObject(i_pCond->m_hMutex, INFINITE);
- if (iReturn != WAIT_OBJECT_0)
- {
- return K_SYS_ERR_COND;
- }
-
- i_pCond->m_iSignalled = 1;
-
- iReturn = SetEvent(i_pCond->m_hEvent);
- if (iReturn == 0)
- {
- iOK = K_SYS_ERR_COND;
- }
- ReleaseMutex(i_pCond->m_hMutex);
-
- return iOK;
-#else
-
- if ( pthread_cond_signal(i_pCond) )
- {
- return K_SYS_ERR_COND;
- }
-
-#endif
- return iOK;
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: K_BroadcastConditionalVariable
- *
- * Description:
- * This function is used to restart all threads that are waiting on
- * the condition variable.
- *
- * Input
- * -----
- * i_pCond the pointer to the conditional variable
- *
- * Output
- * ------
- * (none)
- *
- * Return value Error Code
- *
- *--------------------------------------------------------------------------*/
-
-int K_BroadcastConditionalVariable(K_ConditionalVariable * i_pCond)
-{
-
- int iOK = K_SYS_OK;
-
-#ifdef WIN32
-
- int iReturn;
-
- iReturn = WaitForSingleObject(i_pCond->m_hMutex, INFINITE);
- if (iReturn != WAIT_OBJECT_0)
- {
- return K_SYS_ERR_COND;
- }
- i_pCond->m_iSignalled = 1;
- i_pCond->m_iSignalAll = 1;
-
- iReturn = SetEvent(i_pCond->m_hEvent);
-
- if (iReturn == 0)
- {
- iOK = K_SYS_ERR_COND;
- }
-
- ReleaseMutex(i_pCond->m_hMutex);
-
- return iOK;
-
-#else
-
- if ( pthread_cond_broadcast(i_pCond) )
- {
- return K_SYS_ERR_COND;
- }
-
-#endif
- return iOK;
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: K_Sleep
- *
- * Description:
- * Sleep for a given period in given milliseconds.
- *
- * Input
- * -----
- * i_ms milliseconds
- *
- * Output
- * ------
- * (none)
- *
- * Return value (none)
- *
- *--------------------------------------------------------------------------*/
-
-void K_Sleep(int i_ms)
-{
-#ifdef WIN32
- Sleep(i_ms);
-#else
- usleep(i_ms * 1000);
-#endif
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: K_GetTickCount
- *
- * Description:
- * The K_GetTickCount function retrieves the number of
- * milliseconds that have elapsed since the system was started.
- *
- * Input
- * -----
- * (none)
- *
- * Output
- * ------
- * (none)
- *
- * Return value the elasped milliseconds since the system was started
- *
- *--------------------------------------------------------------------------*/
-
-unsigned int K_GetTickCount()
-{
-#ifdef WIN32
- return (unsigned int)GetTickCount();
-#else
- {
- struct timeval tv;
- gettimeofday( &tv, NULL );
- /* this will rollover ~ every 49.7 days
- dont surprise when it returns negative values, since we are only interested
- in using sth like "tickCount2 - tickCount1" to get the time interval
- */
- return ( tv.tv_sec * 1000 ) + ( tv.tv_usec / 1000 );
- }
-#endif
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: K_AdjustClock
- *
- * Description:
- * The K_AdjustClock function immediately adjusts the system clock by
- * the given number of seconds. A positive number adjusts the system
- * clock forward; a negative number adjusts the system clock backward.
- *
- * Input
- * -----
- * i_iAdjustmentInSeconds Number of seconds by which to adjust the
- * system clock
- * Output
- * ------
- * (none)
- *
- * Return value 1 if successful, 0 on error
- *
- *--------------------------------------------------------------------------*/
-
-int K_AdjustClock( long i_iAdjustmentInSeconds )
-{
-#ifndef WIN32
- struct timeval stDateTime;
- if ( 0 != gettimeofday(&stDateTime, NULL) )
- {
- return FALSE;
- }
-
- stDateTime.tv_sec += i_iAdjustmentInSeconds;
-
- if ( 0 != settimeofday(&stDateTime, NULL) )
- {
- return FALSE;
- }
-#else
- // TODO: implement for Windows
- return FALSE;
-#endif
-
- return TRUE;
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: K_IsLittleEndian
- *
- * Description:
- * Checks to see whether this platform uses little endian integer
- * representation.
- *
- * Input
- * -----
- * (none)
- *
- * Output
- * ------
- * (none)
- *
- * Return value 1 for little endian
- *
- *--------------------------------------------------------------------------*/
-
-int K_IsLittleEndian()
-{
- short iWord = 0x4321;
- return ((*(unsigned char*)&iWord) == 0x21);
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: K_FileLength32
- *
- * Description:
- * Gets the size in bytes of the file associated with the given FILE pointer.
- *
- * Input
- * -----
- * i_fpFile File handle
- *
- * Output
- * ------
- * (none)
- *
- * Return value File size in bytes, or -1L on error
- *
- *--------------------------------------------------------------------------*/
-
-long K_FileLength32( FILE* i_fpFile )
-{
-#ifdef WIN32
- int iFileDescriptor = _fileno( i_fpFile );
- struct _stat stStat;
-
- if ( _fstat(iFileDescriptor, &stStat) != 0)
- {
- // error
- return -1L;
- }
-
-#else
- int iFileDescriptor = fileno( i_fpFile );
- struct stat stStat;
-
- if ( fstat(iFileDescriptor, &stStat) != 0)
- {
- // error
- return -1L;
- }
-
-#endif
-
- return stStat.st_size;
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: K_StringCompareNoCase
- *
- * Description:
- * Compares the two given strings insensitive to case.
- *
- * Input
- * -----
- * i_sString1 First string
- * i_sString2 Second string
- *
- * Output
- * ------
- * (none)
- *
- * Return value 0 if identical, -1 if first string is less than second
- * string, or 1 if first string is greater than second
- *
- *--------------------------------------------------------------------------*/
-
-int K_StringCompareNoCase( const char* i_sString1, const char* i_sString2 )
-{
-#ifdef WIN32
- return _stricmp( i_sString1, i_sString2 );
-#else
- return strcasecmp( i_sString1, i_sString2 );
-#endif
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: K_StringCompareNoCaseWide
- *
- * Description:
- * Compares the two given wide strings insensitive to case.
- *
- * Input
- * -----
- * i_wsString1 First wide string
- * i_wsString2 Second wide string
- *
- * Output
- * ------
- * (none)
- *
- * Return value 0 if identical, -1 if first string is less than second
- * string, or 1 if first string is greater than second
- *
- *--------------------------------------------------------------------------*/
-
-int K_StringCompareNoCaseWide( const wchar_t* i_wsString1, const wchar_t* i_wsString2 )
-{
-#ifdef WIN32
- return _wcsicmp( i_wsString1, i_wsString2 );
-#elif defined K_SOLARIS_PLATFORM
- return wscasecmp( i_wsString1, i_wsString2 );
-#else
- return wcscasecmp( i_wsString1, i_wsString2 );
-#endif
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: K_CreateDirectory
- *
- * Description:
- * Creates a directory with the given path name.
- *
- * Input
- * -----
- * i_sDirectoryName Directory name
- *
- * Output
- * ------
- * (none)
- *
- * Return value 0 on success, -1 on failure
- *
- *--------------------------------------------------------------------------*/
-
-int K_CreateDirectory( const char* i_sDirectoryName )
-{
- // TODO: make this build all parent directories as well.
-
-#ifdef WIN32
- if ( CreateDirectoryA( i_sDirectoryName, NULL ) )
- {
- return 0;
- }
- else
- {
- DWORD dwError = GetLastError();
- return ( dwError == ERROR_ALREADY_EXISTS ) ? 0 : (dwError ? dwError : -1);
- }
-#else
- if ( mkdir( i_sDirectoryName, S_IRWXU ) == 0 )
- {
- return 0;
- }
- else
- {
- return ( errno == EEXIST ) ? 0 : (errno ? errno : -1);
- }
-#endif
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: K_DeleteFile
- *
- * Description:
- * Deletes the given file.
- *
- * Input
- * -----
- * i_sFilename Name of file to delete
- *
- * Output
- * ------
- * (none)
- *
- * Return value 0 on success, errno on failure
- *
- *--------------------------------------------------------------------------*/
-
-int K_DeleteFile( const char* i_sFilename )
-{
- int bSuccess = 0;
-
- bSuccess =
-#ifdef WIN32
- _unlink(
-#else
- unlink(
-#endif
- i_sFilename ) == 0;
-
- return bSuccess ? 0 : errno;
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: K_ReadFile
- *
- * Description:
- * Reads from the given file and passes the bytes read back to the output
- * parameter. The caller must deallocate o_ppFileData using free().
- *
- * Input
- * -----
- * i_sFilename Name of file from which to read
- *
- * Output
- * ------
- * o_ppFileData Pointer to bytes read
- *
- * Return value Number of bytes read on success, -1 on failure
- *
- *--------------------------------------------------------------------------*/
-
-int K_ReadFile( const char* i_sFilename, unsigned char** o_ppFileData )
-{
- FILE* pFile = 0;
- long iFileSize = 0;
-
- if ( !i_sFilename || (strlen(i_sFilename) <= 0) || !o_ppFileData )
- {
- return -1;
- }
-
- *o_ppFileData = 0;
-
- // Open the file
-
- pFile = fopen( i_sFilename, "rb" );
- if ( !pFile )
- {
- return -1;
- }
-
- // Determine the file size
-
- if ( fseek( pFile, 0, SEEK_END ) )
- {
- (void) fclose( pFile );
- return -1;
- }
-
- iFileSize = ftell( pFile );
- if ( iFileSize < 0 )
- {
- (void) fclose( pFile );
- return -1;
- }
- else if ( iFileSize == 0 )
- {
- (void) fclose( pFile );
- return 0;
- }
-
- if ( fseek( pFile, 0, SEEK_SET ) )
- {
- (void) fclose( pFile );
- return -1;
- }
-
- *o_ppFileData = (unsigned char*)malloc( iFileSize );
- if ( !*o_ppFileData )
- {
- // Out of memory.
- (void) fclose( pFile );
- return -1;
- }
-
- if ( iFileSize != (long)fread( *o_ppFileData, 1, iFileSize, pFile ) )
- {
- free( *o_ppFileData );
- *o_ppFileData = 0;
- (void) fclose( pFile );
- return -1;
- }
-
- (void) fclose( pFile );
-
- return iFileSize;
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: K_ReadFileString
- *
- * Description:
- * Reads from the given file and passes the bytes read back to the output
- * parameter, appending these bytes with a null terminator. There is no
- * guarantee that there are no non-text characters in the returned "string".
- * The caller must deallocate o_ppFileData using free().
- *
- * Input
- * -----
- * i_sFilename Name of file from which to read
- *
- * Output
- * ------
- * o_psFileDataString Pointer to bytes read
- *
- * Return value Number of bytes read (including null terminator) on
- * success (0 if file is empty), -1 on failure
- *
- *--------------------------------------------------------------------------*/
-
-int K_ReadFileString( const char* i_sFilename, char** o_psFileDataString )
-{
- unsigned char* pFileData = 0;
- int iFileSize = 0;
-
- *o_psFileDataString = 0;
-
- iFileSize = K_ReadFile( i_sFilename, &pFileData );
-
- if ( iFileSize <= 0 )
- {
- return iFileSize;
- }
-
- *o_psFileDataString = (char*)malloc( iFileSize+1 );
-
- if ( !*o_psFileDataString )
- {
- // Out of memory.
- if ( pFileData )
- {
- free( pFileData );
- }
- return -1;
- }
-
- memcpy( *o_psFileDataString, pFileData, iFileSize );
-
- (*o_psFileDataString)[iFileSize] = '\0';
-
- if ( pFileData )
- {
- free( pFileData );
- }
-
- return iFileSize+1;
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: K_WriteFile
- *
- * Description:
- * Writes the given bytes to the given file.
- *
- * Input
- * -----
- * i_sFilename Name of file to which to write
- * i_pFileData Bytes to write
- * i_iFileDataSize Number of bytes to write
- *
- * Output
- * ------
- * (none)
- *
- * Return value 0 on success, errno or -1 (generic error) on failure
- *
- *--------------------------------------------------------------------------*/
-
-int K_WriteFile( const char* i_sFilename, const unsigned char* i_pFileData, int i_iFileDataSize )
-{
- FILE* pFile = 0;
-
- if ( !i_sFilename || (strlen(i_sFilename) <= 0) || (!i_pFileData && (i_iFileDataSize > 0)) || (i_iFileDataSize < 0) )
- {
- return -1;
- }
-
- pFile = fopen( i_sFilename, "wb" );
- if ( !pFile )
- {
- int iError = errno;
- return (iError != 0) ? iError : -1;
- }
-
- if ( i_iFileDataSize > 0 )
- {
- if ( i_iFileDataSize != (int)fwrite( i_pFileData, 1, i_iFileDataSize, pFile ) )
- {
- int iError = ferror( pFile );
- (void) fclose( pFile );
- return (iError != 0) ? iError : -1;
- }
- }
-
- (void) fclose( pFile );
-
- return 0;
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: K_WriteFileString
- *
- * Description:
- * Writes the given null-terminated bytes to the given file. The null
- * terminator itself is not written to the file.
- *
- * Input
- * -----
- * i_sFilename Name of file to which to write
- * i_sFileData Bytes to write
- *
- * Output
- * ------
- * (none)
- *
- * Return value 0 on success, errno or -1 (generic error) on failure
- *
- *--------------------------------------------------------------------------*/
-
-int K_WriteFileString( const char* i_sFilename, const char* i_sFileData )
-{
- if ( !i_sFilename || (strlen(i_sFilename) <= 0) || !i_sFileData || (strlen(i_sFileData) <= 0) )
- {
- return -1;
- }
-
- return K_WriteFile( i_sFilename, (const unsigned char*)i_sFileData, strlen(i_sFileData) );
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: K_FileExists
- *
- * Description:
- * Checks to see whehter the given file exists.
- *
- * Input
- * -----
- * i_sFilename Name of file to check
- *
- * Output
- * ------
- * (none)
- *
- * Return value 1 if file exists, 0 if not, -1 on failure
- *
- *--------------------------------------------------------------------------*/
-
-int K_FileExists( const char* i_sFilename )
-{
- FILE* pFile = 0;
-
- if ( !i_sFilename || (strlen(i_sFilename) <= 0) )
- {
- return -1;
- }
-
- pFile = fopen( i_sFilename, "r+" );
-
- if ( !pFile )
- {
- if ( errno == ENOENT )
- {
- return 0;
- }
-
- return -1;
- }
-
- (void) fclose( pFile );
-
- return 1;
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: K_CopyFile
- *
- * Description:
- * Reads from the given source file and writes these bytes to the given
- * destination file.
- *
- * Input
- * -----
- * i_sSrcFilename Name of file from which to read
- * i_sDestFilename Name of file to which to write
- *
- * Output
- * ------
- * o_pbFileExists Non-zero if the destination file already exists
- *
- * Return value 0 on success, errno or -1 (generic error) on failure
- *
- *--------------------------------------------------------------------------*/
-
-int K_CopyFile( const char* i_sSrcFilename, const char* i_sDestFilename, int* o_pbFileExists )
-{
- unsigned char* pFileData = 0;
- int iFileSize = 0;
- int iError, iFileExists;
-
- if ( !i_sSrcFilename || (strlen(i_sSrcFilename) <= 0)
- || !i_sDestFilename || (strlen(i_sDestFilename) <= 0)
- || !o_pbFileExists )
- {
- return -1;
- }
-
- *o_pbFileExists = 0;
-
- iFileExists = K_FileExists( i_sDestFilename );
-
- if ( iFileExists < 0 )
- {
- iError = errno;
- return (iError == 0) ? -1 : iError;
- }
- else if ( iFileExists > 0 )
- {
- *o_pbFileExists = 1;
- return -1;
- }
-
- iFileSize = K_ReadFile( i_sSrcFilename, &pFileData );
- if ( iFileSize < 0 )
- {
- iError = errno;
- return (iError == 0) ? -1 : iError;
- }
-
- iError = K_WriteFile( i_sDestFilename, pFileData, iFileSize );
-
- if ( pFileData )
- {
- free( pFileData );
- }
-
- return iError;
-}
-
-
-#ifdef K_LINUX_PLATFORM
-static int fts_compare( const FTSENT** i_ppF1, const FTSENT** i_ppF2 )
-{
- return strcmp( (*i_ppF1)->fts_name, (*i_ppF2)->fts_name );
-}
-#else
-/*
- * Directory traversal code is not yet available for Solaris.
- * If such code will need to be written, then it will probably use ftw.h.
- */
-#endif
-
-
-/*
- * TODO: Set up functions for platform-specific find-file operations to
- * help clean up the code below.
- */
-
-typedef struct K_FindInfo
-{
-#ifdef WIN32
- struct _finddata_t m_stFindData;
- long m_hFile;
-#elif defined K_LINUX_PLATFORM
- FTS* m_pFTS;
- FTSENT* m_pFTSENT;
-#else
-/*
- * Directory traversal code is not yet available for Solaris.
- * If such code will need to be written, then it will probably use ftw.h.
- */
- int unused;
-#endif
-} K_FindInfo;
-
-// Memory for filename is held in i_pFindInfo.
-const char* K_GetFilenameFromInfo( const K_FindInfo* i_pFindInfo )
-{
- if( !i_pFindInfo )
- {
- return 0;
- }
-
-#ifdef WIN32
- return i_pFindInfo->m_stFindData.name;
-#elif defined K_LINUX_PLATFORM
- return i_pFindInfo->m_pFTSENT->fts_name;
-#else
-/*
- * Directory traversal code is not yet available for Solaris.
- * If such code will need to be written, then it will probably use ftw.h.
- */
- FATAL_ASSERT( 0 );
- return 0;
-#endif
-}
-
-// Forward declarations
-int K_FindFileNext( K_FindInfo* io_pFindInfo );
-void K_FindFileClose( K_FindInfo* io_pFindInfo );
-
-// Returns 0 if successful, 1 if not found, -1 if error.
-// If not error, K_FindFileClose must be called.
-// o_pFindInfo must not be null.
-int K_FindFileFirst( const char* i_sDirectoryName, K_FindInfo* o_pFindInfo )
-{
-#ifdef WIN32
- char* sSearchString = 0;
- int iSearchStringIndex = 0;
-#endif
-
- if ( !i_sDirectoryName || (strlen(i_sDirectoryName) <= 0) || !o_pFindInfo )
- {
- return -1;
- }
-
-#ifdef WIN32
- memset( o_pFindInfo, 0, sizeof(K_FindInfo) );
-
- iSearchStringIndex = strlen(i_sDirectoryName);
- if ( i_sDirectoryName[iSearchStringIndex-1] == PATH_SEPARATOR )
- {
- iSearchStringIndex += 2;
- }
- else
- {
- iSearchStringIndex += 3;
- }
-
- sSearchString = (char*)calloc( iSearchStringIndex, 1 );
- if ( !sSearchString )
- {
- return -1;
- }
-
- strcpy( sSearchString, i_sDirectoryName );
- iSearchStringIndex--;
- sSearchString[iSearchStringIndex] = '\0';
- iSearchStringIndex--;
- sSearchString[iSearchStringIndex] = '*';
- iSearchStringIndex--;
- sSearchString[iSearchStringIndex] = PATH_SEPARATOR;
-
- o_pFindInfo->m_hFile = _findfirst( sSearchString, &o_pFindInfo->m_stFindData );
- free( sSearchString );
- if ( o_pFindInfo->m_hFile == -1 )
- {
- if ( errno == ENOENT )
- {
- return 1;
- }
- else
- {
- return -1;
- }
- }
-#elif defined K_LINUX_PLATFORM
- memset( o_pFindInfo, 0, sizeof(K_FindInfo) );
-
- o_pFindInfo->m_pFTS = fts_open( aPath, FTS_PHYSICAL | FTS_NOSTAT, fts_compare );
- if ( !o_pFindInfo->m_pFTS )
- {
- return -1;
- }
-
- o_pFindInfo->m_pFTSENT = fts_read( o_pFindInfo->m_pFTS );
- if ( !o_pFindInfo->m_pFTSENT )
- {
- if ( errno == 0 )
- {
- return 1;
- }
- else
- {
- fts_close( o_pFindInfo->m_pFTS );
- return -1;
- }
- }
-#else
-/*
- * Directory traversal code is not yet available for Solaris.
- * If such code will need to be written, then it will probably use ftw.h.
- */
-#endif
-
- // If what we found is not actually a file, get the next hit.
-#ifdef WIN32
- if ( (o_pFindInfo->m_stFindData.attrib & _A_SUBDIR) )
-#elif defined K_LINUX_PLATFORM
- if ( !(o_pFindInfo->m_pFTSENT->fts_info & FTS_F) )
-#else
-/*
- * Directory traversal code is not yet available for Solaris.
- * If such code will need to be written, then it will probably use ftw.h.
- */
-#endif
- {
- int iNextReturn = K_FindFileNext( o_pFindInfo );
- if ( iNextReturn < 0 )
- {
- K_FindFileClose( o_pFindInfo );
- return -1;
- }
- else
- {
- return iNextReturn;
- }
- }
-
-#if defined(WIN32) || defined(K_LINUX_PLATFORM)
- return 0;
-#endif
-}
-
-// Returns 0 if successful, 1 if not found, -1 if error.
-int K_FindFileNext( K_FindInfo* io_pFindInfo )
-{
- if ( !io_pFindInfo )
- {
- return -1;
- }
-
-#ifdef WIN32
- if ( _findnext( io_pFindInfo->m_hFile, &io_pFindInfo->m_stFindData ) != 0 )
- {
- return (errno == ENOENT) ? 1 : -1;
- }
-#elif defined K_LINUX_PLATFORM
- io_pFindInfo->m_pFTSENT = fts_read( io_pFindInfo->m_pFTS );
- if ( !io_pFindInfo->m_pFTSENT )
- {
- return (errno == 0) ? 1 : -1;
- }
-#else
-/*
- * Directory traversal code is not yet available for Solaris.
- * If such code will need to be written, then it will probably use ftw.h.
- */
-#endif
-
- // If what we found is not actually a file, get the next hit.
-#ifdef WIN32
- if ( (io_pFindInfo->m_stFindData.attrib & _A_SUBDIR) )
-#elif defined K_LINUX_PLATFORM
- if ( !(io_pFindInfo->m_pFTSENT->fts_info & FTS_F) )
-#else
-/*
- * Directory traversal code is not yet available for Solaris.
- * If such code will need to be written, then it will probably use ftw.h.
- */
-#endif
- {
- return K_FindFileNext( io_pFindInfo );
- }
-
-#if defined(WIN32) || defined(K_LINUX_PLATFORM)
- return 0;
-#endif
-}
-
-void K_FindFileClose( K_FindInfo* io_pFindInfo )
-{
- if ( !io_pFindInfo )
- {
- return;
- }
-
-#ifdef WIN32
- _findclose( io_pFindInfo->m_hFile );
-#elif defined K_LINUX_PLATFORM
- fts_close( io_pFindInfo->m_pFTS );
-#else
-/*
- * Directory traversal code is not yet available for Solaris.
- * If such code will need to be written, then it will probably use ftw.h.
- */
-#endif
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: K_GetFilenamesInDirectoryCount
- *
- * Description:
- * Reads the given directory and returns the number of files that it contains.
- *
- * Input
- * -----
- * i_sDirectoryName Name of directory
- *
- * Output
- * ------
- * (none)
- *
- * Return value Number of files on success, -1 on failure
- *
- *--------------------------------------------------------------------------*/
-
-int K_GetFilenamesInDirectoryCount( const char* i_sDirectoryName )
-{
- K_FindInfo stFindInfo;
- int iCurrentFile = 0;
- int iError = 0;
-
- if ( !i_sDirectoryName || (strlen(i_sDirectoryName) <= 0) )
- {
- return -1;
- }
-
- iError = K_FindFileFirst( i_sDirectoryName, &stFindInfo );
- if ( iError < 0 )
- {
- // error
- return -1;
- }
- else if ( iError > 0 )
- {
- // no files found
- K_FindFileClose( &stFindInfo );
- return 0;
- }
-
- while ( 1 )
- {
- iCurrentFile++;
-
- iError = K_FindFileNext( &stFindInfo );
- if ( iError < 0 )
- {
- // error
- K_FindFileClose( &stFindInfo );
- return -1;
- }
- else if ( iError > 0 )
- {
- // no more files found
- break;
- }
- }
-
- K_FindFileClose( &stFindInfo );
-
- return iCurrentFile;
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: K_GetFilenamesInDirectory
- *
- * Description:
- * Reads the given directory and returns an array of names of files that it
- * contains. A null pointer appears at the last item in the array. The
- * caller must deallocate o_pasFilenames by using K_FreeFilenames or by
- * calling free() for each file name and then calling free() on the array
- * itself.
- *
- * Input
- * -----
- * i_sDirectoryName Name of directory
- *
- * Output
- * ------
- * o_pasFilenames Array of names of files found in this directory
- *
- * Return value Number of files on success, -1 on failure
- *
- *--------------------------------------------------------------------------*/
-
-int K_GetFilenamesInDirectory(
- const char* i_sDirectoryName,
- char*** o_pasFilenames )
-{
- // Note that we iterate through the filenames twice -- once to get the count
- // (K_GetFilenamesInDirectoryCount) and then once to get all the names. But
- // it may happen that the count changes between these calls. So we'll retrieve
- // at most the number of files that's returned in the first pass.
-
- K_FindInfo stFindInfo;
- int iFilenameCount = 0, iCurrentFile = 0;
- int iError = 0;
-
- if ( !i_sDirectoryName || (strlen(i_sDirectoryName) <= 0) || !o_pasFilenames )
- {
- return -1;
- }
-
- *o_pasFilenames = 0;
-
- iFilenameCount = K_GetFilenamesInDirectoryCount( i_sDirectoryName );
-
- if ( iFilenameCount < 0 )
- {
- return -1;
- }
-
- iError = K_FindFileFirst( i_sDirectoryName, &stFindInfo );
- if ( iError < 0 )
- {
- // error
- return -1;
- }
- else if ( iError > 0 )
- {
- // No files found
- K_FindFileClose( &stFindInfo );
- return 0;
- }
-
- *o_pasFilenames = (char**)calloc( (iFilenameCount+1), sizeof(char*) ); // +1 for the null last one
- if ( !*o_pasFilenames )
- {
- // Out of memory
- K_FindFileClose( &stFindInfo );
- return -1;
- }
-
- while ( 1 )
- {
- const char* sFilename = K_GetFilenameFromInfo( &stFindInfo );
-
- size_t iFilenameLength = sFilename ? strlen( sFilename ) : 0;
-
- if ( iFilenameLength <= 0 )
- {
- K_FreeFilenames( *o_pasFilenames );
- K_FindFileClose( &stFindInfo );
- return -1;
- }
-
- (*o_pasFilenames)[iCurrentFile] = (char*)calloc( (iFilenameLength+1), sizeof(char) );
- if ( !(*o_pasFilenames)[iCurrentFile] )
- {
- K_FreeFilenames( *o_pasFilenames );
- K_FindFileClose( &stFindInfo );
- return -1;
- }
-
- strncpy( (*o_pasFilenames)[iCurrentFile], sFilename, iFilenameLength );
- (*o_pasFilenames)[iCurrentFile][iFilenameLength] = '\0';
-
- iCurrentFile++;
-
- if ( iCurrentFile >= iFilenameCount )
- {
- break;
- }
-
- iError = K_FindFileNext( &stFindInfo );
- if ( iError < 0 )
- {
- // error
- K_FindFileClose( &stFindInfo );
- return -1;
- }
- else if ( iError > 0 )
- {
- // no more files found
- break;
- }
- }
-
- K_FindFileClose( &stFindInfo );
-
- return iCurrentFile;
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: K_FreeFilenames
- *
- * Description:
- * Deallocates the memory allocated in a successful call to
- * K_GetFilenamesInDirectory.
- *
- * Input
- * -----
- * i_asFilenames Array of names of files
- *
- * Output
- * ------
- * (none)
- *
- * Return value (none)
- *
- *--------------------------------------------------------------------------*/
-
-void K_FreeFilenames( char** i_asFilenames )
-{
- int i;
-
- if ( !i_asFilenames )
- {
- return;
- }
-
- for ( i = 0; (i_asFilenames[i] != 0); i++ )
- {
- free( i_asFilenames[i] );
- i_asFilenames[i] = 0;
- }
-
- free( i_asFilenames );
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: K_AdjustLocalClock
- *
- * Description:
- * The K_AdjustLocalClock function gradually adjusts the system clock by
- * the given number of seconds. A positive number adjusts the system
- * clock forward; a negative number adjusts the system clock backward.
- *
- * Input
- * -----
- * i_iAdjustmentInSeconds Number of seconds by which to adjust the
- * system clock
- * Output
- * ------
- * (none)
- *
- * Return value 1 if successful, 0 on error
- *
- *--------------------------------------------------------------------------*/
-
-int K_AdjustLocalClock( int i_iNumberOfSeconds )
-{
- struct timeval delta, lastchange;
-
-#ifndef K_SOLARIS_PLATFORM
- /* Only supported/tested on Solaris at the moment */
-
- return -1;
-#else
- /* WARNING: uses standard C time functions with Year 2038 limitations */
- time_t now;
-
- if ( (now = time(NULL)) == ((time_t)-1) )
- {
- return -1;
- }
-
- delta.tv_sec = i_iNumberOfSeconds;
- delta.tv_usec = 0;
-
- return adjtime(&delta, &lastchange);
-#endif
-}
-
-
-#ifdef K_SOLARIS_PLATFORM
-static int pam_tty_conv(
- int num_msg,
- struct pam_message** mess,
- struct pam_response** resp,
- void* my_data)
-{
- // Following code implements a console-based PAM "conversation" function
- // (based sample code from Solaris 10 Software Developer Collection >>
- // Solaris Security for Developers Guide >>
- // 3. Writing PAM Applications and Services)
-
- struct pam_message* m = *mess;
- struct pam_response* r;
- int i, j;
- const char* sPassword = (const char*)my_data;
- int error = PAM_CONV_ERR;
-
- if (num_msg <= 0 || num_msg >= PAM_MAX_NUM_MSG)
- {
- (void) fprintf(stderr, "PAM error: bad number of messages");
- *resp = NULL;
- return (PAM_CONV_ERR);
- }
-
- if ((*resp = r = calloc(num_msg, sizeof (struct pam_response))) == NULL)
- {
- return (PAM_BUF_ERR);
- }
-
- // Loop through messages
- for (i = 0; i < num_msg; i++) {
-
- // bad message from service module
- if (m->msg == NULL)
- {
- (void) fprintf(stderr, "PAM error: bad message");
- goto err;
- }
-
- // fix up final newline: removed for prompts, added back for messages
- if (m->msg[strlen(m->msg)] == '\n')
- {
- m->msg[strlen(m->msg)] = '\0';
- }
-
- // Since the KMA has its own password prompts and enforces its own rule checks, we already have the
- // new password in memory. So instead of displaying PAM prompts and collecting user responses, we
- // "automate" by assuming that the prompts correspond to the standard sequence of "New password:"
- // followed by "Confirm password:" and so in each case we immediately return the password we already
- // have in memory. This violates the PAM "conversation" function instructions (which say, basically,
- // not to assume any particular sequence of prompts since there could be any number of underlying
- // password managers), but since the KMA is running on an appliance with a fixed password manager,
- // our assumptions should hold.
-
- r->resp = NULL;
- r->resp_retcode = 0;
- switch (m->msg_style)
- {
- case PAM_PROMPT_ECHO_OFF:
- case PAM_PROMPT_ECHO_ON:
- // Assume the prompt asked for New/Confirm password, so return password.
- if ( (r->resp = strdup(sPassword)) == NULL )
- {
- error = PAM_BUF_ERR;
- goto err;
- }
- break;
-
- case PAM_ERROR_MSG:
- // Assuming the system is configured properly and the KMA password prompts enforce password strength rules,
- // there should not be errors because of weak passwords, etc. Still, print errors so users/support can
- // diagnose problems.
- (void) fputs(m->msg, stderr);
- (void) fputc('\n', stderr);
- break;
-
- case PAM_TEXT_INFO:
- // Supress prompts (again, making assumptions).
- break;
-
- default:
- (void) fprintf(stderr, "PAM error: unknown message");
- goto err;
- }
- if (errno == EINTR)
- {
- goto err;
- }
-
- // next message/response
- m++;
- r++;
- }
- return (PAM_SUCCESS);
-
-err:
- // Service modules do not clean up responses if an error is returned.
- // Free responses here.
- for (j = 0; j < i; j++, r++)
- {
- if (r->resp)
- {
- // clear before freeing -- may be a password
- bzero(r->resp, strlen(r->resp));
- free(r->resp);
- r->resp = NULL;
- }
- }
- free(r);
- *resp = NULL;
- return error;
-}
-#endif
-
-
-/*---------------------------------------------------------------------------
- * Function: K_SetRootPassword
- *
- * Description:
- * The K_SetRootPassword function sets the password for the root user via
- * Pluggable Authentication Module (PAM). This function is interactive.
- *
- * Input
- * -----
- * i_sPassword Password to set
- *
- * Output
- * ------
- * (none)
- *
- * Return value 0 if successful, -1 on error
- *
- *--------------------------------------------------------------------------*/
-
-int K_SetRootPassword( const char* i_sPassword )
-{
- // Only supported/tested on Solaris at the moment
-#ifndef K_SOLARIS_PLATFORM
- return -1;
-#else
- // Based on sample code from Solaris 10 Software Developer Collection >>
- // Solaris Security for Developers Guide >>
- // 3. Writing PAM Applications and Services
-
- // TODO: Return PAM error codes (to be logged) instead of emitting
- // messages to screen?
-
- struct pam_conv conv;
- pam_handle_t *pamh;
- int err;
-
- conv.conv = pam_tty_conv;
- conv.appdata_ptr = (void*)i_sPassword;
-
- // Initialize PAM framework
- err = pam_start("KeyMgr", "root", &conv, &pamh);
- if (err != PAM_SUCCESS)
- {
- fprintf(stderr, "PAM error: %s\n", pam_strerror(pamh, err));
- return -1;
- }
-
- // Change password
- err = pam_chauthtok(pamh, 0);
- if (err != PAM_SUCCESS)
- {
- fprintf(stderr, "PAM error: %s\n", pam_strerror(pamh, err));
- // fall through to cleanup
- }
-
- // Cleanup session
- pam_end(pamh, 0);
-
- return (err == PAM_SUCCESS) ? 0 : -1;
-#endif
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: K_Alarm
- *
- * Description:
- * Calls alarm(2) on Unix in order to cause the operating system to generate
- * a SIGALRM signal for this process after the given number of real-time
- * seconds. Does nothing on Windows.
- *
- * Input
- * -----
- * i_iSeconds Number of seconds after which to generate a SIGALRM
- * signal
- *
- * Output
- * ------
- * (none)
- *
- * Return value If a previous alarm request is pending, then it returns
- * the number of seconds until this previous request would
- * have generated a SIGALRM signal. Otherwise, returns 0.
- *
- *--------------------------------------------------------------------------*/
-
-unsigned int K_Alarm( unsigned int i_iSeconds )
-{
-#ifndef WIN32
- return alarm( i_iSeconds );
-#else
- return 0;
-#endif
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: K_GetExtendedVersionFromBase
- *
- * Description:
- * This KMS-specific function prepends the timestamp value to the specified
- * base replication schema version and returns this value as an extended
- * replication schema version.
- *
- * Input
- * -----
- * i_iBaseSchemaVersion Base replication schema version
- *
- * Output
- * ------
- * (none)
- *
- * Return value Extended replication schema version
- *
- *--------------------------------------------------------------------------*/
-
-unsigned int K_GetExtendedVersionFromBase( unsigned int i_iBaseSchemaVersion )
-{
- // seconds since 1970, force to 32-bit
-#ifdef WIN32
- INT32 iTimeStamp = (INT32) time(NULL);
-#else
- int32_t iTimeStamp = (int32_t) time(NULL);
-#endif
- // minutes since 1970
- iTimeStamp = iTimeStamp / 60;
- // minutes since 2000 (approximately)
- iTimeStamp -= (30*365*24*60);
- // shift 8 bits to clear out room for schema version #
- iTimeStamp = iTimeStamp << 8;
- // add schema version # to lower end
- iTimeStamp |= i_iBaseSchemaVersion;
-
- return (unsigned int) iTimeStamp;
-
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: K_ParseTimestampFromExtendedVersion
- *
- * Description:
- * This KMS-specific function parses the timestamp value from the given
- * extended replication schema version and returns this timestamp value.
- *
- * Input
- * -----
- * i_iExtendedSchemaVersion Extended replication schema version
- *
- * Output
- * ------
- * (none)
- *
- * Return value Timestamp value
- *
- *--------------------------------------------------------------------------*/
-
-unsigned int K_ParseTimestampFromExtendedVersion(
- unsigned int i_iExtendedSchemaVersion )
-{
- unsigned int iTimeStamp = i_iExtendedSchemaVersion >> 8;
-
- return iTimeStamp;
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: K_ParseBaseFromExtendedVersion
- *
- * Description:
- * This KMS-specific function parses the base replication schema value from
- * the given extended replication schema version and returns this base value.
- *
- * Input
- * -----
- * i_iExtendedSchemaVersion Extended replication schema version
- *
- * Output
- * ------
- * (none)
- *
- * Return value Base replication schema value
- *
- *--------------------------------------------------------------------------*/
-
-unsigned int K_ParseBaseFromExtendedVersion(
- unsigned int i_iExtendedSchemaVersion )
-{
- unsigned int iBaseSchemaVersion = i_iExtendedSchemaVersion & 0x000000FF;
-
- return iBaseSchemaVersion;
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: K_System
- *
- * Description:
- * This function is a thread-safe replacement for the unsafe system(3C) call.
- * See the popen(3C) man page for more information.
- *
- * Input
- * -----
- * i_sCmd Command to execute
- *
- * Output
- * ------
- * (none)
- *
- * Return value Termination status of the command language interpreter
- * if successful, -1 on failure
- *
- *--------------------------------------------------------------------------*/
-
-int K_System( const char *i_sCmd )
-{
-#ifndef WIN32
- FILE *p;
- int rc;
- struct sigaction sOldAction;
-
- // Save signal handler
- sigaction( SIGCHLD, NULL, &sOldAction );
-
- // Use default child signal handler
- sigset( SIGCHLD, SIG_DFL );
-
- p = popen( i_sCmd, "w" );
- if ( p == NULL )
- {
- rc = -1;
- }
- else
- {
- rc = pclose( p );
- }
-
- // Reset signal handler
- sigset( SIGCHLD, sOldAction.sa_handler );
-
- return rc;
-#else
- return system( i_sCmd );
-#endif
-}
-