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.2 (Berkeley) 02/19/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 uio->uio_offset = fp->f_offset; 140 if (setjmp(&u.u_qsave)) { 141 if (uio->uio_resid == count) { 142 if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0) 143 u.u_error = EINTR; 144 else 145 u.u_eosys = RESTARTSYS; 146 } 147 } else 148 u.u_error = (*fp->f_ops->fo_rw)(fp, rw, uio); 149 u.u_r.r_val1 = count - uio->uio_resid; 150 fp->f_offset += u.u_r.r_val1; 151 } 152 153 /* 154 * Ioctl system call 155 */ 156 ioctl() 157 { 158 register struct file *fp; 159 struct a { 160 int fdes; 161 int cmd; 162 caddr_t cmarg; 163 } *uap; 164 register int com; 165 register u_int size; 166 struct buf *bp = 0; 167 #define STK_PARAMS 128 168 char buf[STK_PARAMS]; 169 caddr_t data = buf; 170 171 uap = (struct a *)u.u_ap; 172 GETF(fp, uap->fdes); 173 if ((fp->f_flag & (FREAD|FWRITE)) == 0) { 174 u.u_error = EBADF; 175 return; 176 } 177 com = uap->cmd; 178 179 #if defined(vax) && defined(COMPAT) 180 /* 181 * Map old style ioctl's into new for the 182 * sake of backwards compatibility (sigh). 183 */ 184 if ((com&~0xffff) == 0) { 185 com = mapioctl(com); 186 if (com == 0) { 187 u.u_error = EINVAL; 188 return; 189 } 190 } 191 #endif 192 if (com == FIOCLEX) { 193 u.u_pofile[uap->fdes] |= UF_EXCLOSE; 194 return; 195 } 196 if (com == FIONCLEX) { 197 u.u_pofile[uap->fdes] &= ~UF_EXCLOSE; 198 return; 199 } 200 201 /* 202 * Interpret high order word to find 203 * amount of data to be copied to/from the 204 * user's address space. 205 */ 206 size = IOCPARM_LEN(com); 207 if (size > IOCPARM_MAX) { 208 u.u_error = EFAULT; 209 return; 210 } 211 if (size > sizeof (buf)) { 212 bp = geteblk(IOCPARM_MAX); /* XXX */ 213 data = bp->b_un.b_addr; 214 } 215 if (com&IOC_IN) { 216 if (size) { 217 u.u_error = 218 copyin(uap->cmarg, data, (u_int)size); 219 if (u.u_error) 220 return; 221 } else 222 *(caddr_t *)data = uap->cmarg; 223 } else if ((com&IOC_OUT) && size) 224 /* 225 * Zero the buffer on the stack so the user 226 * always gets back something deterministic. 227 */ 228 bzero(data, size); 229 else if (com&IOC_VOID) 230 *(caddr_t *)data = uap->cmarg; 231 232 switch (com) { 233 234 case FIONBIO: 235 u.u_error = fset(fp, FNDELAY, *(int *)data); 236 break; 237 238 case FIOASYNC: 239 u.u_error = fset(fp, FASYNC, *(int *)data); 240 break; 241 242 case FIOSETOWN: 243 u.u_error = fsetown(fp, *(int *)data); 244 break; 245 246 case FIOGETOWN: 247 u.u_error = fgetown(fp, (int *)data); 248 break; 249 default: 250 if (setjmp(&u.u_qsave)) 251 u.u_error = EINTR; 252 else 253 u.u_error = (*fp->f_ops->fo_ioctl)(fp, com, data); 254 /* 255 * Copy any data to user, size was 256 * already set and checked above. 257 */ 258 if (u.u_error == 0 && (com&IOC_OUT) && size) 259 u.u_error = copyout(data, uap->cmarg, (u_int)size); 260 break; 261 } 262 if (bp) 263 brelse(bp); 264 } 265 266 int unselect(); 267 int nselcoll; 268 269 /* 270 * Select system call. 271 */ 272 select() 273 { 274 register struct uap { 275 int nd; 276 fd_set *in, *ou, *ex; 277 struct timeval *tv; 278 } *uap = (struct uap *)u.u_ap; 279 fd_set ibits[3], obits[3]; 280 struct timeval atv; 281 int s, ncoll, ni; 282 label_t lqsave; 283 284 bzero((caddr_t)ibits, sizeof(ibits)); 285 bzero((caddr_t)obits, sizeof(obits)); 286 if (uap->nd > NOFILE) 287 uap->nd = NOFILE; /* forgiving, if slightly wrong */ 288 ni = howmany(uap->nd, NFDBITS); 289 290 #define getbits(name, x) \ 291 if (uap->name) { \ 292 u.u_error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \ 293 (unsigned)(ni * sizeof(fd_mask))); \ 294 if (u.u_error) \ 295 goto done; \ 296 } 297 getbits(in, 0); 298 getbits(ou, 1); 299 getbits(ex, 2); 300 #undef getbits 301 302 if (uap->tv) { 303 u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv, 304 sizeof (atv)); 305 if (u.u_error) 306 goto done; 307 if (itimerfix(&atv)) { 308 u.u_error = EINVAL; 309 goto done; 310 } 311 s = splhigh(); timevaladd(&atv, &time); splx(s); 312 } 313 retry: 314 ncoll = nselcoll; 315 u.u_procp->p_flag |= SSEL; 316 u.u_r.r_val1 = selscan(ibits, obits, uap->nd); 317 if (u.u_error || u.u_r.r_val1) 318 goto done; 319 s = splhigh(); 320 /* this should be timercmp(&time, &atv, >=) */ 321 if (uap->tv && (time.tv_sec > atv.tv_sec || 322 time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) { 323 splx(s); 324 goto done; 325 } 326 if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { 327 u.u_procp->p_flag &= ~SSEL; 328 splx(s); 329 goto retry; 330 } 331 u.u_procp->p_flag &= ~SSEL; 332 if (uap->tv) { 333 lqsave = u.u_qsave; 334 if (setjmp(&u.u_qsave)) { 335 untimeout(unselect, (caddr_t)u.u_procp); 336 u.u_error = EINTR; 337 splx(s); 338 goto done; 339 } 340 timeout(unselect, (caddr_t)u.u_procp, hzto(&atv)); 341 } 342 sleep((caddr_t)&selwait, PZERO+1); 343 if (uap->tv) { 344 u.u_qsave = lqsave; 345 untimeout(unselect, (caddr_t)u.u_procp); 346 } 347 splx(s); 348 goto retry; 349 done: 350 #define putbits(name, x) \ 351 if (uap->name) { \ 352 int error = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \ 353 (unsigned)(ni * sizeof(fd_mask))); \ 354 if (error) \ 355 u.u_error = error; \ 356 } 357 if (u.u_error == 0) { 358 putbits(in, 0); 359 putbits(ou, 1); 360 putbits(ex, 2); 361 #undef putbits 362 } 363 } 364 365 unselect(p) 366 register struct proc *p; 367 { 368 register int s = splhigh(); 369 370 switch (p->p_stat) { 371 372 case SSLEEP: 373 setrun(p); 374 break; 375 376 case SSTOP: 377 unsleep(p); 378 break; 379 } 380 splx(s); 381 } 382 383 selscan(ibits, obits, nfd) 384 fd_set *ibits, *obits; 385 { 386 register int which, i, j; 387 register fd_mask bits; 388 int flag; 389 struct file *fp; 390 int n = 0; 391 392 for (which = 0; which < 3; which++) { 393 switch (which) { 394 395 case 0: 396 flag = FREAD; break; 397 398 case 1: 399 flag = FWRITE; break; 400 401 case 2: 402 flag = 0; break; 403 } 404 for (i = 0; i < nfd; i += NFDBITS) { 405 bits = ibits[which].fds_bits[i/NFDBITS]; 406 while ((j = ffs(bits)) && i + --j < nfd) { 407 bits &= ~(1 << j); 408 fp = u.u_ofile[i + j]; 409 if (fp == NULL) { 410 u.u_error = EBADF; 411 break; 412 } 413 if ((*fp->f_ops->fo_select)(fp, flag)) { 414 FD_SET(i + j, &obits[which]); 415 n++; 416 } 417 } 418 } 419 } 420 return (n); 421 } 422 423 /*ARGSUSED*/ 424 seltrue(dev, flag) 425 dev_t dev; 426 int flag; 427 { 428 429 return (1); 430 } 431 432 selwakeup(p, coll) 433 register struct proc *p; 434 int coll; 435 { 436 437 if (coll) { 438 nselcoll++; 439 wakeup((caddr_t)&selwait); 440 } 441 if (p) { 442 int s = splhigh(); 443 if (p->p_wchan == (caddr_t)&selwait) { 444 if (p->p_stat == SSLEEP) 445 setrun(p); 446 else 447 unsleep(p); 448 } else if (p->p_flag & SSEL) 449 p->p_flag &= ~SSEL; 450 splx(s); 451 } 452 } 453