]>
Commit | Line | Data |
---|---|---|
5958d7c0 A |
1 | /* |
2 | * Copyright (c) 2000 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 | #include "configd.h" | |
24 | #include "configd_server.h" | |
25 | #include "session.h" | |
26 | ||
27 | SCDStatus | |
28 | _SCDNotifierInformViaSignal(SCDSessionRef session, pid_t pid, int sig) | |
29 | { | |
30 | SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; | |
31 | CFStringRef sessionKey; | |
32 | CFDictionaryRef info; | |
33 | ||
34 | SCDLog(LOG_DEBUG, CFSTR("_SCDNotifierInformViaSignal:")); | |
35 | ||
36 | if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) { | |
37 | return SCD_NOSESSION; /* you must have an open session to play */ | |
38 | } | |
39 | ||
40 | if (sessionPrivate->notifyStatus != NotifierNotRegistered) { | |
41 | /* sorry, you can only have one notification registered at once */ | |
42 | return SCD_NOTIFIERACTIVE; | |
43 | } | |
44 | ||
45 | if ((sig <= 0) || (sig > NSIG)) { | |
46 | /* sorry, you must specify a valid signal */ | |
47 | return SCD_INVALIDARGUMENT; | |
48 | } | |
49 | ||
50 | /* push out a notification if any changes are pending */ | |
51 | sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), sessionPrivate->server); | |
52 | info = CFDictionaryGetValue(sessionData, sessionKey); | |
53 | CFRelease(sessionKey); | |
54 | if (info && CFDictionaryContainsKey(info, kSCDChangedKeys)) { | |
55 | CFNumberRef sessionNum; | |
56 | ||
57 | if (needsNotification == NULL) | |
58 | needsNotification = CFSetCreateMutable(NULL, | |
59 | 0, | |
60 | &kCFTypeSetCallBacks); | |
61 | ||
62 | sessionNum = CFNumberCreate(NULL, kCFNumberIntType, &sessionPrivate->server); | |
63 | CFSetAddValue(needsNotification, sessionNum); | |
64 | CFRelease(sessionNum); | |
65 | } | |
66 | ||
67 | return SCD_OK; | |
68 | } | |
69 | ||
70 | ||
71 | kern_return_t | |
72 | _notifyviasignal(mach_port_t server, | |
73 | task_t task, | |
74 | int sig, | |
75 | int *scd_status) | |
76 | { | |
77 | serverSessionRef mySession = getSession(server); | |
78 | SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)mySession->session; | |
79 | #if defined(DEBUG) || defined(NOTYET) | |
80 | kern_return_t status; | |
81 | #endif | |
82 | #ifdef NOTYET | |
83 | mach_port_t oldNotify; | |
84 | #endif /* NOTYET */ | |
85 | ||
86 | SCDLog(LOG_DEBUG, CFSTR("Send signal when a notification key changes.")); | |
87 | SCDLog(LOG_DEBUG, CFSTR(" server = %d"), server); | |
88 | SCDLog(LOG_DEBUG, CFSTR(" task = %d"), task); | |
89 | SCDLog(LOG_DEBUG, CFSTR(" signal = %d"), sig); | |
90 | ||
91 | *scd_status = _SCDNotifierInformViaSignal(mySession->session, 0, sig); /* pid is N/A for server */ | |
92 | if (*scd_status != SCD_OK) { | |
93 | if (task != TASK_NULL) { | |
94 | (void) mach_port_destroy(mach_task_self(), task); | |
95 | } | |
96 | return KERN_SUCCESS; | |
97 | } | |
98 | ||
99 | #ifdef DEBUG | |
100 | { mach_port_type_t pt; | |
101 | ||
102 | status = mach_port_type(mach_task_self(), task, &pt); | |
103 | if (status == MACH_MSG_SUCCESS) { | |
104 | char rights[8], *rp = &rights[0]; | |
105 | ||
106 | if (pt & MACH_PORT_TYPE_SEND) | |
107 | *rp++ = 'S'; | |
108 | if (pt & MACH_PORT_TYPE_RECEIVE) | |
109 | *rp++ = 'R'; | |
110 | if (pt & MACH_PORT_TYPE_SEND_ONCE) | |
111 | *rp++ = 'O'; | |
112 | if (pt & MACH_PORT_TYPE_PORT_SET) | |
113 | *rp++ = 'P'; | |
114 | if (pt & MACH_PORT_TYPE_DEAD_NAME) | |
115 | *rp++ = 'D'; | |
116 | *rp = '\0'; | |
117 | ||
118 | SCDLog(LOG_DEBUG, CFSTR("Task %d, port rights = %s"), task, rights); | |
119 | } | |
120 | } | |
121 | #endif /* DEBUG */ | |
122 | ||
123 | #ifdef NOTYET | |
124 | /* Request a notification when/if the client dies */ | |
125 | status = mach_port_request_notification(mach_task_self(), | |
126 | task, | |
127 | MACH_NOTIFY_DEAD_NAME, | |
128 | 1, | |
129 | task, | |
130 | MACH_MSG_TYPE_MAKE_SEND_ONCE, | |
131 | &oldNotify); | |
132 | if (status != KERN_SUCCESS) { | |
133 | SCDLog(LOG_DEBUG, CFSTR("mach_port_request_notification(): %s"), mach_error_string(status)); | |
134 | *scd_status = SCD_FAILED; | |
135 | return KERN_SUCCESS; | |
136 | } | |
137 | ||
138 | #ifdef DEBUG | |
139 | if (oldNotify != MACH_PORT_NULL) { | |
140 | SCDLog(LOG_DEBUG, CFSTR("_notifyviasignal(): why is oldNotify != MACH_PORT_NULL?")); | |
141 | } | |
142 | #endif /* DEBUG */ | |
143 | ||
144 | SCDLog(LOG_DEBUG, CFSTR("Adding task notification port %d to the server's port set"), task); | |
145 | status = mach_port_move_member(mach_task_self(), task, server_ports); | |
146 | if (status != KERN_SUCCESS) { | |
147 | SCDLog(LOG_DEBUG, CFSTR("mach_port_move_member(): %s"), mach_error_string(status)); | |
148 | *scd_status = SCD_FAILED; | |
149 | return KERN_SUCCESS; | |
150 | } | |
151 | #endif /* NOTYET */ | |
152 | ||
153 | sessionPrivate->notifyStatus = Using_NotifierInformViaSignal; | |
154 | sessionPrivate->notifySignal = sig; | |
155 | sessionPrivate->notifySignalTask = task; | |
156 | ||
157 | return KERN_SUCCESS; | |
158 | } |