
/*
 * mslp_macosx.c : System dependent definitions for MacOS X.
 *
 * Version: 1.0
 * Date:    12/03/99
 *
 * Author: Kevin Arnold
 */

#include <sys/utsname.h>
#include <sys/time.h>
#include <assert.h>
#include <stdarg.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <signal.h>

#include <pthread.h>	// for pthread_*_t
#include <unistd.h>		// for _POSIX_THREADS

#include "mslp_sd.h"
#include "slp.h"
#include "mslp.h"     /* all these includes are for the definition of LOG */

pthread_mutex_t		gClientMutex;
pthread_mutex_t		gServerMutex;
static int			gMutextInitialized = 0;

EXPORT int LinOpenNetworking()
{
    if ( !gMutextInitialized )
    {
        pthread_mutex_init( &gClientMutex, NULL );
        pthread_mutex_init( &gServerMutex, NULL );
        
        gMutextInitialized = 1;
    }
    
    return 0;
}

EXPORT long LinGetTime()
{
  /* normally time() returns time_t, which is defined in sys/types.h to be  */
  /* the time of day in seconds, and typedefed to a long                    */
  long lResult;
/*  struct timeval tv;
  struct timezone tz;

  if (gettimeofday(&tv,&tz)<0) {
    LOG(SLP_LOG_ERR,"LinGetTime: could not gettimeofday");
    tv.tv_sec = 0;
    tv.tv_usec = 0;
  }
*/
//  lResult = 1000 * tv.tv_sec + tv.tv_usec / 1000;
    lResult = time(NULL);
    
    return lResult;
}

EXPORT int Linstrcasecmp(const char *pc1, const char *pc2) {
  assert(pc1 && pc2);
  return strcasecmp(pc1,pc2);
}

EXPORT int Linstrncasecmp(const char *pc1, const char *pc2, int i) {
  return strncasecmp(pc1,pc2,i);
}

EXPORT int Linchmod_writable(const char *pcPath) {

  return chmod(pcPath, FILE_MODE);

}

EXPORT void Linatexit(void (*exit_handler)(int)) {
  signal(SIGHUP,exit_handler);
  signal(SIGINT,exit_handler);
  signal(SIGQUIT,exit_handler);
}

#ifdef EXTRA_MSGS

#if 0
EXPORT static int getfid(FILE *fp) {
  return fileno(fp);
}

/*
 * LockExists
 * returns 1 if it does
 * returns 0 if it does not
 * returns -1 if an error occurred.
 */
EXPORT static int LockFileExists() {
  struct stat fileno;
  int i = stat(LOCK_NAME,&fileno);
  if (i < 0 && errno == ENOENT) return 0;
  if (i == 0) return 1;
  return i;
}

EXPORT static void * OpenLockFile(int iMode) {

  FILE *fp;

  int *pID = (int *) safe_malloc(sizeof(int),NULL,0);
  if (iMode == MSLP_SERVER) {
    if ((fp = fopen(LOCK_NAME,"w")) == NULL) {
      mslplog(SLP_LOG_ERR,"OpenLockFile - fopen failed: ",
              strerror(errno));
      return NULL;
    }
    fprintf(fp," ");
    *pID = getfid(fp);
    return (void*) pID;
  } else {
    if ((fp = fopen(LOCK_NAME,"r")) == NULL) {
      mslplog(SLP_LOG_ERR,"OpenLockFile - fopen failed: ",
              strerror(errno));
      return NULL;
    }
    *pID = getfid(fp);
    return (void*) pID;
  }
}
#endif

/* as client, returns NULL unless file exists
 * as server, removes the file and creates it afresh
 *    log problem if the file exists initially (should not)
 */
 
EXPORT void * LinGetMutex(int iMode) 
{
#ifdef MAC_OS_X
    if (iMode == MSLP_CLIENT)
        return &gClientMutex;
    else
        return &gServerMutex;
#else
    int   iLockFileExists;
    
    if ((iLockFileExists = LockFileExists())<0) {
        mslplog(SLP_LOG_ERR,"LinGetMutex - fopen of lock file failed: ",
                strerror(errno));
        return NULL;
    }
    if (iMode == MSLP_CLIENT) {
    
        if (iLockFileExists) {
        return OpenLockFile(MSLP_CLIENT);
        } else {
        LOG(SLP_LOG_ERR,"LinGetMutex - lock file doesn't exist");
        return NULL;
        }
    
    } else if (iMode == MSLP_SERVER) {
    
        if (iLockFileExists) {
    //      LOG(SLP_LOG_ERR,"Warning:  Lock file exists - unlink/reinitialize it\n");
        unlink(LOCK_NAME); /* remove old file */
        }
    
        return OpenLockFile(MSLP_SERVER);
    
    } else {
    
        SLP_LOG( SLP_LOG_ERR, "LinGetMutex - Must be client or server...");
        return NULL;
    
    }
#endif
}

/*
 * as client, does nothing but frees per process stuff
 * as server, removes the shared file
 * Returns: 0 if OK, <0 if failed (actually SLPInternalError code)
 */
EXPORT int LinFreeMutex(void *pvLock, int iMode) 
{
#ifdef MAC_OS_X
    pthread_mutex_init( (pthread_mutex_t*)pvLock, NULL );
#else
    if (pvLock == NULL) {
        LOG_SLP_ERROR_AND_RETURN(SLP_LOG_ERR,"LinFreeMutex - warning: called with no lock parameter!",
                (int)SLP_PARAMETER_BAD);
    }
    
    if (LockFileExists() == 0) {
        LOG_SLP_ERROR_AND_RETURN(SLP_LOG_ERR,"lock doesn't exist!",(int)SLP_INTERNAL_SYSTEM_ERROR);
    }
    
    if (pvLock) {
        if (iMode == MSLP_CLIENT) { /* release lock before freeing it */
        if (flock(*(int*)pvLock,LOCK_UN)<0) perror("LinFreeMutex - flock");
        }
        if (close(*(int*)pvLock) < 0) perror("LinFreeMutex - close");
        if (iMode == MSLP_SERVER) { /* remove lock entirely - no one may use it! */
        if (unlink(LOCK_NAME) < 0) perror("LinFreeMutex - unlink");
        }
    }
    SLPFree(pvLock);
#endif
    return (int) SLP_OK;
}

/*
 * complain if there is no file
 * as client locks file
 * as server locks file
 * Returns: 0 if OK, <0 if failed (actually SLPInternalError code)
 */
EXPORT int LinLock(void *pvLock) 
{
#ifdef MAC_OS_X
    if ( pvLock )
        pthread_mutex_lock( (pthread_mutex_t*)pvLock );
#else
    if (pvLock == NULL) {
        LOG_SLP_ERROR_AND_RETURN(SLP_LOG_ERR,"LinLock - missing lock param",(int)SLP_PARAMETER_BAD);
    }
    
    if (LockFileExists() == 0) {
        LOG_SLP_ERROR_AND_RETURN(SLP_LOG_ERR,"LinLock - missing lock file",
                (int)SLP_INTERNAL_SYSTEM_ERROR);
    }
    
    if (flock(*(int*) pvLock, LOCK_EX)< 0) {
        mslplog(SLP_LOG_ERR,"LinLock - flock failed",strerror(errno));
        return (int)SLP_INTERNAL_SYSTEM_ERROR;
    }
#endif
    
    return (int)SLP_OK;
}

/*
 * Returns: 0 if OK, <0 if failed (actually SLPInternalError code)
 */
EXPORT int LinUnlock(void *pvLock) 
{
#ifdef MAC_OS_X
    if ( pvLock )
        pthread_mutex_unlock( (pthread_mutex_t*)pvLock );
#else
    if (pvLock == NULL) {
        LOG_SLP_ERROR_AND_RETURN(SLP_LOG_ERR,"LinLock - missing lock param",(int)SLP_PARAMETER_BAD);
    }
    
    if (LockFileExists() == 0) {
        LOG_SLP_ERROR_AND_RETURN(SLP_LOG_ERR,"LinLock - missing lock file",
                (int)SLP_INTERNAL_SYSTEM_ERROR);
    }
    
    if (flock(*(int*)pvLock,LOCK_UN) < 0) {
        mslplog(SLP_LOG_ERR,"LinLock - flock failed",strerror(errno));
        return (int)SLP_INTERNAL_SYSTEM_ERROR;
    }
#endif

    return (int)SLP_OK;
}

EXPORT const char *LinDefaultRegfile() {
  return DEFAULT_REGFILE;
}

EXPORT const char *LinDefaultTempfile() {
  return DEFAULT_TEMPFILE;
}

#endif /* EXTRA_MSGS */
