]> git.saurik.com Git - apple/configd.git/blob - configd.tproj/notify.c
configd-53.tar.gz
[apple/configd.git] / configd.tproj / notify.c
1 /*
2 * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22
23 /*
24 * Modification History
25 *
26 * June 1, 2001 Allan Nathanson <ajn@apple.com>
27 * - public API conversion
28 *
29 * March 31, 2000 Allan Nathanson <ajn@apple.com>
30 * - initial revision
31 */
32
33
34 #include <unistd.h>
35
36 #include "configd.h"
37 #include "configd_server.h"
38 #include "session.h"
39
40
41 void
42 pushNotifications()
43 {
44 const void **sessionsToNotify;
45 CFIndex notifyCnt;
46 int server;
47 serverSessionRef theSession;
48 SCDynamicStorePrivateRef storePrivate;
49
50 if (needsNotification == NULL)
51 return; /* if no sessions need to be kicked */
52
53 notifyCnt = CFSetGetCount(needsNotification);
54 sessionsToNotify = malloc(notifyCnt * sizeof(CFNumberRef));
55 CFSetGetValues(needsNotification, sessionsToNotify);
56 while (--notifyCnt >= 0) {
57 (void) CFNumberGetValue(sessionsToNotify[notifyCnt],
58 kCFNumberIntType,
59 &server);
60 theSession = getSession(server);
61 storePrivate = (SCDynamicStorePrivateRef)theSession->store;
62
63 /*
64 * deliver notifications to client sessions
65 */
66 if ((storePrivate->notifyStatus == Using_NotifierInformViaMachPort) &&
67 (storePrivate->notifyPort != MACH_PORT_NULL)) {
68 mach_msg_empty_send_t msg;
69 mach_msg_option_t options;
70 kern_return_t status;
71 /*
72 * Post notification as mach message
73 */
74 SCLog(_configd_verbose, LOG_DEBUG, CFSTR("sending mach message notification."));
75 SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" port = %d"), storePrivate->notifyPort);
76 SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" msgid = %d"), storePrivate->notifyPortIdentifier);
77 msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
78 msg.header.msgh_size = sizeof(msg);
79 msg.header.msgh_remote_port = storePrivate->notifyPort;
80 msg.header.msgh_local_port = MACH_PORT_NULL;
81 msg.header.msgh_id = storePrivate->notifyPortIdentifier;
82 options = MACH_SEND_TIMEOUT;
83 status = mach_msg(&msg.header, /* msg */
84 MACH_SEND_MSG|options, /* options */
85 msg.header.msgh_size, /* send_size */
86 0, /* rcv_size */
87 MACH_PORT_NULL, /* rcv_name */
88 0, /* timeout */
89 MACH_PORT_NULL); /* notify */
90 }
91
92 if ((storePrivate->notifyStatus == Using_NotifierInformViaFD) &&
93 (storePrivate->notifyFile >= 0)) {
94 ssize_t written;
95
96 SCLog(_configd_verbose, LOG_DEBUG, CFSTR("sending (UNIX domain) socket notification"));
97 SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" fd = %d"), storePrivate->notifyFile);
98 SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" msgid = %d"), storePrivate->notifyFileIdentifier);
99
100 written = write(storePrivate->notifyFile,
101 &storePrivate->notifyFileIdentifier,
102 sizeof(storePrivate->notifyFileIdentifier));
103 if (written == -1) {
104 if (errno == EWOULDBLOCK) {
105 SCLog(_configd_verbose, LOG_DEBUG,
106 CFSTR("sorry, only one outstanding notification per session."));
107 } else {
108 SCLog(_configd_verbose, LOG_DEBUG,
109 CFSTR("could not send notification, write() failed: %s"),
110 strerror(errno));
111 storePrivate->notifyFile = -1;
112 }
113 } else if (written != sizeof(storePrivate->notifyFileIdentifier)) {
114 SCLog(_configd_verbose, LOG_DEBUG,
115 CFSTR("could not send notification, incomplete write()"));
116 storePrivate->notifyFile = -1;
117 }
118 }
119
120 if ((storePrivate->notifyStatus == Using_NotifierInformViaSignal) &&
121 (storePrivate->notifySignal > 0)) {
122 kern_return_t status;
123 pid_t pid;
124 /*
125 * Post notification as signal
126 */
127 status = pid_for_task(storePrivate->notifySignalTask, &pid);
128 if (status == KERN_SUCCESS) {
129 SCLog(_configd_verbose, LOG_DEBUG, CFSTR("sending signal notification"));
130 SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" pid = %d"), pid);
131 SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" signal = %d"), storePrivate->notifySignal);
132 if (kill(pid, storePrivate->notifySignal) != 0) {
133 SCLog(_configd_verbose, LOG_DEBUG, CFSTR("could not send signal: %s"), strerror(errno));
134 status = KERN_FAILURE;
135 }
136 } else {
137 mach_port_type_t pt;
138
139 if ((mach_port_type(mach_task_self(), storePrivate->notifySignalTask, &pt) == KERN_SUCCESS) &&
140 (pt & MACH_PORT_TYPE_DEAD_NAME)) {
141 SCLog(_configd_verbose, LOG_DEBUG, CFSTR("could not send signal, process died"));
142 } else {
143 SCLog(_configd_verbose, LOG_DEBUG, CFSTR("could not send signal: %s"), mach_error_string(status));
144 }
145 }
146
147 if (status != KERN_SUCCESS) {
148 /* don't bother with any more attempts */
149 (void) mach_port_destroy(mach_task_self(), storePrivate->notifySignalTask);
150 storePrivate->notifySignal = 0;
151 storePrivate->notifySignalTask = TASK_NULL;
152 }
153 }
154 }
155 free(sessionsToNotify);
156
157 /*
158 * this list of notifications have been posted, wait for some more.
159 */
160 CFRelease(needsNotification);
161 needsNotification = NULL;
162
163 return;
164 }