Skip to content

Instantly share code, notes, and snippets.

@t0rr3sp3dr0
Last active July 18, 2022 19:05
Show Gist options
  • Save t0rr3sp3dr0/3f8b843c3cc2d356eb34a59a2d192af3 to your computer and use it in GitHub Desktop.
Save t0rr3sp3dr0/3f8b843c3cc2d356eb34a59a2d192af3 to your computer and use it in GitHub Desktop.
https://developer.apple.com/library/archive/qa/qa1133/_index.html clang -framework CoreFoundation -framework SystemConfiguration ./console_user.c
#include <assert.h>
#include <SystemConfiguration/SystemConfiguration.h>
static CFStringRef CopyCurrentConsoleUsername(SCDynamicStoreRef store)
// Returns the name of the current console user, or NULL if there is
// none. store may be NULL, in which case a transient dynamic store
// session is used.
{
CFStringRef result;
result = SCDynamicStoreCopyConsoleUser(store, NULL, NULL);
// If the current console user is "loginwindow", treat that as equivalent
// to none.
if ( (result != NULL) && CFEqual(result, CFSTR("loginwindow")) ) {
CFRelease(result);
result = NULL;
}
return result;
}
static CFStringRef gCurrentConsoleUser;
static void MyNotificationProc(
SCDynamicStoreRef store,
CFArrayRef changedKeys,
void * info
)
// Called out of our runloop when the current console user value
// changes in the dynamic store. It's possible to get multiple
// redundant notifications, so we debounce the notification by checking
// for changes relative to gCurrentConsoleUser.
{
#pragma unused(changedKeys)
#pragma unused(info)
CFStringRef currentConsoleUser;
Boolean didChange;
// Get the current console user.
currentConsoleUser = CopyCurrentConsoleUsername(store);
// See if it changed.
didChange = (gCurrentConsoleUser != NULL) != (currentConsoleUser != NULL);
if ( ! didChange && (gCurrentConsoleUser != NULL) ) {
assert(currentConsoleUser != NULL); // because if it was NULL,
// didChange would already be true
didChange = ! CFEqual(gCurrentConsoleUser, currentConsoleUser);
}
// If it did, log that fact and remember the current value.
if (didChange) {
if (gCurrentConsoleUser != NULL) {
CFRelease(gCurrentConsoleUser);
}
gCurrentConsoleUser = currentConsoleUser;
if (gCurrentConsoleUser != NULL) {
CFRetain(gCurrentConsoleUser);
}
CFShow(gCurrentConsoleUser);
}
}
int main(int argc, char **argv)
{
#pragma unused(argc)
#pragma unused(argv)
Boolean success;
SCDynamicStoreRef store;
CFStringRef key;
CFArrayRef keys;
CFRunLoopSourceRef rls;
// Set up our connection to the dynamic store so that notifications are
// delivered by calling MyNotificationProc.
store = SCDynamicStoreCreate(
NULL,
CFSTR("com.apple.dts.ConsoleUser"),
MyNotificationProc,
NULL
);
assert(store != 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);
// Print the current value.
gCurrentConsoleUser = CopyCurrentConsoleUsername(store);
CFShow(gCurrentConsoleUser);
// Run forever printing any changes.
CFRunLoopRun();
// Clean up code. This simple tool will never execute this code
// (because CFRunLoopRun will never return), but I've left it here
// in case you adapt the code for a more complex situation.
if (gCurrentConsoleUser != NULL) {
CFRelease(gCurrentConsoleUser);
}
CFRunLoopSourceInvalidate(rls);
CFRelease(rls);
CFRelease(keys);
CFRelease(key);
CFRelease(store);
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment