Example #1
2
/* initialise the plug-in */
static long VLCEyeTVPluginInitialize(VLCEyeTVPluginGlobals_t** globals, long apiVersion, EyeTVPluginCallbackProc callback)
{
    printf("VLC media player Plug-In: Initialize\n");
    long result = 0;
    
    /* init our own storage */
    i_deviceCount = 0;
    i_vlcSock = -1;
    
    /* notify a potential VLC instance about our initialisation */
    CFNotificationCenterPostNotification( CFNotificationCenterGetDistributedCenter(),
                                          CFSTR("PluginInit"), 
                                          CFSTR(VLC_NOTIFICATION_OBJECT), 
                                          /*userInfo*/ NULL, 
                                          TRUE );
    
    /* init our notification support */
    CFNotificationCenterAddObserver( CFNotificationCenterGetDistributedCenter(),
                                     /* observer */ NULL, 
                                     /* callBack */ VLCEyeTVPluginGlobalNotificationReceived,
                                     /* name, NULL==all */ NULL,
                                     CFSTR(VLC_NOTIFICATION_OBJECT), 
                                     CFNotificationSuspensionBehaviorDeliverImmediately );
    
    *globals = (VLCEyeTVPluginGlobals_t *) calloc(1, sizeof( VLCEyeTVPluginGlobals_t ) );
    ( *globals )->callback = callback;
        
    return result;
}
void
PA_DeviceControl::Initialize()
{
	center = CFNotificationCenterGetDistributedCenter();
	
	CFNotificationCenterAddObserver(center, this,
					staticScanDevices,
					CFSTR("scanDevices"),
					CFSTR("PAHP_Device"),
					CFNotificationSuspensionBehaviorDeliverImmediately);
	
	CFNotificationCenterAddObserver(center, this,
					staticSetConfig,
					CFSTR("setConfiguration"),
					CFSTR("PAHP_Device"),
					CFNotificationSuspensionBehaviorDeliverImmediately);
	
	CFNotificationCenterAddObserver(center, this,
					staticStreamVolumeChanged,
					CFSTR("updateStreamVolume"),
					CFSTR("PAHP_LevelControl"),
					CFNotificationSuspensionBehaviorDeliverImmediately);
	
	CFNotificationCenterAddObserver(center, this,
					staticStreamMuteChanged,
					CFSTR("updateMuteVolume"),
					CFSTR("PAHP_BooleanControl"),
					CFNotificationSuspensionBehaviorDeliverImmediately);
}
void
SetSkypeDelegate(SkypeDelegate *aDelegate)
{
	if (!aDelegate->clientApplicationName)
	{
		printf("Deletegate requires application name\n");
		delegate = NULL;
		return;
	}
	
	if (delegate)
	{
		RemoveSkypeDelegate();
	}
	
	delegate = aDelegate;
	
	CFNotificationCenterRef center = CFNotificationCenterGetDistributedCenter();
	
	CFNotificationCenterAddObserver(
		center,
		delegate->clientApplicationName,
		apiNotificationCallback,
		CFSTR("SKSkypeAPINotification"),
		NULL,
		CFNotificationSuspensionBehaviorDeliverImmediately);

	CFNotificationCenterAddObserver(
		center,
		delegate->clientApplicationName,
		skypeQuitCallback,
		CFSTR("SKSkypeWillQuit"),
		NULL,
		CFNotificationSuspensionBehaviorDeliverImmediately);

	CFNotificationCenterAddObserver(
		center,
		delegate->clientApplicationName,
		skypeAvailableCallback,
		CFSTR("SKSkypeBecameAvailable"),
		NULL,
		CFNotificationSuspensionBehaviorDeliverImmediately);

	CFNotificationCenterAddObserver(
		center,
		delegate->clientApplicationName,
		availabilityUpdateCallback,
		CFSTR("SKAvailabilityUpdate"),
		NULL,
		CFNotificationSuspensionBehaviorDeliverImmediately);

	CFNotificationCenterAddObserver(
		center,
		delegate->clientApplicationName,
		attachResponseCallback,
		CFSTR("SKSkypeAttachResponse"),
		NULL,
		CFNotificationSuspensionBehaviorDeliverImmediately);
}
Example #4
0
NetworkMonitor::NetworkMonitor(boost::asio::io_service& io)
  : m_impl(new Impl(io))
{
  m_impl->scheduleCfLoop();

  // Potentially useful System Configuration regex patterns:
  //
  // State:/Network/Interface/.*/Link
  // State:/Network/Interface/.*/IPv4
  // State:/Network/Interface/.*/IPv6
  //
  // State:/Network/Global/DNS
  // State:/Network/Global/IPv4
  //
  // Potentially useful notifications from Darwin Notify Center:
  //
  // com.apple.system.config.network_change

  // network change observations
  CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),
                                  static_cast<void*>(this),
                                  &NetworkMonitor::Impl::afterNotificationCenterEvent,
                                  CFSTR("com.apple.system.config.network_change"),
                                  nullptr, // object to observe
                                  CFNotificationSuspensionBehaviorDeliverImmediately);
}
Example #5
0
static void setupIPodSystem()
{
    if ( !Moose::iPodScrobblingEnabled() )
    {
        deleteTwiddlyDatabases();
        return;
    }

#if TARGET_OS_WIN32
    LOG( 3, "Initialising ITunesComThread" );
    gCom = new ITunesComThread();
#endif

#if TARGET_OS_MAC
    LOG( 3, "Initialising ITunesPlaysDatabase" );
    ITunesPlaysDatabase::init(); // must be done b4 notification center registration

    CFNotificationCenterAddObserver( CFNotificationCenterGetDistributedCenter(),
                                     NULL,
                                     notificationCallback,
                                     CFSTR( "com.apple.iTunes.playerInfo" ),
                                     NULL,
                                     CFNotificationSuspensionBehaviorDeliverImmediately );
#endif

    LOG( 3, "Initialising IPodDetector" );
    gIPodDetector = new IPodDetector;
}
Example #6
0
extern void GPStartWhenGriPIsReady(void(*initializer)()) {
	CFMessagePortRef serverPort = CFMessagePortCreateRemote(NULL, CFSTR("hk.kennytm.GriP.server"));
	
	if (serverPort != NULL) {
		// GriP is already running. call the initializer directly.
		initializer();
		CFRelease(serverPort);
		
	} else {
		// GriP is not running. register for the notification and set the initializer as callback.
		CFNotificationCenterAddObserver(CFNotificationCenterGetLocalCenter(), initializer, (CFNotificationCallback)&GPGriPIsReadyCallback, CFSTR("hk.kennytm.GriP.ready"), NULL, CFNotificationSuspensionBehaviorCoalesce);
	}
}
void	CACFDistributedNotification::AddObserver(const void* inObserver, CFNotificationCallback inCallback, CFStringRef inName, CFNotificationSuspensionBehavior inSuspensionBehavior)
{
#if	!TARGET_OS_IPHONE
	CFNotificationCenterRef theCenter = CFNotificationCenterGetDistributedCenter();
	CFNotificationSuspensionBehavior theSuspensionBehavior = inSuspensionBehavior;
#else
	#pragma unused(inSuspensionBehavior)
	CFNotificationCenterRef theCenter = CFNotificationCenterGetDarwinNotifyCenter();
	CFNotificationSuspensionBehavior theSuspensionBehavior = 0;
#endif
	 
	CFNotificationCenterAddObserver(theCenter, inObserver, inCallback, inName, NULL, theSuspensionBehavior);
}
Example #8
0
void
ITunesScript::run()
{
    setupCurrentTrack();

    CFNotificationCenterAddObserver( CFNotificationCenterGetDistributedCenter(), 
                                     this,
                                     callback, 
                                     CFSTR( "com.apple.iTunes.playerInfo" ), 
                                     NULL, 
                                     CFNotificationSuspensionBehaviorDeliverImmediately );
    
    exec();
}
Example #9
0
KGlobalAccelImpl::KGlobalAccelImpl(GlobalShortcutsRegistry* owner)
	: m_owner(owner)
    , m_eventTarget(GetApplicationEventTarget())
    , m_eventHandler(NewEventHandlerUPP(hotKeyEventHandler))
{
    m_eventType[0].eventClass = kEventClassKeyboard;
    m_eventType[0].eventKind = kEventHotKeyPressed; 
    m_eventType[1].eventClass = kEventClassKeyboard; // only useful for testing, is not used because count passed in call to InstallEventHandler is 1
    m_eventType[1].eventKind = kEventRawKeyDown;
    refs = new QMap<int, QList<EventHotKeyRef> >();
    
    CFStringRef str = CFStringCreateWithCString(NULL, "AppleKeyboardPreferencesChangedNotification", kCFStringEncodingASCII);
    if (str) {
        CFNotificationCenterAddObserver(CFNotificationCenterGetDistributedCenter(), this, layoutChanged, str, NULL, CFNotificationSuspensionBehaviorHold);
        CFRelease(str);
    } else {
        kWarning(125) << "Couldn't create CFString to register for keyboard notifications";
    }
}
Example #10
0
int
main(int argc, char* argv[])
{
    bool add = false, create = false, destroy = false, erase = false, header = false;
    bool list = false, lvcreate = false, lvdestroy = false, lvlist = false, lvmodify = false, lvresize = false, lvsnap = false;
    bool modify = false, remove = false, spare = false, watch = false;
    char * setLevel = 0, * setName = 0; 

    /* options descriptor */
    static struct option longopts[] = {
	{ "add",	required_argument,	0,	'a' },
	{ "create",	no_argument,		0,	'c' },
	{ "destroy",	required_argument,	0,	'd' },
	{ "erase",	no_argument,		0,	'e' },
	{ "header",	no_argument,		0,	'h' },
	{ "list",	no_argument,		0,	'l' },
	{ "modify",	required_argument,	0,	'm' },
	{ "remove",	required_argument,	0,	'r' },
	{ "spare",	required_argument,	0,	's' },
	{ "watch",	no_argument,		0,	'w' },
	
	{ "lvcreate",	required_argument,	0,	'C' },
	{ "lvdestroy",	required_argument,	0,	'D' },
	{ "lvlist",	no_argument,		0,	'L' },
	{ "lvmodify",	required_argument,	0,	'M' },
	{ "lvresize",	required_argument,	0,	'R' },
	{ "lvsnap",	required_argument,	0,	'S' },
	
	{ "auto-rebuild",required_argument,	0,	'A' },
	{ "block-size", required_argument,	0,	'B' },
	{ "extents",	no_argument,		0,	'E' },
	{ "hint",	required_argument,	0,	'H' },
	{ "level",	required_argument,	0,	'V' },
	{ "name",	required_argument,	0,	'N' },
	{ "quick-rebuild",required_argument,	0,	'Q' },
	{ "size",	required_argument,	0,	'Z' },
	{ "timeout",	required_argument,	0,	'T' },

	{ "verbose",	no_argument,		0,	'v' },
	{ "help",	no_argument,		0,	'?' },
	{ 0,		0,			0,	0   }
    };

    int ch;
    while ((ch = getopt_long(argc, argv, "a:cd:ehlm:r:s:wC:D:LM:R:S:A:B:EH:V:N:Q:Z:T:v?", longopts, NULL)) != -1) {
	
	switch(ch) {

	case 'a':
	    add = true;
	    setName = strdup(optarg);
	    break;
	case 'c':
	    create = true;
	    break;
	case 'd':
	    destroy = true;
	    setName = strdup(optarg);
	    break;
	case 'e':
	    erase = true;
	    break;
	case 'h':
	    header = true;
	    break;
	case 'l':
	    list = true;
	    break;
	case 'm':
	    modify = true;
	    setName = strdup(optarg);
	    break;
	case 'r':
	    remove = true;
	    setName = strdup(optarg);
	    break;
	case 's':
	    spare = true;
	    setName = strdup(optarg);
	    break;
	case 'w':
	    watch = true;
	    break;

	    
	case 'C':
	    lvcreate = true;
	    setName = strdup(optarg);
	    break;
	case 'D':
	    lvdestroy = true;
	    setName = strdup(optarg);
	    break;
	case 'L':
	    lvlist = true;
	    break;
	case 'M':
	    lvmodify = true;
	    setName = strdup(optarg);
	    break;
	case 'R':
	    lvresize = true;
	    setName = strdup(optarg);
	    break;
	case 'S':
	    lvsnap = true;
	    setName = strdup(optarg);
	    break;


	case 'A':
	    autoRebuild = ((optarg[0] == 'Y') || (optarg[0] == 'y')) ? AUTO_YES : AUTO_NO;
	    break;
	case 'B':
	    sscanf(optarg, "%lli", &blockSize);
	    break;
	case 'E':
	    extents = true;
	    break;
	case 'H':
	    hint = strdup(optarg);
	    break;
	case 'V':
	    setLevel = strdup(optarg);
	    break;
	case 'N':
	    nickname = strdup(optarg);
	    break;
	case 'Q':
	    quickRebuild = ((optarg[0] == 'Y') || (optarg[0] == 'y')) ? AUTO_YES : AUTO_NO;
	    break;
	case 'Z':
	    sscanf(optarg, "%lli", &volSize);
	    break;
	case 'T':
	    sscanf(optarg, "%lli", &timeout);
	    break;


	case 'v':
	    verbose = true;
	    break;
	case 0:
	case '?':
	default:
	    usage();
	    exit(0);
	}
    }
    argc -= optind;
    argv += optind;

    if (!add && !create && !destroy && !erase && !header && !list && !modify && !remove && !spare && !watch &&
	!lvcreate && !lvdestroy && !lvlist && !lvmodify && !lvresize && !lvsnap) {
	usage();
	exit(0);
    }

    if (list) {
	listRAIDSets();
	exit(0);
    }

    if (lvlist) {
	listLogicalVolumes(NULL, argc, argv);
	exit(0);
    }

    if (geteuid()) {
	printf("ERROR: you must be super user for this operation.\n");
	exit(1);
    }
	
    if (erase) {
	erasePartition(argc, argv);
	exit(0);
    };

    if (header) {
	dumpHeader(argc, argv);
	exit(0);
    };

    if (watch) {

	CFNotificationCenterAddObserver(CFNotificationCenterGetLocalCenter(),
					NULL,					// const void *observer
					callBack,
					CFSTR(kAppleRAIDNotificationSetDiscovered),
					NULL,					// const void *object
					CFNotificationSuspensionBehaviorHold);

	CFNotificationCenterAddObserver(CFNotificationCenterGetLocalCenter(),
					NULL,					// const void *observer
					callBack,
					CFSTR(kAppleRAIDNotificationSetTerminated),
					NULL,					// const void *object
					CFNotificationSuspensionBehaviorHold);

	CFNotificationCenterAddObserver(CFNotificationCenterGetLocalCenter(),
					NULL,					// const void *observer
					callBack,
					CFSTR(kAppleRAIDNotificationSetChanged),
					NULL,					// const void *object
					CFNotificationSuspensionBehaviorHold);

	CFNotificationCenterAddObserver(CFNotificationCenterGetLocalCenter(),
					NULL,					// const void *observer
					callBack,
					CFSTR(kAppleLVMNotificationVolumeDiscovered),
					NULL,					// const void *object
					CFNotificationSuspensionBehaviorHold);

	CFNotificationCenterAddObserver(CFNotificationCenterGetLocalCenter(),
					NULL,					// const void *observer
					callBack,
					CFSTR(kAppleLVMNotificationVolumeTerminated),
					NULL,					// const void *object
					CFNotificationSuspensionBehaviorHold);

	CFNotificationCenterAddObserver(CFNotificationCenterGetLocalCenter(),
					NULL,					// const void *observer
					callBack,
					CFSTR(kAppleLVMNotificationVolumeChanged),
					NULL,					// const void *object
					CFNotificationSuspensionBehaviorHold);

	// this will not fail if there is no raid controller, ie, if AppleRAID class is not instantiated in the kernel

	AppleRAIDEnableNotifications();
    }


    if (add) addMember(setName, CFSTR(kAppleRAIDMembersKey), argc, argv);
    if (create) createSet(setLevel, nickname, argc, argv);
    if (destroy) destroySet(setName, argc, argv);
    if (modify) modifySet(setName, argc, argv);
    if (remove) removeMember(setName, argc, argv);
    if (spare) addMember(setName, CFSTR(kAppleRAIDSparesKey), argc, argv);

    
    if (lvcreate) createLogicalVolume(setName, setLevel, argc, argv);
    if (lvdestroy) destroyLogicalVolume(setName, argc, argv);
    if (lvmodify) modifyLogicalVolume(setName, argc, argv);
    if (lvresize) resizeLogicalVolume(setName, argc, argv);
    if (lvsnap) snapshotLogicalVolume(setName, setLevel, argc, argv);

    
    if (watch) {

	printf("watching...\n");

	// Set up a signal handler so we can clean up when we're interrupted from the command line
	// Otherwise we stay in our run loop forever.
	sig_t oldHandler = signal(SIGINT, signalHandler);
	if (oldHandler == SIG_ERR) {
	    printf("Could not establish new signal handler");
	    exit(1);
	}

	// Start the run loop. Now we'll receive notifications.
	//
	printf("Starting run loop.\n");
	CFRunLoopRun();
        
	printf("Unexpectedly back from CFRunLoopRun()!\n");
    }

    return 0;
}
ITunesController::ITunesController()
{
	// TODO: Poll iTunes for current playing tune
	CFNotificationCenterRef center = CFNotificationCenterGetDistributedCenter();
	CFNotificationCenterAddObserver(center, this, ITunesController::iTunesCallback, CFSTR("com.apple.iTunes.playerInfo"), NULL, CFNotificationSuspensionBehaviorDeliverImmediately);
}
Example #12
0
int main(int argc, char** argv) {
  if(argc < 4) {
    PrintUsage(stdout);
    return 0;
  }
  
  /* <argv parsing> */
  
  /* Parse argument: mountpoint (CFString) */
  /*CFStringRef mountpoint = CFStringCreateWithCString(kCFAllocatorDefault, 
    argv[1], kCFStringEncodingUTF8); */
  /* Parse argument: mountpointRaw (char*) */
  char *mountpointRaw = argv[1];
  
  /* Parse argument: timeout (double) */
  double timeout;
  {
    CFStringRef timeoutString = CFStringCreateWithCString(kCFAllocatorDefault, 
							 argv[2], kCFStringEncodingUTF8);
    timeout = CFStringGetDoubleValue(timeoutString);
    CFRelease(timeoutString);
    if(timeout == 0.0) {
      fprintf(stdout, "Invalid argument: timeout (\"%s\"", argv[2]);
      return -1;
    }
  }
  
  /* Parse argument: mount_command */
  const char *mount_command = argv[3];
  
  /* </argv parsing> */
 
  CFNotificationCenterRef centerRef;
  CFStringRef notificationObjectName = CFSTR(FUSE_LISTEN_OBJECT);
  CFStringRef notificationName = CFSTR(FUSE_MOUNT_NOTIFICATION_NAME);
  CFRunLoopRef crl;
  
  if(DEBUGMODE) {
    DEBUG("Testing NotificationCallback...\n");
    NotificationCallback(NULL, NULL, notificationObjectName, NULL, NULL);
    DEBUG("Test completed. Adding observer...\n");
  }
  
  centerRef = CFNotificationCenterGetDistributedCenter();
  crl = CFRunLoopGetCurrent();
  
  /* Think. Will the child process also be an observer? I don't think so... */
  CFNotificationCenterAddObserver(centerRef, NULL, NotificationCallback, notificationName,
				  notificationObjectName, CFNotificationSuspensionBehaviorDrop);
    

  int forkRetval = fork();
  if(forkRetval == -1) {
    fprintf(stderr, "Could not fork!\n");
    return -1;
  }
  else if(forkRetval != 0) {
    // Parent process
    int childProcessPID = forkRetval;

    int waitpid_status = 0;
    DEBUG("Waiting for PID %d...\n", childProcessPID);
    int waitpidres = waitpid(childProcessPID, &waitpid_status, 0);
    if(waitpidres == childProcessPID) {
      if(!WIFEXITED(waitpid_status)) {
	DEBUG("Child process did not exit cleanly! Returning -1.");
	return -1;
      }
      
      int retval = WEXITSTATUS(waitpid_status);
      DEBUG("PID %d returned with exit code: %d Exiting fuse_wait with this exit code...\n", childProcessPID, retval);
      if(retval != 0) {
	DEBUG("Exit value indicates an error while executing mount command. Returning without\n");
	DEBUG("waiting for notification.\n");
	DEBUG("Returning retval: %d\n", retval);
	return retval;
      }
    }
    else {
      DEBUG("Abnormal termination of process %d. :( waitpid returned: %d\n", childProcessPID, waitpidres);
      return -1;
    }
    
    DEBUG("Running run loop a long time...\n");
    CFStringRef mountPathSnapshot = NULL;
    while(mountPathSnapshot == NULL) {
      int crlrimRetval = CFRunLoopRunInMode(kCFRunLoopDefaultMode, timeout, true);
      DEBUG("Exited from run loop. Let's find out why... crlrimRetval: %d (handled: %d)\n", crlrimRetval, kCFRunLoopRunHandledSource);
      mountPathSnapshot = mountPath; // Might have been modified during run loop.
      if(crlrimRetval != kCFRunLoopRunHandledSource) {
	fprintf(stderr, "Did not receive a signal within %f seconds. Exiting...\n", timeout);
	break;
      }
      else if(mountPathSnapshot != NULL) {
	DEBUG("mountPathSnapshot: %X\n", (int)mountPathSnapshot);
	
	int mountPathUTF8Length = CFStringGetLength(mountPath) + 1;  // null terminator
	char *mountPathUTF8 = malloc(mountPathUTF8Length);
	memset(mountPathUTF8, 0, mountPathUTF8Length);
	GetCorruptedMacFUSEStringAsUTF8(mountPath, mountPathUTF8, mountPathUTF8Length);
	
	char *canonicalMountPath = malloc(PATH_MAX);
	char *canonicalMountpoint = malloc(PATH_MAX);
	memset(canonicalMountPath, 0, PATH_MAX);
	memset(canonicalMountpoint, 0, PATH_MAX);
	
	realpath(mountPathUTF8, canonicalMountPath);
	realpath(mountpointRaw, canonicalMountpoint);
	
	int cmpres = strncmp(canonicalMountPath, canonicalMountpoint, PATH_MAX);
	
	if(cmpres != 0) {
	  if(DEBUGMODE) {
	    DEBUG("Strings NOT equal. cmpres=%d\n", cmpres);
	    DEBUG("mountPath (UTF-8): \"%s\"\n", canonicalMountPath);
	    DEBUG("mountpoint (UTF-8): \"%s\"\n", canonicalMountpoint);
	  }
	  mountPathSnapshot = NULL;
	}
	else
	  DEBUG("Mounter has signaled! Great success!\n");
	
	free(mountPathUTF8);
	free(canonicalMountPath);
	free(canonicalMountpoint);
      }
      //CFRunLoopRun();
    }
    DEBUG("Run loop done.\n");
    if(mountPath != NULL)
      CFRelease(mountPath);
    
    return 0; // We have previously checked that the return value from the child process is 0. We can't get here if it isn't.
  }
  else { // forkRetval == 0
    // Child process
    const int childargc = argc-3;
    char *childargv[childargc+1];
    childargv[childargc] = NULL; // Null terminated
    int i;
    for(i = 0; i < childargc; ++i)
      childargv[i] = argv[i+(argc-childargc)];
    
    if(DEBUGMODE) {
      DEBUG("Contents of argv:\n");
      for(i = 0; i < argc; ++i)
	DEBUG("  argv[%i]: \"%s\"\n", i, argv[i]);
      
      DEBUG("Contents of childargv:\n");
      for(i = 0; i < childargc; ++i)
	DEBUG("  childargv[%i]: \"%s\"\n", i, childargv[i]);
    }
    
    execvp(mount_command, childargv);
    fprintf(stderr, "Could not execute %s!\n", argv[3]);
    return -1;
  }
}
Example #13
0
int main(int argc, char** argv) {
  LOG_DEBUG("[Debug messages enabled]\n");
  if(argc < 4) {
    PrintUsage(stdout);
    return 0;
  }
  
  /* <argv parsing> */
  
  /* Parse argument: mountpoint (CFString) */
  /*CFStringRef mountpoint = CFStringCreateWithCString(kCFAllocatorDefault, 
    argv[1], kCFStringEncodingUTF8); */
  /* Parse argument: mountpointRaw (char*) */
  char *mountpointRaw = argv[1];
  
  /* Parse argument: timeout (double) */
  double timeout;
  {
    CFStringRef timeoutString = CFStringCreateWithCString(kCFAllocatorDefault, 
							  argv[2],
							  kCFStringEncodingUTF8);
    timeout = CFStringGetDoubleValue(timeoutString);
    CFRelease(timeoutString);
    if(timeout == 0.0) {
      fprintf(stdout, "Invalid argument: timeout (\"%s\")\n", argv[2]);
      return -1;
    }
  }
  
  /* Parse argument: mount_command */
  const char *mount_command = argv[3];
  
  /* </argv parsing> */
 
  CFNotificationCenterRef centerRef;
  CFStringRef notificationObjectName = CFSTR(FUSE_LISTEN_OBJECT);
  CFStringRef notificationName = CFSTR(FUSE_MOUNT_NOTIFICATION_NAME);
  //CFRunLoopRef runLoop;
  
  if(DEBUGMODE) {
    LOG_DEBUG("Testing NotificationCallback...\n");
    NotificationCallback(NULL, NULL, notificationObjectName, NULL, NULL);
    LOG_DEBUG("Test completed. Adding observer...\n");
  }
  
  centerRef = CFNotificationCenterGetDistributedCenter();
  //runLoop = CFRunLoopGetCurrent();
  
  /*
   * We need to add ourselves as an observer before the fork, in case the forked
   * process outruns us.
   *
   * Will the child process also be an observer? Possibly, but even if that is
   * the case, it shouldn't seem to make any practical difference (we never
   * enter a CFRunLoop in the child process, at least not before execvp).
   */
  CFNotificationCenterAddObserver(centerRef, NULL, NotificationCallback, notificationName,
				  notificationObjectName, CFNotificationSuspensionBehaviorDrop);

  int forkRetval = fork();
  if(forkRetval == -1) {
    fprintf(stderr, "Could not fork!\n");
    return -1;
  }
  else if(forkRetval != 0) {
    // Parent process
    int childProcessPID = forkRetval;

    int waitpid_status = 0;
    LOG_DEBUG("Waiting for PID %d...\n", childProcessPID);
    int waitpidres = waitpid(childProcessPID, &waitpid_status, 0);
    if(waitpidres == childProcessPID) {
      if(!WIFEXITED(waitpid_status)) {
	LOG_DEBUG("Child process did not exit cleanly! Returning -1.");
	return -1;
      }
      
      int retval = WEXITSTATUS(waitpid_status);
      LOG_DEBUG("PID %d returned with exit code: %d Exiting fuse_wait with this exit code...\n", childProcessPID, retval);
      if(retval != 0) {
	LOG_DEBUG("Exit value indicates an error while executing mount command. Returning without\n");
	LOG_DEBUG("waiting for notification.\n");
	LOG_DEBUG("Returning retval: %d\n", retval);
	return retval;
      }
    }
    else {
      LOG_DEBUG("Abnormal termination of process %d. waitpid returned: %d\n", childProcessPID, waitpidres);
      return -1;
    }
    
    LOG_DEBUG("Running run loop a long time...\n");
    CFStringRef mountPathSnapshot = NULL;
    while(mountPathSnapshot == NULL) {
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
      int crlrimRetval = CFRunLoopRunInMode(kCFRunLoopDefaultMode, timeout, true);
      LOG_DEBUG("Exited from run loop. Let's find out why... crlrimRetval: %d "
		"(handled: %d)\n", crlrimRetval, kCFRunLoopRunHandledSource);
#else
      CFRunLoopRunInMode(kCFRunLoopDefaultMode, timeout, true);
      LOG_DEBUG("Exited from run loop. Let's find out why.\n");
#endif
      mountPathSnapshot = mountPath; // Might have been modified during RunLoop.
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
      if(crlrimRetval != kCFRunLoopRunHandledSource) {
	fprintf(stderr, "Did not receive a signal within %f seconds. "
		"Exiting...\n", timeout);
	return -2;
      }
#endif
      if(mountPathSnapshot != NULL) {
	LOG_DEBUG("mountPathSnapshot: %p\n", mountPathSnapshot);
	
	/*
	 * Convert the CFString that we got back from the CFNotificationCenter
	 * into UTF-8 data. (We assume that UTF-8 is the encoding used by the
	 * system, which is true in Mac OS X.)
	 */
	CFDataRef utf8Data =
	  CFStringCreateExternalRepresentation(NULL, mountPath,
					       kCFStringEncodingUTF8, 0);
	
	if(utf8Data != NULL) {
	  /*
	   * Put the UTF-8 data in a NULL-terminated C-string.
	   */
	  size_t mountPathUTF8Length = CFDataGetLength(utf8Data) + 1;
	  char *mountPathUTF8 = calloc(1, mountPathUTF8Length);
	  CFDataGetBytes(utf8Data, CFRangeMake(0, mountPathUTF8Length - 1),
			 (unsigned char*) mountPathUTF8);
	  
	  //int mountPathUTF8Length = CFStringGetLength(mountPath) + 1;  // null terminator
	  //char *mountPathUTF8 = malloc(mountPathUTF8Length);
	  //memset(mountPathUTF8, 0, mountPathUTF8Length);
	  //GetCorruptedMacFUSEStringAsUTF8(mountPath, mountPathUTF8, mountPathUTF8Length);
	  
	  /*
	   * Canonicalize the two paths, in case one of the pathnames contain
	   * symbolic links, but not the other.
	   */
	  char *canonicalMountPath = malloc(PATH_MAX);
	  char *canonicalMountpoint = malloc(PATH_MAX);
	  memset(canonicalMountPath, 0, PATH_MAX);
	  memset(canonicalMountpoint, 0, PATH_MAX);
	  
	  realpath(mountPathUTF8, canonicalMountPath);
	  realpath(mountpointRaw, canonicalMountpoint);
	  
	  /*
	   * Finally, compare the two paths for equality.
	   */
	  int cmpres = strncmp(canonicalMountPath, canonicalMountpoint, PATH_MAX);
	  
	  if(cmpres != 0) {
	    LOG_DEBUG("Strings NOT equal. cmpres=%d\n", cmpres);
	    LOG_DEBUG("mountPath (UTF-8): \"%s\"\n", canonicalMountPath);
	    LOG_DEBUG("mountpoint (UTF-8): \"%s\"\n", canonicalMountpoint);
	    
	    mountPathSnapshot = NULL;
	  }
	  else
	    LOG_DEBUG("Recieved a signal for the mount point.\n");
	  
	  free(mountPathUTF8);
	  free(canonicalMountPath);
	  free(canonicalMountpoint);
	}

	CFRelease(utf8Data);
      }
    }
    LOG_DEBUG("Run loop done.\n");
    if(mountPath != NULL)
      CFRelease(mountPath);
    
    return 0; // We have previously checked that the return value from the child process is 0. We can't get here if it isn't.
  }
  else { // forkRetval == 0
    // Child process
    const int childargc = argc-3;
    char *childargv[childargc+1];
    childargv[childargc] = NULL; // Null terminated
    int i;
    for(i = 0; i < childargc; ++i)
      childargv[i] = argv[i+(argc-childargc)];
    
    LOG_DEBUG("Contents of argv:\n");
    for(i = 0; i < argc; ++i)
      LOG_DEBUG("  argv[%i]: \"%s\"\n", i, argv[i]);
    
    LOG_DEBUG("Contents of childargv:\n");
    for(i = 0; i < childargc; ++i)
      LOG_DEBUG("  childargv[%i]: \"%s\"\n", i, childargv[i]);
    
    execvp(mount_command, childargv);
    fprintf(stderr, "Could not execute %s!\n", argv[3]);
    return -1;
  }
}