5

I have a daemon (written in Obj C) running, and I would like to perform some action when some user logs in. Is it possible for a Daemon to know when a particular user logs in or out in OSX? Are there any Notifications thrown when a log in occurs? I would like to avoid the use of Log in Item or Launch Agent. And also i would like to avoid polling on a timer to check the logged in user.

Shanti K
  • 2,873
  • 1
  • 16
  • 31

1 Answers1

8

Use SCDynamicStoreCopyConsoleUser to get the console user name.

CFStringRef  consoleUserName = nil;
uid_t        uid;
gid_t        gid;
consoleUserName = SCDynamicStoreCopyConsoleUser(NULL, &uid, &gid);

Store consoleUserName in some member variable. Now creates a session to interact with the dynamic store maintained by the System Configuration server using SCDynamicStoreCreate

     SCDynamicStoreRef   store;
     CFStringRef         key;
     CFArrayRef          keys;
     CFRunLoopSourceRef  rls;
     store = SCDynamicStoreCreate(
                                     NULL, 
                                     CFSTR("com.apple.dts.ConsoleUser"), 
                                     callBackFunction, 
                                     NULL
                                     );

    // Set it up to notify us when the console user value changes.

    key = SCDynamicStoreKeyCreateConsoleUser(NULL);
    assert(key != NULL);

    keys = CFArrayCreate(NULL, (const void **) &key, 1, &kCFTypeArrayCallBacks);
    //assert(keys != NULL);

    success = SCDynamicStoreSetNotificationKeys(store, keys, NULL);
    //assert(success);

    // Add it to the runloop.

    rls = SCDynamicStoreCreateRunLoopSource(NULL, store, 0);
   // assert(rls != NULL);

    CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);


    mConsoleUserName = CopyCurrentConsoleUsername(store);
    CFRunLoopRun();

    CFRunLoopSourceInvalidate(rls);
    CFRelease(rls);
    CFRelease(keys);
    CFRelease(key);
    CFRelease(store);   

Implement callBackFunction function. You will get callback when the console user value changes.

static void callBackFunction(
                               SCDynamicStoreRef    store,
                               CFArrayRef          changedKeys,
                               void *              info
                               )
{
    CFStringRef         currentConsoleUser;
    Boolean             didChange;

    // Get the current console user.

    currentConsoleUser = CopyCurrentConsoleUsername(store);

    if (currentConsoleUser == NULL)
    {
        return;
    }
    didChange = ! CFEqual(storedvalue, currentConsoleUser);
    if (![currentConsoleUser isEqualToString:@"loginwindow"])
    {
      // pass this value to some method
    }
}
Parag Bafna
  • 22,812
  • 8
  • 71
  • 144
  • It is not necessarily that the log in user changes. I would like to be notified even if the same user logs out and logs in back again – Shanti K Apr 24 '14 at 12:27
  • You can modify callBackFunction as per your requirements. You will get call Back when user logout and login. – Parag Bafna Apr 24 '14 at 12:29
  • When user logout you will get notification that console user changed to "loginWindow". for login you will get notification that console user is changed to "loginwindow" to "Some user" – Parag Bafna Apr 24 '14 at 12:39
  • Oh ok.. for some reason, it doesn't seem to work for me. I will check further – Shanti K Apr 24 '14 at 12:52
  • or Have a look at [Multiple User Environment Programming Topics](https://developer.apple.com/library/mac/documentation/macosx/conceptual/BPMultipleUsers/BPMultipleUsers.pdf) – Parag Bafna Apr 24 '14 at 13:08