SCDNotifierInformViaMachPort.c [plain text]
#include <mach/mach.h>
#include <mach/mach_error.h>
#include <SystemConfiguration/SystemConfiguration.h>
#include <SystemConfiguration/SCPrivate.h>
#include "SCDynamicStoreInternal.h"
#include "config.h"
Boolean
SCDynamicStoreNotifyMachPort(SCDynamicStoreRef store, mach_msg_id_t identifier, mach_port_t *port)
{
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
kern_return_t status;
mach_port_t oldNotify;
int sc_status;
SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyMachPort:"));
if (!store) {
_SCErrorSet(kSCStatusNoStoreSession);
return FALSE;
}
if (storePrivate->server == MACH_PORT_NULL) {
_SCErrorSet(kSCStatusNoStoreServer);
return FALSE;
}
if (storePrivate->notifyStatus != NotifierNotRegistered) {
_SCErrorSet(kSCStatusNotifierActive);
return FALSE;
}
status = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, port);
if (status != KERN_SUCCESS) {
SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_port_allocate(): %s"), mach_error_string(status));
_SCErrorSet(status);
return FALSE;
}
SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" port = %d"), *port);
status = mach_port_insert_right(mach_task_self(),
*port,
*port,
MACH_MSG_TYPE_MAKE_SEND);
if (status != KERN_SUCCESS) {
SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_port_insert_right(): %s"), mach_error_string(status));
(void) mach_port_destroy(mach_task_self(), *port);
*port = MACH_PORT_NULL;
_SCErrorSet(status);
return FALSE;
}
status = mach_port_request_notification(mach_task_self(),
*port,
MACH_NOTIFY_NO_SENDERS,
1,
*port,
MACH_MSG_TYPE_MAKE_SEND_ONCE,
&oldNotify);
if (status != KERN_SUCCESS) {
SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_port_request_notification(): %s"), mach_error_string(status));
(void) mach_port_destroy(mach_task_self(), *port);
*port = MACH_PORT_NULL;
_SCErrorSet(status);
return FALSE;
}
if (oldNotify != MACH_PORT_NULL) {
SCLog(_sc_verbose, LOG_ERR, CFSTR("SCDynamicStoreNotifyMachPort(): why is oldNotify != MACH_PORT_NULL?"));
}
status = notifyviaport(storePrivate->server,
*port,
identifier,
(int *)&sc_status);
if (status != KERN_SUCCESS) {
if (status != MACH_SEND_INVALID_DEST)
SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifyviaport(): %s"), mach_error_string(status));
(void) mach_port_destroy(mach_task_self(), *port);
*port = MACH_PORT_NULL;
(void) mach_port_destroy(mach_task_self(), storePrivate->server);
storePrivate->server = MACH_PORT_NULL;
_SCErrorSet(status);
return FALSE;
}
storePrivate->notifyStatus = Using_NotifierInformViaMachPort;
return TRUE;
}