xref: /freebsd/sys/compat/linux/linux_signal.c (revision 81338031c4839351c7f27c04c1e4924751319a88)
1c21dee17SSøren Schmidt /*-
29a14aa01SUlrich Spörlein  * Copyright (c) 1994-1995 Søren Schmidt
3c21dee17SSøren Schmidt  * All rights reserved.
4c21dee17SSøren Schmidt  *
5c21dee17SSøren Schmidt  * Redistribution and use in source and binary forms, with or without
6c21dee17SSøren Schmidt  * modification, are permitted provided that the following conditions
7c21dee17SSøren Schmidt  * are met:
8c21dee17SSøren Schmidt  * 1. Redistributions of source code must retain the above copyright
9c21dee17SSøren Schmidt  *    notice, this list of conditions and the following disclaimer
10c21dee17SSøren Schmidt  *    in this position and unchanged.
11c21dee17SSøren Schmidt  * 2. Redistributions in binary form must reproduce the above copyright
12c21dee17SSøren Schmidt  *    notice, this list of conditions and the following disclaimer in the
13c21dee17SSøren Schmidt  *    documentation and/or other materials provided with the distribution.
14c21dee17SSøren Schmidt  * 3. The name of the author may not be used to endorse or promote products
1521dc7d4fSJens Schweikhardt  *    derived from this software without specific prior written permission
16c21dee17SSøren Schmidt  *
17c21dee17SSøren Schmidt  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18c21dee17SSøren Schmidt  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19c21dee17SSøren Schmidt  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20c21dee17SSøren Schmidt  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21c21dee17SSøren Schmidt  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22c21dee17SSøren Schmidt  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23c21dee17SSøren Schmidt  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24c21dee17SSøren Schmidt  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25c21dee17SSøren Schmidt  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26c21dee17SSøren Schmidt  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27c21dee17SSøren Schmidt  */
28c21dee17SSøren Schmidt 
2916dbc7f2SDavid E. O'Brien #include <sys/cdefs.h>
301e8d246eSNate Lawson __FBSDID("$FreeBSD$");
3116dbc7f2SDavid E. O'Brien 
32c21dee17SSøren Schmidt #include <sys/param.h>
33c21dee17SSøren Schmidt #include <sys/systm.h>
34fb919e4dSMark Murray #include <sys/lock.h>
35fb919e4dSMark Murray #include <sys/mutex.h>
3629ddc19bSAlexander Leidinger #include <sys/sx.h>
37c21dee17SSøren Schmidt #include <sys/proc.h>
38c21dee17SSøren Schmidt #include <sys/signalvar.h>
39206a5d3aSIan Dowse #include <sys/syscallsubr.h>
40fb919e4dSMark Murray #include <sys/sysproto.h>
41c21dee17SSøren Schmidt 
42aa8b2011SKonstantin Belousov #include <security/audit/audit.h>
43aa8b2011SKonstantin Belousov 
44aefce619SRuslan Ermilov #include "opt_compat.h"
45aefce619SRuslan Ermilov 
461997c537SDavid E. O'Brien #ifdef COMPAT_LINUX32
474af27623STim J. Robbins #include <machine/../linux32/linux.h>
484af27623STim J. Robbins #include <machine/../linux32/linux32_proto.h>
491997c537SDavid E. O'Brien #else
501997c537SDavid E. O'Brien #include <machine/../linux/linux.h>
511997c537SDavid E. O'Brien #include <machine/../linux/linux_proto.h>
524af27623STim J. Robbins #endif
53ba9ef45bSMarcel Moolenaar #include <compat/linux/linux_signal.h>
54ba9ef45bSMarcel Moolenaar #include <compat/linux/linux_util.h>
559b44bfc5SAlexander Leidinger #include <compat/linux/linux_emul.h>
56*81338031SDmitry Chagin #include <compat/linux/linux_misc.h>
57*81338031SDmitry Chagin 
58*81338031SDmitry Chagin static int	linux_do_tkill(struct thread *td, struct thread *tdt,
59*81338031SDmitry Chagin 		    ksiginfo_t *ksi);
609b44bfc5SAlexander Leidinger 
61ba9ef45bSMarcel Moolenaar void
625002a60fSMarcel Moolenaar linux_to_bsd_sigset(l_sigset_t *lss, sigset_t *bss)
63956d3333SMarcel Moolenaar {
64d66a5066SPeter Wemm 	int b, l;
65c21dee17SSøren Schmidt 
66956d3333SMarcel Moolenaar 	SIGEMPTYSET(*bss);
67956d3333SMarcel Moolenaar 	bss->__bits[0] = lss->__bits[0] & ~((1U << LINUX_SIGTBLSZ) - 1);
68956d3333SMarcel Moolenaar 	bss->__bits[1] = lss->__bits[1];
69956d3333SMarcel Moolenaar 	for (l = 1; l <= LINUX_SIGTBLSZ; l++) {
70956d3333SMarcel Moolenaar 		if (LINUX_SIGISMEMBER(*lss, l)) {
71956d3333SMarcel Moolenaar 			b = linux_to_bsd_signal[_SIG_IDX(l)];
72956d3333SMarcel Moolenaar 			if (b)
73956d3333SMarcel Moolenaar 				SIGADDSET(*bss, b);
74d66a5066SPeter Wemm 		}
75d66a5066SPeter Wemm 	}
76c21dee17SSøren Schmidt }
77c21dee17SSøren Schmidt 
7879363394SAndrew Gallatin void
795002a60fSMarcel Moolenaar bsd_to_linux_sigset(sigset_t *bss, l_sigset_t *lss)
80956d3333SMarcel Moolenaar {
81d66a5066SPeter Wemm 	int b, l;
82c21dee17SSøren Schmidt 
83956d3333SMarcel Moolenaar 	LINUX_SIGEMPTYSET(*lss);
84956d3333SMarcel Moolenaar 	lss->__bits[0] = bss->__bits[0] & ~((1U << LINUX_SIGTBLSZ) - 1);
85956d3333SMarcel Moolenaar 	lss->__bits[1] = bss->__bits[1];
86956d3333SMarcel Moolenaar 	for (b = 1; b <= LINUX_SIGTBLSZ; b++) {
87956d3333SMarcel Moolenaar 		if (SIGISMEMBER(*bss, b)) {
88956d3333SMarcel Moolenaar 			l = bsd_to_linux_signal[_SIG_IDX(b)];
89956d3333SMarcel Moolenaar 			if (l)
90956d3333SMarcel Moolenaar 				LINUX_SIGADDSET(*lss, l);
91d66a5066SPeter Wemm 		}
92d66a5066SPeter Wemm 	}
93c21dee17SSøren Schmidt }
94c21dee17SSøren Schmidt 
95a1ebcbfbSPeter Wemm static void
965002a60fSMarcel Moolenaar linux_to_bsd_sigaction(l_sigaction_t *lsa, struct sigaction *bsa)
97d66a5066SPeter Wemm {
98956d3333SMarcel Moolenaar 
99956d3333SMarcel Moolenaar 	linux_to_bsd_sigset(&lsa->lsa_mask, &bsa->sa_mask);
1004af27623STim J. Robbins 	bsa->sa_handler = PTRIN(lsa->lsa_handler);
101d66a5066SPeter Wemm 	bsa->sa_flags = 0;
1028f437f44SMartin Cracauer 	if (lsa->lsa_flags & LINUX_SA_NOCLDSTOP)
103d66a5066SPeter Wemm 		bsa->sa_flags |= SA_NOCLDSTOP;
10406ebbe77SMarcel Moolenaar 	if (lsa->lsa_flags & LINUX_SA_NOCLDWAIT)
10506ebbe77SMarcel Moolenaar 		bsa->sa_flags |= SA_NOCLDWAIT;
10606ebbe77SMarcel Moolenaar 	if (lsa->lsa_flags & LINUX_SA_SIGINFO)
10706ebbe77SMarcel Moolenaar 		bsa->sa_flags |= SA_SIGINFO;
1088f437f44SMartin Cracauer 	if (lsa->lsa_flags & LINUX_SA_ONSTACK)
109d66a5066SPeter Wemm 		bsa->sa_flags |= SA_ONSTACK;
1108f437f44SMartin Cracauer 	if (lsa->lsa_flags & LINUX_SA_RESTART)
111d66a5066SPeter Wemm 		bsa->sa_flags |= SA_RESTART;
1128f437f44SMartin Cracauer 	if (lsa->lsa_flags & LINUX_SA_ONESHOT)
113d66a5066SPeter Wemm 		bsa->sa_flags |= SA_RESETHAND;
1148f437f44SMartin Cracauer 	if (lsa->lsa_flags & LINUX_SA_NOMASK)
115d66a5066SPeter Wemm 		bsa->sa_flags |= SA_NODEFER;
116d66a5066SPeter Wemm }
117d66a5066SPeter Wemm 
118a1ebcbfbSPeter Wemm static void
1195002a60fSMarcel Moolenaar bsd_to_linux_sigaction(struct sigaction *bsa, l_sigaction_t *lsa)
120d66a5066SPeter Wemm {
121956d3333SMarcel Moolenaar 
122956d3333SMarcel Moolenaar 	bsd_to_linux_sigset(&bsa->sa_mask, &lsa->lsa_mask);
1231997c537SDavid E. O'Brien #ifdef COMPAT_LINUX32
1244af27623STim J. Robbins 	lsa->lsa_handler = (uintptr_t)bsa->sa_handler;
1254af27623STim J. Robbins #else
1268f437f44SMartin Cracauer 	lsa->lsa_handler = bsa->sa_handler;
1274af27623STim J. Robbins #endif
1284af27623STim J. Robbins 	lsa->lsa_restorer = 0;		/* unsupported */
1298f437f44SMartin Cracauer 	lsa->lsa_flags = 0;
130d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_NOCLDSTOP)
1318f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_NOCLDSTOP;
13206ebbe77SMarcel Moolenaar 	if (bsa->sa_flags & SA_NOCLDWAIT)
13306ebbe77SMarcel Moolenaar 		lsa->lsa_flags |= LINUX_SA_NOCLDWAIT;
13406ebbe77SMarcel Moolenaar 	if (bsa->sa_flags & SA_SIGINFO)
13506ebbe77SMarcel Moolenaar 		lsa->lsa_flags |= LINUX_SA_SIGINFO;
136d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_ONSTACK)
1378f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_ONSTACK;
138d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_RESTART)
1398f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_RESTART;
140d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_RESETHAND)
1418f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_ONESHOT;
142d66a5066SPeter Wemm 	if (bsa->sa_flags & SA_NODEFER)
1438f437f44SMartin Cracauer 		lsa->lsa_flags |= LINUX_SA_NOMASK;
144d66a5066SPeter Wemm }
145c21dee17SSøren Schmidt 
146ba9ef45bSMarcel Moolenaar int
147b40ce416SJulian Elischer linux_do_sigaction(struct thread *td, int linux_sig, l_sigaction_t *linux_nsa,
1485002a60fSMarcel Moolenaar 		   l_sigaction_t *linux_osa)
14906ebbe77SMarcel Moolenaar {
150206a5d3aSIan Dowse 	struct sigaction act, oact, *nsa, *osa;
151206a5d3aSIan Dowse 	int error, sig;
15206ebbe77SMarcel Moolenaar 
153687c23beSAlexander Leidinger 	if (!LINUX_SIG_VALID(linux_sig))
154956d3333SMarcel Moolenaar 		return (EINVAL);
15506ebbe77SMarcel Moolenaar 
156206a5d3aSIan Dowse 	osa = (linux_osa != NULL) ? &oact : NULL;
157956d3333SMarcel Moolenaar 	if (linux_nsa != NULL) {
158206a5d3aSIan Dowse 		nsa = &act;
159ec99e322SMarcel Moolenaar 		linux_to_bsd_sigaction(linux_nsa, nsa);
160206a5d3aSIan Dowse 	} else
16106ebbe77SMarcel Moolenaar 		nsa = NULL;
16206ebbe77SMarcel Moolenaar 
163956d3333SMarcel Moolenaar 	if (linux_sig <= LINUX_SIGTBLSZ)
164206a5d3aSIan Dowse 		sig = linux_to_bsd_signal[_SIG_IDX(linux_sig)];
165956d3333SMarcel Moolenaar 	else
166206a5d3aSIan Dowse 		sig = linux_sig;
167956d3333SMarcel Moolenaar 
168206a5d3aSIan Dowse 	error = kern_sigaction(td, sig, nsa, osa, 0);
16906ebbe77SMarcel Moolenaar 	if (error)
170956d3333SMarcel Moolenaar 		return (error);
17106ebbe77SMarcel Moolenaar 
172ec99e322SMarcel Moolenaar 	if (linux_osa != NULL)
173ec99e322SMarcel Moolenaar 		bsd_to_linux_sigaction(osa, linux_osa);
17406ebbe77SMarcel Moolenaar 
175956d3333SMarcel Moolenaar 	return (0);
17606ebbe77SMarcel Moolenaar }
17706ebbe77SMarcel Moolenaar 
1785231fb20SDavid E. O'Brien 
179c21dee17SSøren Schmidt int
180b40ce416SJulian Elischer linux_signal(struct thread *td, struct linux_signal_args *args)
181d66a5066SPeter Wemm {
1825002a60fSMarcel Moolenaar 	l_sigaction_t nsa, osa;
183d66a5066SPeter Wemm 	int error;
184d66a5066SPeter Wemm 
185d66a5066SPeter Wemm #ifdef DEBUG
18624593369SJonathan Lemon 	if (ldebug(signal))
18724593369SJonathan Lemon 		printf(ARGS(signal, "%d, %p"),
188b61c60d4SDavid E. O'Brien 		    args->sig, (void *)(uintptr_t)args->handler);
189d66a5066SPeter Wemm #endif
190d66a5066SPeter Wemm 
19106ebbe77SMarcel Moolenaar 	nsa.lsa_handler = args->handler;
19206ebbe77SMarcel Moolenaar 	nsa.lsa_flags = LINUX_SA_ONESHOT | LINUX_SA_NOMASK;
193956d3333SMarcel Moolenaar 	LINUX_SIGEMPTYSET(nsa.lsa_mask);
194d66a5066SPeter Wemm 
195b40ce416SJulian Elischer 	error = linux_do_sigaction(td, args->sig, &nsa, &osa);
1964af27623STim J. Robbins 	td->td_retval[0] = (int)(intptr_t)osa.lsa_handler;
197d66a5066SPeter Wemm 
198956d3333SMarcel Moolenaar 	return (error);
199d66a5066SPeter Wemm }
200d66a5066SPeter Wemm 
201c21dee17SSøren Schmidt int
202b40ce416SJulian Elischer linux_rt_sigaction(struct thread *td, struct linux_rt_sigaction_args *args)
203c21dee17SSøren Schmidt {
2045002a60fSMarcel Moolenaar 	l_sigaction_t nsa, osa;
20506ebbe77SMarcel Moolenaar 	int error;
206c21dee17SSøren Schmidt 
207c21dee17SSøren Schmidt #ifdef DEBUG
20824593369SJonathan Lemon 	if (ldebug(rt_sigaction))
20924593369SJonathan Lemon 		printf(ARGS(rt_sigaction, "%ld, %p, %p, %ld"),
21024593369SJonathan Lemon 		    (long)args->sig, (void *)args->act,
2115231fb20SDavid E. O'Brien 		    (void *)args->oact, (long)args->sigsetsize);
212c21dee17SSøren Schmidt #endif
213d66a5066SPeter Wemm 
2145002a60fSMarcel Moolenaar 	if (args->sigsetsize != sizeof(l_sigset_t))
215956d3333SMarcel Moolenaar 		return (EINVAL);
21606ebbe77SMarcel Moolenaar 
217956d3333SMarcel Moolenaar 	if (args->act != NULL) {
2185002a60fSMarcel Moolenaar 		error = copyin(args->act, &nsa, sizeof(l_sigaction_t));
21906ebbe77SMarcel Moolenaar 		if (error)
220956d3333SMarcel Moolenaar 			return (error);
22106ebbe77SMarcel Moolenaar 	}
22206ebbe77SMarcel Moolenaar 
223b40ce416SJulian Elischer 	error = linux_do_sigaction(td, args->sig,
22406ebbe77SMarcel Moolenaar 				   args->act ? &nsa : NULL,
22506ebbe77SMarcel Moolenaar 				   args->oact ? &osa : NULL);
22606ebbe77SMarcel Moolenaar 
227956d3333SMarcel Moolenaar 	if (args->oact != NULL && !error) {
2285002a60fSMarcel Moolenaar 		error = copyout(&osa, args->oact, sizeof(l_sigaction_t));
22906ebbe77SMarcel Moolenaar 	}
23006ebbe77SMarcel Moolenaar 
231956d3333SMarcel Moolenaar 	return (error);
23206ebbe77SMarcel Moolenaar }
23306ebbe77SMarcel Moolenaar 
23406ebbe77SMarcel Moolenaar static int
235b40ce416SJulian Elischer linux_do_sigprocmask(struct thread *td, int how, l_sigset_t *new,
2365002a60fSMarcel Moolenaar 		     l_sigset_t *old)
23706ebbe77SMarcel Moolenaar {
238fe8cdcaeSJohn Baldwin 	sigset_t omask, nmask;
239fe8cdcaeSJohn Baldwin 	sigset_t *nmaskp;
240216af822SJohn Baldwin 	int error;
24106ebbe77SMarcel Moolenaar 
242b40ce416SJulian Elischer 	td->td_retval[0] = 0;
243d66a5066SPeter Wemm 
24419dde5cdSJohn Baldwin 	switch (how) {
24519dde5cdSJohn Baldwin 	case LINUX_SIG_BLOCK:
24619dde5cdSJohn Baldwin 		how = SIG_BLOCK;
24719dde5cdSJohn Baldwin 		break;
24819dde5cdSJohn Baldwin 	case LINUX_SIG_UNBLOCK:
24919dde5cdSJohn Baldwin 		how = SIG_UNBLOCK;
25019dde5cdSJohn Baldwin 		break;
25119dde5cdSJohn Baldwin 	case LINUX_SIG_SETMASK:
25219dde5cdSJohn Baldwin 		how = SIG_SETMASK;
25319dde5cdSJohn Baldwin 		break;
25419dde5cdSJohn Baldwin 	default:
25519dde5cdSJohn Baldwin 		return (EINVAL);
25619dde5cdSJohn Baldwin 	}
25706ebbe77SMarcel Moolenaar 	if (new != NULL) {
258fe8cdcaeSJohn Baldwin 		linux_to_bsd_sigset(new, &nmask);
259fe8cdcaeSJohn Baldwin 		nmaskp = &nmask;
260fe8cdcaeSJohn Baldwin 	} else
261fe8cdcaeSJohn Baldwin 		nmaskp = NULL;
26219dde5cdSJohn Baldwin 	error = kern_sigprocmask(td, how, nmaskp, &omask, 0);
2632f7ed219SJohn Baldwin 	if (error == 0 && old != NULL)
264fe8cdcaeSJohn Baldwin 		bsd_to_linux_sigset(&omask, old);
26506ebbe77SMarcel Moolenaar 
266956d3333SMarcel Moolenaar 	return (error);
26706ebbe77SMarcel Moolenaar }
26806ebbe77SMarcel Moolenaar 
26906ebbe77SMarcel Moolenaar int
270b40ce416SJulian Elischer linux_sigprocmask(struct thread *td, struct linux_sigprocmask_args *args)
27106ebbe77SMarcel Moolenaar {
2725002a60fSMarcel Moolenaar 	l_osigset_t mask;
2735002a60fSMarcel Moolenaar 	l_sigset_t set, oset;
27406ebbe77SMarcel Moolenaar 	int error;
27506ebbe77SMarcel Moolenaar 
27606ebbe77SMarcel Moolenaar #ifdef DEBUG
27724593369SJonathan Lemon 	if (ldebug(sigprocmask))
27824593369SJonathan Lemon 		printf(ARGS(sigprocmask, "%d, *, *"), args->how);
27906ebbe77SMarcel Moolenaar #endif
28006ebbe77SMarcel Moolenaar 
28106ebbe77SMarcel Moolenaar 	if (args->mask != NULL) {
2825002a60fSMarcel Moolenaar 		error = copyin(args->mask, &mask, sizeof(l_osigset_t));
28306ebbe77SMarcel Moolenaar 		if (error)
284956d3333SMarcel Moolenaar 			return (error);
285956d3333SMarcel Moolenaar 		LINUX_SIGEMPTYSET(set);
286956d3333SMarcel Moolenaar 		set.__bits[0] = mask;
28706ebbe77SMarcel Moolenaar 	}
28806ebbe77SMarcel Moolenaar 
289b40ce416SJulian Elischer 	error = linux_do_sigprocmask(td, args->how,
290956d3333SMarcel Moolenaar 				     args->mask ? &set : NULL,
291956d3333SMarcel Moolenaar 				     args->omask ? &oset : NULL);
29206ebbe77SMarcel Moolenaar 
293956d3333SMarcel Moolenaar 	if (args->omask != NULL && !error) {
294956d3333SMarcel Moolenaar 		mask = oset.__bits[0];
2955002a60fSMarcel Moolenaar 		error = copyout(&mask, args->omask, sizeof(l_osigset_t));
29606ebbe77SMarcel Moolenaar 	}
29706ebbe77SMarcel Moolenaar 
298956d3333SMarcel Moolenaar 	return (error);
29906ebbe77SMarcel Moolenaar }
30006ebbe77SMarcel Moolenaar 
30106ebbe77SMarcel Moolenaar int
302b40ce416SJulian Elischer linux_rt_sigprocmask(struct thread *td, struct linux_rt_sigprocmask_args *args)
30306ebbe77SMarcel Moolenaar {
3045002a60fSMarcel Moolenaar 	l_sigset_t set, oset;
30506ebbe77SMarcel Moolenaar 	int error;
30606ebbe77SMarcel Moolenaar 
30706ebbe77SMarcel Moolenaar #ifdef DEBUG
30824593369SJonathan Lemon 	if (ldebug(rt_sigprocmask))
30924593369SJonathan Lemon 		printf(ARGS(rt_sigprocmask, "%d, %p, %p, %ld"),
31024593369SJonathan Lemon 		    args->how, (void *)args->mask,
3115231fb20SDavid E. O'Brien 		    (void *)args->omask, (long)args->sigsetsize);
31206ebbe77SMarcel Moolenaar #endif
31306ebbe77SMarcel Moolenaar 
3145002a60fSMarcel Moolenaar 	if (args->sigsetsize != sizeof(l_sigset_t))
31506ebbe77SMarcel Moolenaar 		return EINVAL;
31606ebbe77SMarcel Moolenaar 
31706ebbe77SMarcel Moolenaar 	if (args->mask != NULL) {
3185002a60fSMarcel Moolenaar 		error = copyin(args->mask, &set, sizeof(l_sigset_t));
31906ebbe77SMarcel Moolenaar 		if (error)
320956d3333SMarcel Moolenaar 			return (error);
32106ebbe77SMarcel Moolenaar 	}
32206ebbe77SMarcel Moolenaar 
323b40ce416SJulian Elischer 	error = linux_do_sigprocmask(td, args->how,
324956d3333SMarcel Moolenaar 				     args->mask ? &set : NULL,
325956d3333SMarcel Moolenaar 				     args->omask ? &oset : NULL);
32606ebbe77SMarcel Moolenaar 
327956d3333SMarcel Moolenaar 	if (args->omask != NULL && !error) {
3285002a60fSMarcel Moolenaar 		error = copyout(&oset, args->omask, sizeof(l_sigset_t));
32906ebbe77SMarcel Moolenaar 	}
33006ebbe77SMarcel Moolenaar 
331956d3333SMarcel Moolenaar 	return (error);
332c21dee17SSøren Schmidt }
333c21dee17SSøren Schmidt 
334c21dee17SSøren Schmidt int
335b40ce416SJulian Elischer linux_sgetmask(struct thread *td, struct linux_sgetmask_args *args)
336c21dee17SSøren Schmidt {
337b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
3385002a60fSMarcel Moolenaar 	l_sigset_t mask;
339956d3333SMarcel Moolenaar 
340c21dee17SSøren Schmidt #ifdef DEBUG
3415002a60fSMarcel Moolenaar 	if (ldebug(sgetmask))
3425002a60fSMarcel Moolenaar 		printf(ARGS(sgetmask, ""));
343c21dee17SSøren Schmidt #endif
344956d3333SMarcel Moolenaar 
345216af822SJohn Baldwin 	PROC_LOCK(p);
3464093529dSJeff Roberson 	bsd_to_linux_sigset(&td->td_sigmask, &mask);
347216af822SJohn Baldwin 	PROC_UNLOCK(p);
348b40ce416SJulian Elischer 	td->td_retval[0] = mask.__bits[0];
349956d3333SMarcel Moolenaar 	return (0);
350c21dee17SSøren Schmidt }
351c21dee17SSøren Schmidt 
352c21dee17SSøren Schmidt int
353b40ce416SJulian Elischer linux_ssetmask(struct thread *td, struct linux_ssetmask_args *args)
354c21dee17SSøren Schmidt {
355b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
3565002a60fSMarcel Moolenaar 	l_sigset_t lset;
357956d3333SMarcel Moolenaar 	sigset_t bset;
358c21dee17SSøren Schmidt 
359c21dee17SSøren Schmidt #ifdef DEBUG
3605002a60fSMarcel Moolenaar 	if (ldebug(ssetmask))
3615002a60fSMarcel Moolenaar 		printf(ARGS(ssetmask, "%08lx"), (unsigned long)args->mask);
362c21dee17SSøren Schmidt #endif
363d66a5066SPeter Wemm 
364216af822SJohn Baldwin 	PROC_LOCK(p);
3654093529dSJeff Roberson 	bsd_to_linux_sigset(&td->td_sigmask, &lset);
366b40ce416SJulian Elischer 	td->td_retval[0] = lset.__bits[0];
367956d3333SMarcel Moolenaar 	LINUX_SIGEMPTYSET(lset);
368956d3333SMarcel Moolenaar 	lset.__bits[0] = args->mask;
369956d3333SMarcel Moolenaar 	linux_to_bsd_sigset(&lset, &bset);
3704093529dSJeff Roberson 	td->td_sigmask = bset;
3714093529dSJeff Roberson 	SIG_CANTMASK(td->td_sigmask);
3724093529dSJeff Roberson 	signotify(td);
373216af822SJohn Baldwin 	PROC_UNLOCK(p);
374956d3333SMarcel Moolenaar 	return (0);
375c21dee17SSøren Schmidt }
376c21dee17SSøren Schmidt 
3775d58e285STim J. Robbins /*
3785d58e285STim J. Robbins  * MPSAFE
3795d58e285STim J. Robbins  */
380c21dee17SSøren Schmidt int
381b40ce416SJulian Elischer linux_sigpending(struct thread *td, struct linux_sigpending_args *args)
382c21dee17SSøren Schmidt {
383b40ce416SJulian Elischer 	struct proc *p = td->td_proc;
384956d3333SMarcel Moolenaar 	sigset_t bset;
3855002a60fSMarcel Moolenaar 	l_sigset_t lset;
3865002a60fSMarcel Moolenaar 	l_osigset_t mask;
387c21dee17SSøren Schmidt 
388c21dee17SSøren Schmidt #ifdef DEBUG
38924593369SJonathan Lemon 	if (ldebug(sigpending))
39024593369SJonathan Lemon 		printf(ARGS(sigpending, "*"));
391c21dee17SSøren Schmidt #endif
392956d3333SMarcel Moolenaar 
393216af822SJohn Baldwin 	PROC_LOCK(p);
3941d9c5696SJuli Mallett 	bset = p->p_siglist;
3954093529dSJeff Roberson 	SIGSETOR(bset, td->td_siglist);
3964093529dSJeff Roberson 	SIGSETAND(bset, td->td_sigmask);
397216af822SJohn Baldwin 	PROC_UNLOCK(p);
3989d8643ecSJohn Baldwin 	bsd_to_linux_sigset(&bset, &lset);
399956d3333SMarcel Moolenaar 	mask = lset.__bits[0];
400956d3333SMarcel Moolenaar 	return (copyout(&mask, args->mask, sizeof(mask)));
401c21dee17SSøren Schmidt }
40217138b61SAlexander Leidinger 
40317138b61SAlexander Leidinger /*
40417138b61SAlexander Leidinger  * MPSAFE
40517138b61SAlexander Leidinger  */
40617138b61SAlexander Leidinger int
40717138b61SAlexander Leidinger linux_rt_sigpending(struct thread *td, struct linux_rt_sigpending_args *args)
40817138b61SAlexander Leidinger {
40917138b61SAlexander Leidinger 	struct proc *p = td->td_proc;
41017138b61SAlexander Leidinger 	sigset_t bset;
41117138b61SAlexander Leidinger 	l_sigset_t lset;
41217138b61SAlexander Leidinger 
41317138b61SAlexander Leidinger 	if (args->sigsetsize > sizeof(lset))
41417138b61SAlexander Leidinger 		return EINVAL;
41517138b61SAlexander Leidinger 		/* NOT REACHED */
41617138b61SAlexander Leidinger 
41717138b61SAlexander Leidinger #ifdef DEBUG
41817138b61SAlexander Leidinger 	if (ldebug(rt_sigpending))
41917138b61SAlexander Leidinger 		printf(ARGS(rt_sigpending, "*"));
42017138b61SAlexander Leidinger #endif
42117138b61SAlexander Leidinger 
42217138b61SAlexander Leidinger 	PROC_LOCK(p);
42317138b61SAlexander Leidinger 	bset = p->p_siglist;
42417138b61SAlexander Leidinger 	SIGSETOR(bset, td->td_siglist);
42517138b61SAlexander Leidinger 	SIGSETAND(bset, td->td_sigmask);
42617138b61SAlexander Leidinger 	PROC_UNLOCK(p);
42717138b61SAlexander Leidinger 	bsd_to_linux_sigset(&bset, &lset);
42817138b61SAlexander Leidinger 	return (copyout(&lset, args->set, args->sigsetsize));
42917138b61SAlexander Leidinger }
430c21dee17SSøren Schmidt 
431c9447c75SAlexander Leidinger /*
432c9447c75SAlexander Leidinger  * MPSAFE
433c9447c75SAlexander Leidinger  */
434c9447c75SAlexander Leidinger int
435c9447c75SAlexander Leidinger linux_rt_sigtimedwait(struct thread *td,
436c9447c75SAlexander Leidinger 	struct linux_rt_sigtimedwait_args *args)
437c9447c75SAlexander Leidinger {
438f3481dd9SDmitry Chagin 	int error, sig;
439c9447c75SAlexander Leidinger 	l_timeval ltv;
440c9447c75SAlexander Leidinger 	struct timeval tv;
441c9447c75SAlexander Leidinger 	struct timespec ts, *tsa;
442c9447c75SAlexander Leidinger 	l_sigset_t lset;
443c9447c75SAlexander Leidinger 	sigset_t bset;
444c9447c75SAlexander Leidinger 	l_siginfo_t linfo;
445c9447c75SAlexander Leidinger 	ksiginfo_t info;
446c9447c75SAlexander Leidinger 
447c9447c75SAlexander Leidinger #ifdef DEBUG
448c9447c75SAlexander Leidinger 	if (ldebug(rt_sigtimedwait))
449c9447c75SAlexander Leidinger 		printf(ARGS(rt_sigtimedwait, "*"));
450c9447c75SAlexander Leidinger #endif
451c9447c75SAlexander Leidinger 	if (args->sigsetsize != sizeof(l_sigset_t))
452c9447c75SAlexander Leidinger 		return (EINVAL);
453c9447c75SAlexander Leidinger 
454c9447c75SAlexander Leidinger 	if ((error = copyin(args->mask, &lset, sizeof(lset))))
455c9447c75SAlexander Leidinger 		return (error);
456c9447c75SAlexander Leidinger 	linux_to_bsd_sigset(&lset, &bset);
457c9447c75SAlexander Leidinger 
458c9447c75SAlexander Leidinger 	tsa = NULL;
459c9447c75SAlexander Leidinger 	if (args->timeout) {
460c9447c75SAlexander Leidinger 		if ((error = copyin(args->timeout, &ltv, sizeof(ltv))))
461c9447c75SAlexander Leidinger 			return (error);
462c9447c75SAlexander Leidinger #ifdef DEBUG
463c9447c75SAlexander Leidinger 		if (ldebug(rt_sigtimedwait))
4648c50c562SDmitry Chagin 			printf(LMSG("linux_rt_sigtimedwait: "
4658c50c562SDmitry Chagin 			    "incoming timeout (%d/%d)\n"),
466c9447c75SAlexander Leidinger 			    ltv.tv_sec, ltv.tv_usec);
467c9447c75SAlexander Leidinger #endif
468c9447c75SAlexander Leidinger 		tv.tv_sec = (long)ltv.tv_sec;
469c9447c75SAlexander Leidinger 		tv.tv_usec = (suseconds_t)ltv.tv_usec;
470c9447c75SAlexander Leidinger 		if (itimerfix(&tv)) {
471c9447c75SAlexander Leidinger 			/*
472c9447c75SAlexander Leidinger 			 * The timeout was invalid. Convert it to something
473c9447c75SAlexander Leidinger 			 * valid that will act as it does under Linux.
474c9447c75SAlexander Leidinger 			 */
475c9447c75SAlexander Leidinger 			tv.tv_sec += tv.tv_usec / 1000000;
476c9447c75SAlexander Leidinger 			tv.tv_usec %= 1000000;
477c9447c75SAlexander Leidinger 			if (tv.tv_usec < 0) {
478c9447c75SAlexander Leidinger 				tv.tv_sec -= 1;
479c9447c75SAlexander Leidinger 				tv.tv_usec += 1000000;
480c9447c75SAlexander Leidinger 			}
481c9447c75SAlexander Leidinger 			if (tv.tv_sec < 0)
482c9447c75SAlexander Leidinger 				timevalclear(&tv);
483c9447c75SAlexander Leidinger #ifdef DEBUG
484c9447c75SAlexander Leidinger 			if (ldebug(rt_sigtimedwait))
4858c50c562SDmitry Chagin 				printf(LMSG("linux_rt_sigtimedwait: "
4868c50c562SDmitry Chagin 				    "converted timeout (%jd/%ld)\n"),
48759038483SXin LI 				    (intmax_t)tv.tv_sec, tv.tv_usec);
488c9447c75SAlexander Leidinger #endif
489c9447c75SAlexander Leidinger 		}
490c9447c75SAlexander Leidinger 		TIMEVAL_TO_TIMESPEC(&tv, &ts);
491c9447c75SAlexander Leidinger 		tsa = &ts;
492c9447c75SAlexander Leidinger 	}
493c9447c75SAlexander Leidinger 	error = kern_sigtimedwait(td, bset, &info, tsa);
494c9447c75SAlexander Leidinger #ifdef DEBUG
495c9447c75SAlexander Leidinger 	if (ldebug(rt_sigtimedwait))
4968c50c562SDmitry Chagin 		printf(LMSG("linux_rt_sigtimedwait: "
4978c50c562SDmitry Chagin 		    "sigtimedwait returning (%d)\n"), error);
498c9447c75SAlexander Leidinger #endif
499c9447c75SAlexander Leidinger 	if (error)
500c9447c75SAlexander Leidinger 		return (error);
501c9447c75SAlexander Leidinger 
502f3481dd9SDmitry Chagin 	sig = BSD_TO_LINUX_SIGNAL(info.ksi_signo);
503f3481dd9SDmitry Chagin 
504c9447c75SAlexander Leidinger 	if (args->ptr) {
505c9447c75SAlexander Leidinger 		memset(&linfo, 0, sizeof(linfo));
506f3481dd9SDmitry Chagin 		ksiginfo_to_lsiginfo(&info, &linfo, sig);
507c9447c75SAlexander Leidinger 		error = copyout(&linfo, args->ptr, sizeof(linfo));
508c9447c75SAlexander Leidinger 	}
509f3481dd9SDmitry Chagin 	if (error == 0)
510f3481dd9SDmitry Chagin 		td->td_retval[0] = sig;
511c9447c75SAlexander Leidinger 
512c9447c75SAlexander Leidinger 	return (error);
513c9447c75SAlexander Leidinger }
514c9447c75SAlexander Leidinger 
515c21dee17SSøren Schmidt int
516b40ce416SJulian Elischer linux_kill(struct thread *td, struct linux_kill_args *args)
517c21dee17SSøren Schmidt {
518ef04503dSPeter Wemm 	struct kill_args /* {
519c21dee17SSøren Schmidt 	    int pid;
520c21dee17SSøren Schmidt 	    int signum;
521ef04503dSPeter Wemm 	} */ tmp;
522c21dee17SSøren Schmidt 
523c21dee17SSøren Schmidt #ifdef DEBUG
52424593369SJonathan Lemon 	if (ldebug(kill))
52524593369SJonathan Lemon 		printf(ARGS(kill, "%d, %d"), args->pid, args->signum);
526c21dee17SSøren Schmidt #endif
527956d3333SMarcel Moolenaar 
528956d3333SMarcel Moolenaar 	/*
529956d3333SMarcel Moolenaar 	 * Allow signal 0 as a means to check for privileges
530956d3333SMarcel Moolenaar 	 */
53164742216SAlexander Leidinger 	if (!LINUX_SIG_VALID(args->signum) && args->signum != 0)
5329a6a64d3SDmitry Chagin 		return (EINVAL);
533956d3333SMarcel Moolenaar 
534956d3333SMarcel Moolenaar 	if (args->signum > 0 && args->signum <= LINUX_SIGTBLSZ)
535956d3333SMarcel Moolenaar 		tmp.signum = linux_to_bsd_signal[_SIG_IDX(args->signum)];
536956d3333SMarcel Moolenaar 	else
537956d3333SMarcel Moolenaar 		tmp.signum = args->signum;
538956d3333SMarcel Moolenaar 
539c21dee17SSøren Schmidt 	tmp.pid = args->pid;
5408451d0ddSKip Macy 	return (sys_kill(td, &tmp));
541c21dee17SSøren Schmidt }
5429b44bfc5SAlexander Leidinger 
543aa8b2011SKonstantin Belousov static int
544*81338031SDmitry Chagin linux_do_tkill(struct thread *td, struct thread *tdt, ksiginfo_t *ksi)
545aa8b2011SKonstantin Belousov {
546aa8b2011SKonstantin Belousov 	struct proc *p;
547aa8b2011SKonstantin Belousov 	int error;
548aa8b2011SKonstantin Belousov 
549*81338031SDmitry Chagin 	p = tdt->td_proc;
550*81338031SDmitry Chagin 	AUDIT_ARG_SIGNUM(ksi->ksi_signo);
551*81338031SDmitry Chagin 	AUDIT_ARG_PID(p->p_pid);
55214961ba7SRobert Watson 	AUDIT_ARG_PROCESS(p);
553*81338031SDmitry Chagin 
554*81338031SDmitry Chagin 	error = p_cansignal(td, p, ksi->ksi_signo);
555*81338031SDmitry Chagin 	if (error != 0 || ksi->ksi_signo == 0)
556aa8b2011SKonstantin Belousov 		goto out;
557aa8b2011SKonstantin Belousov 
558*81338031SDmitry Chagin 	tdksignal(tdt, ksi->ksi_signo, ksi);
559aa8b2011SKonstantin Belousov 
560aa8b2011SKonstantin Belousov out:
561aa8b2011SKonstantin Belousov 	PROC_UNLOCK(p);
562aa8b2011SKonstantin Belousov 	return (error);
563aa8b2011SKonstantin Belousov }
564aa8b2011SKonstantin Belousov 
5659b44bfc5SAlexander Leidinger int
5669b44bfc5SAlexander Leidinger linux_tgkill(struct thread *td, struct linux_tgkill_args *args)
5679b44bfc5SAlexander Leidinger {
568*81338031SDmitry Chagin 	struct thread *tdt;
569*81338031SDmitry Chagin 	ksiginfo_t ksi;
570*81338031SDmitry Chagin 	int sig;
5719b44bfc5SAlexander Leidinger 
5729b44bfc5SAlexander Leidinger #ifdef DEBUG
5739b44bfc5SAlexander Leidinger 	if (ldebug(tgkill))
574*81338031SDmitry Chagin 		printf(ARGS(tgkill, "%d, %d, %d"),
575*81338031SDmitry Chagin 		    args->tgid, args->pid, args->sig);
5769b44bfc5SAlexander Leidinger #endif
577*81338031SDmitry Chagin 
578aa8b2011SKonstantin Belousov 	if (args->pid <= 0 || args->tgid <=0)
579aa8b2011SKonstantin Belousov 		return (EINVAL);
5809b44bfc5SAlexander Leidinger 
581*81338031SDmitry Chagin 	/*
582*81338031SDmitry Chagin 	 * Allow signal 0 as a means to check for privileges
583*81338031SDmitry Chagin 	 */
584*81338031SDmitry Chagin 	if (!LINUX_SIG_VALID(args->sig) && args->sig != 0)
585*81338031SDmitry Chagin 		return (EINVAL);
586*81338031SDmitry Chagin 
587*81338031SDmitry Chagin 	if (args->sig > 0 && args->sig <= LINUX_SIGTBLSZ)
588*81338031SDmitry Chagin 		sig = linux_to_bsd_signal[_SIG_IDX(args->sig)];
589*81338031SDmitry Chagin 	else
590*81338031SDmitry Chagin 		sig = args->sig;
591*81338031SDmitry Chagin 
592*81338031SDmitry Chagin 	tdt = linux_tdfind(td, args->pid, args->tgid);
593*81338031SDmitry Chagin 	if (tdt == NULL)
594*81338031SDmitry Chagin 		return (ESRCH);
595*81338031SDmitry Chagin 
596*81338031SDmitry Chagin 	ksiginfo_init(&ksi);
597*81338031SDmitry Chagin 	ksi.ksi_signo = sig;
598*81338031SDmitry Chagin 	ksi.ksi_code = LINUX_SI_TKILL;
599*81338031SDmitry Chagin 	ksi.ksi_errno = 0;
600*81338031SDmitry Chagin 	ksi.ksi_pid = td->td_proc->p_pid;
601*81338031SDmitry Chagin 	ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid;
602*81338031SDmitry Chagin 	return (linux_do_tkill(td, tdt, &ksi));
6039b44bfc5SAlexander Leidinger }
6049b44bfc5SAlexander Leidinger 
605*81338031SDmitry Chagin /*
606*81338031SDmitry Chagin  * Deprecated since 2.5.75. Replaced by tgkill().
607*81338031SDmitry Chagin  */
6089b44bfc5SAlexander Leidinger int
6099b44bfc5SAlexander Leidinger linux_tkill(struct thread *td, struct linux_tkill_args *args)
6109b44bfc5SAlexander Leidinger {
611*81338031SDmitry Chagin 	struct thread *tdt;
612*81338031SDmitry Chagin 	ksiginfo_t ksi;
613*81338031SDmitry Chagin 	int sig;
614*81338031SDmitry Chagin 
6159b44bfc5SAlexander Leidinger #ifdef DEBUG
6169b44bfc5SAlexander Leidinger 	if (ldebug(tkill))
6179b44bfc5SAlexander Leidinger 		printf(ARGS(tkill, "%i, %i"), args->tid, args->sig);
6189b44bfc5SAlexander Leidinger #endif
619aa8b2011SKonstantin Belousov 	if (args->tid <= 0)
620aa8b2011SKonstantin Belousov 		return (EINVAL);
6219b44bfc5SAlexander Leidinger 
622*81338031SDmitry Chagin 	if (!LINUX_SIG_VALID(args->sig))
623*81338031SDmitry Chagin 		return (EINVAL);
624*81338031SDmitry Chagin 
625*81338031SDmitry Chagin 	if (args->sig > 0 && args->sig <= LINUX_SIGTBLSZ)
626*81338031SDmitry Chagin 		sig = linux_to_bsd_signal[_SIG_IDX(args->sig)];
627*81338031SDmitry Chagin 	else
628*81338031SDmitry Chagin 		sig = args->sig;
629*81338031SDmitry Chagin 
630*81338031SDmitry Chagin 	tdt = linux_tdfind(td, args->tid, -1);
631*81338031SDmitry Chagin 	if (tdt == NULL)
632*81338031SDmitry Chagin 		return (ESRCH);
633*81338031SDmitry Chagin 
634*81338031SDmitry Chagin 	ksiginfo_init(&ksi);
635*81338031SDmitry Chagin 	ksi.ksi_signo = sig;
636*81338031SDmitry Chagin 	ksi.ksi_code = LINUX_SI_TKILL;
637*81338031SDmitry Chagin 	ksi.ksi_errno = 0;
638*81338031SDmitry Chagin 	ksi.ksi_pid = td->td_proc->p_pid;
639*81338031SDmitry Chagin 	ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid;
640*81338031SDmitry Chagin 	return (linux_do_tkill(td, tdt, &ksi));
641aa8b2011SKonstantin Belousov }
642aa8b2011SKonstantin Belousov 
643aa8b2011SKonstantin Belousov void
644aa8b2011SKonstantin Belousov ksiginfo_to_lsiginfo(ksiginfo_t *ksi, l_siginfo_t *lsi, l_int sig)
645aa8b2011SKonstantin Belousov {
646aa8b2011SKonstantin Belousov 
647aa8b2011SKonstantin Belousov 	lsi->lsi_signo = sig;
648aa8b2011SKonstantin Belousov 	lsi->lsi_code = ksi->ksi_code;
649aa8b2011SKonstantin Belousov 
650aa8b2011SKonstantin Belousov 	switch (sig) {
651aa8b2011SKonstantin Belousov 	case LINUX_SIGPOLL:
652aa8b2011SKonstantin Belousov 		/* XXX si_fd? */
653aa8b2011SKonstantin Belousov 		lsi->lsi_band = ksi->ksi_band;
654aa8b2011SKonstantin Belousov 		break;
655aa8b2011SKonstantin Belousov 	case LINUX_SIGCHLD:
656aa8b2011SKonstantin Belousov 		lsi->lsi_pid = ksi->ksi_pid;
657aa8b2011SKonstantin Belousov 		lsi->lsi_uid = ksi->ksi_uid;
658aa8b2011SKonstantin Belousov 		lsi->lsi_status = ksi->ksi_status;
659aa8b2011SKonstantin Belousov 		break;
660aa8b2011SKonstantin Belousov 	case LINUX_SIGBUS:
661aa8b2011SKonstantin Belousov 	case LINUX_SIGILL:
662aa8b2011SKonstantin Belousov 	case LINUX_SIGFPE:
663aa8b2011SKonstantin Belousov 	case LINUX_SIGSEGV:
664aa8b2011SKonstantin Belousov 		lsi->lsi_addr = PTROUT(ksi->ksi_addr);
665aa8b2011SKonstantin Belousov 		break;
666aa8b2011SKonstantin Belousov 	default:
667aa8b2011SKonstantin Belousov 		/* XXX SI_TIMER etc... */
668aa8b2011SKonstantin Belousov 		lsi->lsi_pid = ksi->ksi_pid;
669aa8b2011SKonstantin Belousov 		lsi->lsi_uid = ksi->ksi_uid;
670aa8b2011SKonstantin Belousov 		break;
671aa8b2011SKonstantin Belousov 	}
67209d6cb0aSDmitry Chagin 	if (sig >= LINUX_SIGRTMIN) {
67309d6cb0aSDmitry Chagin 		lsi->lsi_int = ksi->ksi_info.si_value.sival_int;
67409d6cb0aSDmitry Chagin 		lsi->lsi_ptr = PTROUT(ksi->ksi_info.si_value.sival_ptr);
67509d6cb0aSDmitry Chagin 	}
6769b44bfc5SAlexander Leidinger }
677