Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / sys / emulation / ibcs2 / i386 / ibcs2_signal.c
1 /*
2  * Copyright (c) 1995 Scott Bartram
3  * Copyright (c) 1995 Steven Wallace
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  * $FreeBSD: src/sys/i386/ibcs2/ibcs2_signal.c,v 1.16 1999/10/10 09:14:31 marcel Exp $
29  * $DragonFly: src/sys/emulation/ibcs2/i386/Attic/ibcs2_signal.c,v 1.2 2003/06/17 04:28:35 dillon Exp $
30  */
31
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/signalvar.h>
35 #include <sys/sysproto.h>
36
37 #include <i386/ibcs2/ibcs2_types.h>
38 #include <i386/ibcs2/ibcs2_signal.h>
39 #include <i386/ibcs2/ibcs2_proto.h>
40 #include <i386/ibcs2/ibcs2_xenix.h>
41 #include <i386/ibcs2/ibcs2_util.h>
42
43 #define sigemptyset(s)          SIGEMPTYSET(*(s))
44 #define sigismember(s, n)       SIGISMEMBER(*(s), n)
45 #define sigaddset(s, n)         SIGADDSET(*(s), n)
46
47 #define ibcs2_sigmask(n)        (1 << ((n) - 1))
48 #define ibcs2_sigemptyset(s)    bzero((s), sizeof(*(s)))
49 #define ibcs2_sigismember(s, n) (*(s) & ibcs2_sigmask(n))
50 #define ibcs2_sigaddset(s, n)   (*(s) |= ibcs2_sigmask(n))
51
52 static void ibcs2_to_bsd_sigset    __P((const ibcs2_sigset_t *, sigset_t *));
53 static void bsd_to_ibcs2_sigset    __P((const sigset_t *, ibcs2_sigset_t *));
54 static void ibcs2_to_bsd_sigaction __P((struct ibcs2_sigaction *,
55                                         struct sigaction *));
56 static void bsd_to_ibcs2_sigaction __P((struct sigaction *,
57                                         struct ibcs2_sigaction *));
58
59 int bsd_to_ibcs2_sig[IBCS2_SIGTBLSZ] = {
60         IBCS2_SIGHUP,           /* 1 */
61         IBCS2_SIGINT,           /* 2 */
62         IBCS2_SIGQUIT,          /* 3 */
63         IBCS2_SIGILL,           /* 4 */
64         IBCS2_SIGTRAP,          /* 5 */
65         IBCS2_SIGABRT,          /* 6 */
66         IBCS2_SIGEMT,           /* 7 */
67         IBCS2_SIGFPE,           /* 8 */
68         IBCS2_SIGKILL,          /* 9 */
69         IBCS2_SIGBUS,           /* 10 */
70         IBCS2_SIGSEGV,          /* 11 */
71         IBCS2_SIGSYS,           /* 12 */
72         IBCS2_SIGPIPE,          /* 13 */
73         IBCS2_SIGALRM,          /* 14 */
74         IBCS2_SIGTERM,          /* 15 */
75         0,                      /* 16 - SIGURG */
76         IBCS2_SIGSTOP,          /* 17 */
77         IBCS2_SIGTSTP,          /* 18 */
78         IBCS2_SIGCONT,          /* 19 */
79         IBCS2_SIGCLD,           /* 20 */
80         IBCS2_SIGTTIN,          /* 21 */
81         IBCS2_SIGTTOU,          /* 22 */
82         IBCS2_SIGPOLL,          /* 23 */
83         0,                      /* 24 - SIGXCPU */
84         0,                      /* 25 - SIGXFSZ */
85         IBCS2_SIGVTALRM,        /* 26 */
86         IBCS2_SIGPROF,          /* 27 */
87         IBCS2_SIGWINCH,         /* 28 */
88         0,                      /* 29 */
89         IBCS2_SIGUSR1,          /* 30 */
90         IBCS2_SIGUSR2,          /* 31 */
91         0                       /* 32 */
92 };
93
94 static int ibcs2_to_bsd_sig[IBCS2_SIGTBLSZ] = {
95         SIGHUP,                 /* 1 */
96         SIGINT,                 /* 2 */
97         SIGQUIT,                /* 3 */
98         SIGILL,                 /* 4 */
99         SIGTRAP,                /* 5 */
100         SIGABRT,                /* 6 */
101         SIGEMT,                 /* 7 */
102         SIGFPE,                 /* 8 */
103         SIGKILL,                /* 9 */
104         SIGBUS,                 /* 10 */
105         SIGSEGV,                /* 11 */
106         SIGSYS,                 /* 12 */
107         SIGPIPE,                /* 13 */
108         SIGALRM,                /* 14 */
109         SIGTERM,                /* 15 */
110         SIGUSR1,                /* 16 */
111         SIGUSR2,                /* 17 */
112         SIGCHLD,                /* 18 */
113         0,                      /* 19 - SIGPWR */
114         SIGWINCH,               /* 20 */
115         0,                      /* 21 */
116         SIGIO,                  /* 22 */
117         SIGSTOP,                /* 23 */
118         SIGTSTP,                /* 24 */
119         SIGCONT,                /* 25 */
120         SIGTTIN,                /* 26 */
121         SIGTTOU,                /* 27 */
122         SIGVTALRM,              /* 28 */
123         SIGPROF,                /* 29 */
124         0,                      /* 30 */
125         0,                      /* 31 */
126         0                       /* 32 */
127 };
128
129 void
130 ibcs2_to_bsd_sigset(iss, bss)
131         const ibcs2_sigset_t *iss;
132         sigset_t *bss;
133 {
134         int i, newsig;
135
136         sigemptyset(bss);
137         for (i = 1; i <= IBCS2_SIGTBLSZ; i++) {
138                 if (ibcs2_sigismember(iss, i)) {
139                         newsig = ibcs2_to_bsd_sig[_SIG_IDX(i)];
140                         if (newsig)
141                                 sigaddset(bss, newsig);
142                 }
143         }
144 }
145
146 static void
147 bsd_to_ibcs2_sigset(bss, iss)
148         const sigset_t *bss;
149         ibcs2_sigset_t *iss;
150 {
151         int i, newsig;
152
153         ibcs2_sigemptyset(iss);
154         for (i = 1; i <= IBCS2_SIGTBLSZ; i++) {
155                 if (sigismember(bss, i)) {
156                         newsig = bsd_to_ibcs2_sig[_SIG_IDX(i)];
157                         if (newsig)
158                                 ibcs2_sigaddset(iss, newsig);
159                 }
160         }
161 }
162
163 static void
164 ibcs2_to_bsd_sigaction(isa, bsa)
165         struct ibcs2_sigaction *isa;
166         struct sigaction *bsa;
167 {
168
169         bsa->sa_handler = isa->isa_handler;
170         ibcs2_to_bsd_sigset(&isa->isa_mask, &bsa->sa_mask);
171         bsa->sa_flags = 0;      /* ??? SA_NODEFER */
172         if ((isa->isa_flags & IBCS2_SA_NOCLDSTOP) != 0)
173                 bsa->sa_flags |= SA_NOCLDSTOP;
174 }
175
176 static void
177 bsd_to_ibcs2_sigaction(bsa, isa)
178         struct sigaction *bsa;
179         struct ibcs2_sigaction *isa;
180 {
181
182         isa->isa_handler = bsa->sa_handler;
183         bsd_to_ibcs2_sigset(&bsa->sa_mask, &isa->isa_mask);
184         isa->isa_flags = 0;
185         if ((bsa->sa_flags & SA_NOCLDSTOP) != 0)
186                 isa->isa_flags |= IBCS2_SA_NOCLDSTOP;
187 }
188
189 int
190 ibcs2_sigaction(p, uap)
191         register struct proc *p;
192         struct ibcs2_sigaction_args *uap;
193 {
194         struct ibcs2_sigaction *nisa, *oisa, tmpisa;
195         struct sigaction *nbsa, *obsa, tmpbsa;
196         struct sigaction_args sa;
197         caddr_t sg;
198         int error;
199
200         sg = stackgap_init();
201         nisa = SCARG(uap, act);
202         oisa = SCARG(uap, oact);
203
204         if (oisa != NULL)
205                 obsa = stackgap_alloc(&sg, sizeof(struct sigaction));
206         else
207                 obsa = NULL;
208
209         if (nisa != NULL) {
210                 nbsa = stackgap_alloc(&sg, sizeof(struct sigaction));
211                 if ((error = copyin(nisa, &tmpisa, sizeof(tmpisa))) != 0)
212                         return error;
213                 ibcs2_to_bsd_sigaction(&tmpisa, &tmpbsa);
214                 if ((error = copyout(&tmpbsa, nbsa, sizeof(tmpbsa))) != 0)
215                         return error;
216         } else
217                 nbsa = NULL;
218
219         SCARG(&sa, sig) = ibcs2_to_bsd_sig[_SIG_IDX(SCARG(uap, sig))];
220         SCARG(&sa, act) = nbsa;
221         SCARG(&sa, oact) = obsa;
222
223         if ((error = sigaction(p, &sa)) != 0)
224                 return error;
225
226         if (oisa != NULL) {
227                 if ((error = copyin(obsa, &tmpbsa, sizeof(tmpbsa))) != 0)
228                         return error;
229                 bsd_to_ibcs2_sigaction(&tmpbsa, &tmpisa);
230                 if ((error = copyout(&tmpisa, oisa, sizeof(tmpisa))) != 0)
231                         return error;
232         }
233
234         return 0;
235 }
236
237 int
238 ibcs2_sigsys(p, uap)
239         register struct proc *p;
240         struct ibcs2_sigsys_args *uap;
241 {
242         struct sigaction sa;
243         int signum = ibcs2_to_bsd_sig[_SIG_IDX(IBCS2_SIGNO(SCARG(uap, sig)))];
244         int error;
245         caddr_t sg = stackgap_init();
246
247         if (signum <= 0 || signum >= IBCS2_NSIG) {
248                 if (IBCS2_SIGCALL(SCARG(uap, sig)) == IBCS2_SIGNAL_MASK ||
249                     IBCS2_SIGCALL(SCARG(uap, sig)) == IBCS2_SIGSET_MASK)
250                         p->p_retval[0] = (int)IBCS2_SIG_ERR;
251                 return EINVAL;
252         }
253         
254         switch (IBCS2_SIGCALL(SCARG(uap, sig))) {
255         case IBCS2_SIGSET_MASK:
256                 /*
257                  * Check for SIG_HOLD action.
258                  * Otherwise, perform signal() except with different sa_flags.
259                  */
260                 if (SCARG(uap, fp) != IBCS2_SIG_HOLD) {
261                         /* add sig to mask before exececuting signal handler */
262                         sa.sa_flags = 0;
263                         goto ibcs2_sigset;
264                 }
265                 /* else fallthrough to sighold */
266
267         case IBCS2_SIGHOLD_MASK:
268                 {
269                         sigset_t mask;
270                         struct sigprocmask_args sa;
271
272                         SIGEMPTYSET(mask);
273                         SIGADDSET(mask, signum);
274                         SCARG(&sa, how) = SIG_BLOCK;
275                         SCARG(&sa, set) = &mask;
276                         SCARG(&sa, oset) = NULL;
277                         return sigprocmask(p, &sa);
278                 }
279                 
280         case IBCS2_SIGNAL_MASK:
281                 {
282                         struct sigaction_args sa_args;
283                         struct sigaction *nbsa, *obsa;
284
285                         /* do not automatically block signal */
286                         sa.sa_flags = SA_NODEFER;
287 #ifdef SA_RESETHAND
288                         if((signum != IBCS2_SIGILL) &&
289                            (signum != IBCS2_SIGTRAP) &&
290                            (signum != IBCS2_SIGPWR))
291                                 /* set to SIG_DFL before executing handler */
292                                 sa.sa_flags |= SA_RESETHAND;
293 #endif
294                 ibcs2_sigset:
295                         nbsa = stackgap_alloc(&sg, sizeof(struct sigaction));
296                         obsa = stackgap_alloc(&sg, sizeof(struct sigaction));
297                         SCARG(&sa_args, sig) = signum;
298                         SCARG(&sa_args, act) = nbsa;
299                         SCARG(&sa_args, oact) = obsa;
300
301                         sa.sa_handler = SCARG(uap, fp);
302                         sigemptyset(&sa.sa_mask);
303 #if 0
304                         if (signum != SIGALRM)
305                                 sa.sa_flags |= SA_RESTART;
306 #endif
307                         p->p_retval[0] = (int)IBCS2_SIG_ERR; /* init error return */
308
309                         /* perform native sigaction() */
310                         if ((error = copyout(&sa, nbsa, sizeof(sa))) != 0)
311                                 return error;
312                         if ((error = sigaction(p, &sa_args)) != 0) {
313                                 DPRINTF(("signal: sigaction failed: %d\n",
314                                          error));
315                                 return error;
316                         }
317                         if ((error = copyin(obsa, &sa, sizeof(sa))) != 0)
318                                 return error;
319                         p->p_retval[0] = (int)sa.sa_handler;
320
321                         /* special sigset() check */
322                         if(IBCS2_SIGCALL(SCARG(uap, sig)) == IBCS2_SIGSET_MASK)
323                                 /* check to make sure signal is not blocked */
324                                 if(sigismember(&p->p_sigmask, signum)) {
325                                         /* return SIG_HOLD and unblock signal*/
326                                         p->p_retval[0] = (int)IBCS2_SIG_HOLD;
327                                         SIGDELSET(p->p_sigmask, signum);
328                                 }
329                                 
330                         return 0;
331                 }
332                 
333         case IBCS2_SIGRELSE_MASK:
334                 {
335                         sigset_t mask;
336                         struct sigprocmask_args sa;
337
338                         SIGEMPTYSET(mask);
339                         SIGADDSET(mask, signum);
340                         SCARG(&sa, how) = SIG_UNBLOCK;
341                         SCARG(&sa, set) = &mask;
342                         SCARG(&sa, oset) = NULL;
343                         return sigprocmask(p, &sa);
344                 }
345                 
346         case IBCS2_SIGIGNORE_MASK:
347                 {
348                         struct sigaction_args sa_args;
349                         struct sigaction *bsa;
350
351                         bsa = stackgap_alloc(&sg, sizeof(struct sigaction));
352                         SCARG(&sa_args, sig) = signum;
353                         SCARG(&sa_args, act) = bsa;
354                         SCARG(&sa_args, oact) = NULL;
355
356                         sa.sa_handler = SIG_IGN;
357                         sigemptyset(&sa.sa_mask);
358                         sa.sa_flags = 0;
359                         if ((error = copyout(&sa, bsa, sizeof(sa))) != 0)
360                                 return error;
361                         if ((error = sigaction(p, &sa_args)) != 0) {
362                                 DPRINTF(("sigignore: sigaction failed\n"));
363                                 return error;
364                         }
365                         return 0;
366                 }
367                 
368         case IBCS2_SIGPAUSE_MASK:
369                 {
370                         sigset_t mask;
371                         struct sigsuspend_args sa;
372
373                         mask = p->p_sigmask;
374                         SIGDELSET(mask, signum);
375                         SCARG(&sa, sigmask) = &mask;
376                         return sigsuspend(p, &sa);
377                 }
378                 
379         default:
380                 return ENOSYS;
381         }
382 }
383
384 int
385 ibcs2_sigprocmask(p, uap)
386         register struct proc *p;
387         struct ibcs2_sigprocmask_args *uap;
388 {
389         ibcs2_sigset_t iss;
390         sigset_t bss;
391         int error = 0;
392
393         if (SCARG(uap, oset) != NULL) {
394                 /* Fix the return value first if needed */
395                 bsd_to_ibcs2_sigset(&p->p_sigmask, &iss);
396                 if ((error = copyout(&iss, SCARG(uap, oset), sizeof(iss))) != 0)
397                         return error;
398         }
399                 
400         if (SCARG(uap, set) == NULL)
401                 /* Just examine */
402                 return 0;
403
404         if ((error = copyin(SCARG(uap, set), &iss, sizeof(iss))) != 0)
405                 return error;
406
407         ibcs2_to_bsd_sigset(&iss, &bss);
408
409         (void) splhigh();
410
411         switch (SCARG(uap, how)) {
412         case IBCS2_SIG_BLOCK:
413                 SIGSETOR(p->p_sigmask, bss);
414                 SIG_CANTMASK(p->p_sigmask);
415                 break;
416
417         case IBCS2_SIG_UNBLOCK:
418                 SIGSETNAND(p->p_sigmask, bss);
419                 break;
420
421         case IBCS2_SIG_SETMASK:
422                 p->p_sigmask = bss;
423                 SIG_CANTMASK(p->p_sigmask);
424                 break;
425
426         default:
427                 error = EINVAL;
428                 break;
429         }
430
431         (void) spl0();
432
433         return error;
434 }
435
436 int
437 ibcs2_sigpending(p, uap)
438         register struct proc *p;
439         struct ibcs2_sigpending_args *uap;
440 {
441         sigset_t bss;
442         ibcs2_sigset_t iss;
443
444         bss = p->p_siglist;
445         SIGSETAND(bss, p->p_sigmask);
446         bsd_to_ibcs2_sigset(&bss, &iss);
447
448         return copyout(&iss, SCARG(uap, mask), sizeof(iss));
449 }
450
451 int
452 ibcs2_sigsuspend(p, uap)
453         register struct proc *p;
454         struct ibcs2_sigsuspend_args *uap;
455 {
456         ibcs2_sigset_t sss;
457         sigset_t bss;
458         struct sigsuspend_args sa;
459         int error;
460
461         if ((error = copyin(SCARG(uap, mask), &sss, sizeof(sss))) != 0)
462                 return error;
463
464         ibcs2_to_bsd_sigset(&sss, &bss);
465         SCARG(&sa, sigmask) = &bss;
466         return sigsuspend(p, &sa);
467 }
468
469 int
470 ibcs2_pause(p, uap)
471         register struct proc *p;
472         struct ibcs2_pause_args *uap;
473 {
474         sigset_t mask;
475         struct sigsuspend_args sa;
476
477         mask = p->p_sigmask;
478         SCARG(&sa, sigmask) = &mask;
479         return sigsuspend(p, &sa);
480 }
481
482 int
483 ibcs2_kill(p, uap)
484         register struct proc *p;
485         struct ibcs2_kill_args *uap;
486 {
487         struct kill_args ka;
488
489         SCARG(&ka, pid) = SCARG(uap, pid);
490         SCARG(&ka, signum) = ibcs2_to_bsd_sig[_SIG_IDX(SCARG(uap, signo))];
491         return kill(p, &ka);
492 }