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.7 1996/03/02 19:37:56 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 42 static int linux_semop __P((struct proc *, struct linux_ipc_args *, int *)); 43 static int linux_semget __P((struct proc *, struct linux_ipc_args *, int *)); 44 static int linux_semctl __P((struct proc *, struct linux_ipc_args *, int *)); 45 static int linux_msgsnd __P((struct proc *, struct linux_ipc_args *, int *)); 46 static int linux_msgrcv __P((struct proc *, struct linux_ipc_args *, int *)); 47 static int linux_msgctl __P((struct proc *, struct linux_ipc_args *, int *)); 48 static int linux_shmat __P((struct proc *, struct linux_ipc_args *, int *)); 49 static int linux_shmdt __P((struct proc *, struct linux_ipc_args *, int *)); 50 static int linux_shmget __P((struct proc *, struct linux_ipc_args *, int *)); 51 static int linux_shmctl __P((struct proc *, struct linux_ipc_args *, int *)); 52 53 struct linux_ipc_perm { 54 linux_key_t key; 55 unsigned short uid; 56 unsigned short gid; 57 unsigned short cuid; 58 unsigned short cgid; 59 unsigned short mode; 60 unsigned short seq; 61 }; 62 63 static void 64 linux_to_bsd_ipc_perm(struct linux_ipc_perm *lpp, struct ipc_perm *bpp) 65 { 66 bpp->key = lpp->key; 67 bpp->uid = lpp->uid; 68 bpp->gid = lpp->gid; 69 bpp->cuid = lpp->cuid; 70 bpp->cgid = lpp->cgid; 71 bpp->mode = lpp->mode; 72 bpp->seq = lpp->seq; 73 } 74 75 76 static void 77 bsd_to_linux_ipc_perm(struct ipc_perm *bpp, struct linux_ipc_perm *lpp) 78 { 79 lpp->key = bpp->key; 80 lpp->uid = bpp->uid; 81 lpp->gid = bpp->gid; 82 lpp->cuid = bpp->cuid; 83 lpp->cgid = bpp->cgid; 84 lpp->mode = bpp->mode; 85 lpp->seq = bpp->seq; 86 } 87 88 struct linux_shmid_ds { 89 struct linux_ipc_perm shm_perm; 90 int shm_segsz; 91 linux_time_t shm_atime; 92 linux_time_t shm_dtime; 93 linux_time_t shm_ctime; 94 ushort shm_cpid; 95 ushort shm_lpid; 96 short shm_nattch; 97 ushort private1; 98 void *private2; 99 void *private3; 100 }; 101 102 static void 103 linux_to_bsd_shmid_ds(struct linux_shmid_ds *lsp, struct shmid_ds *bsp) 104 { 105 linux_to_bsd_ipc_perm(&lsp->shm_perm, &bsp->shm_perm); 106 bsp->shm_segsz = lsp->shm_segsz; 107 bsp->shm_lpid = lsp->shm_lpid; 108 bsp->shm_cpid = lsp->shm_cpid; 109 bsp->shm_nattch = lsp->shm_nattch; 110 bsp->shm_atime = lsp->shm_atime; 111 bsp->shm_dtime = lsp->shm_dtime; 112 bsp->shm_ctime = lsp->shm_ctime; 113 bsp->shm_internal = lsp->private3; /* this goes (yet) SOS */ 114 } 115 116 static void 117 bsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct linux_shmid_ds *lsp) 118 { 119 bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->shm_perm); 120 lsp->shm_segsz = bsp->shm_segsz; 121 lsp->shm_lpid = bsp->shm_lpid; 122 lsp->shm_cpid = bsp->shm_cpid; 123 lsp->shm_nattch = bsp->shm_nattch; 124 lsp->shm_atime = bsp->shm_atime; 125 lsp->shm_dtime = bsp->shm_dtime; 126 lsp->shm_ctime = bsp->shm_ctime; 127 lsp->private3 = bsp->shm_internal; /* this goes (yet) SOS */ 128 } 129 130 static int 131 linux_semop(struct proc *p, struct linux_ipc_args *args, int *retval) 132 { 133 return ENOSYS; 134 } 135 136 static int 137 linux_semget(struct proc *p, struct linux_ipc_args *args, int *retval) 138 { 139 return ENOSYS; 140 } 141 142 static int 143 linux_semctl(struct proc *p, struct linux_ipc_args *args, int *retval) 144 { 145 return ENOSYS; 146 } 147 148 static int 149 linux_msgsnd(struct proc *p, struct linux_ipc_args *args, int *retval) 150 { 151 struct msgsnd_args /* { 152 int msqid; 153 void *msgp; 154 size_t msgsz; 155 int msgflg; 156 } */ bsd_args; 157 158 bsd_args.msqid = args->arg1; 159 bsd_args.msgp = args->ptr; 160 bsd_args.msgsz = args->arg2; 161 bsd_args.msgflg = args->arg3; 162 return msgsnd(p, &bsd_args, retval); 163 } 164 165 static int 166 linux_msgrcv(struct proc *p, struct linux_ipc_args *args, int *retval) 167 { 168 struct msgrcv_args /* { 169 int msqid; 170 void *msgp; 171 size_t msgsz; 172 long msgtyp; 173 int msgflg; 174 } */ bsd_args; 175 176 bsd_args.msqid = args->arg1; 177 bsd_args.msgp = args->ptr; 178 bsd_args.msgsz = args->arg2; 179 bsd_args.msgtyp = 0; 180 bsd_args.msgflg = args->arg3; 181 return msgrcv(p, &bsd_args, retval); 182 } 183 184 static int 185 linux_msgget(struct proc *p, struct linux_ipc_args *args, int *retval) 186 { 187 struct msgget_args /* { 188 key_t key; 189 int msgflg; 190 } */ bsd_args; 191 192 bsd_args.key = args->arg1; 193 bsd_args.msgflg = args->arg2; 194 return msgget(p, &bsd_args, retval); 195 } 196 197 static int 198 linux_msgctl(struct proc *p, struct linux_ipc_args *args, int *retval) 199 { 200 struct msgctl_args /* { 201 int msqid; 202 int cmd; 203 struct msqid_ds *buf; 204 } */ bsd_args; 205 206 bsd_args.msqid = args->arg1; 207 bsd_args.cmd = args->arg2; 208 bsd_args.buf = (struct msqid_ds *)args->ptr; 209 return msgctl(p, &bsd_args, retval); 210 } 211 212 static int 213 linux_shmat(struct proc *p, struct linux_ipc_args *args, int *retval) 214 { 215 struct shmat_args /* { 216 int shmid; 217 void *shmaddr; 218 int shmflg; 219 } */ bsd_args; 220 int error; 221 222 bsd_args.shmid = args->arg1; 223 bsd_args.shmaddr = args->ptr; 224 bsd_args.shmflg = args->arg2; 225 if ((error = shmat(p, &bsd_args, retval))) 226 return error; 227 if ((error = copyout(retval, (caddr_t)args->arg3, sizeof(int)))) 228 return error; 229 retval[0] = 0; 230 return 0; 231 } 232 233 static int 234 linux_shmdt(struct proc *p, struct linux_ipc_args *args, int *retval) 235 { 236 struct shmdt_args /* { 237 void *shmaddr; 238 } */ bsd_args; 239 240 bsd_args.shmaddr = args->ptr; 241 return shmdt(p, &bsd_args, retval); 242 } 243 244 static int 245 linux_shmget(struct proc *p, struct linux_ipc_args *args, int *retval) 246 { 247 struct shmget_args /* { 248 key_t key; 249 int size; 250 int shmflg; 251 } */ bsd_args; 252 253 bsd_args.key = args->arg1; 254 bsd_args.size = args->arg2; 255 bsd_args.shmflg = args->arg3; 256 return shmget(p, &bsd_args, retval); 257 } 258 259 static int 260 linux_shmctl(struct proc *p, struct linux_ipc_args *args, int *retval) 261 { 262 struct shmid_ds bsd_shmid; 263 struct linux_shmid_ds linux_shmid; 264 struct shmctl_args /* { 265 int shmid; 266 int cmd; 267 struct shmid_ds *buf; 268 } */ bsd_args; 269 int error; 270 caddr_t sg = stackgap_init(); 271 272 switch (args->arg2) { 273 case LINUX_IPC_STAT: 274 bsd_args.shmid = args->arg1; 275 bsd_args.cmd = IPC_STAT; 276 bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds)); 277 if ((error = shmctl(p, &bsd_args, retval))) 278 return error; 279 if ((error = copyin((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf, 280 sizeof(struct shmid_ds)))) 281 return error; 282 bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid); 283 return copyout((caddr_t)&linux_shmid, args->ptr, sizeof(linux_shmid)); 284 285 case LINUX_IPC_SET: 286 if ((error = copyin(args->ptr, (caddr_t)&linux_shmid, 287 sizeof(linux_shmid)))) 288 return error; 289 linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid); 290 bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds)); 291 if ((error = copyout((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf, 292 sizeof(struct shmid_ds)))) 293 return error; 294 bsd_args.shmid = args->arg1; 295 bsd_args.cmd = IPC_SET; 296 return shmctl(p, &bsd_args, retval); 297 298 case LINUX_IPC_RMID: 299 bsd_args.shmid = args->arg1; 300 bsd_args.cmd = IPC_RMID; 301 if ((error = copyin(args->ptr, (caddr_t)&linux_shmid, 302 sizeof(linux_shmid)))) 303 return error; 304 linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid); 305 bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds)); 306 if ((error = copyout((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf, 307 sizeof(struct shmid_ds)))) 308 return error; 309 return shmctl(p, &bsd_args, retval); 310 311 case LINUX_IPC_INFO: 312 case LINUX_SHM_STAT: 313 case LINUX_SHM_INFO: 314 case LINUX_SHM_LOCK: 315 case LINUX_SHM_UNLOCK: 316 default: 317 uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->what); 318 return EINVAL; 319 } 320 } 321 322 int 323 linux_ipc(struct proc *p, struct linux_ipc_args *args, int *retval) 324 { 325 switch (args->what) { 326 case LINUX_SEMOP: 327 return linux_semop(p, args, retval); 328 case LINUX_SEMGET: 329 return linux_semget(p, args, retval); 330 case LINUX_SEMCTL: 331 return linux_semctl(p, args, retval); 332 case LINUX_MSGSND: 333 return linux_msgsnd(p, args, retval); 334 case LINUX_MSGRCV: 335 return linux_msgrcv(p, args, retval); 336 case LINUX_MSGGET: 337 return linux_msgget(p, args, retval); 338 case LINUX_MSGCTL: 339 return linux_msgctl(p, args, retval); 340 case LINUX_SHMAT: 341 return linux_shmat(p, args, retval); 342 case LINUX_SHMDT: 343 return linux_shmdt(p, args, retval); 344 case LINUX_SHMGET: 345 return linux_shmget(p, args, retval); 346 case LINUX_SHMCTL: 347 return linux_shmctl(p, args, retval); 348 default: 349 uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->what); 350 return ENOSYS; 351 } 352 } 353