linux_ipc.c revision 14331
1/*- 2 * Copyright (c) 1994-1995 S�ren Schmidt 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer 10 * in this position and unchanged. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software withough specific prior written permission 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * $Id: linux_ipc.c,v 1.6 1996/01/08 04:34:54 peter Exp $ 29 */ 30 31 32#include <sys/param.h> 33#include <sys/systm.h> 34#include <sys/sysproto.h> 35#include <sys/proc.h> 36#include <sys/shm.h> 37 38#include <i386/linux/linux.h> 39#include <i386/linux/linux_proto.h> 40#include <i386/linux/linux_util.h> 41 42static int linux_semop __P((struct proc *, struct linux_ipc_args *, int *)); 43static int linux_semget __P((struct proc *, struct linux_ipc_args *, int *)); 44static int linux_semctl __P((struct proc *, struct linux_ipc_args *, int *)); 45static int linux_msgsnd __P((struct proc *, struct linux_ipc_args *, int *)); 46static int linux_msgrcv __P((struct proc *, struct linux_ipc_args *, int *)); 47static int linux_msgop __P((struct proc *, struct linux_ipc_args *, int *)); 48static int linux_msgctl __P((struct proc *, struct linux_ipc_args *, int *)); 49static int linux_shmat __P((struct proc *, struct linux_ipc_args *, int *)); 50static int linux_shmdt __P((struct proc *, struct linux_ipc_args *, int *)); 51static int linux_shmget __P((struct proc *, struct linux_ipc_args *, int *)); 52static int linux_shmctl __P((struct proc *, struct linux_ipc_args *, int *)); 53 54struct linux_ipc_perm { 55 linux_key_t key; 56 unsigned short uid; 57 unsigned short gid; 58 unsigned short cuid; 59 unsigned short cgid; 60 unsigned short mode; 61 unsigned short seq; 62}; 63 64static void 65linux_to_bsd_ipc_perm(struct linux_ipc_perm *lpp, struct ipc_perm *bpp) 66{ 67 bpp->key = lpp->key; 68 bpp->uid = lpp->uid; 69 bpp->gid = lpp->gid; 70 bpp->cuid = lpp->cuid; 71 bpp->cgid = lpp->cgid; 72 bpp->mode = lpp->mode; 73 bpp->seq = lpp->seq; 74} 75 76 77static void 78bsd_to_linux_ipc_perm(struct ipc_perm *bpp, struct linux_ipc_perm *lpp) 79{ 80 lpp->key = bpp->key; 81 lpp->uid = bpp->uid; 82 lpp->gid = bpp->gid; 83 lpp->cuid = bpp->cuid; 84 lpp->cgid = bpp->cgid; 85 lpp->mode = bpp->mode; 86 lpp->seq = bpp->seq; 87} 88 89struct linux_shmid_ds { 90 struct linux_ipc_perm shm_perm; 91 int shm_segsz; 92 linux_time_t shm_atime; 93 linux_time_t shm_dtime; 94 linux_time_t shm_ctime; 95 ushort shm_cpid; 96 ushort shm_lpid; 97 short shm_nattch; 98 ushort private1; 99 void *private2; 100 void *private3; 101}; 102 103static void 104linux_to_bsd_shmid_ds(struct linux_shmid_ds *lsp, struct shmid_ds *bsp) 105{ 106 linux_to_bsd_ipc_perm(&lsp->shm_perm, &bsp->shm_perm); 107 bsp->shm_segsz = lsp->shm_segsz; 108 bsp->shm_lpid = lsp->shm_lpid; 109 bsp->shm_cpid = lsp->shm_cpid; 110 bsp->shm_nattch = lsp->shm_nattch; 111 bsp->shm_atime = lsp->shm_atime; 112 bsp->shm_dtime = lsp->shm_dtime; 113 bsp->shm_ctime = lsp->shm_ctime; 114 bsp->shm_internal = lsp->private3; /* this goes (yet) SOS */ 115} 116 117static void 118bsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct linux_shmid_ds *lsp) 119{ 120 bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->shm_perm); 121 lsp->shm_segsz = bsp->shm_segsz; 122 lsp->shm_lpid = bsp->shm_lpid; 123 lsp->shm_cpid = bsp->shm_cpid; 124 lsp->shm_nattch = bsp->shm_nattch; 125 lsp->shm_atime = bsp->shm_atime; 126 lsp->shm_dtime = bsp->shm_dtime; 127 lsp->shm_ctime = bsp->shm_ctime; 128 lsp->private3 = bsp->shm_internal; /* this goes (yet) SOS */ 129} 130 131static int 132linux_semop(struct proc *p, struct linux_ipc_args *args, int *retval) 133{ 134 return ENOSYS; 135} 136 137static int 138linux_semget(struct proc *p, struct linux_ipc_args *args, int *retval) 139{ 140 return ENOSYS; 141} 142 143static int 144linux_semctl(struct proc *p, struct linux_ipc_args *args, int *retval) 145{ 146 return ENOSYS; 147} 148 149static int 150linux_msgsnd(struct proc *p, struct linux_ipc_args *args, int *retval) 151{ 152 struct msgsnd_args /* { 153 int msqid; 154 void *msgp; 155 size_t msgsz; 156 int msgflg; 157 } */ bsd_args; 158 159 bsd_args.msqid = args->arg1; 160 bsd_args.msgp = args->ptr; 161 bsd_args.msgsz = args->arg2; 162 bsd_args.msgflg = args->arg3; 163 return msgsnd(p, &bsd_args, retval); 164} 165 166static int 167linux_msgrcv(struct proc *p, struct linux_ipc_args *args, int *retval) 168{ 169 struct msgrcv_args /* { 170 int msqid; 171 void *msgp; 172 size_t msgsz; 173 long msgtyp; 174 int msgflg; 175 } */ bsd_args; 176 177 bsd_args.msqid = args->arg1; 178 bsd_args.msgp = args->ptr; 179 bsd_args.msgsz = args->arg2; 180 bsd_args.msgtyp = 0; 181 bsd_args.msgflg = args->arg3; 182 return msgrcv(p, &bsd_args, retval); 183} 184 185static int 186linux_msgget(struct proc *p, struct linux_ipc_args *args, int *retval) 187{ 188 struct msgget_args /* { 189 key_t key; 190 int msgflg; 191 } */ bsd_args; 192 193 bsd_args.key = args->arg1; 194 bsd_args.msgflg = args->arg2; 195 return msgget(p, &bsd_args, retval); 196} 197 198static int 199linux_msgctl(struct proc *p, struct linux_ipc_args *args, int *retval) 200{ 201 struct msgctl_args /* { 202 int msqid; 203 int cmd; 204 struct msqid_ds *buf; 205 } */ bsd_args; 206 207 bsd_args.msqid = args->arg1; 208 bsd_args.cmd = args->arg2; 209 bsd_args.buf = (struct msqid_ds *)args->ptr; 210 return msgctl(p, &bsd_args, retval); 211} 212 213static int 214linux_shmat(struct proc *p, struct linux_ipc_args *args, int *retval) 215{ 216 struct shmat_args /* { 217 int shmid; 218 void *shmaddr; 219 int shmflg; 220 } */ bsd_args; 221 int error; 222 223 bsd_args.shmid = args->arg1; 224 bsd_args.shmaddr = args->ptr; 225 bsd_args.shmflg = args->arg2; 226 if ((error = shmat(p, &bsd_args, retval))) 227 return error; 228 if ((error = copyout(retval, (caddr_t)args->arg3, sizeof(int)))) 229 return error; 230 retval[0] = 0; 231 return 0; 232} 233 234static int 235linux_shmdt(struct proc *p, struct linux_ipc_args *args, int *retval) 236{ 237 struct shmdt_args /* { 238 void *shmaddr; 239 } */ bsd_args; 240 241 bsd_args.shmaddr = args->ptr; 242 return shmdt(p, &bsd_args, retval); 243} 244 245static int 246linux_shmget(struct proc *p, struct linux_ipc_args *args, int *retval) 247{ 248 struct shmget_args /* { 249 key_t key; 250 int size; 251 int shmflg; 252 } */ bsd_args; 253 254 bsd_args.key = args->arg1; 255 bsd_args.size = args->arg2; 256 bsd_args.shmflg = args->arg3; 257 return shmget(p, &bsd_args, retval); 258} 259 260static int 261linux_shmctl(struct proc *p, struct linux_ipc_args *args, int *retval) 262{ 263 struct shmid_ds bsd_shmid; 264 struct linux_shmid_ds linux_shmid; 265 struct shmctl_args /* { 266 int shmid; 267 int cmd; 268 struct shmid_ds *buf; 269 } */ bsd_args; 270 int error; 271 caddr_t sg = stackgap_init(); 272 273 switch (args->arg2) { 274 case LINUX_IPC_STAT: 275 bsd_args.shmid = args->arg1; 276 bsd_args.cmd = IPC_STAT; 277 bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds)); 278 if ((error = shmctl(p, &bsd_args, retval))) 279 return error; 280 if ((error = copyin((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf, 281 sizeof(struct shmid_ds)))) 282 return error; 283 bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid); 284 return copyout((caddr_t)&linux_shmid, args->ptr, sizeof(linux_shmid)); 285 286 case LINUX_IPC_SET: 287 if ((error = copyin(args->ptr, (caddr_t)&linux_shmid, 288 sizeof(linux_shmid)))) 289 return error; 290 linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid); 291 bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds)); 292 if ((error = copyout((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf, 293 sizeof(struct shmid_ds)))) 294 return error; 295 bsd_args.shmid = args->arg1; 296 bsd_args.cmd = IPC_SET; 297 return shmctl(p, &bsd_args, retval); 298 299 case LINUX_IPC_RMID: 300 bsd_args.shmid = args->arg1; 301 bsd_args.cmd = IPC_RMID; 302 if ((error = copyin(args->ptr, (caddr_t)&linux_shmid, 303 sizeof(linux_shmid)))) 304 return error; 305 linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid); 306 bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds)); 307 if ((error = copyout((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf, 308 sizeof(struct shmid_ds)))) 309 return error; 310 return shmctl(p, &bsd_args, retval); 311 312 case LINUX_IPC_INFO: 313 case LINUX_SHM_STAT: 314 case LINUX_SHM_INFO: 315 case LINUX_SHM_LOCK: 316 case LINUX_SHM_UNLOCK: 317 default: 318 uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->what); 319 return EINVAL; 320 } 321} 322 323int 324linux_ipc(struct proc *p, struct linux_ipc_args *args, int *retval) 325{ 326 switch (args->what) { 327 case LINUX_SEMOP: 328 return linux_semop(p, args, retval); 329 case LINUX_SEMGET: 330 return linux_semget(p, args, retval); 331 case LINUX_SEMCTL: 332 return linux_semctl(p, args, retval); 333 case LINUX_MSGSND: 334 return linux_msgsnd(p, args, retval); 335 case LINUX_MSGRCV: 336 return linux_msgrcv(p, args, retval); 337 case LINUX_MSGGET: 338 return linux_msgget(p, args, retval); 339 case LINUX_MSGCTL: 340 return linux_msgctl(p, args, retval); 341 case LINUX_SHMAT: 342 return linux_shmat(p, args, retval); 343 case LINUX_SHMDT: 344 return linux_shmdt(p, args, retval); 345 case LINUX_SHMGET: 346 return linux_shmget(p, args, retval); 347 case LINUX_SHMCTL: 348 return linux_shmctl(p, args, retval); 349 default: 350 uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->what); 351 return ENOSYS; 352 } 353} 354