Print this page
5218 posix definition of NULL
correct unistd.h and iso/stddef_iso.h
update gate source affected
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/syseventd/modules/devfsadmd_mod/devfsadmd_mod.c
+++ new/usr/src/cmd/syseventd/modules/devfsadmd_mod/devfsadmd_mod.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
23 23 */
24 24
25 25 #include <unistd.h>
26 26 #include <stdlib.h>
27 27 #include <string.h>
28 28 #include <strings.h>
29 29 #include <limits.h>
30 30 #include <thread.h>
31 31 #include <wait.h>
32 32 #include <synch.h>
33 33 #include <syslog.h>
34 34 #include <libintl.h>
35 35 #include <sys/stat.h>
36 36 #include <sys/sunddi.h>
37 37
38 38 #include <libsysevent.h>
39 39
40 40 #include "sysevent_signal.h"
41 41 #include "../devfsadm/devfsadm.h"
42 42
43 43 /*
44 44 * SLM for devfsadmd device configuration daemon
45 45 */
46 46
47 47 extern char *root_dir;
48 48 extern void syseventd_print();
49 49
50 50 sysevent_handle_t *sysevent_hp;
51 51
52 52 /* Alternate root declarations during install */
53 53 static int use_alt_root = 0;
54 54
55 55 static int devfsadmdeliver_event(sysevent_t *ev, int flag);
56 56
57 57 static struct slm_mod_ops devfsadm_mod_ops = {
58 58 SE_MAJOR_VERSION, SE_MINOR_VERSION, 10, devfsadmdeliver_event};
59 59
60 60 typedef struct ev_queue {
61 61 struct ev_queue *evq_next;
62 62 sysevent_t *evq_ev;
63 63 } ev_queue_t;
64 64
65 65 static mutex_t evq_lock;
66 66 static cond_t evq_cv;
67 67 static ev_queue_t *eventq_head;
68 68 static ev_queue_t *eventq_tail;
69 69
70 70 #define DELIVERY_FAILED \
71 71 gettext("devfsadmd not responding, /dev may not be current")
72 72
73 73 #define DELIVERY_RESUMED \
74 74 gettext("devfsadmd now responding again")
75 75
76 76 /*
77 77 * Retry error recovery when attempting to send an event to devfsadmd
78 78 */
79 79 #define RETRY_DAEMON_RESTART 0
80 80 #define RETRY_MSG_THRESHOLD 60
81 81 #define RETRY_DAEMON_INTERVAL 60
82 82
83 83 static int
84 84 system1(const char *s_path, const char *s)
85 85 {
86 86 struct sigaction cbuf, ibuf, qbuf, ignore, dfl;
87 87 sigset_t mask, savemask;
88 88 struct stat st;
89 89 pid_t pid;
90 90 int status, w;
91 91
92 92 /* Check the requested command */
93 93 if (s == NULL) {
94 94 errno = EINVAL;
95 95 return (-1);
96 96 }
97 97
98 98 /* Check the ability to execute devfsadmd from this process */
99 99 if (stat(s_path, &st) < 0) {
100 100 return (-1);
101 101 }
102 102 if (((geteuid() == st.st_uid) && ((st.st_mode & S_IXUSR) == 0)) ||
103 103 ((getegid() == st.st_gid) && ((st.st_mode & S_IXGRP) == 0)) ||
104 104 ((st.st_mode & S_IXOTH) == 0)) {
105 105 errno = EPERM;
106 106 return (-1);
107 107 }
108 108
109 109 /*
110 110 * Block SIGCHLD and set up a default handler for the duration of the
111 111 * system1 call.
112 112 */
113 113 (void) sigemptyset(&mask);
114 114 (void) sigaddset(&mask, SIGCHLD);
115 115 (void) sigprocmask(SIG_BLOCK, &mask, &savemask);
116 116 (void) memset(&dfl, 0, sizeof (dfl));
117 117 dfl.sa_handler = SIG_DFL;
118 118 (void) sigaction(SIGCHLD, &dfl, &cbuf);
119 119
120 120 /* Fork off the child process (using fork1(), because it's MT-safe) */
121 121 switch (pid = fork1()) {
122 122 case -1:
123 123 /* Error */
124 124 (void) sigaction(SIGCHLD, &cbuf, NULL);
125 125 (void) sigprocmask(SIG_SETMASK, &savemask, NULL);
126 126 return (-1);
127 127 case 0:
128 128 /* Set-up an initial signal mask for the child */
129 129 (void) sigemptyset(&mask);
130 130 (void) sigprocmask(SIG_SETMASK, &mask, NULL);
131 131 closefrom(3);
132 132 (void) execl(s_path, s, (char *)0);
133 133 _exit(-1);
134 134 break;
135 135 default:
136 136 /* Parent */
137 137 break;
138 138 }
139 139
140 140 (void) memset(&ignore, 0, sizeof (ignore));
141 141 ignore.sa_handler = SIG_IGN;
142 142 (void) sigaction(SIGINT, &ignore, &ibuf);
143 143 (void) sigaction(SIGQUIT, &ignore, &qbuf);
144 144
145 145 do {
146 146 w = waitpid(pid, &status, 0);
147 147 } while (w == -1 && errno == EINTR);
148 148
149 149 (void) sigaction(SIGINT, &ibuf, NULL);
150 150 (void) sigaction(SIGQUIT, &qbuf, NULL);
151 151 (void) sigaction(SIGCHLD, &cbuf, NULL);
152 152 (void) sigprocmask(SIG_SETMASK, &savemask, NULL);
153 153
154 154 return ((w == -1)? w: status);
155 155 }
156 156
157 157 /*
158 158 * devfsadmdeliver_event - called by syseventd to deliver an event buffer.
159 159 * The event buffer is subsequently delivered to
160 160 * devfsadmd. If devfsadmd, is not responding to the
161 161 * delivery attempt, we will try to startup the
162 162 * daemon. MT protection is provided by syseventd
163 163 * and the client lock. This insures sequential
164 164 * event delivery and protection from re-entrance.
165 165 */
166 166 /*ARGSUSED*/
167 167 static int
168 168 devfsadmdeliver_event(sysevent_t *ev, int flag)
169 169 {
170 170 int ev_size;
171 171 ev_queue_t *new_evq;
172 172
173 173 /* Not initialized */
174 174 if (sysevent_hp == NULL) {
175 175 return (0);
176 176 }
177 177
178 178 /* Quick return for uninteresting events */
179 179 if (strcmp(sysevent_get_class_name(ev), EC_DEVFS) != 0) {
180 180 return (0);
181 181 }
182 182
183 183 /* Queue event for delivery to devfsadmd */
184 184 new_evq = (ev_queue_t *)calloc(1, sizeof (ev_queue_t));
185 185 if (new_evq == NULL) {
186 186 return (EAGAIN);
187 187 }
188 188
189 189 ev_size = sysevent_get_size(ev);
190 190 new_evq->evq_ev = (sysevent_t *)malloc(ev_size);
191 191 if (new_evq->evq_ev == NULL) {
192 192 free(new_evq);
193 193 return (EAGAIN);
194 194 }
195 195 bcopy(ev, new_evq->evq_ev, ev_size);
196 196
197 197 (void) mutex_lock(&evq_lock);
198 198 if (eventq_head == NULL) {
199 199 eventq_head = new_evq;
200 200 } else {
201 201 eventq_tail->evq_next = new_evq;
202 202 }
203 203 eventq_tail = new_evq;
204 204
205 205 (void) cond_signal(&evq_cv);
206 206 (void) mutex_unlock(&evq_lock);
207 207
208 208 return (0);
209 209 }
210 210
211 211 static int cleanup;
212 212 thread_t deliver_thr_id;
213 213
214 214 void
215 215 devfsadmd_deliver_thr()
216 216 {
217 217 int retry = 0;
218 218 int msg_emitted = 0;
219 219 ev_queue_t *evqp;
220 220
221 221 (void) mutex_lock(&evq_lock);
222 222 for (;;) {
223 223 while (eventq_head == NULL) {
224 224 (void) cond_wait(&evq_cv, &evq_lock);
225 225 if (cleanup && eventq_head == NULL) {
226 226 (void) cond_signal(&evq_cv);
227 227 (void) mutex_unlock(&evq_lock);
228 228 return;
229 229 }
230 230 }
231 231
232 232 /* Send events on to devfsadmd */
233 233 evqp = eventq_head;
234 234 while (evqp) {
235 235 (void) mutex_unlock(&evq_lock);
236 236 retry = 0;
237 237 while (sysevent_send_event(sysevent_hp,
238 238 evqp->evq_ev) != 0) {
239 239 /*
240 240 * Invoke devfsadm to handle node creation
241 241 * but not for an alternate root.
242 242 */
243 243 if (use_alt_root != 0)
244 244 break;
245 245 /*
246 246 * daemon unresponsive -
247 247 * restart daemon and retry once more
248 248 */
249 249 if ((errno == EBADF || errno == ENOENT) &&
250 250 (retry == RETRY_DAEMON_RESTART) ||
251 251 ((retry % RETRY_DAEMON_INTERVAL) == 0)) {
252 252 (void) system1(
253 253 DEVFSADMD_START_PATH,
254 254 DEVFSADMD_START);
255 255 }
256 256 if (retry == RETRY_MSG_THRESHOLD) {
257 257 syslog(LOG_ERR, DELIVERY_FAILED);
258 258 msg_emitted = 1;
259 259 }
260 260 (void) sleep(1);
261 261 ++retry;
262 262 continue;
263 263 }
264 264
265 265 /*
266 266 * Event delivered: remove from queue
267 267 * and reset delivery retry state.
268 268 */
269 269 if (msg_emitted) {
270 270 syslog(LOG_ERR, DELIVERY_RESUMED);
271 271 msg_emitted = 0;
272 272 }
273 273 retry = 0;
274 274 (void) mutex_lock(&evq_lock);
275 275 if (eventq_head != NULL) {
276 276 eventq_head = eventq_head->evq_next;
277 277 if (eventq_head == NULL)
278 278 eventq_tail = NULL;
279 279 }
280 280 free(evqp->evq_ev);
281 281 free(evqp);
282 282 evqp = eventq_head;
283 283 }
284 284 if (cleanup) {
285 285 (void) cond_signal(&evq_cv);
286 286 (void) mutex_unlock(&evq_lock);
287 287 return;
288 288 }
289 289 }
290 290
291 291 /* NOTREACHED */
292 292 }
293 293
294 294 struct slm_mod_ops *
295 295 slm_init()
296 296 {
297 297 char alt_door[MAXPATHLEN];
298 298
299 299 if (strcmp(root_dir, "") == 0) {
300 300 /* Initialize the private sysevent handle */
301 301 sysevent_hp = sysevent_open_channel_alt(DEVFSADM_SERVICE_DOOR);
302 302 } else {
303 303
304 304 /* Try alternate door during install time */
305 305 if (snprintf(alt_door, MAXPATHLEN, "%s%s", "/tmp",
306 306 DEVFSADM_SERVICE_DOOR) >= MAXPATHLEN)
307 307 return (NULL);
308 308
309 309 sysevent_hp = sysevent_open_channel_alt(alt_door);
310 310 use_alt_root = 1;
311 311 }
312 312 if (sysevent_hp == NULL) {
313 313 syseventd_print(0, "Unable to allocate sysevent handle"
314 314 " for devfsadm module\n");
315 315 return (NULL);
316 316 }
317 317
318 318 if (sysevent_bind_publisher(sysevent_hp) != 0) {
319 319 if (errno == EBUSY) {
320 320 sysevent_cleanup_publishers(sysevent_hp);
321 321 if (sysevent_bind_publisher(sysevent_hp) != 0) {
322 322 (void) sysevent_close_channel(sysevent_hp);
323 323 return (NULL);
324 324 }
325 325 }
↓ open down ↓ |
325 lines elided |
↑ open up ↑ |
326 326 }
327 327
328 328 sysevent_cleanup_subscribers(sysevent_hp);
329 329 cleanup = 0;
330 330 eventq_head = NULL;
331 331 eventq_tail = NULL;
332 332
333 333 (void) mutex_init(&evq_lock, USYNC_THREAD, NULL);
334 334 (void) cond_init(&evq_cv, USYNC_THREAD, NULL);
335 335
336 - if (thr_create(NULL, NULL, (void *(*)(void *))devfsadmd_deliver_thr,
336 + if (thr_create(NULL, 0, (void *(*)(void *))devfsadmd_deliver_thr,
337 337 NULL, THR_BOUND, &deliver_thr_id) != 0) {
338 338 (void) mutex_destroy(&evq_lock);
339 339 (void) cond_destroy(&evq_cv);
340 340 sysevent_close_channel(sysevent_hp);
341 341 return (NULL);
342 342 }
343 343
344 344 return (&devfsadm_mod_ops);
345 345 }
346 346
347 347 void
348 348 slm_fini()
349 349 {
350 350 /* Wait for all events to be flushed out to devfsadmd */
351 351 (void) mutex_lock(&evq_lock);
352 352 cleanup = 1;
353 353 (void) cond_signal(&evq_cv);
354 354 (void) cond_wait(&evq_cv, &evq_lock);
355 355 (void) mutex_unlock(&evq_lock);
356 356
357 357 /* Wait for delivery thread to exit */
358 358 (void) thr_join(deliver_thr_id, NULL, NULL);
359 359
360 360 (void) mutex_destroy(&evq_lock);
361 361 (void) cond_destroy(&evq_cv);
362 362
363 363 sysevent_close_channel(sysevent_hp);
364 364 sysevent_hp = NULL;
365 365 }
↓ open down ↓ |
19 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX