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