int main (int argc, char **argv)
{
    ::testing::InitGoogleTest (&argc, argv);

    SetupSignalHandlers ();

    environment = new compiz::testing::XorgEnvironment ();
    ::testing::AddGlobalTestEnvironment (environment);

    return RUN_ALL_TESTS ();
}
int main ( int argc, char *argv[], char *envp[]) {
   int ret;

   /**********************************/
   /* Read in command-line arguments */
   /**********************************/

   /* FIXME: Argument for daemonizing or not */
   /* FIXME: Argument for debug level */
   /* FIXME: Arguments affecting the log files, whether to use syslog, etc. (Read conf file?) */


   /* Report our debug level */
   if ( GetDebugLevel() > DEBUG_NONE) {

     DbgLog(GetDebugLevel(), "Starting with debugging messages logged at level %d (%d = No messages; %d = few; %d = more, etc.)", 
	    GetDebugLevel(), DEBUG_NONE, DEBUG_LEVEL0, DEBUG_LEVEL1);

   }


   /* Save our startup directory */
   SaveStartupDirectory( argv[0]  );

   ret = load_and_parse(OCK_CONFIG);
   if (ret != 0) {
      ErrLog("Failed to read config file.\n");
      return 1;
   } else
      DbgLog (DL0, "Parse config file succeeded.\n");

   /* Allocate and Attach the shared memory region */
   if ( ! CreateSharedMemory() ) {
     /* CreateSharedMemory() does it's own error logging */
     return 1;
   }

   DbgLog(DL0,"SHMID %d  token %#X \n", shmid, tok);

   /* Now that we've created the shared memory segment, we attach to it */
   if ( ! AttachToSharedMemory() ) {
     /* AttachToSharedMemory() does it's own error logging */
     DestroySharedMemory();
     return 2;
   }

   /* Initialize the global shared memory mutex (and the attribute used to create the per-process mutexes */
   if ( ! InitializeMutexes() ) {
     DetachFromSharedMemory();
     DestroySharedMemory();
     return 3;
   }

   /* Get the global shared memory mutex */

   XProcLock();

   /* Populate the Shared Memory Region */
   if ( ! InitSharedMemory(shmp) ) {

      XProcUnLock();

     DetachFromSharedMemory();
     DestroySharedMemory();
     return 4;
   }
   
   /* Release the global shared memory mutex */
   XProcUnLock();

   if ((socketfd = CreateListenerSocket()) < 0) {
      DestroyMutexes();
      DetachFromSharedMemory();
      DestroySharedMemory();
      return 5;
   }

   if (!InitSocketData(&socketData)) {
      DetachSocketListener(socketfd);
      DestroyMutexes();
      DetachFromSharedMemory();
      DestroySharedMemory();
      return 6;
   }

   /*
    *  Become a Daemon, if called for
    */
   if ( Daemon ) {
        pid_t  pid;
        if ( (pid = fork()) < 0 ){
          DetachSocketListener(socketfd);
          DestroyMutexes();
          DetachFromSharedMemory();
          DestroySharedMemory();
          return 7;
        } else {
           if ( pid != 0) {
              exit(0); // Terminate the parent
           } else {

              setsid(); // Session leader
#ifndef DEV
              fclose(stderr);
              fclose(stdout);
              fclose(stdin);
#endif

           }
        }


   } else {

#ifdef DEV
     // Log only on development builds
     LogLog("Not becoming a daemon...\n");
#endif

   }

   
   /*****************************************
    * 
    * Register Signal Handlers
    * Daemon probably should ignore ALL signals possible, since termination
    * while active is a bad thing...  however one could check for 
    * any processes active in the shared memory, and destroy the shm if
    * the process wishes to terminate.
    * 
    *****************************************/

   /*   
    *   We have to set up the signal handlers after we daemonize because
    *   the daemonization process redefines our handler for (at least) SIGTERM
    */

   if ( ! SetupSignalHandlers() ) {
     DetachSocketListener(socketfd);
     DestroyMutexes();
     DetachFromSharedMemory();
     DestroySharedMemory();
     return 8;
   }




   /*  ultimatly we will create a couple of threads which monitor the slot db
       and handle the insertion and removal of tokens from the slot.
    */

   /* For Testing the Garbage collection routines */
   /*
      shmp->proc_table[3].inuse = TRUE;
      shmp->proc_table[3].proc_id = 24328;
      */

#if !defined(NOGARBAGE)
printf("Start garbage \n");
   /* start garbage collection thread */
   if ( ! StartGCThread(shmp) ) {
     DetachSocketListener(socketfd);
     DestroyMutexes();
     DetachFromSharedMemory();
     DestroySharedMemory();
     return 9;
   }
#endif

     // We've fully become a daemon.  Now create the PID file
     {
        FILE *pidfile;

        pidfile = fopen(PID_FILE_PATH,"w");
        if (pidfile) {
           fprintf(pidfile,"%d",getpid());
	   fclose(pidfile);
        }
     }

   while (1) {
#if !(THREADED) && !(NOGARBAGE)
     CheckForGarbage(shmp);
#endif

     SocketConnectionHandler(socketfd, 10);

   }


   /*************************************************************
    * 
    *  Here we need to actualy go through the processes and verify that thye
    *  still exist.  If not, then they terminated with out properly calling
    *  C_Finalize and therefore need to be removed from the system.
    *  Look for a system routine to determine if the shared memory is held by 
    *  the process to further verify that the proper processes are in the 
    *  table.
    * 
    *************************************************************/

} /* end main */