]> git.saurik.com Git - apple/configd.git/blob - configd.tproj/_notifyviasignal.c
configd-84.6.tar.gz
[apple/configd.git] / configd.tproj / _notifyviasignal.c
1 /*
2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 /*
25 * Modification History
26 *
27 * June 1, 2001 Allan Nathanson <ajn@apple.com>
28 * - public API conversion
29 *
30 * March 24, 2000 Allan Nathanson <ajn@apple.com>
31 * - initial revision
32 */
33
34 #include "configd.h"
35 #include "configd_server.h"
36 #include "session.h"
37
38 __private_extern__
39 int
40 __SCDynamicStoreNotifySignal(SCDynamicStoreRef store, pid_t pid, int sig)
41 {
42 SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
43 CFStringRef sessionKey;
44 CFDictionaryRef info;
45
46 SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreNotifySignal:"));
47
48 if (!store || (storePrivate->server == MACH_PORT_NULL)) {
49 return kSCStatusNoStoreSession; /* you must have an open session to play */
50 }
51
52 if (storePrivate->notifyStatus != NotifierNotRegistered) {
53 /* sorry, you can only have one notification registered at once */
54 return kSCStatusNotifierActive;
55 }
56
57 if (pid == getpid()) {
58 /* sorry, you can't request that configd be signalled */
59 return kSCStatusInvalidArgument;
60 }
61
62 if ((sig <= 0) || (sig > NSIG)) {
63 /* sorry, you must specify a valid signal */
64 return kSCStatusInvalidArgument;
65 }
66
67 /* push out a notification if any changes are pending */
68 sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), storePrivate->server);
69 info = CFDictionaryGetValue(sessionData, sessionKey);
70 CFRelease(sessionKey);
71 if (info && CFDictionaryContainsKey(info, kSCDChangedKeys)) {
72 CFNumberRef sessionNum;
73
74 if (needsNotification == NULL)
75 needsNotification = CFSetCreateMutable(NULL,
76 0,
77 &kCFTypeSetCallBacks);
78
79 sessionNum = CFNumberCreate(NULL, kCFNumberIntType, &storePrivate->server);
80 CFSetAddValue(needsNotification, sessionNum);
81 CFRelease(sessionNum);
82 }
83
84 return kSCStatusOK;
85 }
86
87
88 __private_extern__
89 kern_return_t
90 _notifyviasignal(mach_port_t server,
91 task_t task,
92 int sig,
93 int *sc_status)
94 {
95 serverSessionRef mySession = getSession(server);
96 pid_t pid;
97 kern_return_t status;
98 SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)mySession->store;
99 #ifdef NOTYET
100 mach_port_t oldNotify;
101 #endif /* NOTYET */
102
103 if (_configd_verbose) {
104 SCLog(TRUE, LOG_DEBUG, CFSTR("Send signal when a notification key changes."));
105 SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server);
106 SCLog(TRUE, LOG_DEBUG, CFSTR(" task = %d"), task);
107 SCLog(TRUE, LOG_DEBUG, CFSTR(" signal = %d"), sig);
108 }
109
110 status = pid_for_task(task, &pid);
111 if (status != KERN_SUCCESS) {
112 *sc_status = kSCStatusFailed; /* could not determine pid for task */
113 return KERN_SUCCESS;
114 }
115
116 if (!mySession) {
117 *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
118 return KERN_SUCCESS;
119 }
120
121 *sc_status = __SCDynamicStoreNotifySignal(mySession->store, pid, sig);
122 if (*sc_status != kSCStatusOK) {
123 if (task != TASK_NULL) {
124 (void) mach_port_destroy(mach_task_self(), task);
125 }
126 return KERN_SUCCESS;
127 }
128
129 #ifdef DEBUG
130 { mach_port_type_t pt;
131
132 status = mach_port_type(mach_task_self(), task, &pt);
133 if (status == MACH_MSG_SUCCESS) {
134 char rights[8], *rp = &rights[0];
135
136 if (pt & MACH_PORT_TYPE_SEND)
137 *rp++ = 'S';
138 if (pt & MACH_PORT_TYPE_RECEIVE)
139 *rp++ = 'R';
140 if (pt & MACH_PORT_TYPE_SEND_ONCE)
141 *rp++ = 'O';
142 if (pt & MACH_PORT_TYPE_PORT_SET)
143 *rp++ = 'P';
144 if (pt & MACH_PORT_TYPE_DEAD_NAME)
145 *rp++ = 'D';
146 *rp = '\0';
147
148 SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Task %d, port rights = %s"), task, rights);
149 }
150 }
151 #endif /* DEBUG */
152
153 #ifdef NOTYET
154 /* Request a notification when/if the client dies */
155 status = mach_port_request_notification(mach_task_self(),
156 task,
157 MACH_NOTIFY_DEAD_NAME,
158 1,
159 task,
160 MACH_MSG_TYPE_MAKE_SEND_ONCE,
161 &oldNotify);
162 if (status != KERN_SUCCESS) {
163 SCLog(_configd_verbose, LOG_DEBUG, CFSTR("mach_port_request_notification(): %s"), mach_error_string(status));
164 *sc_status = kSCStatusFailed;
165 return KERN_SUCCESS;
166 }
167
168 if (oldNotify != MACH_PORT_NULL) {
169 SCLog(_configd_verbose, LOG_ERR, CFSTR("_notifyviasignal(): why is oldNotify != MACH_PORT_NULL?"));
170 }
171
172 SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Adding task notification port %d to the server's port set"), task);
173 status = mach_port_move_member(mach_task_self(), task, server_ports);
174 if (status != KERN_SUCCESS) {
175 SCLog(_configd_verbose, LOG_DEBUG, CFSTR("mach_port_move_member(): %s"), mach_error_string(status));
176 *sc_status = kSCStatusFailed;
177 return KERN_SUCCESS;
178 }
179 #endif /* NOTYET */
180
181 storePrivate->notifyStatus = Using_NotifierInformViaSignal;
182 storePrivate->notifySignal = sig;
183 storePrivate->notifySignalTask = task;
184
185 return KERN_SUCCESS;
186 }