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.8 (Berkeley) 08/27/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 (com == FIOCLEX) { 178 u.u_pofile[uap->fdes] |= UF_EXCLOSE; 179 return; 180 } 181 if (com == FIONCLEX) { 182 u.u_pofile[uap->fdes] &= ~UF_EXCLOSE; 183 return; 184 } 185 186 /* 187 * Interpret high order word to find 188 * amount of data to be copied to/from the 189 * user's address space. 190 */ 191 size = IOCPARM_LEN(com); 192 if (size > IOCPARM_MAX) { 193 u.u_error = EFAULT; 194 return; 195 } 196 if (size > sizeof (stkbuf)) { 197 memp = (caddr_t)malloc((u_long)IOCPARM_MAX, M_IOCTLOPS, 198 M_WAITOK); 199 data = memp; 200 } 201 if (com&IOC_IN) { 202 if (size) { 203 u.u_error = 204 copyin(uap->cmarg, data, (u_int)size); 205 if (u.u_error) { 206 if (memp) 207 free(memp, M_IOCTLOPS); 208 return; 209 } 210 } else 211 *(caddr_t *)data = uap->cmarg; 212 } else if ((com&IOC_OUT) && size) 213 /* 214 * Zero the buffer on the stack so the user 215 * always gets back something deterministic. 216 */ 217 bzero(data, size); 218 else if (com&IOC_VOID) 219 *(caddr_t *)data = uap->cmarg; 220 221 switch (com) { 222 223 case FIONBIO: 224 u.u_error = fset(fp, FNDELAY, *(int *)data); 225 break; 226 227 case FIOASYNC: 228 u.u_error = fset(fp, FASYNC, *(int *)data); 229 break; 230 231 case FIOSETOWN: 232 u.u_error = fsetown(fp, *(int *)data); 233 break; 234 235 case FIOGETOWN: 236 u.u_error = fgetown(fp, (int *)data); 237 break; 238 default: 239 if (setjmp(&u.u_qsave)) 240 u.u_error = EINTR; 241 else 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 break; 250 } 251 if (memp) 252 free(memp, M_IOCTLOPS); 253 } 254 255 int unselect(); 256 int nselcoll; 257 258 /* 259 * Select system call. 260 */ 261 select() 262 { 263 register struct uap { 264 int nd; 265 fd_set *in, *ou, *ex; 266 struct timeval *tv; 267 } *uap = (struct uap *)u.u_ap; 268 fd_set ibits[3], obits[3]; 269 struct timeval atv; 270 int s, ncoll, ni; 271 label_t lqsave; 272 273 bzero((caddr_t)ibits, sizeof(ibits)); 274 bzero((caddr_t)obits, sizeof(obits)); 275 if (uap->nd > NOFILE) 276 uap->nd = NOFILE; /* forgiving, if slightly wrong */ 277 ni = howmany(uap->nd, NFDBITS); 278 279 #define getbits(name, x) \ 280 if (uap->name) { \ 281 u.u_error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \ 282 (unsigned)(ni * sizeof(fd_mask))); \ 283 if (u.u_error) \ 284 goto done; \ 285 } 286 getbits(in, 0); 287 getbits(ou, 1); 288 getbits(ex, 2); 289 #undef getbits 290 291 if (uap->tv) { 292 u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv, 293 sizeof (atv)); 294 if (u.u_error) 295 goto done; 296 if (itimerfix(&atv)) { 297 u.u_error = EINVAL; 298 goto done; 299 } 300 s = splhigh(); timevaladd(&atv, &time); splx(s); 301 } 302 retry: 303 ncoll = nselcoll; 304 u.u_procp->p_flag |= SSEL; 305 u.u_r.r_val1 = selscan(ibits, obits, uap->nd); 306 if (u.u_error || u.u_r.r_val1) 307 goto done; 308 s = splhigh(); 309 /* this should be timercmp(&time, &atv, >=) */ 310 if (uap->tv && (time.tv_sec > atv.tv_sec || 311 time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) { 312 splx(s); 313 goto done; 314 } 315 if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { 316 splx(s); 317 goto retry; 318 } 319 u.u_procp->p_flag &= ~SSEL; 320 if (uap->tv) { 321 lqsave = u.u_qsave; 322 if (setjmp(&u.u_qsave)) { 323 untimeout(unselect, (caddr_t)u.u_procp); 324 u.u_error = EINTR; 325 splx(s); 326 goto done; 327 } 328 timeout(unselect, (caddr_t)u.u_procp, hzto(&atv)); 329 } 330 sleep((caddr_t)&selwait, PZERO+1); 331 if (uap->tv) { 332 u.u_qsave = lqsave; 333 untimeout(unselect, (caddr_t)u.u_procp); 334 } 335 splx(s); 336 goto retry; 337 done: 338 u.u_procp->p_flag &= ~SSEL; 339 #define putbits(name, x) \ 340 if (uap->name) { \ 341 int error = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \ 342 (unsigned)(ni * sizeof(fd_mask))); \ 343 if (error) \ 344 u.u_error = error; \ 345 } 346 if (u.u_error == 0) { 347 putbits(in, 0); 348 putbits(ou, 1); 349 putbits(ex, 2); 350 #undef putbits 351 } 352 } 353 354 unselect(p) 355 register struct proc *p; 356 { 357 register int s = splhigh(); 358 359 switch (p->p_stat) { 360 361 case SSLEEP: 362 setrun(p); 363 break; 364 365 case SSTOP: 366 unsleep(p); 367 break; 368 } 369 splx(s); 370 } 371 372 selscan(ibits, obits, nfd) 373 fd_set *ibits, *obits; 374 { 375 register int which, i, j; 376 register fd_mask bits; 377 int flag; 378 struct file *fp; 379 int n = 0; 380 381 for (which = 0; which < 3; which++) { 382 switch (which) { 383 384 case 0: 385 flag = FREAD; break; 386 387 case 1: 388 flag = FWRITE; break; 389 390 case 2: 391 flag = 0; break; 392 } 393 for (i = 0; i < nfd; i += NFDBITS) { 394 bits = ibits[which].fds_bits[i/NFDBITS]; 395 while ((j = ffs(bits)) && i + --j < nfd) { 396 bits &= ~(1 << j); 397 fp = u.u_ofile[i + j]; 398 if (fp == NULL) { 399 u.u_error = EBADF; 400 break; 401 } 402 if ((*fp->f_ops->fo_select)(fp, flag)) { 403 FD_SET(i + j, &obits[which]); 404 n++; 405 } 406 } 407 } 408 } 409 return (n); 410 } 411 412 /*ARGSUSED*/ 413 seltrue(dev, flag) 414 dev_t dev; 415 int flag; 416 { 417 418 return (1); 419 } 420 421 selwakeup(p, coll) 422 register struct proc *p; 423 int coll; 424 { 425 426 if (coll) { 427 nselcoll++; 428 wakeup((caddr_t)&selwait); 429 } 430 if (p) { 431 int s = splhigh(); 432 if (p->p_wchan == (caddr_t)&selwait) { 433 if (p->p_stat == SSLEEP) 434 setrun(p); 435 else 436 unsleep(p); 437 } else if (p->p_flag & SSEL) 438 p->p_flag &= ~SSEL; 439 splx(s); 440 } 441 } 442