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.3 (Berkeley) 03/17/87 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 "buf.h" /* XXX */ 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 struct buf *bp = 0; 165 #define STK_PARAMS 128 166 char buf[STK_PARAMS]; 167 caddr_t data = buf; 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 (buf)) { 210 bp = geteblk(IOCPARM_MAX); /* XXX */ 211 data = bp->b_un.b_addr; 212 } 213 if (com&IOC_IN) { 214 if (size) { 215 u.u_error = 216 copyin(uap->cmarg, data, (u_int)size); 217 if (u.u_error) 218 return; 219 } else 220 *(caddr_t *)data = uap->cmarg; 221 } else if ((com&IOC_OUT) && size) 222 /* 223 * Zero the buffer on the stack so the user 224 * always gets back something deterministic. 225 */ 226 bzero(data, size); 227 else if (com&IOC_VOID) 228 *(caddr_t *)data = uap->cmarg; 229 230 switch (com) { 231 232 case FIONBIO: 233 u.u_error = fset(fp, FNDELAY, *(int *)data); 234 break; 235 236 case FIOASYNC: 237 u.u_error = fset(fp, FASYNC, *(int *)data); 238 break; 239 240 case FIOSETOWN: 241 u.u_error = fsetown(fp, *(int *)data); 242 break; 243 244 case FIOGETOWN: 245 u.u_error = fgetown(fp, (int *)data); 246 break; 247 default: 248 if (setjmp(&u.u_qsave)) 249 u.u_error = EINTR; 250 else 251 u.u_error = (*fp->f_ops->fo_ioctl)(fp, com, data); 252 /* 253 * Copy any data to user, size was 254 * already set and checked above. 255 */ 256 if (u.u_error == 0 && (com&IOC_OUT) && size) 257 u.u_error = copyout(data, uap->cmarg, (u_int)size); 258 break; 259 } 260 if (bp) 261 brelse(bp); 262 } 263 264 int unselect(); 265 int nselcoll; 266 267 /* 268 * Select system call. 269 */ 270 select() 271 { 272 register struct uap { 273 int nd; 274 fd_set *in, *ou, *ex; 275 struct timeval *tv; 276 } *uap = (struct uap *)u.u_ap; 277 fd_set ibits[3], obits[3]; 278 struct timeval atv; 279 int s, ncoll, ni; 280 label_t lqsave; 281 282 bzero((caddr_t)ibits, sizeof(ibits)); 283 bzero((caddr_t)obits, sizeof(obits)); 284 if (uap->nd > NOFILE) 285 uap->nd = NOFILE; /* forgiving, if slightly wrong */ 286 ni = howmany(uap->nd, NFDBITS); 287 288 #define getbits(name, x) \ 289 if (uap->name) { \ 290 u.u_error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \ 291 (unsigned)(ni * sizeof(fd_mask))); \ 292 if (u.u_error) \ 293 goto done; \ 294 } 295 getbits(in, 0); 296 getbits(ou, 1); 297 getbits(ex, 2); 298 #undef getbits 299 300 if (uap->tv) { 301 u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv, 302 sizeof (atv)); 303 if (u.u_error) 304 goto done; 305 if (itimerfix(&atv)) { 306 u.u_error = EINVAL; 307 goto done; 308 } 309 s = splhigh(); timevaladd(&atv, &time); splx(s); 310 } 311 retry: 312 ncoll = nselcoll; 313 u.u_procp->p_flag |= SSEL; 314 u.u_r.r_val1 = selscan(ibits, obits, uap->nd); 315 if (u.u_error || u.u_r.r_val1) 316 goto done; 317 s = splhigh(); 318 /* this should be timercmp(&time, &atv, >=) */ 319 if (uap->tv && (time.tv_sec > atv.tv_sec || 320 time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) { 321 splx(s); 322 goto done; 323 } 324 if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { 325 u.u_procp->p_flag &= ~SSEL; 326 splx(s); 327 goto retry; 328 } 329 u.u_procp->p_flag &= ~SSEL; 330 if (uap->tv) { 331 lqsave = u.u_qsave; 332 if (setjmp(&u.u_qsave)) { 333 untimeout(unselect, (caddr_t)u.u_procp); 334 u.u_error = EINTR; 335 splx(s); 336 goto done; 337 } 338 timeout(unselect, (caddr_t)u.u_procp, hzto(&atv)); 339 } 340 sleep((caddr_t)&selwait, PZERO+1); 341 if (uap->tv) { 342 u.u_qsave = lqsave; 343 untimeout(unselect, (caddr_t)u.u_procp); 344 } 345 splx(s); 346 goto retry; 347 done: 348 #define putbits(name, x) \ 349 if (uap->name) { \ 350 int error = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \ 351 (unsigned)(ni * sizeof(fd_mask))); \ 352 if (error) \ 353 u.u_error = error; \ 354 } 355 if (u.u_error == 0) { 356 putbits(in, 0); 357 putbits(ou, 1); 358 putbits(ex, 2); 359 #undef putbits 360 } 361 } 362 363 unselect(p) 364 register struct proc *p; 365 { 366 register int s = splhigh(); 367 368 switch (p->p_stat) { 369 370 case SSLEEP: 371 setrun(p); 372 break; 373 374 case SSTOP: 375 unsleep(p); 376 break; 377 } 378 splx(s); 379 } 380 381 selscan(ibits, obits, nfd) 382 fd_set *ibits, *obits; 383 { 384 register int which, i, j; 385 register fd_mask bits; 386 int flag; 387 struct file *fp; 388 int n = 0; 389 390 for (which = 0; which < 3; which++) { 391 switch (which) { 392 393 case 0: 394 flag = FREAD; break; 395 396 case 1: 397 flag = FWRITE; break; 398 399 case 2: 400 flag = 0; break; 401 } 402 for (i = 0; i < nfd; i += NFDBITS) { 403 bits = ibits[which].fds_bits[i/NFDBITS]; 404 while ((j = ffs(bits)) && i + --j < nfd) { 405 bits &= ~(1 << j); 406 fp = u.u_ofile[i + j]; 407 if (fp == NULL) { 408 u.u_error = EBADF; 409 break; 410 } 411 if ((*fp->f_ops->fo_select)(fp, flag)) { 412 FD_SET(i + j, &obits[which]); 413 n++; 414 } 415 } 416 } 417 } 418 return (n); 419 } 420 421 /*ARGSUSED*/ 422 seltrue(dev, flag) 423 dev_t dev; 424 int flag; 425 { 426 427 return (1); 428 } 429 430 selwakeup(p, coll) 431 register struct proc *p; 432 int coll; 433 { 434 435 if (coll) { 436 nselcoll++; 437 wakeup((caddr_t)&selwait); 438 } 439 if (p) { 440 int s = splhigh(); 441 if (p->p_wchan == (caddr_t)&selwait) { 442 if (p->p_stat == SSLEEP) 443 setrun(p); 444 else 445 unsleep(p); 446 } else if (p->p_flag & SSEL) 447 p->p_flag &= ~SSEL; 448 splx(s); 449 } 450 } 451