initial commit
[freebsd-arm:freebsd-arm.git] / compat / svr4 / svr4_signal.c
1 /*-
2  * Copyright (c) 1998 Mark Newton
3  * Copyright (c) 1994 Christos Zoulas
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
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/filedesc.h>
35 #include <sys/lock.h>
36 #include <sys/mutex.h>
37 #include <sys/proc.h>
38 #include <sys/signal.h>
39 #include <sys/signalvar.h>
40 #include <sys/syscallsubr.h>
41 #include <sys/sysproto.h>
42
43 #include <machine/cpu.h>
44
45 #include <compat/svr4/svr4.h>
46 #include <compat/svr4/svr4_types.h>
47 #include <compat/svr4/svr4_signal.h>
48 #include <compat/svr4/svr4_proto.h>
49 #include <compat/svr4/svr4_util.h>
50 #include <compat/svr4/svr4_ucontext.h>
51
52 #define svr4_sigmask(n)         (1 << (((n) - 1) & 31))
53 #define svr4_sigword(n)         (((n) - 1) >> 5)
54 #define svr4_sigemptyset(s)     memset((s), 0, sizeof(*(s)))
55 #define svr4_sigismember(s, n)  ((s)->bits[svr4_sigword(n)] & svr4_sigmask(n))
56 #define svr4_sigaddset(s, n)    ((s)->bits[svr4_sigword(n)] |= svr4_sigmask(n))
57
58 void svr4_to_bsd_sigaction(const struct svr4_sigaction *, struct sigaction *);
59 void bsd_to_svr4_sigaction(const struct sigaction *, struct svr4_sigaction *);
60 void svr4_sigfillset(svr4_sigset_t *);
61
62 int bsd_to_svr4_sig[SVR4_NSIG] = {
63         0,
64         SVR4_SIGHUP,
65         SVR4_SIGINT,
66         SVR4_SIGQUIT,
67         SVR4_SIGILL,
68         SVR4_SIGTRAP,
69         SVR4_SIGABRT,
70         SVR4_SIGEMT,
71         SVR4_SIGFPE,
72         SVR4_SIGKILL,
73         SVR4_SIGBUS,
74         SVR4_SIGSEGV,
75         SVR4_SIGSYS,
76         SVR4_SIGPIPE,
77         SVR4_SIGALRM,
78         SVR4_SIGTERM,
79         SVR4_SIGURG,
80         SVR4_SIGSTOP,
81         SVR4_SIGTSTP,
82         SVR4_SIGCONT,
83         SVR4_SIGCHLD,
84         SVR4_SIGTTIN,
85         SVR4_SIGTTOU,
86         SVR4_SIGIO,
87         SVR4_SIGXCPU,
88         SVR4_SIGXFSZ,
89         SVR4_SIGVTALRM,
90         SVR4_SIGPROF,
91         SVR4_SIGWINCH,
92         0,                      /* SIGINFO */
93         SVR4_SIGUSR1,
94         SVR4_SIGUSR2,
95 };
96
97 int svr4_to_bsd_sig[SVR4_NSIG] = {
98         0,
99         SIGHUP,
100         SIGINT,
101         SIGQUIT,
102         SIGILL,
103         SIGTRAP,
104         SIGABRT,
105         SIGEMT,
106         SIGFPE,
107         SIGKILL,
108         SIGBUS,
109         SIGSEGV,
110         SIGSYS,
111         SIGPIPE,
112         SIGALRM,
113         SIGTERM,
114         SIGUSR1,
115         SIGUSR2,
116         SIGCHLD,
117         0,              /* XXX NetBSD uses SIGPWR here, but we don't seem to have one */
118         SIGWINCH,
119         SIGURG,
120         SIGIO,
121         SIGSTOP,
122         SIGTSTP,
123         SIGCONT,
124         SIGTTIN,
125         SIGTTOU,
126         SIGVTALRM,
127         SIGPROF,
128         SIGXCPU,
129         SIGXFSZ,
130 };
131
132 void
133 svr4_sigfillset(s)
134         svr4_sigset_t *s;
135 {
136         int i;
137
138         svr4_sigemptyset(s);
139         for (i = 1; i < SVR4_NSIG; i++) 
140                 if (svr4_to_bsd_sig[i] != 0)
141                         svr4_sigaddset(s, i);
142 }
143
144 void
145 svr4_to_bsd_sigset(sss, bss)
146         const svr4_sigset_t *sss;
147         sigset_t *bss;
148 {
149         int i, newsig;
150
151         SIGEMPTYSET(*bss);
152         for (i = 1; i < SVR4_NSIG; i++)
153                 if (svr4_sigismember(sss, i)) {
154                         newsig = svr4_to_bsd_sig[i];
155                         if (newsig)
156                                 SIGADDSET(*bss, newsig);
157                 }
158 }
159
160 void
161 bsd_to_svr4_sigset(bss, sss)
162         const sigset_t *bss;
163         svr4_sigset_t *sss;
164 {
165         int i, newsig;
166
167         svr4_sigemptyset(sss);
168         for (i = 1; i < SVR4_NSIG; i++) {
169                 if (SIGISMEMBER(*bss, i)) {
170                         newsig = bsd_to_svr4_sig[i];
171                         if (newsig)
172                                 svr4_sigaddset(sss, newsig);
173                 }
174         }
175 }
176
177 /*
178  * XXX: Only a subset of the flags is currently implemented.
179  */
180 void
181 svr4_to_bsd_sigaction(ssa, bsa)
182         const struct svr4_sigaction *ssa;
183         struct sigaction *bsa;
184 {
185
186         bsa->sa_handler = (sig_t) ssa->ssa_handler;
187         svr4_to_bsd_sigset(&ssa->ssa_mask, &bsa->sa_mask);
188         bsa->sa_flags = 0;
189         if ((ssa->ssa_flags & SVR4_SA_ONSTACK) != 0)
190                 bsa->sa_flags |= SA_ONSTACK;
191         if ((ssa->ssa_flags & SVR4_SA_RESETHAND) != 0)
192                 bsa->sa_flags |= SA_RESETHAND;
193         if ((ssa->ssa_flags & SVR4_SA_RESTART) != 0)
194                 bsa->sa_flags |= SA_RESTART;
195         if ((ssa->ssa_flags & SVR4_SA_SIGINFO) != 0)
196                 DPRINTF(("svr4_to_bsd_sigaction: SA_SIGINFO ignored\n"));
197         if ((ssa->ssa_flags & SVR4_SA_NOCLDSTOP) != 0)
198                 bsa->sa_flags |= SA_NOCLDSTOP;
199         if ((ssa->ssa_flags & SVR4_SA_NODEFER) != 0)
200                 bsa->sa_flags |= SA_NODEFER;
201         if ((ssa->ssa_flags & SVR4_SA_NOCLDWAIT) != 0)
202                 bsa->sa_flags |= SA_NOCLDWAIT;
203         if ((ssa->ssa_flags & ~SVR4_SA_ALLBITS) != 0)
204                 DPRINTF(("svr4_to_bsd_sigaction: extra bits ignored\n"));
205 }
206
207 void
208 bsd_to_svr4_sigaction(bsa, ssa)
209         const struct sigaction *bsa;
210         struct svr4_sigaction *ssa;
211 {
212
213         ssa->ssa_handler = (svr4_sig_t) bsa->sa_handler;
214         bsd_to_svr4_sigset(&bsa->sa_mask, &ssa->ssa_mask);
215         ssa->ssa_flags = 0;
216         if ((bsa->sa_flags & SA_ONSTACK) != 0)
217                 ssa->ssa_flags |= SVR4_SA_ONSTACK;
218         if ((bsa->sa_flags & SA_RESETHAND) != 0)
219                 ssa->ssa_flags |= SVR4_SA_RESETHAND;
220         if ((bsa->sa_flags & SA_RESTART) != 0)
221                 ssa->ssa_flags |= SVR4_SA_RESTART;
222         if ((bsa->sa_flags & SA_NODEFER) != 0)
223                 ssa->ssa_flags |= SVR4_SA_NODEFER;
224         if ((bsa->sa_flags & SA_NOCLDSTOP) != 0)
225                 ssa->ssa_flags |= SVR4_SA_NOCLDSTOP;
226 }
227
228 void
229 svr4_to_bsd_sigaltstack(sss, bss)
230         const struct svr4_sigaltstack *sss;
231         struct sigaltstack *bss;
232 {
233
234         bss->ss_sp = sss->ss_sp;
235         bss->ss_size = sss->ss_size;
236         bss->ss_flags = 0;
237         if ((sss->ss_flags & SVR4_SS_DISABLE) != 0)
238                 bss->ss_flags |= SS_DISABLE;
239         if ((sss->ss_flags & SVR4_SS_ONSTACK) != 0)
240                 bss->ss_flags |= SS_ONSTACK;
241         if ((sss->ss_flags & ~SVR4_SS_ALLBITS) != 0)
242           /*XXX*/ uprintf("svr4_to_bsd_sigaltstack: extra bits ignored\n");
243 }
244
245 void
246 bsd_to_svr4_sigaltstack(bss, sss)
247         const struct sigaltstack *bss;
248         struct svr4_sigaltstack *sss;
249 {
250
251         sss->ss_sp = bss->ss_sp;
252         sss->ss_size = bss->ss_size;
253         sss->ss_flags = 0;
254         if ((bss->ss_flags & SS_DISABLE) != 0)
255                 sss->ss_flags |= SVR4_SS_DISABLE;
256         if ((bss->ss_flags & SS_ONSTACK) != 0)
257                 sss->ss_flags |= SVR4_SS_ONSTACK;
258 }
259
260 int
261 svr4_sys_sigaction(td, uap)
262         struct thread *td;
263         struct svr4_sys_sigaction_args *uap;
264 {
265         struct svr4_sigaction isa;
266         struct sigaction nbsa, obsa;
267         struct sigaction *nbsap;
268         int error;
269
270         if (uap->signum < 0 || uap->signum >= SVR4_NSIG)
271                 return (EINVAL);
272
273         DPRINTF(("@@@ svr4_sys_sigaction(%d, %d, %d)\n", td->td_proc->p_pid,
274                         uap->signum,
275                         SVR4_SVR42BSD_SIG(uap->signum)));
276         
277         if (uap->nsa != NULL) {
278                 if ((error = copyin(uap->nsa, &isa, sizeof(isa))) != 0)
279                         return (error);
280                 svr4_to_bsd_sigaction(&isa, &nbsa);
281                 nbsap = &nbsa;
282         } else
283                 nbsap = NULL;
284 #if defined(DEBUG_SVR4)
285         {
286                 int i;
287                 for (i = 0; i < 4; i++) 
288                         DPRINTF(("\tssa_mask[%d] = %lx\n", i,
289                                                 isa.ssa_mask.bits[i]));
290                 DPRINTF(("\tssa_handler = %p\n", isa.ssa_handler));
291         }
292 #endif
293         error = kern_sigaction(td, SVR4_SVR42BSD_SIG(uap->signum), nbsap, &obsa,
294             0);
295         if (error == 0 && uap->osa != NULL) {
296                 bsd_to_svr4_sigaction(&obsa, &isa);
297                 error = copyout(&isa, uap->osa, sizeof(isa));
298         }
299         return (error);
300 }
301
302 int 
303 svr4_sys_sigaltstack(td, uap)
304         struct thread *td;
305         struct svr4_sys_sigaltstack_args *uap;
306 {
307         struct svr4_sigaltstack sss;
308         struct sigaltstack nbss, obss, *nbssp;
309         int error;
310
311         if (uap->nss != NULL) {
312                 if ((error = copyin(uap->nss, &sss, sizeof(sss))) != 0)
313                         return (error);
314                 svr4_to_bsd_sigaltstack(&sss, &nbss);
315                 nbssp = &nbss;
316         } else
317                 nbssp = NULL;
318         error = kern_sigaltstack(td, nbssp, &obss);
319         if (error == 0 && uap->oss != NULL) {
320                 bsd_to_svr4_sigaltstack(&obss, &sss);
321                 error = copyout(&sss, uap->oss, sizeof(sss));
322         }
323         return (error);
324 }
325
326 /*
327  * Stolen from the ibcs2 one
328  */
329 int
330 svr4_sys_signal(td, uap)
331         struct thread *td;
332         struct svr4_sys_signal_args *uap;
333 {
334         struct proc *p;
335         int signum;
336         int error;
337
338         p = td->td_proc;
339         DPRINTF(("@@@ svr4_sys_signal(%d)\n", p->p_pid));
340
341         signum = SVR4_SIGNO(uap->signum);
342         if (signum < 0 || signum >= SVR4_NSIG) {
343                 if (SVR4_SIGCALL(uap->signum) == SVR4_SIGNAL_MASK ||
344                     SVR4_SIGCALL(uap->signum) == SVR4_SIGDEFER_MASK)
345                         td->td_retval[0] = (int)SVR4_SIG_ERR;
346                 return (EINVAL);
347         }
348         signum = SVR4_SVR42BSD_SIG(signum);
349
350         switch (SVR4_SIGCALL(uap->signum)) {
351         case SVR4_SIGDEFER_MASK:
352                 if (uap->handler == SVR4_SIG_HOLD)
353                         goto sighold;
354                 /* FALLTHROUGH */
355
356         case SVR4_SIGNAL_MASK:
357                 {
358                         struct sigaction nbsa, obsa;
359
360                         nbsa.sa_handler = (sig_t) uap->handler;
361                         SIGEMPTYSET(nbsa.sa_mask);
362                         nbsa.sa_flags = 0;
363                         if (signum != SIGALRM)
364                                 nbsa.sa_flags = SA_RESTART;
365                         error = kern_sigaction(td, signum, &nbsa, &obsa, 0);
366                         if (error != 0) {
367                                 DPRINTF(("signal: sigaction failed: %d\n",
368                                          error));
369                                 td->td_retval[0] = (int)SVR4_SIG_ERR;
370                                 return (error);
371                         }
372                         td->td_retval[0] = (int)obsa.sa_handler;
373                         return (0);
374                 }
375
376         case SVR4_SIGHOLD_MASK:
377 sighold:
378                 {
379                         sigset_t set;
380
381                         SIGEMPTYSET(set);
382                         SIGADDSET(set, signum);
383                         return (kern_sigprocmask(td, SIG_BLOCK, &set, NULL, 0));
384                 }
385
386         case SVR4_SIGRELSE_MASK:
387                 {
388                         sigset_t set;
389
390                         SIGEMPTYSET(set);
391                         SIGADDSET(set, signum);
392                         return (kern_sigprocmask(td, SIG_UNBLOCK, &set, NULL,
393                                     0));
394                 }
395
396         case SVR4_SIGIGNORE_MASK:
397                 {
398                         struct sigaction sa;
399
400                         sa.sa_handler = SIG_IGN;
401                         SIGEMPTYSET(sa.sa_mask);
402                         sa.sa_flags = 0;
403                         error = kern_sigaction(td, signum, &sa, NULL, 0);
404                         if (error != 0)
405                                 DPRINTF(("sigignore: sigaction failed\n"));
406                         return (error);
407                 }
408
409         case SVR4_SIGPAUSE_MASK:
410                 {
411                         sigset_t mask;
412
413                         PROC_LOCK(p);
414                         mask = td->td_sigmask;
415                         PROC_UNLOCK(p);
416                         SIGDELSET(mask, signum);
417                         return kern_sigsuspend(td, mask);
418                 }
419
420         default:
421                 return (ENOSYS);
422         }
423 }
424
425
426 int
427 svr4_sys_sigprocmask(td, uap)
428         struct thread *td;
429         struct svr4_sys_sigprocmask_args *uap;
430 {
431         svr4_sigset_t sss;
432         sigset_t oss, nss;
433         sigset_t *nssp;
434         int error;
435
436         if (uap->set != NULL) {
437                 if ((error = copyin(uap->set, &sss, sizeof(sss))) != 0)
438                         return error;
439                 svr4_to_bsd_sigset(&sss, &nss);
440                 nssp = &nss;
441         } else
442                 nssp = NULL;
443
444         /* SVR/4 sigprocmask flag values are the same as the FreeBSD values. */
445         error = kern_sigprocmask(td, uap->how, nssp, &oss, 0);
446         if (error == 0 && uap->oset != NULL) {
447                 bsd_to_svr4_sigset(&oss, &sss);
448                 error = copyout(&sss, uap->oset, sizeof(sss));
449         }
450         return (error);
451 }
452
453 int
454 svr4_sys_sigpending(td, uap)
455         struct thread *td;
456         struct svr4_sys_sigpending_args *uap;
457 {
458         struct proc *p;
459         sigset_t bss;
460         svr4_sigset_t sss;
461
462         p = td->td_proc;
463         DPRINTF(("@@@ svr4_sys_sigpending(%d)\n", p->p_pid));
464         switch (uap->what) {
465         case 1: /* sigpending */
466                 if (uap->mask == NULL)
467                         return 0;
468                 PROC_LOCK(p);
469                 bss = p->p_siglist;
470                 SIGSETOR(bss, td->td_siglist);
471                 SIGSETAND(bss, td->td_sigmask);
472                 PROC_UNLOCK(p);
473                 bsd_to_svr4_sigset(&bss, &sss);
474                 break;
475
476         case 2: /* sigfillset */
477                 svr4_sigfillset(&sss);
478 #if defined(DEBUG_SVR4)
479                 {
480                         int i;
481                         for (i = 0; i < 4; i++)
482                                 DPRINTF(("new sigset[%d] = %lx\n", i, (long)sss.bits[i]));
483                 }
484 #endif
485                 break;
486
487         default:
488                 return EINVAL;
489         }
490                 
491         return copyout(&sss, uap->mask, sizeof(sss));
492 }
493
494 int
495 svr4_sys_sigsuspend(td, uap)
496         struct thread *td;
497         struct svr4_sys_sigsuspend_args *uap;
498 {
499         svr4_sigset_t sss;
500         sigset_t bss;
501         int error;
502
503         if ((error = copyin(uap->ss, &sss, sizeof(sss))) != 0)
504                 return error;
505
506         svr4_to_bsd_sigset(&sss, &bss);
507         return kern_sigsuspend(td, bss);
508 }
509
510
511 int
512 svr4_sys_kill(td, uap)
513         struct thread *td;
514         struct svr4_sys_kill_args *uap;
515 {
516         struct kill_args ka;
517
518         if (uap->signum < 0 || uap->signum >= SVR4_NSIG)
519                 return (EINVAL);
520         ka.pid = uap->pid;
521         ka.signum = SVR4_SVR42BSD_SIG(uap->signum);
522         return kill(td, &ka);
523 }
524
525
526 int 
527 svr4_sys_context(td, uap)
528         struct thread *td;
529         struct svr4_sys_context_args *uap;
530 {
531         struct svr4_ucontext uc;
532         int error, onstack;
533
534         switch (uap->func) {
535         case 0:
536                 DPRINTF(("getcontext(%p)\n", uap->uc));
537                 PROC_LOCK(td->td_proc);
538                 onstack = sigonstack(cpu_getstack(td));
539                 PROC_UNLOCK(td->td_proc);
540                 svr4_getcontext(td, &uc, &td->td_sigmask, onstack);
541                 return copyout(&uc, uap->uc, sizeof(uc));
542
543         case 1: 
544                 DPRINTF(("setcontext(%p)\n", uap->uc));
545                 if ((error = copyin(uap->uc, &uc, sizeof(uc))) != 0)
546                         return error;
547                 DPRINTF(("uc_flags = %lx\n", uc.uc_flags));
548 #if defined(DEBUG_SVR4)
549                 {
550                         int i;
551                         for (i = 0; i < 4; i++)
552                                 DPRINTF(("uc_sigmask[%d] = %lx\n", i,
553                                                         uc.uc_sigmask.bits[i]));
554                 }
555 #endif
556                 return svr4_setcontext(td, &uc);
557
558         default:
559                 DPRINTF(("context(%d, %p)\n", uap->func,
560                     uap->uc));
561                 return ENOSYS;
562         }
563         return 0;
564 }
565
566 int
567 svr4_sys_pause(td, uap)
568         struct thread *td;
569         struct svr4_sys_pause_args *uap;
570 {
571         sigset_t mask;
572
573         PROC_LOCK(td->td_proc);
574         mask = td->td_sigmask;
575         PROC_UNLOCK(td->td_proc);
576         return kern_sigsuspend(td, mask);
577 }