SCDNotifierInformViaFD.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"
#include <paths.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
Boolean
SCDynamicStoreNotifyFileDescriptor(SCDynamicStoreRef store,
int32_t identifier,
int *fd)
{
size_t n;
int sc_status;
int sock;
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
kern_return_t status;
char tmpdir[PATH_MAX];
struct sockaddr_un un;
if (store == NULL) {
_SCErrorSet(kSCStatusNoStoreSession);
return FALSE;
}
if (storePrivate->server == MACH_PORT_NULL) {
_SCErrorSet(kSCStatusNoStoreServer);
return FALSE;
}
if (storePrivate->notifyStatus != NotifierNotRegistered) {
_SCErrorSet(kSCStatusNotifierActive);
return FALSE;
}
if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
_SCErrorSet(errno);
SCLog(TRUE, LOG_NOTICE, CFSTR("SCDynamicStoreNotifyFileDescriptor socket(): %s"), strerror(errno));
return FALSE;
}
n = confstr(_CS_DARWIN_USER_TEMP_DIR, tmpdir, sizeof(tmpdir));
if ((n <= 0) || (n >= sizeof(tmpdir))) {
(void) strlcpy(tmpdir, _PATH_TMP, sizeof(tmpdir));
}
bzero(&un, sizeof(un));
un.sun_family = AF_UNIX;
snprintf(un.sun_path,
sizeof(un.sun_path)-1,
"%s%s-%d-%d",
tmpdir,
"SCDynamicStoreNotifyFileDescriptor",
getpid(),
storePrivate->server);
(void) unlink(un.sun_path);
if (bind(sock, (struct sockaddr *)&un, sizeof(un)) == -1) {
_SCErrorSet(errno);
SCLog(TRUE, LOG_NOTICE, CFSTR("SCDynamicStoreNotifyFileDescriptor bind(): %s"), strerror(errno));
(void) unlink(un.sun_path);
(void) close(sock);
return FALSE;
}
if (listen(sock, 0) == -1) {
_SCErrorSet(errno);
SCLog(TRUE, LOG_NOTICE, CFSTR("SCDynamicStoreNotifyFileDescriptor listen(): %s"), strerror(errno));
(void) unlink(un.sun_path);
(void) close(sock);
return FALSE;
}
retry :
status = notifyviafd(storePrivate->server,
un.sun_path,
strlen(un.sun_path),
identifier,
(int *)&sc_status);
if (__SCDynamicStoreCheckRetryAndHandleError(store,
status,
&sc_status,
"SCDynamicStoreNotifyFileDescriptor notifyviafd()")) {
goto retry;
}
if (status != KERN_SUCCESS) {
_SCErrorSet(status);
return FALSE;
}
(void) unlink(un.sun_path);
if (sc_status != kSCStatusOK) {
_SCErrorSet(sc_status);
SCLog(TRUE, LOG_NOTICE,
CFSTR("SCDynamicStoreNotifyFileDescriptor server error: %s"),
SCErrorString(sc_status));
(void) close(sock);
return FALSE;
}
*fd = accept(sock, 0, 0);
if (*fd == -1) {
_SCErrorSet(errno);
SCLog(TRUE, LOG_NOTICE, CFSTR("SCDynamicStoreNotifyFileDescriptor accept(): %s"), strerror(errno));
(void) close(sock);
return FALSE;
}
(void) close(sock);
storePrivate->notifyStatus = Using_NotifierInformViaFD;
return TRUE;
}