svr4_ipc.c revision 148541
190075Sobrien/*-
290075Sobrien * Copyright (c) 1995 The NetBSD Foundation, Inc.
390075Sobrien * All rights reserved.
490075Sobrien *
590075Sobrien * This code is derived from software contributed to The NetBSD Foundation
690075Sobrien * by Christos Zoulas.
790075Sobrien *
890075Sobrien * Redistribution and use in source and binary forms, with or without
990075Sobrien * modification, are permitted provided that the following conditions
1090075Sobrien * are met:
1190075Sobrien * 1. Redistributions of source code must retain the above copyright
1290075Sobrien *    notice, this list of conditions and the following disclaimer.
1390075Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1490075Sobrien *    notice, this list of conditions and the following disclaimer in the
1590075Sobrien *    documentation and/or other materials provided with the distribution.
1690075Sobrien * 3. All advertising materials mentioning features or use of this software
1790075Sobrien *    must display the following acknowledgement:
1890075Sobrien *        This product includes software developed by the NetBSD
1990075Sobrien *        Foundation, Inc. and its contributors.
2090075Sobrien * 4. Neither the name of The NetBSD Foundation nor the names of its
2190075Sobrien *    contributors may be used to endorse or promote products derived
2290075Sobrien *    from this software without specific prior written permission.
2390075Sobrien *
2490075Sobrien * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2590075Sobrien * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2690075Sobrien * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2790075Sobrien * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2890075Sobrien * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2990075Sobrien * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
3090075Sobrien * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
3190075Sobrien * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32169689Skan * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33169689Skan * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34169689Skan * POSSIBILITY OF SUCH DAMAGE.
3590075Sobrien */
3690075Sobrien/*-
3790075Sobrien * Portions of this code have been derived from software contributed
38 * to the FreeBSD Project by Mark Newton.
39 *
40 * Copyright (c) 1999 Mark Newton
41 * All rights reserved.
42 *
43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions
45 * are met:
46 * 1. Redistributions of source code must retain the above copyright
47 *    notice, this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright
49 *    notice, this list of conditions and the following disclaimer in the
50 *    documentation and/or other materials provided with the distribution.
51 * 3. The name of the author may not be used to endorse or promote products
52 *    derived from this software without specific prior written permission
53 *
54 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
55 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
56 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
57 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
58 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
59 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
60 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
61 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
62 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
63 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64 *
65 * XXX- This code is presently a no-op on FreeBSD (and isn't compiled due
66 * to preprocessor conditionals).  A nice project for a kernel hacking
67 * novice might be to MakeItGo, but I have more important fish to fry
68 * at present.
69 *
70 *	Derived from: $NetBSD: svr4_ipc.c,v 1.7 1998/10/19 22:43:00 tron Exp $
71 */
72
73#include <sys/cdefs.h>
74__FBSDID("$FreeBSD: head/sys/compat/svr4/svr4_ipc.c 148541 2005-07-29 19:41:04Z jhb $");
75
76#include "opt_sysvipc.h"
77
78#include <sys/param.h>
79#include <sys/ipc.h>
80#include <sys/msg.h>
81#include <sys/proc.h>
82#include <sys/sem.h>
83#include <sys/shm.h>
84#include <sys/syscallsubr.h>
85#include <sys/sysproto.h>
86#include <sys/systm.h>
87#include <sys/time.h>
88
89#include <compat/svr4/svr4.h>
90#include <compat/svr4/svr4_types.h>
91#include <compat/svr4/svr4_signal.h>
92#include <compat/svr4/svr4_proto.h>
93#include <compat/svr4/svr4_util.h>
94#include <compat/svr4/svr4_ipc.h>
95
96#if defined(SYSVMSG) || defined(SYSVSHM) || defined(SYSVSEM)
97static void svr4_to_bsd_ipc_perm(const struct svr4_ipc_perm *,
98				      struct ipc_perm *);
99static void bsd_to_svr4_ipc_perm(const struct ipc_perm *,
100				      struct svr4_ipc_perm *);
101#endif
102
103#ifdef SYSVSEM
104static void bsd_to_svr4_semid_ds(const struct semid_ds *,
105				      struct svr4_semid_ds *);
106static void svr4_to_bsd_semid_ds(const struct svr4_semid_ds *,
107				      struct semid_ds *);
108static int svr4_setsemun(caddr_t *sgp, union semun **argp,
109			      union semun *usp);
110static int svr4_semop(struct thread *, void *);
111static int svr4_semget(struct thread *, void *);
112static int svr4_semctl(struct thread *, void *);
113#endif
114
115#ifdef SYSVMSG
116static void bsd_to_svr4_msqid_ds(const struct msqid_ds *,
117				      struct svr4_msqid_ds *);
118static void svr4_to_bsd_msqid_ds(const struct svr4_msqid_ds *,
119				      struct msqid_ds *);
120static int svr4_msgsnd(struct thread *, void *);
121static int svr4_msgrcv(struct thread *, void *);
122static int svr4_msgget(struct thread *, void *);
123static int svr4_msgctl(struct thread *, void *);
124#endif
125
126#ifdef SYSVSHM
127static void bsd_to_svr4_shmid_ds(const struct shmid_ds *,
128				      struct svr4_shmid_ds *);
129static void svr4_to_bsd_shmid_ds(const struct svr4_shmid_ds *,
130				      struct shmid_ds *);
131static int svr4_shmat(struct thread *, void *);
132static int svr4_shmdt(struct thread *, void *);
133static int svr4_shmget(struct thread *, void *);
134static int svr4_shmctl(struct thread *, void *);
135#endif
136
137#if defined(SYSVMSG) || defined(SYSVSHM) || defined(SYSVSEM)
138
139static void
140svr4_to_bsd_ipc_perm(spp, bpp)
141	const struct svr4_ipc_perm *spp;
142	struct ipc_perm *bpp;
143{
144	bpp->key = spp->key;
145	bpp->uid = spp->uid;
146	bpp->gid = spp->gid;
147	bpp->cuid = spp->cuid;
148	bpp->cgid = spp->cgid;
149	bpp->mode = spp->mode;
150	bpp->seq = spp->seq;
151}
152
153static void
154bsd_to_svr4_ipc_perm(bpp, spp)
155	const struct ipc_perm *bpp;
156	struct svr4_ipc_perm *spp;
157{
158	spp->key = bpp->key;
159	spp->uid = bpp->uid;
160	spp->gid = bpp->gid;
161	spp->cuid = bpp->cuid;
162	spp->cgid = bpp->cgid;
163	spp->mode = bpp->mode;
164	spp->seq = bpp->seq;
165}
166#endif
167
168#ifdef SYSVSEM
169static void
170bsd_to_svr4_semid_ds(bds, sds)
171	const struct semid_ds *bds;
172	struct svr4_semid_ds *sds;
173{
174	bsd_to_svr4_ipc_perm(&bds->sem_perm, &sds->sem_perm);
175	sds->sem_base = (struct svr4_sem *) bds->sem_base;
176	sds->sem_nsems = bds->sem_nsems;
177	sds->sem_otime = bds->sem_otime;
178	sds->sem_pad1 = bds->sem_pad1;
179	sds->sem_ctime = bds->sem_ctime;
180	sds->sem_pad2 = bds->sem_pad2;
181}
182
183static void
184svr4_to_bsd_semid_ds(sds, bds)
185	const struct svr4_semid_ds *sds;
186	struct semid_ds *bds;
187{
188	svr4_to_bsd_ipc_perm(&sds->sem_perm, &bds->sem_perm);
189	bds->sem_base = (struct sem *) bds->sem_base;
190	bds->sem_nsems = sds->sem_nsems;
191	bds->sem_otime = sds->sem_otime;
192	bds->sem_pad1 = sds->sem_pad1;
193	bds->sem_ctime = sds->sem_ctime;
194	bds->sem_pad2 = sds->sem_pad2;
195}
196
197static int
198svr4_setsemun(sgp, argp, usp)
199	caddr_t *sgp;
200	union semun **argp;
201	union semun *usp;
202{
203	*argp = stackgap_alloc(sgp, sizeof(union semun));
204	return copyout((caddr_t)usp, *argp, sizeof(union semun));
205}
206
207struct svr4_sys_semctl_args {
208	int what;
209	int semid;
210	int semnum;
211	int cmd;
212	union semun arg;
213};
214
215static int
216svr4_semctl(td, v)
217	struct thread *td;
218	void *v;
219{
220	int error;
221	struct svr4_sys_semctl_args *uap = v;
222	struct __semctl_args ap;
223	struct svr4_semid_ds ss;
224	struct semid_ds bs, *bsp;
225	caddr_t sg = stackgap_init();
226
227	ap.semid = uap->semid;
228	ap.semnum = uap->semnum;
229
230	switch (uap->cmd) {
231	case SVR4_SEM_GETZCNT:
232	case SVR4_SEM_GETNCNT:
233	case SVR4_SEM_GETPID:
234	case SVR4_SEM_GETVAL:
235		switch (uap->cmd) {
236		case SVR4_SEM_GETZCNT:
237			ap.cmd = GETZCNT;
238			break;
239		case SVR4_SEM_GETNCNT:
240			ap.cmd = GETNCNT;
241			break;
242		case SVR4_SEM_GETPID:
243			ap.cmd = GETPID;
244			break;
245		case SVR4_SEM_GETVAL:
246			ap.cmd = GETVAL;
247			break;
248		}
249		return __semctl(td, &ap);
250
251	case SVR4_SEM_SETVAL:
252		error = svr4_setsemun(&sg, &ap.arg, &uap->arg);
253		if (error)
254			return error;
255		ap.cmd = SETVAL;
256		return __semctl(td, &ap);
257
258	case SVR4_SEM_GETALL:
259		error = svr4_setsemun(&sg, &ap.arg, &uap->arg);
260		if (error)
261			return error;
262		ap.cmd = GETVAL;
263		return __semctl(td, &ap);
264
265	case SVR4_SEM_SETALL:
266		error = svr4_setsemun(&sg, &ap.arg, &uap->arg);
267		if (error)
268			return error;
269		ap.cmd = SETVAL;
270		return __semctl(td, &ap);
271
272	case SVR4_IPC_STAT:
273                ap.cmd = IPC_STAT;
274		bsp = stackgap_alloc(&sg, sizeof(bs));
275		error = svr4_setsemun(&sg, &ap.arg,
276				      (union semun *)&bsp);
277		if (error)
278			return error;
279                if ((error = __semctl(td, &ap)) != 0)
280                        return error;
281		error = copyin((caddr_t)bsp, (caddr_t)&bs, sizeof(bs));
282                if (error)
283                        return error;
284                bsd_to_svr4_semid_ds(&bs, &ss);
285		return copyout(&ss, uap->arg.buf, sizeof(ss));
286
287	case SVR4_IPC_SET:
288		ap.cmd = IPC_SET;
289		bsp = stackgap_alloc(&sg, sizeof(bs));
290		error = svr4_setsemun(&sg, &ap.arg,
291				      (union semun *)&bsp);
292		if (error)
293			return error;
294		error = copyin(uap->arg.buf, (caddr_t) &ss, sizeof ss);
295                if (error)
296                        return error;
297                svr4_to_bsd_semid_ds(&ss, &bs);
298		error = copyout(&bs, bsp, sizeof(bs));
299                if (error)
300                        return error;
301		return __semctl(td, &ap);
302
303	case SVR4_IPC_RMID:
304		ap.cmd = IPC_RMID;
305		bsp = stackgap_alloc(&sg, sizeof(bs));
306		error = svr4_setsemun(&sg, &ap.arg,
307				      (union semun *)&bsp);
308		if (error)
309			return error;
310		error = copyin(uap->arg.buf, &ss, sizeof ss);
311                if (error)
312                        return error;
313                svr4_to_bsd_semid_ds(&ss, &bs);
314		error = copyout(&bs, bsp, sizeof(bs));
315		if (error)
316			return error;
317		return __semctl(td, &ap);
318
319	default:
320		return EINVAL;
321	}
322}
323
324struct svr4_sys_semget_args {
325	int what;
326	svr4_key_t key;
327	int nsems;
328	int semflg;
329};
330
331static int
332svr4_semget(td, v)
333	struct thread *td;
334	void *v;
335{
336	struct svr4_sys_semget_args *uap = v;
337	struct semget_args ap;
338
339	ap.key = uap->key;
340	ap.nsems = uap->nsems;
341	ap.semflg = uap->semflg;
342
343	return semget(td, &ap);
344}
345
346struct svr4_sys_semop_args {
347	int what;
348	int semid;
349	struct svr4_sembuf * sops;
350	u_int nsops;
351};
352
353static int
354svr4_semop(td, v)
355	struct thread *td;
356	void *v;
357{
358	struct svr4_sys_semop_args *uap = v;
359	struct semop_args ap;
360
361	ap.semid = uap->semid;
362	/* These are the same */
363	ap.sops = (struct sembuf *) uap->sops;
364	ap.nsops = uap->nsops;
365
366	return semop(td, &ap);
367}
368
369int
370svr4_sys_semsys(td, uap)
371	struct thread *td;
372	struct svr4_sys_semsys_args *uap;
373{
374
375	DPRINTF(("svr4_semsys(%d)\n", uap->what));
376
377	switch (uap->what) {
378	case SVR4_semctl:
379		return svr4_semctl(td, uap);
380	case SVR4_semget:
381		return svr4_semget(td, uap);
382	case SVR4_semop:
383		return svr4_semop(td, uap);
384	default:
385		return EINVAL;
386	}
387}
388
389MODULE_DEPEND(svr4elf, sysvsem, 1, 1, 1);
390#endif
391
392#ifdef SYSVMSG
393static void
394bsd_to_svr4_msqid_ds(bds, sds)
395	const struct msqid_ds *bds;
396	struct svr4_msqid_ds *sds;
397{
398	bsd_to_svr4_ipc_perm(&bds->msg_perm, &sds->msg_perm);
399	sds->msg_first = (struct svr4_msg *) bds->msg_first;
400	sds->msg_last = (struct svr4_msg *) bds->msg_last;
401	sds->msg_cbytes = bds->msg_cbytes;
402	sds->msg_qnum = bds->msg_qnum;
403	sds->msg_qbytes = bds->msg_qbytes;
404	sds->msg_lspid = bds->msg_lspid;
405	sds->msg_lrpid = bds->msg_lrpid;
406	sds->msg_stime = bds->msg_stime;
407	sds->msg_pad1 = bds->msg_pad1;
408	sds->msg_rtime = bds->msg_rtime;
409	sds->msg_pad2 = bds->msg_pad2;
410	sds->msg_ctime = bds->msg_ctime;
411	sds->msg_pad3 = bds->msg_pad3;
412
413	/* use the padding for the rest of the fields */
414	{
415		const short *pad = (const short *) bds->msg_pad4;
416		sds->msg_cv = pad[0];
417		sds->msg_qnum_cv = pad[1];
418	}
419}
420
421static void
422svr4_to_bsd_msqid_ds(sds, bds)
423	const struct svr4_msqid_ds *sds;
424	struct msqid_ds *bds;
425{
426	svr4_to_bsd_ipc_perm(&sds->msg_perm, &bds->msg_perm);
427	bds->msg_first = (struct msg *) sds->msg_first;
428	bds->msg_last = (struct msg *) sds->msg_last;
429	bds->msg_cbytes = sds->msg_cbytes;
430	bds->msg_qnum = sds->msg_qnum;
431	bds->msg_qbytes = sds->msg_qbytes;
432	bds->msg_lspid = sds->msg_lspid;
433	bds->msg_lrpid = sds->msg_lrpid;
434	bds->msg_stime = sds->msg_stime;
435	bds->msg_pad1 = sds->msg_pad1;
436	bds->msg_rtime = sds->msg_rtime;
437	bds->msg_pad2 = sds->msg_pad2;
438	bds->msg_ctime = sds->msg_ctime;
439	bds->msg_pad3 = sds->msg_pad3;
440
441	/* use the padding for the rest of the fields */
442	{
443		short *pad = (short *) bds->msg_pad4;
444		pad[0] = sds->msg_cv;
445		pad[1] = sds->msg_qnum_cv;
446	}
447}
448
449struct svr4_sys_msgsnd_args {
450	int what;
451	int msqid;
452	void * msgp;
453	size_t msgsz;
454	int msgflg;
455};
456
457static int
458svr4_msgsnd(td, v)
459	struct thread *td;
460	void *v;
461{
462	struct svr4_sys_msgsnd_args *uap = v;
463	struct msgsnd_args ap;
464
465	ap.msqid = uap->msqid;
466	ap.msgp = uap->msgp;
467	ap.msgsz = uap->msgsz;
468	ap.msgflg = uap->msgflg;
469
470	return msgsnd(td, &ap);
471}
472
473struct svr4_sys_msgrcv_args {
474	int what;
475	int msqid;
476	void * msgp;
477	size_t msgsz;
478	long msgtyp;
479	int msgflg;
480};
481
482static int
483svr4_msgrcv(td, v)
484	struct thread *td;
485	void *v;
486{
487	struct svr4_sys_msgrcv_args *uap = v;
488	struct msgrcv_args ap;
489
490	ap.msqid = uap->msqid;
491	ap.msgp = uap->msgp;
492	ap.msgsz = uap->msgsz;
493	ap.msgtyp = uap->msgtyp;
494	ap.msgflg = uap->msgflg;
495
496	return msgrcv(td, &ap);
497}
498
499struct svr4_sys_msgget_args {
500	int what;
501	svr4_key_t key;
502	int msgflg;
503};
504
505static int
506svr4_msgget(td, v)
507	struct thread *td;
508	void *v;
509{
510	struct svr4_sys_msgget_args *uap = v;
511	struct msgget_args ap;
512
513	ap.key = uap->key;
514	ap.msgflg = uap->msgflg;
515
516	return msgget(td, &ap);
517}
518
519struct svr4_sys_msgctl_args {
520	int what;
521	int msqid;
522	int cmd;
523	struct svr4_msqid_ds * buf;
524};
525
526static int
527svr4_msgctl(td, v)
528	struct thread *td;
529	void *v;
530{
531	struct svr4_sys_msgctl_args *uap = v;
532	struct svr4_msqid_ds ss;
533	struct msqid_ds bs;
534	int error;
535
536	switch (uap->cmd) {
537	case SVR4_IPC_STAT:
538		error = kern_msgctl(td, uap->msqid, IPC_STAT, &bs);
539		if (error)
540			return error;
541		bsd_to_svr4_msqid_ds(&bs, &ss);
542		return copyout(&ss, uap->buf, sizeof ss);
543
544	case SVR4_IPC_SET:
545		error = copyin(uap->buf, &ss, sizeof ss);
546		if (error)
547			return error;
548		svr4_to_bsd_msqid_ds(&ss, &bs);
549		return (kern_msgctl(td, uap->msqid, IPC_SET, &bs));
550
551	case SVR4_IPC_RMID:
552		error = copyin(uap->buf, &ss, sizeof ss);
553		if (error)
554			return error;
555		svr4_to_bsd_msqid_ds(&ss, &bs);
556		return (kern_msgctl(td, uap->msqid, IPC_RMID, &bs));
557
558	default:
559		return EINVAL;
560	}
561}
562
563int
564svr4_sys_msgsys(td, uap)
565	struct thread *td;
566	struct svr4_sys_msgsys_args *uap;
567{
568
569	DPRINTF(("svr4_msgsys(%d)\n", uap->what));
570
571	switch (uap->what) {
572	case SVR4_msgsnd:
573		return svr4_msgsnd(td, uap);
574	case SVR4_msgrcv:
575		return svr4_msgrcv(td, uap);
576	case SVR4_msgget:
577		return svr4_msgget(td, uap);
578	case SVR4_msgctl:
579		return svr4_msgctl(td, uap);
580	default:
581		return EINVAL;
582	}
583}
584
585MODULE_DEPEND(svr4elf, sysvmsg, 1, 1, 1);
586#endif
587
588#ifdef SYSVSHM
589
590static void
591bsd_to_svr4_shmid_ds(bds, sds)
592	const struct shmid_ds *bds;
593	struct svr4_shmid_ds *sds;
594{
595	bsd_to_svr4_ipc_perm(&bds->shm_perm, &sds->shm_perm);
596	sds->shm_segsz = bds->shm_segsz;
597	sds->shm_lkcnt = 0;
598	sds->shm_lpid = bds->shm_lpid;
599	sds->shm_cpid = bds->shm_cpid;
600	sds->shm_amp = bds->shm_internal;
601	sds->shm_nattch = bds->shm_nattch;
602	sds->shm_cnattch = 0;
603	sds->shm_atime = bds->shm_atime;
604	sds->shm_pad1 = 0;
605	sds->shm_dtime = bds->shm_dtime;
606	sds->shm_pad2 = 0;
607	sds->shm_ctime = bds->shm_ctime;
608	sds->shm_pad3 = 0;
609}
610
611static void
612svr4_to_bsd_shmid_ds(sds, bds)
613	const struct svr4_shmid_ds *sds;
614	struct shmid_ds *bds;
615{
616	svr4_to_bsd_ipc_perm(&sds->shm_perm, &bds->shm_perm);
617	bds->shm_segsz = sds->shm_segsz;
618	bds->shm_lpid = sds->shm_lpid;
619	bds->shm_cpid = sds->shm_cpid;
620	bds->shm_internal = sds->shm_amp;
621	bds->shm_nattch = sds->shm_nattch;
622	bds->shm_atime = sds->shm_atime;
623	bds->shm_dtime = sds->shm_dtime;
624	bds->shm_ctime = sds->shm_ctime;
625}
626
627struct svr4_sys_shmat_args {
628	int what;
629	int shmid;
630	void * shmaddr;
631	int shmflg;
632};
633
634static int
635svr4_shmat(td, v)
636	struct thread *td;
637	void *v;
638{
639	struct svr4_sys_shmat_args *uap = v;
640	struct shmat_args ap;
641
642	ap.shmid = uap->shmid;
643	ap.shmaddr = uap->shmaddr;
644	ap.shmflg = uap->shmflg;
645
646	return shmat(td, &ap);
647}
648
649struct svr4_sys_shmdt_args {
650	int what;
651	void * shmaddr;
652};
653
654static int
655svr4_shmdt(td, v)
656	struct thread *td;
657	void *v;
658{
659	struct svr4_sys_shmdt_args *uap = v;
660	struct shmdt_args ap;
661
662	ap.shmaddr = uap->shmaddr;
663
664	return shmdt(td, &ap);
665}
666
667struct svr4_sys_shmget_args {
668	int what;
669	key_t key;
670	int size;
671	int shmflg;
672};
673
674static int
675svr4_shmget(td, v)
676	struct thread *td;
677	void *v;
678{
679	struct svr4_sys_shmget_args *uap = v;
680	struct shmget_args ap;
681
682	ap.key = uap->key;
683	ap.size = uap->size;
684	ap.shmflg = uap->shmflg;
685
686	return shmget(td, &ap);
687}
688
689struct svr4_sys_shmctl_args {
690	int what;
691	int shmid;
692	int cmd;
693	struct svr4_shmid_ds * buf;
694};
695
696int
697svr4_shmctl(td, v)
698	struct thread *td;
699	void *v;
700{
701	struct svr4_sys_shmctl_args *uap = v;
702	int error;
703	caddr_t sg = stackgap_init();
704	struct shmctl_args ap;
705	struct shmid_ds bs;
706	struct svr4_shmid_ds ss;
707
708	ap.shmid = uap->shmid;
709
710	if (uap->buf != NULL) {
711		ap.buf = stackgap_alloc(&sg, sizeof (struct shmid_ds));
712		switch (uap->cmd) {
713		case SVR4_IPC_SET:
714		case SVR4_IPC_RMID:
715		case SVR4_SHM_LOCK:
716		case SVR4_SHM_UNLOCK:
717			error = copyin(uap->buf, (caddr_t) &ss,
718			    sizeof ss);
719			if (error)
720				return error;
721			svr4_to_bsd_shmid_ds(&ss, &bs);
722			error = copyout(&bs, ap.buf, sizeof bs);
723			if (error)
724				return error;
725			break;
726		default:
727			break;
728		}
729	}
730	else
731		ap.buf = NULL;
732
733
734	switch (uap->cmd) {
735	case SVR4_IPC_STAT:
736		ap.cmd = IPC_STAT;
737		if ((error = shmctl(td, &ap)) != 0)
738			return error;
739		if (uap->buf == NULL)
740			return 0;
741		error = copyin(&bs, ap.buf, sizeof bs);
742		if (error)
743			return error;
744		bsd_to_svr4_shmid_ds(&bs, &ss);
745		return copyout(&ss, uap->buf, sizeof ss);
746
747	case SVR4_IPC_SET:
748		ap.cmd = IPC_SET;
749		return shmctl(td, &ap);
750
751	case SVR4_IPC_RMID:
752	case SVR4_SHM_LOCK:
753	case SVR4_SHM_UNLOCK:
754		switch (uap->cmd) {
755		case SVR4_IPC_RMID:
756			ap.cmd = IPC_RMID;
757			break;
758		case SVR4_SHM_LOCK:
759			ap.cmd = SHM_LOCK;
760			break;
761		case SVR4_SHM_UNLOCK:
762			ap.cmd = SHM_UNLOCK;
763			break;
764		default:
765			return EINVAL;
766		}
767		return shmctl(td, &ap);
768
769	default:
770		return EINVAL;
771	}
772}
773
774int
775svr4_sys_shmsys(td, uap)
776	struct thread *td;
777	struct svr4_sys_shmsys_args *uap;
778{
779
780	DPRINTF(("svr4_shmsys(%d)\n", uap->what));
781
782	switch (uap->what) {
783	case SVR4_shmat:
784		return svr4_shmat(td, uap);
785	case SVR4_shmdt:
786		return svr4_shmdt(td, uap);
787	case SVR4_shmget:
788		return svr4_shmget(td, uap);
789	case SVR4_shmctl:
790		return svr4_shmctl(td, uap);
791	default:
792		return ENOSYS;
793	}
794}
795
796MODULE_DEPEND(svr4elf, sysvshm, 1, 1, 1);
797#endif /* SYSVSHM */
798