]> git.saurik.com Git - apple/configd.git/blob - configd.tproj/session.c
configd-212.2.tar.gz
[apple/configd.git] / configd.tproj / session.c
1 /*
2 * Copyright (c) 2000, 2001, 2003-2005, 2007 Apple 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 /* information maintained for each active session */
39 static serverSessionRef *sessions = NULL;
40 static int nSessions = 0;
41
42
43 __private_extern__
44 serverSessionRef
45 getSession(mach_port_t server)
46 {
47 int i;
48
49 if (server == MACH_PORT_NULL) {
50 SCLog(TRUE, LOG_NOTICE, CFSTR("Excuse me, why is getSession() being called with an invalid port?"));
51 return NULL;
52 }
53
54 for (i = 0; i < nSessions; i++) {
55 serverSessionRef thisSession = sessions[i];
56
57 if (thisSession == NULL) {
58 /* found an empty slot, skip it */
59 continue;
60 } else if (thisSession->key == server) {
61 return thisSession; /* we've seen this server before */
62 } else if (thisSession->store &&
63 (((SCDynamicStorePrivateRef)thisSession->store)->notifySignalTask == server)) {
64 return thisSession;
65 }
66 }
67
68 /* no sessions available */
69 return NULL;
70 }
71
72
73 __private_extern__
74 serverSessionRef
75 addSession(mach_port_t server, CFStringRef (*copyDescription)(const void *info))
76 {
77 CFMachPortContext context = { 0, NULL, NULL, NULL, NULL };
78 int n = -1;
79
80 if (nSessions <= 0) {
81 /* new session (actually, the first) found */
82 sessions = malloc(sizeof(serverSessionRef));
83 n = 0;
84 nSessions = 1;
85 } else {
86 int i;
87
88 for (i = 0; i < nSessions; i++) {
89 if (sessions[i] == NULL) {
90 /* found an empty slot, use it */
91 n = i;
92 break;
93 }
94 }
95 /* new session identified */
96 if (n < 0) {
97 /* no empty slots, add one to the list */
98 n = nSessions++;
99 sessions = reallocf(sessions, ((nSessions) * sizeof(serverSessionRef)));
100 }
101 }
102
103 // allocate a new session for this server
104 sessions[n] = malloc(sizeof(serverSession));
105 bzero(sessions[n], sizeof(serverSession));
106
107 // create server port
108 context.info = sessions[n];
109 context.copyDescription = copyDescription;
110
111 if (server == MACH_PORT_NULL) {
112 // SCDynamicStore client ports
113 (void) mach_port_allocate(mach_task_self(),
114 MACH_PORT_RIGHT_RECEIVE,
115 &server);
116 (void) mach_port_insert_right(mach_task_self(),
117 server,
118 server,
119 MACH_MSG_TYPE_MAKE_SEND);
120 }
121 sessions[n]->key = server;
122 sessions[n]->serverPort = CFMachPortCreateWithPort(NULL,
123 server,
124 configdCallback,
125 &context,
126 NULL);
127 // sessions[n]->serverRunLoopSource = NULL;
128 // sessions[n]->store = NULL;
129 sessions[n]->callerEUID = 1; /* not "root" */
130
131 return sessions[n];
132 }
133
134
135 __private_extern__
136 void
137 removeSession(mach_port_t server)
138 {
139 int i;
140 serverSessionRef thisSession;
141 CFStringRef sessionKey;
142
143 for (i = 0; i < nSessions; i++) {
144 thisSession = sessions[i];
145
146 if (thisSession == NULL) {
147 /* found an empty slot, skip it */
148 continue;
149 } else if (thisSession->key == server) {
150 /*
151 * We don't need any remaining information in the
152 * sessionData dictionary, remove it.
153 */
154 sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), server);
155 CFDictionaryRemoveValue(sessionData, sessionKey);
156 CFRelease(sessionKey);
157
158 /*
159 * Lastly, get rid of the per-session structure.
160 */
161 free(thisSession);
162 sessions[i] = NULL;
163
164 return;
165 }
166 }
167
168 return;
169 }
170
171
172 __private_extern__
173 void
174 cleanupSession(mach_port_t server)
175 {
176 int i;
177
178 for (i = 0; i < nSessions; i++) {
179 serverSessionRef thisSession = sessions[i];
180
181 if ((thisSession != NULL) && (thisSession->key == server)) {
182 /*
183 * session entry still exists.
184 */
185
186 if (_configd_trace) {
187 SCTrace(TRUE, _configd_trace, CFSTR("cleanup : %5d\n"), server);
188 }
189
190 /*
191 * Ensure that any changes made while we held the "lock"
192 * are discarded.
193 */
194 if ((storeLocked > 0) &&
195 ((SCDynamicStorePrivateRef)thisSession->store)->locked) {
196 /*
197 * swap store and associated data which, after
198 * being closed, will result in the restoration
199 * of the original pre-"locked" data.
200 */
201 _swapLockedStoreData();
202 }
203
204 /*
205 * Close any open connections including cancelling any outstanding
206 * notification requests and releasing any locks.
207 */
208 (void) __SCDynamicStoreClose(&thisSession->store, TRUE);
209
210 /*
211 * Our send right has already been removed. Remove our
212 * receive right.
213 */
214 mach_port_mod_refs(mach_task_self(),
215 thisSession->key,
216 MACH_PORT_RIGHT_RECEIVE,
217 -1);
218
219 /*
220 * Lastly, remove the session entry.
221 */
222 removeSession(server);
223
224 return;
225 }
226 }
227 return;
228 }
229
230
231 __private_extern__
232 void
233 listSessions()
234 {
235 int i;
236
237 fprintf(stderr, "Current sessions:");
238 for (i = 0; i < nSessions; i++) {
239 serverSessionRef thisSession = sessions[i];
240
241 if (thisSession == NULL) {
242 continue;
243 }
244
245 fprintf(stderr, " %d", thisSession->key);
246
247 if (thisSession->store) {
248 task_t task = ((SCDynamicStorePrivateRef)thisSession->store)->notifySignalTask;
249
250 if (task != TASK_NULL) {
251 fprintf(stderr, "/%d", task);
252 }
253 }
254 }
255 fprintf(stderr, "\n");
256 }
257