1 /* 2 * Copyright (c) 1982, 1986 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)sys_generic.c 7.7 (Berkeley) 05/24/88 7 */ 8 9 #include "param.h" 10 #include "systm.h" 11 #include "dir.h" 12 #include "user.h" 13 #include "ioctl.h" 14 #include "file.h" 15 #include "proc.h" 16 #include "uio.h" 17 #include "kernel.h" 18 #include "stat.h" 19 #include "malloc.h" 20 21 /* 22 * Read system call. 23 */ 24 read() 25 { 26 register struct a { 27 int fdes; 28 char *cbuf; 29 unsigned count; 30 } *uap = (struct a *)u.u_ap; 31 struct uio auio; 32 struct iovec aiov; 33 34 aiov.iov_base = (caddr_t)uap->cbuf; 35 aiov.iov_len = uap->count; 36 auio.uio_iov = &aiov; 37 auio.uio_iovcnt = 1; 38 rwuio(&auio, UIO_READ); 39 } 40 41 readv() 42 { 43 register struct a { 44 int fdes; 45 struct iovec *iovp; 46 unsigned iovcnt; 47 } *uap = (struct a *)u.u_ap; 48 struct uio auio; 49 struct iovec aiov[16]; /* XXX */ 50 51 if (uap->iovcnt > sizeof(aiov)/sizeof(aiov[0])) { 52 u.u_error = EINVAL; 53 return; 54 } 55 auio.uio_iov = aiov; 56 auio.uio_iovcnt = uap->iovcnt; 57 u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)aiov, 58 uap->iovcnt * sizeof (struct iovec)); 59 if (u.u_error) 60 return; 61 rwuio(&auio, UIO_READ); 62 } 63 64 /* 65 * Write system call 66 */ 67 write() 68 { 69 register struct a { 70 int fdes; 71 char *cbuf; 72 unsigned count; 73 } *uap = (struct a *)u.u_ap; 74 struct uio auio; 75 struct iovec aiov; 76 77 auio.uio_iov = &aiov; 78 auio.uio_iovcnt = 1; 79 aiov.iov_base = uap->cbuf; 80 aiov.iov_len = uap->count; 81 rwuio(&auio, UIO_WRITE); 82 } 83 84 writev() 85 { 86 register struct a { 87 int fdes; 88 struct iovec *iovp; 89 unsigned iovcnt; 90 } *uap = (struct a *)u.u_ap; 91 struct uio auio; 92 struct iovec aiov[16]; /* XXX */ 93 94 if (uap->iovcnt > sizeof(aiov)/sizeof(aiov[0])) { 95 u.u_error = EINVAL; 96 return; 97 } 98 auio.uio_iov = aiov; 99 auio.uio_iovcnt = uap->iovcnt; 100 u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)aiov, 101 uap->iovcnt * sizeof (struct iovec)); 102 if (u.u_error) 103 return; 104 rwuio(&auio, UIO_WRITE); 105 } 106 107 rwuio(uio, rw) 108 register struct uio *uio; 109 enum uio_rw rw; 110 { 111 struct a { 112 int fdes; 113 }; 114 register struct file *fp; 115 register struct iovec *iov; 116 int i, count; 117 118 GETF(fp, ((struct a *)u.u_ap)->fdes); 119 if ((fp->f_flag&(rw==UIO_READ ? FREAD : FWRITE)) == 0) { 120 u.u_error = EBADF; 121 return; 122 } 123 uio->uio_resid = 0; 124 uio->uio_segflg = UIO_USERSPACE; 125 iov = uio->uio_iov; 126 for (i = 0; i < uio->uio_iovcnt; i++) { 127 if (iov->iov_len < 0) { 128 u.u_error = EINVAL; 129 return; 130 } 131 uio->uio_resid += iov->iov_len; 132 if (uio->uio_resid < 0) { 133 u.u_error = EINVAL; 134 return; 135 } 136 iov++; 137 } 138 count = uio->uio_resid; 139 if (setjmp(&u.u_qsave)) { 140 if (uio->uio_resid == count) { 141 if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0) 142 u.u_error = EINTR; 143 else 144 u.u_eosys = RESTARTSYS; 145 } 146 } else 147 u.u_error = (*fp->f_ops->fo_rw)(fp, rw, uio); 148 u.u_r.r_val1 = count - uio->uio_resid; 149 } 150 151 /* 152 * Ioctl system call 153 */ 154 ioctl() 155 { 156 register struct file *fp; 157 struct a { 158 int fdes; 159 int cmd; 160 caddr_t cmarg; 161 } *uap; 162 register int com; 163 register u_int size; 164 caddr_t memp = 0; 165 #define STK_PARAMS 128 166 char stkbuf[STK_PARAMS]; 167 caddr_t data = stkbuf; 168 169 uap = (struct a *)u.u_ap; 170 GETF(fp, uap->fdes); 171 if ((fp->f_flag & (FREAD|FWRITE)) == 0) { 172 u.u_error = EBADF; 173 return; 174 } 175 com = uap->cmd; 176 177 #if defined(vax) && defined(COMPAT) 178 /* 179 * Map old style ioctl's into new for the 180 * sake of backwards compatibility (sigh). 181 */ 182 if ((com&~0xffff) == 0) { 183 com = mapioctl(com); 184 if (com == 0) { 185 u.u_error = EINVAL; 186 return; 187 } 188 } 189 #endif 190 if (com == FIOCLEX) { 191 u.u_pofile[uap->fdes] |= UF_EXCLOSE; 192 return; 193 } 194 if (com == FIONCLEX) { 195 u.u_pofile[uap->fdes] &= ~UF_EXCLOSE; 196 return; 197 } 198 199 /* 200 * Interpret high order word to find 201 * amount of data to be copied to/from the 202 * user's address space. 203 */ 204 size = IOCPARM_LEN(com); 205 if (size > IOCPARM_MAX) { 206 u.u_error = EFAULT; 207 return; 208 } 209 if (size > sizeof (stkbuf)) { 210 memp = (caddr_t)malloc((u_long)IOCPARM_MAX, M_IOCTLOPS, 211 M_WAITOK); 212 data = memp; 213 } 214 if (com&IOC_IN) { 215 if (size) { 216 u.u_error = 217 copyin(uap->cmarg, data, (u_int)size); 218 if (u.u_error) { 219 if (memp) 220 free(memp, M_IOCTLOPS); 221 return; 222 } 223 } else 224 *(caddr_t *)data = uap->cmarg; 225 } else if ((com&IOC_OUT) && size) 226 /* 227 * Zero the buffer on the stack so the user 228 * always gets back something deterministic. 229 */ 230 bzero(data, size); 231 else if (com&IOC_VOID) 232 *(caddr_t *)data = uap->cmarg; 233 234 switch (com) { 235 236 case FIONBIO: 237 u.u_error = fset(fp, FNDELAY, *(int *)data); 238 break; 239 240 case FIOASYNC: 241 u.u_error = fset(fp, FASYNC, *(int *)data); 242 break; 243 244 case FIOSETOWN: 245 u.u_error = fsetown(fp, *(int *)data); 246 break; 247 248 case FIOGETOWN: 249 u.u_error = fgetown(fp, (int *)data); 250 break; 251 default: 252 if (setjmp(&u.u_qsave)) 253 u.u_error = EINTR; 254 else 255 u.u_error = (*fp->f_ops->fo_ioctl)(fp, com, data); 256 /* 257 * Copy any data to user, size was 258 * already set and checked above. 259 */ 260 if (u.u_error == 0 && (com&IOC_OUT) && size) 261 u.u_error = copyout(data, uap->cmarg, (u_int)size); 262 break; 263 } 264 if (memp) 265 free(memp, M_IOCTLOPS); 266 } 267 268 int unselect(); 269 int nselcoll; 270 271 /* 272 * Select system call. 273 */ 274 select() 275 { 276 register struct uap { 277 int nd; 278 fd_set *in, *ou, *ex; 279 struct timeval *tv; 280 } *uap = (struct uap *)u.u_ap; 281 fd_set ibits[3], obits[3]; 282 struct timeval atv; 283 int s, ncoll, ni; 284 label_t lqsave; 285 286 bzero((caddr_t)ibits, sizeof(ibits)); 287 bzero((caddr_t)obits, sizeof(obits)); 288 if (uap->nd > NOFILE) 289 uap->nd = NOFILE; /* forgiving, if slightly wrong */ 290 ni = howmany(uap->nd, NFDBITS); 291 292 #define getbits(name, x) \ 293 if (uap->name) { \ 294 u.u_error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \ 295 (unsigned)(ni * sizeof(fd_mask))); \ 296 if (u.u_error) \ 297 goto done; \ 298 } 299 getbits(in, 0); 300 getbits(ou, 1); 301 getbits(ex, 2); 302 #undef getbits 303 304 if (uap->tv) { 305 u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv, 306 sizeof (atv)); 307 if (u.u_error) 308 goto done; 309 if (itimerfix(&atv)) { 310 u.u_error = EINVAL; 311 goto done; 312 } 313 s = splhigh(); timevaladd(&atv, &time); splx(s); 314 } 315 retry: 316 ncoll = nselcoll; 317 u.u_procp->p_flag |= SSEL; 318 u.u_r.r_val1 = selscan(ibits, obits, uap->nd); 319 if (u.u_error || u.u_r.r_val1) 320 goto done; 321 s = splhigh(); 322 /* this should be timercmp(&time, &atv, >=) */ 323 if (uap->tv && (time.tv_sec > atv.tv_sec || 324 time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) { 325 splx(s); 326 goto done; 327 } 328 if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { 329 splx(s); 330 goto retry; 331 } 332 u.u_procp->p_flag &= ~SSEL; 333 if (uap->tv) { 334 lqsave = u.u_qsave; 335 if (setjmp(&u.u_qsave)) { 336 untimeout(unselect, (caddr_t)u.u_procp); 337 u.u_error = EINTR; 338 splx(s); 339 goto done; 340 } 341 timeout(unselect, (caddr_t)u.u_procp, hzto(&atv)); 342 } 343 sleep((caddr_t)&selwait, PZERO+1); 344 if (uap->tv) { 345 u.u_qsave = lqsave; 346 untimeout(unselect, (caddr_t)u.u_procp); 347 } 348 splx(s); 349 goto retry; 350 done: 351 u.u_procp->p_flag &= ~SSEL; 352 #define putbits(name, x) \ 353 if (uap->name) { \ 354 int error = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \ 355 (unsigned)(ni * sizeof(fd_mask))); \ 356 if (error) \ 357 u.u_error = error; \ 358 } 359 if (u.u_error == 0) { 360 putbits(in, 0); 361 putbits(ou, 1); 362 putbits(ex, 2); 363 #undef putbits 364 } 365 } 366 367 unselect(p) 368 register struct proc *p; 369 { 370 register int s = splhigh(); 371 372 switch (p->p_stat) { 373 374 case SSLEEP: 375 setrun(p); 376 break; 377 378 case SSTOP: 379 unsleep(p); 380 break; 381 } 382 splx(s); 383 } 384 385 selscan(ibits, obits, nfd) 386 fd_set *ibits, *obits; 387 { 388 register int which, i, j; 389 register fd_mask bits; 390 int flag; 391 struct file *fp; 392 int n = 0; 393 394 for (which = 0; which < 3; which++) { 395 switch (which) { 396 397 case 0: 398 flag = FREAD; break; 399 400 case 1: 401 flag = FWRITE; break; 402 403 case 2: 404 flag = 0; break; 405 } 406 for (i = 0; i < nfd; i += NFDBITS) { 407 bits = ibits[which].fds_bits[i/NFDBITS]; 408 while ((j = ffs(bits)) && i + --j < nfd) { 409 bits &= ~(1 << j); 410 fp = u.u_ofile[i + j]; 411 if (fp == NULL) { 412 u.u_error = EBADF; 413 break; 414 } 415 if ((*fp->f_ops->fo_select)(fp, flag)) { 416 FD_SET(i + j, &obits[which]); 417 n++; 418 } 419 } 420 } 421 } 422 return (n); 423 } 424 425 /*ARGSUSED*/ 426 seltrue(dev, flag) 427 dev_t dev; 428 int flag; 429 { 430 431 return (1); 432 } 433 434 selwakeup(p, coll) 435 register struct proc *p; 436 int coll; 437 { 438 439 if (coll) { 440 nselcoll++; 441 wakeup((caddr_t)&selwait); 442 } 443 if (p) { 444 int s = splhigh(); 445 if (p->p_wchan == (caddr_t)&selwait) { 446 if (p->p_stat == SSLEEP) 447 setrun(p); 448 else 449 unsleep(p); 450 } else if (p->p_flag & SSEL) 451 p->p_flag &= ~SSEL; 452 splx(s); 453 } 454 } 455