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