]> git.saurik.com Git - apple/configd.git/blob - configd.tproj/_notifyviasignal.c
configd-53.tar.gz
[apple/configd.git] / configd.tproj / _notifyviasignal.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 24, 2000 Allan Nathanson <ajn@apple.com>
30 * - initial revision
31 */
32
33 #include "configd.h"
34 #include "configd_server.h"
35 #include "session.h"
36
37 int
38 __SCDynamicStoreNotifySignal(SCDynamicStoreRef store, pid_t pid, int sig)
39 {
40 SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
41 CFStringRef sessionKey;
42 CFDictionaryRef info;
43
44 SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreNotifySignal:"));
45
46 if (!store || (storePrivate->server == MACH_PORT_NULL)) {
47 return kSCStatusNoStoreSession; /* you must have an open session to play */
48 }
49
50 if (storePrivate->notifyStatus != NotifierNotRegistered) {
51 /* sorry, you can only have one notification registered at once */
52 return kSCStatusNotifierActive;
53 }
54
55 if (pid == getpid()) {
56 /* sorry, you can't request that configd be signalled */
57 return kSCStatusInvalidArgument;
58 }
59
60 if ((sig <= 0) || (sig > NSIG)) {
61 /* sorry, you must specify a valid signal */
62 return kSCStatusInvalidArgument;
63 }
64
65 /* push out a notification if any changes are pending */
66 sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), storePrivate->server);
67 info = CFDictionaryGetValue(sessionData, sessionKey);
68 CFRelease(sessionKey);
69 if (info && CFDictionaryContainsKey(info, kSCDChangedKeys)) {
70 CFNumberRef sessionNum;
71
72 if (needsNotification == NULL)
73 needsNotification = CFSetCreateMutable(NULL,
74 0,
75 &kCFTypeSetCallBacks);
76
77 sessionNum = CFNumberCreate(NULL, kCFNumberIntType, &storePrivate->server);
78 CFSetAddValue(needsNotification, sessionNum);
79 CFRelease(sessionNum);
80 }
81
82 return kSCStatusOK;
83 }
84
85
86 kern_return_t
87 _notifyviasignal(mach_port_t server,
88 task_t task,
89 int sig,
90 int *sc_status)
91 {
92 serverSessionRef mySession = getSession(server);
93 pid_t pid;
94 kern_return_t status;
95 SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)mySession->store;
96 #ifdef NOTYET
97 mach_port_t oldNotify;
98 #endif /* NOTYET */
99
100 SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Send signal when a notification key changes."));
101 SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server);
102 SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" task = %d"), task);
103 SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" signal = %d"), sig);
104
105 status = pid_for_task(task, &pid);
106 if (status != KERN_SUCCESS) {
107 /* could not determine pid for task */
108 *sc_status = kSCStatusFailed;
109 return KERN_SUCCESS;
110 }
111
112 *sc_status = __SCDynamicStoreNotifySignal(mySession->store, pid, sig);
113 if (*sc_status != kSCStatusOK) {
114 if (task != TASK_NULL) {
115 (void) mach_port_destroy(mach_task_self(), task);
116 }
117 return KERN_SUCCESS;
118 }
119
120 #ifdef DEBUG
121 { mach_port_type_t pt;
122
123 status = mach_port_type(mach_task_self(), task, &pt);
124 if (status == MACH_MSG_SUCCESS) {
125 char rights[8], *rp = &rights[0];
126
127 if (pt & MACH_PORT_TYPE_SEND)
128 *rp++ = 'S';
129 if (pt & MACH_PORT_TYPE_RECEIVE)
130 *rp++ = 'R';
131 if (pt & MACH_PORT_TYPE_SEND_ONCE)
132 *rp++ = 'O';
133 if (pt & MACH_PORT_TYPE_PORT_SET)
134 *rp++ = 'P';
135 if (pt & MACH_PORT_TYPE_DEAD_NAME)
136 *rp++ = 'D';
137 *rp = '\0';
138
139 SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Task %d, port rights = %s"), task, rights);
140 }
141 }
142 #endif /* DEBUG */
143
144 #ifdef NOTYET
145 /* Request a notification when/if the client dies */
146 status = mach_port_request_notification(mach_task_self(),
147 task,
148 MACH_NOTIFY_DEAD_NAME,
149 1,
150 task,
151 MACH_MSG_TYPE_MAKE_SEND_ONCE,
152 &oldNotify);
153 if (status != KERN_SUCCESS) {
154 SCLog(_configd_verbose, LOG_DEBUG, CFSTR("mach_port_request_notification(): %s"), mach_error_string(status));
155 *sc_status = kSCStatusFailed;
156 return KERN_SUCCESS;
157 }
158
159 if (oldNotify != MACH_PORT_NULL) {
160 SCLog(_configd_verbose, LOG_ERR, CFSTR("_notifyviasignal(): why is oldNotify != MACH_PORT_NULL?"));
161 }
162
163 SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Adding task notification port %d to the server's port set"), task);
164 status = mach_port_move_member(mach_task_self(), task, server_ports);
165 if (status != KERN_SUCCESS) {
166 SCLog(_configd_verbose, LOG_DEBUG, CFSTR("mach_port_move_member(): %s"), mach_error_string(status));
167 *sc_status = kSCStatusFailed;
168 return KERN_SUCCESS;
169 }
170 #endif /* NOTYET */
171
172 storePrivate->notifyStatus = Using_NotifierInformViaSignal;
173 storePrivate->notifySignal = sig;
174 storePrivate->notifySignalTask = task;
175
176 return KERN_SUCCESS;
177 }