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