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