linux_ipccall.c revision 1.16 1 /* $NetBSD: linux_ipccall.c,v 1.16 1998/10/04 00:02:35 fvdl Exp $ */
2
3 /*-
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Frank van der Linden and Eric Haszlakiewicz.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 #include <sys/types.h>
40 #include <sys/param.h>
41 #include <sys/shm.h>
42 #include <sys/sem.h>
43 #include <sys/msg.h>
44 #include <sys/proc.h>
45 #include <sys/systm.h>
46
47 /* real syscalls */
48 #include <sys/mount.h>
49 #include <sys/syscallargs.h>
50
51
52 /* sys_ipc + args prototype */
53 #include <compat/linux/common/linux_types.h>
54 #include <compat/linux/common/linux_signal.h>
55
56 #include <compat/linux/linux_syscallargs.h>
57 #include <compat/linux/linux_syscall.h>
58
59 /* general ipc defines */
60 #include <compat/linux/common/linux_ipc.h>
61
62 /* prototypes for real/normal linux-emul syscalls */
63 #include <compat/linux/common/linux_msg.h>
64 #include <compat/linux/common/linux_shm.h>
65 #include <compat/linux/common/linux_sem.h>
66
67 /* prototypes for sys_ipc stuff */
68 #include <compat/linux/common/linux_ipccall.h>
69
70
71 /* Used on: arm, i386, m68k, mips, ppc, sparc, sparc64 */
72 /* Not used on: alpha */
73
74 /*
75 * Stuff to deal with the SysV ipc/shm/semaphore interface in Linux.
76 * The main difference is, that Linux handles it all via one
77 * system call, which has the usual maximum amount of 5 arguments.
78 * This results in a kludge for calls that take 6 of them.
79 *
80 * The SYSV??? options have to be enabled to get the appropriate
81 * functions to work.
82 */
83
84 int
85 linux_sys_ipc(p, v, retval)
86 struct proc *p;
87 void *v;
88 register_t *retval;
89 {
90 struct linux_sys_ipc_args /* {
91 syscallarg(int) what;
92 syscallarg(int) a1;
93 syscallarg(int) a2;
94 syscallarg(int) a3;
95 syscallarg(caddr_t) ptr;
96 } */ *uap = v;
97
98 switch (SCARG(uap, what)) {
99 #ifdef SYSVSEM
100 case LINUX_SYS_semop:
101 return linux_semop(p, uap, retval);
102 case LINUX_SYS_semget:
103 return linux_semget(p, uap, retval);
104 case LINUX_SYS_semctl: {
105 struct linux_sys_semctl_args bsa;
106 union linux_semun arg;
107 int error;
108
109 SCARG(&bsa, semid) = SCARG(uap, a1);
110 SCARG(&bsa, semnum) = SCARG(uap, a2);
111 SCARG(&bsa, cmd) = SCARG(uap, a3);
112 /* Convert from (union linux_semun *) to (union linux_semun) */
113 if ((error = copyin(SCARG(uap, ptr), &arg, sizeof arg)))
114 return error;
115 SCARG(&bsa, arg) = arg;
116
117 return linux_sys_semctl(p, &bsa, retval);
118 }
119 #endif
120 #ifdef SYSVMSG
121 case LINUX_SYS_msgsnd:
122 return linux_msgsnd(p, uap, retval);
123 case LINUX_SYS_msgrcv:
124 return linux_msgrcv(p, uap, retval);
125 case LINUX_SYS_msgget:
126 return linux_msgget(p, uap, retval);
127 case LINUX_SYS_msgctl: {
128 struct linux_sys_msgctl_args bsa;
129
130 SCARG(&bsa, msqid) = SCARG(uap, a1);
131 SCARG(&bsa, cmd) = SCARG(uap, a2);
132 SCARG(&bsa, buf) = (struct linux_msqid_ds *)SCARG(uap, ptr);
133
134 return linux_sys_msgctl(p, &bsa, retval);
135 }
136 #endif
137 #ifdef SYSVSHM
138 case LINUX_SYS_shmat: {
139 struct linux_sys_shmat_args bsa;
140
141 SCARG(&bsa, shmid) = SCARG(uap, a1);
142 SCARG(&bsa, shmaddr) = (void *)SCARG(uap, ptr);
143 SCARG(&bsa, shmflg) = SCARG(uap, a2);
144 /* XXX passing pointer inside int here */
145 SCARG(&bsa, raddr) = (u_long *)SCARG(uap, a3);
146
147 return linux_sys_shmat(p, &bsa, retval);
148 }
149 case LINUX_SYS_shmdt:
150 return linux_shmdt(p, uap, retval);
151 case LINUX_SYS_shmget:
152 return linux_shmget(p, uap, retval);
153 case LINUX_SYS_shmctl: {
154 struct linux_sys_shmctl_args bsa;
155
156 SCARG(&bsa, shmid) = SCARG(uap, a1);
157 SCARG(&bsa, cmd) = SCARG(uap, a2);
158 SCARG(&bsa, buf) = (struct linux_shmid_ds *)SCARG(uap, ptr);
159
160 return linux_sys_shmctl(p, &bsa, retval);
161 }
162 #endif
163 default:
164 return ENOSYS;
165 }
166 }
167
168 #ifdef SYSVSEM
169 inline int
170 linux_semop(p, uap, retval)
171 struct proc *p;
172 struct linux_sys_ipc_args /* {
173 syscallarg(int) what;
174 syscallarg(int) a1;
175 syscallarg(int) a2;
176 syscallarg(int) a3;
177 syscallarg(caddr_t) ptr;
178 } */ *uap;
179 register_t *retval;
180 {
181 struct sys_semop_args bsa;
182
183 SCARG(&bsa, semid) = SCARG(uap, a1);
184 SCARG(&bsa, sops) = (struct sembuf *)SCARG(uap, ptr);
185 SCARG(&bsa, nsops) = SCARG(uap, a2);
186
187 return sys_semop(p, &bsa, retval);
188 }
189
190 inline int
191 linux_semget(p, uap, retval)
192 struct proc *p;
193 struct linux_sys_ipc_args /* {
194 syscallarg(int) what;
195 syscallarg(int) a1;
196 syscallarg(int) a2;
197 syscallarg(int) a3;
198 syscallarg(caddr_t) ptr;
199 } */ *uap;
200 register_t *retval;
201 {
202 struct sys_semget_args bsa;
203
204 SCARG(&bsa, key) = (key_t)SCARG(uap, a1);
205 SCARG(&bsa, nsems) = SCARG(uap, a2);
206 SCARG(&bsa, semflg) = SCARG(uap, a3);
207
208 return sys_semget(p, &bsa, retval);
209 }
210
211 #endif /* SYSVSEM */
212
213 #ifdef SYSVMSG
214
215 inline int
216 linux_msgsnd(p, uap, retval)
217 struct proc *p;
218 struct linux_sys_ipc_args /* {
219 syscallarg(int) what;
220 syscallarg(int) a1;
221 syscallarg(int) a2;
222 syscallarg(int) a3;
223 syscallarg(caddr_t) ptr;
224 } */ *uap;
225 register_t *retval;
226 {
227 struct sys_msgsnd_args bma;
228
229 SCARG(&bma, msqid) = SCARG(uap, a1);
230 SCARG(&bma, msgp) = SCARG(uap, ptr);
231 SCARG(&bma, msgsz) = SCARG(uap, a2);
232 SCARG(&bma, msgflg) = SCARG(uap, a3);
233
234 return sys_msgsnd(p, &bma, retval);
235 }
236
237 inline int
238 linux_msgrcv(p, uap, retval)
239 struct proc *p;
240 struct linux_sys_ipc_args /* {
241 syscallarg(int) what;
242 syscallarg(int) a1;
243 syscallarg(int) a2;
244 syscallarg(int) a3;
245 syscallarg(caddr_t) ptr;
246 } */ *uap;
247 register_t *retval;
248 {
249 struct sys_msgrcv_args bma;
250 struct linux_msgrcv_msgarg kluge;
251 int error;
252
253 if ((error = copyin(SCARG(uap, ptr), &kluge, sizeof kluge)))
254 return error;
255
256 SCARG(&bma, msqid) = SCARG(uap, a1);
257 SCARG(&bma, msgp) = kluge.msg;
258 SCARG(&bma, msgsz) = SCARG(uap, a2);
259 SCARG(&bma, msgtyp) = kluge.type;
260 SCARG(&bma, msgflg) = SCARG(uap, a3);
261
262 return sys_msgrcv(p, &bma, retval);
263 }
264
265 inline int
266 linux_msgget(p, uap, retval)
267 struct proc *p;
268 struct linux_sys_ipc_args /* {
269 syscallarg(int) what;
270 syscallarg(int) a1;
271 syscallarg(int) a2;
272 syscallarg(int) a3;
273 syscallarg(caddr_t) ptr;
274 } */ *uap;
275 register_t *retval;
276 {
277 struct sys_msgget_args bma;
278
279 SCARG(&bma, key) = (key_t)SCARG(uap, a1);
280 SCARG(&bma, msgflg) = SCARG(uap, a2);
281
282 return sys_msgget(p, &bma, retval);
283 }
284
285 #endif /* SYSVMSG */
286
287 #ifdef SYSVSHM
288 /*
289 * shmdt(): this could have been mapped directly, if it wasn't for
290 * the extra indirection by the linux_ipc system call.
291 */
292 inline int
293 linux_shmdt(p, uap, retval)
294 struct proc *p;
295 struct linux_sys_ipc_args /* {
296 syscallarg(int) what;
297 syscallarg(int) a1;
298 syscallarg(int) a2;
299 syscallarg(int) a3;
300 syscallarg(caddr_t) ptr;
301 } */ *uap;
302 register_t *retval;
303 {
304 struct sys_shmdt_args bsa;
305
306 SCARG(&bsa, shmaddr) = SCARG(uap, ptr);
307
308 return sys_shmdt(p, &bsa, retval);
309 }
310
311 /*
312 * Same story as shmdt.
313 */
314 inline int
315 linux_shmget(p, uap, retval)
316 struct proc *p;
317 struct linux_sys_ipc_args /* {
318 syscallarg(int) what;
319 syscallarg(int) a1;
320 syscallarg(int) a2;
321 syscallarg(int) a3;
322 syscallarg(caddr_t) ptr;
323 } */ *uap;
324 register_t *retval;
325 {
326 struct sys_shmget_args bsa;
327
328 SCARG(&bsa, key) = SCARG(uap, a1);
329 SCARG(&bsa, size) = SCARG(uap, a2);
330 SCARG(&bsa, shmflg) = SCARG(uap, a3);
331
332 return sys_shmget(p, &bsa, retval);
333 }
334
335 #endif /* SYSVSHM */
336