svr4_ipc.c revision 147817
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 147817 2005-07-07 19:25:47Z 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#endif
389
390#ifdef SYSVMSG
391static void
392bsd_to_svr4_msqid_ds(bds, sds)
393	const struct msqid_ds *bds;
394	struct svr4_msqid_ds *sds;
395{
396	bsd_to_svr4_ipc_perm(&bds->msg_perm, &sds->msg_perm);
397	sds->msg_first = (struct svr4_msg *) bds->msg_first;
398	sds->msg_last = (struct svr4_msg *) bds->msg_last;
399	sds->msg_cbytes = bds->msg_cbytes;
400	sds->msg_qnum = bds->msg_qnum;
401	sds->msg_qbytes = bds->msg_qbytes;
402	sds->msg_lspid = bds->msg_lspid;
403	sds->msg_lrpid = bds->msg_lrpid;
404	sds->msg_stime = bds->msg_stime;
405	sds->msg_pad1 = bds->msg_pad1;
406	sds->msg_rtime = bds->msg_rtime;
407	sds->msg_pad2 = bds->msg_pad2;
408	sds->msg_ctime = bds->msg_ctime;
409	sds->msg_pad3 = bds->msg_pad3;
410
411	/* use the padding for the rest of the fields */
412	{
413		const short *pad = (const short *) bds->msg_pad4;
414		sds->msg_cv = pad[0];
415		sds->msg_qnum_cv = pad[1];
416	}
417}
418
419static void
420svr4_to_bsd_msqid_ds(sds, bds)
421	const struct svr4_msqid_ds *sds;
422	struct msqid_ds *bds;
423{
424	svr4_to_bsd_ipc_perm(&sds->msg_perm, &bds->msg_perm);
425	bds->msg_first = (struct msg *) sds->msg_first;
426	bds->msg_last = (struct msg *) sds->msg_last;
427	bds->msg_cbytes = sds->msg_cbytes;
428	bds->msg_qnum = sds->msg_qnum;
429	bds->msg_qbytes = sds->msg_qbytes;
430	bds->msg_lspid = sds->msg_lspid;
431	bds->msg_lrpid = sds->msg_lrpid;
432	bds->msg_stime = sds->msg_stime;
433	bds->msg_pad1 = sds->msg_pad1;
434	bds->msg_rtime = sds->msg_rtime;
435	bds->msg_pad2 = sds->msg_pad2;
436	bds->msg_ctime = sds->msg_ctime;
437	bds->msg_pad3 = sds->msg_pad3;
438
439	/* use the padding for the rest of the fields */
440	{
441		short *pad = (short *) bds->msg_pad4;
442		pad[0] = sds->msg_cv;
443		pad[1] = sds->msg_qnum_cv;
444	}
445}
446
447struct svr4_sys_msgsnd_args {
448	int what;
449	int msqid;
450	void * msgp;
451	size_t msgsz;
452	int msgflg;
453};
454
455static int
456svr4_msgsnd(td, v)
457	struct thread *td;
458	void *v;
459{
460	struct svr4_sys_msgsnd_args *uap = v;
461	struct msgsnd_args ap;
462
463	ap.msqid = uap->msqid;
464	ap.msgp = uap->msgp;
465	ap.msgsz = uap->msgsz;
466	ap.msgflg = uap->msgflg;
467
468	return msgsnd(td, &ap);
469}
470
471struct svr4_sys_msgrcv_args {
472	int what;
473	int msqid;
474	void * msgp;
475	size_t msgsz;
476	long msgtyp;
477	int msgflg;
478};
479
480static int
481svr4_msgrcv(td, v)
482	struct thread *td;
483	void *v;
484{
485	struct svr4_sys_msgrcv_args *uap = v;
486	struct msgrcv_args ap;
487
488	ap.msqid = uap->msqid;
489	ap.msgp = uap->msgp;
490	ap.msgsz = uap->msgsz;
491	ap.msgtyp = uap->msgtyp;
492	ap.msgflg = uap->msgflg;
493
494	return msgrcv(td, &ap);
495}
496
497struct svr4_sys_msgget_args {
498	int what;
499	svr4_key_t key;
500	int msgflg;
501};
502
503static int
504svr4_msgget(td, v)
505	struct thread *td;
506	void *v;
507{
508	struct svr4_sys_msgget_args *uap = v;
509	struct msgget_args ap;
510
511	ap.key = uap->key;
512	ap.msgflg = uap->msgflg;
513
514	return msgget(td, &ap);
515}
516
517struct svr4_sys_msgctl_args {
518	int what;
519	int msqid;
520	int cmd;
521	struct svr4_msqid_ds * buf;
522};
523
524static int
525svr4_msgctl(td, v)
526	struct thread *td;
527	void *v;
528{
529	struct svr4_sys_msgctl_args *uap = v;
530	struct svr4_msqid_ds ss;
531	struct msqid_ds bs;
532	int error;
533
534	switch (uap->cmd) {
535	case SVR4_IPC_STAT:
536		error = kern_msgctl(td, uap->msqid, IPC_STAT, &bs);
537		if (error)
538			return error;
539		bsd_to_svr4_msqid_ds(&bs, &ss);
540		return copyout(&ss, uap->buf, sizeof ss);
541
542	case SVR4_IPC_SET:
543		error = copyin(uap->buf, &ss, sizeof ss);
544		if (error)
545			return error;
546		svr4_to_bsd_msqid_ds(&ss, &bs);
547		return (kern_msgctl(td, uap->msqid, IPC_SET, &bs));
548
549	case SVR4_IPC_RMID:
550		error = copyin(uap->buf, &ss, sizeof ss);
551		if (error)
552			return error;
553		svr4_to_bsd_msqid_ds(&ss, &bs);
554		return (kern_msgctl(td, uap->msqid, IPC_RMID, &bs));
555
556	default:
557		return EINVAL;
558	}
559}
560
561int
562svr4_sys_msgsys(td, uap)
563	struct thread *td;
564	struct svr4_sys_msgsys_args *uap;
565{
566
567	DPRINTF(("svr4_msgsys(%d)\n", uap->what));
568
569	switch (uap->what) {
570	case SVR4_msgsnd:
571		return svr4_msgsnd(td, uap);
572	case SVR4_msgrcv:
573		return svr4_msgrcv(td, uap);
574	case SVR4_msgget:
575		return svr4_msgget(td, uap);
576	case SVR4_msgctl:
577		return svr4_msgctl(td, uap);
578	default:
579		return EINVAL;
580	}
581}
582#endif
583
584#ifdef SYSVSHM
585
586static void
587bsd_to_svr4_shmid_ds(bds, sds)
588	const struct shmid_ds *bds;
589	struct svr4_shmid_ds *sds;
590{
591	bsd_to_svr4_ipc_perm(&bds->shm_perm, &sds->shm_perm);
592	sds->shm_segsz = bds->shm_segsz;
593	sds->shm_lkcnt = 0;
594	sds->shm_lpid = bds->shm_lpid;
595	sds->shm_cpid = bds->shm_cpid;
596	sds->shm_amp = bds->shm_internal;
597	sds->shm_nattch = bds->shm_nattch;
598	sds->shm_cnattch = 0;
599	sds->shm_atime = bds->shm_atime;
600	sds->shm_pad1 = 0;
601	sds->shm_dtime = bds->shm_dtime;
602	sds->shm_pad2 = 0;
603	sds->shm_ctime = bds->shm_ctime;
604	sds->shm_pad3 = 0;
605}
606
607static void
608svr4_to_bsd_shmid_ds(sds, bds)
609	const struct svr4_shmid_ds *sds;
610	struct shmid_ds *bds;
611{
612	svr4_to_bsd_ipc_perm(&sds->shm_perm, &bds->shm_perm);
613	bds->shm_segsz = sds->shm_segsz;
614	bds->shm_lpid = sds->shm_lpid;
615	bds->shm_cpid = sds->shm_cpid;
616	bds->shm_internal = sds->shm_amp;
617	bds->shm_nattch = sds->shm_nattch;
618	bds->shm_atime = sds->shm_atime;
619	bds->shm_dtime = sds->shm_dtime;
620	bds->shm_ctime = sds->shm_ctime;
621}
622
623struct svr4_sys_shmat_args {
624	int what;
625	int shmid;
626	void * shmaddr;
627	int shmflg;
628};
629
630static int
631svr4_shmat(td, v)
632	struct thread *td;
633	void *v;
634{
635	struct svr4_sys_shmat_args *uap = v;
636	struct shmat_args ap;
637
638	ap.shmid = uap->shmid;
639	ap.shmaddr = uap->shmaddr;
640	ap.shmflg = uap->shmflg;
641
642	return shmat(td, &ap);
643}
644
645struct svr4_sys_shmdt_args {
646	int what;
647	void * shmaddr;
648};
649
650static int
651svr4_shmdt(td, v)
652	struct thread *td;
653	void *v;
654{
655	struct svr4_sys_shmdt_args *uap = v;
656	struct shmdt_args ap;
657
658	ap.shmaddr = uap->shmaddr;
659
660	return shmdt(td, &ap);
661}
662
663struct svr4_sys_shmget_args {
664	int what;
665	key_t key;
666	int size;
667	int shmflg;
668};
669
670static int
671svr4_shmget(td, v)
672	struct thread *td;
673	void *v;
674{
675	struct svr4_sys_shmget_args *uap = v;
676	struct shmget_args ap;
677
678	ap.key = uap->key;
679	ap.size = uap->size;
680	ap.shmflg = uap->shmflg;
681
682	return shmget(td, &ap);
683}
684
685struct svr4_sys_shmctl_args {
686	int what;
687	int shmid;
688	int cmd;
689	struct svr4_shmid_ds * buf;
690};
691
692int
693svr4_shmctl(td, v)
694	struct thread *td;
695	void *v;
696{
697	struct svr4_sys_shmctl_args *uap = v;
698	int error;
699	caddr_t sg = stackgap_init();
700	struct shmctl_args ap;
701	struct shmid_ds bs;
702	struct svr4_shmid_ds ss;
703
704	ap.shmid = uap->shmid;
705
706	if (uap->buf != NULL) {
707		ap.buf = stackgap_alloc(&sg, sizeof (struct shmid_ds));
708		switch (uap->cmd) {
709		case SVR4_IPC_SET:
710		case SVR4_IPC_RMID:
711		case SVR4_SHM_LOCK:
712		case SVR4_SHM_UNLOCK:
713			error = copyin(uap->buf, (caddr_t) &ss,
714			    sizeof ss);
715			if (error)
716				return error;
717			svr4_to_bsd_shmid_ds(&ss, &bs);
718			error = copyout(&bs, ap.buf, sizeof bs);
719			if (error)
720				return error;
721			break;
722		default:
723			break;
724		}
725	}
726	else
727		ap.buf = NULL;
728
729
730	switch (uap->cmd) {
731	case SVR4_IPC_STAT:
732		ap.cmd = IPC_STAT;
733		if ((error = shmctl(td, &ap)) != 0)
734			return error;
735		if (uap->buf == NULL)
736			return 0;
737		error = copyin(&bs, ap.buf, sizeof bs);
738		if (error)
739			return error;
740		bsd_to_svr4_shmid_ds(&bs, &ss);
741		return copyout(&ss, uap->buf, sizeof ss);
742
743	case SVR4_IPC_SET:
744		ap.cmd = IPC_SET;
745		return shmctl(td, &ap);
746
747	case SVR4_IPC_RMID:
748	case SVR4_SHM_LOCK:
749	case SVR4_SHM_UNLOCK:
750		switch (uap->cmd) {
751		case SVR4_IPC_RMID:
752			ap.cmd = IPC_RMID;
753			break;
754		case SVR4_SHM_LOCK:
755			ap.cmd = SHM_LOCK;
756			break;
757		case SVR4_SHM_UNLOCK:
758			ap.cmd = SHM_UNLOCK;
759			break;
760		default:
761			return EINVAL;
762		}
763		return shmctl(td, &ap);
764
765	default:
766		return EINVAL;
767	}
768}
769
770int
771svr4_sys_shmsys(td, uap)
772	struct thread *td;
773	struct svr4_sys_shmsys_args *uap;
774{
775
776	DPRINTF(("svr4_shmsys(%d)\n", uap->what));
777
778	switch (uap->what) {
779	case SVR4_shmat:
780		return svr4_shmat(td, uap);
781	case SVR4_shmdt:
782		return svr4_shmdt(td, uap);
783	case SVR4_shmget:
784		return svr4_shmget(td, uap);
785	case SVR4_shmctl:
786		return svr4_shmctl(td, uap);
787	default:
788		return ENOSYS;
789	}
790}
791#endif /* SYSVSHM */
792