1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate * CDDL HEADER START
3*0Sstevel@tonic-gate *
4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
7*0Sstevel@tonic-gate * with the License.
8*0Sstevel@tonic-gate *
9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate * and limitations under the License.
13*0Sstevel@tonic-gate *
14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate *
20*0Sstevel@tonic-gate * CDDL HEADER END
21*0Sstevel@tonic-gate */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24*0Sstevel@tonic-gate * Use is subject to license terms.
25*0Sstevel@tonic-gate */
26*0Sstevel@tonic-gate
27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
28*0Sstevel@tonic-gate
29*0Sstevel@tonic-gate #include <stdlib.h>
30*0Sstevel@tonic-gate #include <errno.h>
31*0Sstevel@tonic-gate #include <sys/types.h>
32*0Sstevel@tonic-gate #include <sys/stropts.h> /* INFTIM */
33*0Sstevel@tonic-gate
34*0Sstevel@tonic-gate #include <libinetutil.h>
35*0Sstevel@tonic-gate #include "libinetutil_impl.h"
36*0Sstevel@tonic-gate
37*0Sstevel@tonic-gate static int grow_fds(iu_eh_t *, int);
38*0Sstevel@tonic-gate
39*0Sstevel@tonic-gate /*
40*0Sstevel@tonic-gate * signal_to_eh[] is pretty much useless, since the event handler is
41*0Sstevel@tonic-gate * really a singleton (we pass iu_eh_t *'s around to maintain an
42*0Sstevel@tonic-gate * abstraction, not to allow multiple event handlers to exist). we
43*0Sstevel@tonic-gate * need some way to get back our event handler in post_signal(),
44*0Sstevel@tonic-gate * and since the signal model is too lame to provide opaque pointers,
45*0Sstevel@tonic-gate * we have to resort to global variables.
46*0Sstevel@tonic-gate */
47*0Sstevel@tonic-gate
48*0Sstevel@tonic-gate static iu_eh_t *signal_to_eh[NSIG];
49*0Sstevel@tonic-gate
50*0Sstevel@tonic-gate /*
51*0Sstevel@tonic-gate * iu_eh_create(): creates, initializes, and returns an event handler for use
52*0Sstevel@tonic-gate *
53*0Sstevel@tonic-gate * input: void
54*0Sstevel@tonic-gate * output: iu_eh_t *: the new event handler
55*0Sstevel@tonic-gate */
56*0Sstevel@tonic-gate
57*0Sstevel@tonic-gate iu_eh_t *
iu_eh_create(void)58*0Sstevel@tonic-gate iu_eh_create(void)
59*0Sstevel@tonic-gate {
60*0Sstevel@tonic-gate iu_eh_t *eh = malloc(sizeof (iu_eh_t));
61*0Sstevel@tonic-gate int sig;
62*0Sstevel@tonic-gate
63*0Sstevel@tonic-gate if (eh == NULL)
64*0Sstevel@tonic-gate return (NULL);
65*0Sstevel@tonic-gate
66*0Sstevel@tonic-gate eh->iueh_pollfds = NULL;
67*0Sstevel@tonic-gate eh->iueh_events = NULL;
68*0Sstevel@tonic-gate eh->iueh_shutdown = NULL;
69*0Sstevel@tonic-gate eh->iueh_num_fds = 0;
70*0Sstevel@tonic-gate eh->iueh_stop = B_FALSE;
71*0Sstevel@tonic-gate eh->iueh_reason = 0;
72*0Sstevel@tonic-gate eh->iueh_shutdown_arg = NULL;
73*0Sstevel@tonic-gate
74*0Sstevel@tonic-gate (void) sigemptyset(&eh->iueh_sig_regset);
75*0Sstevel@tonic-gate for (sig = 0; sig < NSIG; sig++) {
76*0Sstevel@tonic-gate eh->iueh_sig_info[sig].iues_pending = B_FALSE;
77*0Sstevel@tonic-gate eh->iueh_sig_info[sig].iues_handler = NULL;
78*0Sstevel@tonic-gate eh->iueh_sig_info[sig].iues_data = NULL;
79*0Sstevel@tonic-gate }
80*0Sstevel@tonic-gate
81*0Sstevel@tonic-gate return (eh);
82*0Sstevel@tonic-gate }
83*0Sstevel@tonic-gate
84*0Sstevel@tonic-gate /*
85*0Sstevel@tonic-gate * iu_eh_destroy(): destroys an existing event handler
86*0Sstevel@tonic-gate *
87*0Sstevel@tonic-gate * input: iu_eh_t *: the event handler to destroy
88*0Sstevel@tonic-gate * output: void
89*0Sstevel@tonic-gate * notes: it is assumed all events related to this eh have been unregistered
90*0Sstevel@tonic-gate * prior to calling iu_eh_destroy()
91*0Sstevel@tonic-gate */
92*0Sstevel@tonic-gate
93*0Sstevel@tonic-gate void
iu_eh_destroy(iu_eh_t * eh)94*0Sstevel@tonic-gate iu_eh_destroy(iu_eh_t *eh)
95*0Sstevel@tonic-gate {
96*0Sstevel@tonic-gate int sig;
97*0Sstevel@tonic-gate
98*0Sstevel@tonic-gate for (sig = 0; sig < NSIG; sig++)
99*0Sstevel@tonic-gate if (signal_to_eh[sig] == eh)
100*0Sstevel@tonic-gate (void) iu_eh_unregister_signal(eh, sig, NULL);
101*0Sstevel@tonic-gate
102*0Sstevel@tonic-gate free(eh->iueh_pollfds);
103*0Sstevel@tonic-gate free(eh->iueh_events);
104*0Sstevel@tonic-gate free(eh);
105*0Sstevel@tonic-gate }
106*0Sstevel@tonic-gate
107*0Sstevel@tonic-gate /*
108*0Sstevel@tonic-gate * iu_stop_handling_events(): informs the event handler to stop handling events
109*0Sstevel@tonic-gate *
110*0Sstevel@tonic-gate * input: iu_eh_t *: the event handler to stop.
111*0Sstevel@tonic-gate * unsigned int: the (user-defined) reason why
112*0Sstevel@tonic-gate * iu_eh_shutdown_t *: the shutdown callback. if it is NULL,
113*0Sstevel@tonic-gate * the event handler will stop right away;
114*0Sstevel@tonic-gate * otherwise, the event handler will not
115*0Sstevel@tonic-gate * stop until the callback returns B_TRUE
116*0Sstevel@tonic-gate * void *: data for the shutdown callback. it may be NULL
117*0Sstevel@tonic-gate * output: void
118*0Sstevel@tonic-gate * notes: the event handler in question must be in iu_handle_events()
119*0Sstevel@tonic-gate */
120*0Sstevel@tonic-gate
121*0Sstevel@tonic-gate void
iu_stop_handling_events(iu_eh_t * eh,unsigned int reason,iu_eh_shutdown_t * shutdown,void * arg)122*0Sstevel@tonic-gate iu_stop_handling_events(iu_eh_t *eh, unsigned int reason,
123*0Sstevel@tonic-gate iu_eh_shutdown_t *shutdown, void *arg)
124*0Sstevel@tonic-gate {
125*0Sstevel@tonic-gate eh->iueh_stop = B_TRUE;
126*0Sstevel@tonic-gate eh->iueh_reason = reason;
127*0Sstevel@tonic-gate eh->iueh_shutdown = shutdown;
128*0Sstevel@tonic-gate eh->iueh_shutdown_arg = arg;
129*0Sstevel@tonic-gate }
130*0Sstevel@tonic-gate
131*0Sstevel@tonic-gate /*
132*0Sstevel@tonic-gate * grow_fds(): grows the internal file descriptor set used by the event
133*0Sstevel@tonic-gate * handler
134*0Sstevel@tonic-gate *
135*0Sstevel@tonic-gate * input: iu_eh_t *: the event handler whose descriptor set needs to be grown
136*0Sstevel@tonic-gate * int: the new total number of descriptors needed in the set
137*0Sstevel@tonic-gate * output: int: zero on failure, success otherwise
138*0Sstevel@tonic-gate */
139*0Sstevel@tonic-gate
140*0Sstevel@tonic-gate static int
grow_fds(iu_eh_t * eh,int total_fds)141*0Sstevel@tonic-gate grow_fds(iu_eh_t *eh, int total_fds)
142*0Sstevel@tonic-gate {
143*0Sstevel@tonic-gate unsigned int i;
144*0Sstevel@tonic-gate struct pollfd *new_pollfds;
145*0Sstevel@tonic-gate iu_event_node_t *new_events;
146*0Sstevel@tonic-gate
147*0Sstevel@tonic-gate if (total_fds <= eh->iueh_num_fds)
148*0Sstevel@tonic-gate return (1);
149*0Sstevel@tonic-gate
150*0Sstevel@tonic-gate new_pollfds = realloc(eh->iueh_pollfds,
151*0Sstevel@tonic-gate total_fds * sizeof (struct pollfd));
152*0Sstevel@tonic-gate if (new_pollfds == NULL)
153*0Sstevel@tonic-gate return (0);
154*0Sstevel@tonic-gate
155*0Sstevel@tonic-gate eh->iueh_pollfds = new_pollfds;
156*0Sstevel@tonic-gate
157*0Sstevel@tonic-gate new_events = realloc(eh->iueh_events,
158*0Sstevel@tonic-gate total_fds * sizeof (iu_event_node_t));
159*0Sstevel@tonic-gate if (new_events == NULL) {
160*0Sstevel@tonic-gate
161*0Sstevel@tonic-gate /*
162*0Sstevel@tonic-gate * yow. one realloc failed, but the other succeeded.
163*0Sstevel@tonic-gate * we will just leave the descriptor size at the
164*0Sstevel@tonic-gate * original size. if the caller tries again, then the
165*0Sstevel@tonic-gate * first realloc() will do nothing since the requested
166*0Sstevel@tonic-gate * number of descriptors is already allocated.
167*0Sstevel@tonic-gate */
168*0Sstevel@tonic-gate
169*0Sstevel@tonic-gate return (0);
170*0Sstevel@tonic-gate }
171*0Sstevel@tonic-gate
172*0Sstevel@tonic-gate for (i = eh->iueh_num_fds; i < total_fds; i++)
173*0Sstevel@tonic-gate eh->iueh_pollfds[i].fd = -1;
174*0Sstevel@tonic-gate
175*0Sstevel@tonic-gate eh->iueh_events = new_events;
176*0Sstevel@tonic-gate eh->iueh_num_fds = total_fds;
177*0Sstevel@tonic-gate return (1);
178*0Sstevel@tonic-gate }
179*0Sstevel@tonic-gate
180*0Sstevel@tonic-gate /*
181*0Sstevel@tonic-gate * when increasing the file descriptor set size, how much to increase by:
182*0Sstevel@tonic-gate */
183*0Sstevel@tonic-gate
184*0Sstevel@tonic-gate #define EH_FD_SLACK 10
185*0Sstevel@tonic-gate
186*0Sstevel@tonic-gate /*
187*0Sstevel@tonic-gate * iu_register_event(): adds an event to the set managed by an event handler
188*0Sstevel@tonic-gate *
189*0Sstevel@tonic-gate * input: iu_eh_t *: the event handler to add the event to
190*0Sstevel@tonic-gate * int: the descriptor on which to listen for events. must be
191*0Sstevel@tonic-gate * a descriptor which has not yet been registered.
192*0Sstevel@tonic-gate * short: the events to listen for on that descriptor
193*0Sstevel@tonic-gate * iu_eh_callback_t: the callback to execute when the event happens
194*0Sstevel@tonic-gate * void *: the argument to pass to the callback function
195*0Sstevel@tonic-gate * output: iu_event_id_t: -1 on failure, the new event id otherwise
196*0Sstevel@tonic-gate */
197*0Sstevel@tonic-gate
198*0Sstevel@tonic-gate iu_event_id_t
iu_register_event(iu_eh_t * eh,int fd,short events,iu_eh_callback_t * callback,void * arg)199*0Sstevel@tonic-gate iu_register_event(iu_eh_t *eh, int fd, short events, iu_eh_callback_t *callback,
200*0Sstevel@tonic-gate void *arg)
201*0Sstevel@tonic-gate {
202*0Sstevel@tonic-gate if (eh->iueh_num_fds <= fd)
203*0Sstevel@tonic-gate if (grow_fds(eh, fd + EH_FD_SLACK) == 0)
204*0Sstevel@tonic-gate return (-1);
205*0Sstevel@tonic-gate
206*0Sstevel@tonic-gate /*
207*0Sstevel@tonic-gate * the current implementation uses the file descriptor itself
208*0Sstevel@tonic-gate * as the iu_event_id_t, since we know the kernel's gonna be
209*0Sstevel@tonic-gate * pretty smart about managing file descriptors and we know
210*0Sstevel@tonic-gate * that they're per-process unique. however, it does mean
211*0Sstevel@tonic-gate * that the same descriptor cannot be registered multiple
212*0Sstevel@tonic-gate * times for different callbacks depending on its events. if
213*0Sstevel@tonic-gate * this behavior is desired, either use dup(2) to get a unique
214*0Sstevel@tonic-gate * descriptor, or demultiplex in the callback function based
215*0Sstevel@tonic-gate * on `events'.
216*0Sstevel@tonic-gate */
217*0Sstevel@tonic-gate
218*0Sstevel@tonic-gate if (eh->iueh_pollfds[fd].fd != -1)
219*0Sstevel@tonic-gate return (-1);
220*0Sstevel@tonic-gate
221*0Sstevel@tonic-gate eh->iueh_pollfds[fd].fd = fd;
222*0Sstevel@tonic-gate eh->iueh_pollfds[fd].events = events;
223*0Sstevel@tonic-gate eh->iueh_events[fd].iuen_callback = callback;
224*0Sstevel@tonic-gate eh->iueh_events[fd].iuen_arg = arg;
225*0Sstevel@tonic-gate
226*0Sstevel@tonic-gate return (fd);
227*0Sstevel@tonic-gate }
228*0Sstevel@tonic-gate
229*0Sstevel@tonic-gate /*
230*0Sstevel@tonic-gate * iu_unregister_event(): removes an event from the set managed by an event
231*0Sstevel@tonic-gate * handler
232*0Sstevel@tonic-gate *
233*0Sstevel@tonic-gate * input: iu_eh_t *: the event handler to remove the event from
234*0Sstevel@tonic-gate * iu_event_id_t: the event to remove (from iu_register_event())
235*0Sstevel@tonic-gate * void **: if non-NULL, will be set to point to the argument passed
236*0Sstevel@tonic-gate * into iu_register_event()
237*0Sstevel@tonic-gate * output: int: zero on failure, success otherwise
238*0Sstevel@tonic-gate */
239*0Sstevel@tonic-gate
240*0Sstevel@tonic-gate int
iu_unregister_event(iu_eh_t * eh,iu_event_id_t event_id,void ** arg)241*0Sstevel@tonic-gate iu_unregister_event(iu_eh_t *eh, iu_event_id_t event_id, void **arg)
242*0Sstevel@tonic-gate {
243*0Sstevel@tonic-gate if (event_id < 0 || event_id >= eh->iueh_num_fds ||
244*0Sstevel@tonic-gate eh->iueh_pollfds[event_id].fd == -1)
245*0Sstevel@tonic-gate return (0);
246*0Sstevel@tonic-gate
247*0Sstevel@tonic-gate /*
248*0Sstevel@tonic-gate * fringe condition: in case this event was about to be called
249*0Sstevel@tonic-gate * back in iu_handle_events(), zero revents to prevent it.
250*0Sstevel@tonic-gate * (having an unregistered event get called back could be
251*0Sstevel@tonic-gate * disastrous depending on if `arg' is reference counted).
252*0Sstevel@tonic-gate */
253*0Sstevel@tonic-gate
254*0Sstevel@tonic-gate eh->iueh_pollfds[event_id].revents = 0;
255*0Sstevel@tonic-gate eh->iueh_pollfds[event_id].fd = -1;
256*0Sstevel@tonic-gate if (arg != NULL)
257*0Sstevel@tonic-gate *arg = eh->iueh_events[event_id].iuen_arg;
258*0Sstevel@tonic-gate
259*0Sstevel@tonic-gate return (1);
260*0Sstevel@tonic-gate }
261*0Sstevel@tonic-gate
262*0Sstevel@tonic-gate /*
263*0Sstevel@tonic-gate * iu_handle_events(): begins handling events on an event handler
264*0Sstevel@tonic-gate *
265*0Sstevel@tonic-gate * input: iu_eh_t *: the event handler to begin event handling on
266*0Sstevel@tonic-gate * tq_t *: a timer queue of timers to process while handling events
267*0Sstevel@tonic-gate * (see timer_queue.h for details)
268*0Sstevel@tonic-gate * output: int: the reason why we stopped, -1 if due to internal failure
269*0Sstevel@tonic-gate */
270*0Sstevel@tonic-gate
271*0Sstevel@tonic-gate int
iu_handle_events(iu_eh_t * eh,iu_tq_t * tq)272*0Sstevel@tonic-gate iu_handle_events(iu_eh_t *eh, iu_tq_t *tq)
273*0Sstevel@tonic-gate {
274*0Sstevel@tonic-gate int n_lit, timeout, sig, saved_errno;
275*0Sstevel@tonic-gate unsigned int i;
276*0Sstevel@tonic-gate sigset_t oset;
277*0Sstevel@tonic-gate
278*0Sstevel@tonic-gate eh->iueh_stop = B_FALSE;
279*0Sstevel@tonic-gate do {
280*0Sstevel@tonic-gate timeout = tq ? iu_earliest_timer(tq) : INFTIM;
281*0Sstevel@tonic-gate
282*0Sstevel@tonic-gate /*
283*0Sstevel@tonic-gate * we only unblock registered signals around poll(); this
284*0Sstevel@tonic-gate * way other parts of the code don't have to worry about
285*0Sstevel@tonic-gate * restarting "non-restartable" system calls and so forth.
286*0Sstevel@tonic-gate */
287*0Sstevel@tonic-gate
288*0Sstevel@tonic-gate (void) sigprocmask(SIG_UNBLOCK, &eh->iueh_sig_regset, &oset);
289*0Sstevel@tonic-gate n_lit = poll(eh->iueh_pollfds, eh->iueh_num_fds, timeout);
290*0Sstevel@tonic-gate saved_errno = errno;
291*0Sstevel@tonic-gate (void) sigprocmask(SIG_SETMASK, &oset, NULL);
292*0Sstevel@tonic-gate
293*0Sstevel@tonic-gate switch (n_lit) {
294*0Sstevel@tonic-gate
295*0Sstevel@tonic-gate case -1:
296*0Sstevel@tonic-gate if (saved_errno != EINTR)
297*0Sstevel@tonic-gate return (-1);
298*0Sstevel@tonic-gate
299*0Sstevel@tonic-gate for (sig = 0; sig < NSIG; sig++) {
300*0Sstevel@tonic-gate if (eh->iueh_sig_info[sig].iues_pending) {
301*0Sstevel@tonic-gate eh->iueh_sig_info[sig].iues_pending =
302*0Sstevel@tonic-gate B_FALSE;
303*0Sstevel@tonic-gate eh->iueh_sig_info[sig].iues_handler(eh,
304*0Sstevel@tonic-gate sig,
305*0Sstevel@tonic-gate eh->iueh_sig_info[sig].iues_data);
306*0Sstevel@tonic-gate }
307*0Sstevel@tonic-gate }
308*0Sstevel@tonic-gate
309*0Sstevel@tonic-gate if (eh->iueh_shutdown != NULL)
310*0Sstevel@tonic-gate break;
311*0Sstevel@tonic-gate
312*0Sstevel@tonic-gate continue;
313*0Sstevel@tonic-gate
314*0Sstevel@tonic-gate case 0:
315*0Sstevel@tonic-gate /*
316*0Sstevel@tonic-gate * timeout occurred. we must have a valid tq pointer
317*0Sstevel@tonic-gate * since that's the only way a timeout can happen.
318*0Sstevel@tonic-gate */
319*0Sstevel@tonic-gate
320*0Sstevel@tonic-gate (void) iu_expire_timers(tq);
321*0Sstevel@tonic-gate continue;
322*0Sstevel@tonic-gate
323*0Sstevel@tonic-gate default:
324*0Sstevel@tonic-gate break;
325*0Sstevel@tonic-gate }
326*0Sstevel@tonic-gate
327*0Sstevel@tonic-gate /* file descriptors are lit; call 'em back */
328*0Sstevel@tonic-gate
329*0Sstevel@tonic-gate for (i = 0; i < eh->iueh_num_fds && n_lit > 0; i++) {
330*0Sstevel@tonic-gate
331*0Sstevel@tonic-gate if (eh->iueh_pollfds[i].revents == 0)
332*0Sstevel@tonic-gate continue;
333*0Sstevel@tonic-gate
334*0Sstevel@tonic-gate n_lit--;
335*0Sstevel@tonic-gate
336*0Sstevel@tonic-gate /*
337*0Sstevel@tonic-gate * turn off any descriptors that have gone
338*0Sstevel@tonic-gate * bad. shouldn't happen, but...
339*0Sstevel@tonic-gate */
340*0Sstevel@tonic-gate
341*0Sstevel@tonic-gate if (eh->iueh_pollfds[i].revents & (POLLNVAL|POLLERR)) {
342*0Sstevel@tonic-gate /* TODO: issue a warning here - but how? */
343*0Sstevel@tonic-gate (void) iu_unregister_event(eh, i, NULL);
344*0Sstevel@tonic-gate continue;
345*0Sstevel@tonic-gate }
346*0Sstevel@tonic-gate
347*0Sstevel@tonic-gate eh->iueh_events[i].iuen_callback(eh, i,
348*0Sstevel@tonic-gate eh->iueh_pollfds[i].revents, i,
349*0Sstevel@tonic-gate eh->iueh_events[i].iuen_arg);
350*0Sstevel@tonic-gate }
351*0Sstevel@tonic-gate
352*0Sstevel@tonic-gate } while (eh->iueh_stop == B_FALSE || (eh->iueh_shutdown != NULL &&
353*0Sstevel@tonic-gate eh->iueh_shutdown(eh, eh->iueh_shutdown_arg) == B_FALSE));
354*0Sstevel@tonic-gate
355*0Sstevel@tonic-gate return (eh->iueh_reason);
356*0Sstevel@tonic-gate }
357*0Sstevel@tonic-gate
358*0Sstevel@tonic-gate /*
359*0Sstevel@tonic-gate * post_signal(): posts a signal for later consumption in iu_handle_events()
360*0Sstevel@tonic-gate *
361*0Sstevel@tonic-gate * input: int: the signal that's been received
362*0Sstevel@tonic-gate * output: void
363*0Sstevel@tonic-gate */
364*0Sstevel@tonic-gate
365*0Sstevel@tonic-gate static void
post_signal(int sig)366*0Sstevel@tonic-gate post_signal(int sig)
367*0Sstevel@tonic-gate {
368*0Sstevel@tonic-gate if (signal_to_eh[sig] != NULL)
369*0Sstevel@tonic-gate signal_to_eh[sig]->iueh_sig_info[sig].iues_pending = B_TRUE;
370*0Sstevel@tonic-gate }
371*0Sstevel@tonic-gate
372*0Sstevel@tonic-gate /*
373*0Sstevel@tonic-gate * iu_eh_register_signal(): registers a signal handler with an event handler
374*0Sstevel@tonic-gate *
375*0Sstevel@tonic-gate * input: iu_eh_t *: the event handler to register the signal handler with
376*0Sstevel@tonic-gate * int: the signal to register
377*0Sstevel@tonic-gate * iu_eh_sighandler_t *: the signal handler to call back
378*0Sstevel@tonic-gate * void *: the argument to pass to the signal handler function
379*0Sstevel@tonic-gate * output: int: zero on failure, success otherwise
380*0Sstevel@tonic-gate */
381*0Sstevel@tonic-gate
382*0Sstevel@tonic-gate int
iu_eh_register_signal(iu_eh_t * eh,int sig,iu_eh_sighandler_t * handler,void * data)383*0Sstevel@tonic-gate iu_eh_register_signal(iu_eh_t *eh, int sig, iu_eh_sighandler_t *handler,
384*0Sstevel@tonic-gate void *data)
385*0Sstevel@tonic-gate {
386*0Sstevel@tonic-gate struct sigaction act;
387*0Sstevel@tonic-gate
388*0Sstevel@tonic-gate if (sig < 0 || sig >= NSIG || signal_to_eh[sig] != NULL)
389*0Sstevel@tonic-gate return (0);
390*0Sstevel@tonic-gate
391*0Sstevel@tonic-gate act.sa_flags = 0;
392*0Sstevel@tonic-gate act.sa_handler = &post_signal;
393*0Sstevel@tonic-gate (void) sigemptyset(&act.sa_mask);
394*0Sstevel@tonic-gate (void) sigaddset(&act.sa_mask, sig); /* used for sigprocmask() */
395*0Sstevel@tonic-gate
396*0Sstevel@tonic-gate if (sigaction(sig, &act, NULL) == -1)
397*0Sstevel@tonic-gate return (0);
398*0Sstevel@tonic-gate
399*0Sstevel@tonic-gate (void) sigprocmask(SIG_BLOCK, &act.sa_mask, NULL);
400*0Sstevel@tonic-gate
401*0Sstevel@tonic-gate eh->iueh_sig_info[sig].iues_data = data;
402*0Sstevel@tonic-gate eh->iueh_sig_info[sig].iues_handler = handler;
403*0Sstevel@tonic-gate signal_to_eh[sig] = eh;
404*0Sstevel@tonic-gate
405*0Sstevel@tonic-gate (void) sigaddset(&eh->iueh_sig_regset, sig);
406*0Sstevel@tonic-gate return (0);
407*0Sstevel@tonic-gate }
408*0Sstevel@tonic-gate
409*0Sstevel@tonic-gate /*
410*0Sstevel@tonic-gate * iu_eh_unregister_signal(): unregisters a signal handler from an event handler
411*0Sstevel@tonic-gate *
412*0Sstevel@tonic-gate * input: iu_eh_t *: the event handler to unregister the signal handler from
413*0Sstevel@tonic-gate * int: the signal to unregister
414*0Sstevel@tonic-gate * void **: if non-NULL, will be set to point to the argument passed
415*0Sstevel@tonic-gate * into iu_eh_register_signal()
416*0Sstevel@tonic-gate * output: int: zero on failure, success otherwise
417*0Sstevel@tonic-gate */
418*0Sstevel@tonic-gate
419*0Sstevel@tonic-gate int
iu_eh_unregister_signal(iu_eh_t * eh,int sig,void ** datap)420*0Sstevel@tonic-gate iu_eh_unregister_signal(iu_eh_t *eh, int sig, void **datap)
421*0Sstevel@tonic-gate {
422*0Sstevel@tonic-gate sigset_t set;
423*0Sstevel@tonic-gate
424*0Sstevel@tonic-gate if (sig < 0 || sig >= NSIG || signal_to_eh[sig] != eh)
425*0Sstevel@tonic-gate return (0);
426*0Sstevel@tonic-gate
427*0Sstevel@tonic-gate if (signal(sig, SIG_DFL) == SIG_ERR)
428*0Sstevel@tonic-gate return (0);
429*0Sstevel@tonic-gate
430*0Sstevel@tonic-gate if (datap != NULL)
431*0Sstevel@tonic-gate *datap = eh->iueh_sig_info[sig].iues_data;
432*0Sstevel@tonic-gate
433*0Sstevel@tonic-gate (void) sigemptyset(&set);
434*0Sstevel@tonic-gate (void) sigaddset(&set, sig);
435*0Sstevel@tonic-gate (void) sigprocmask(SIG_UNBLOCK, &set, NULL);
436*0Sstevel@tonic-gate
437*0Sstevel@tonic-gate eh->iueh_sig_info[sig].iues_data = NULL;
438*0Sstevel@tonic-gate eh->iueh_sig_info[sig].iues_handler = NULL;
439*0Sstevel@tonic-gate eh->iueh_sig_info[sig].iues_pending = B_FALSE;
440*0Sstevel@tonic-gate signal_to_eh[sig] = NULL;
441*0Sstevel@tonic-gate
442*0Sstevel@tonic-gate (void) sigdelset(&eh->iueh_sig_regset, sig);
443*0Sstevel@tonic-gate return (1);
444*0Sstevel@tonic-gate }
445