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.11 (Berkeley) 06/08/85 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 int iovcnt; 46 } *uap = (struct a *)u.u_ap; 47 struct uio auio; 48 struct iovec aiov[16]; /* XXX */ 49 50 if (uap->iovcnt <= 0 || 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 (unsigned)(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 int 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 int iovcnt; 89 } *uap = (struct a *)u.u_ap; 90 struct uio auio; 91 struct iovec aiov[16]; /* XXX */ 92 93 if (uap->iovcnt <= 0 || 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 (unsigned)(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 uses bit masks of file descriptors in ints. 256 * These macros manipulate such bit fields (the filesystem macros use chars). 257 */ 258 #define NBI (sizeof(int) * NBBY) /* bits per int */ 259 #define NI howmany(NOFILE, NBI) 260 #define tbit(p, n) ((p)[(n)/NBI] & (1 << ((n) % NBI))) 261 #define sbit(p, n) ((p)[(n)/NBI] |= (1 << ((n) % NBI))) 262 #define cbit(p, n) ((p)[(n)/NBI] &= ~(1 << ((n) % NBI))) 263 264 /* 265 * Select system call. 266 */ 267 select() 268 { 269 register struct uap { 270 int nd; 271 int *in, *ou, *ex; 272 struct timeval *tv; 273 } *uap = (struct uap *)u.u_ap; 274 int ibits[3][NI], obits[3][NI]; 275 struct timeval atv; 276 int s, ncoll, ni; 277 label_t lqsave; 278 279 bzero(ibits, sizeof(ibits)); 280 bzero(obits, sizeof(obits)); 281 if (uap->nd > NOFILE) 282 uap->nd = NOFILE; /* forgiving, if slightly wrong */ 283 ni = howmany(uap->nd, NBI); 284 285 #define getbits(name, x) \ 286 if (uap->name) { \ 287 u.u_error = copyin((caddr_t)uap->name, (caddr_t)ibits[x], \ 288 ni * sizeof(int)); \ 289 if (u.u_error) \ 290 goto done; \ 291 } 292 getbits(in, 0); 293 getbits(ou, 1); 294 getbits(ex, 2); 295 #undef getbits 296 297 if (uap->tv) { 298 u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv, 299 sizeof (atv)); 300 if (u.u_error) 301 goto done; 302 if (itimerfix(&atv)) { 303 u.u_error = EINVAL; 304 goto done; 305 } 306 s = splhigh(); timevaladd(&atv, &time); splx(s); 307 } 308 retry: 309 ncoll = nselcoll; 310 u.u_procp->p_flag |= SSEL; 311 u.u_r.r_val1 = selscan(ibits, obits, uap->nd); 312 if (u.u_error || u.u_r.r_val1) 313 goto done; 314 s = splhigh(); 315 /* this should be timercmp(&time, &atv, >=) */ 316 if (uap->tv && (time.tv_sec > atv.tv_sec || 317 time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) { 318 splx(s); 319 goto done; 320 } 321 if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { 322 u.u_procp->p_flag &= ~SSEL; 323 splx(s); 324 goto retry; 325 } 326 u.u_procp->p_flag &= ~SSEL; 327 if (uap->tv) { 328 lqsave = u.u_qsave; 329 if (setjmp(&u.u_qsave)) { 330 untimeout(unselect, (caddr_t)u.u_procp); 331 u.u_error = EINTR; 332 splx(s); 333 goto done; 334 } 335 timeout(unselect, (caddr_t)u.u_procp, hzto(&atv)); 336 } 337 sleep((caddr_t)&selwait, PZERO+1); 338 if (uap->tv) { 339 u.u_qsave = lqsave; 340 untimeout(unselect, (caddr_t)u.u_procp); 341 } 342 splx(s); 343 goto retry; 344 done: 345 #define putbits(name, x) \ 346 if (uap->name) { \ 347 int error = copyout((caddr_t)obits[x], (caddr_t)uap->name, \ 348 ni * sizeof(int)); \ 349 if (error) \ 350 u.u_error = error; \ 351 } 352 if (u.u_error != EINTR) { 353 putbits(in, 0); 354 putbits(ou, 1); 355 putbits(ex, 2); 356 #undef putbits 357 } 358 } 359 360 unselect(p) 361 register struct proc *p; 362 { 363 register int s = splhigh(); 364 365 switch (p->p_stat) { 366 367 case SSLEEP: 368 setrun(p); 369 break; 370 371 case SSTOP: 372 unsleep(p); 373 break; 374 } 375 splx(s); 376 } 377 378 selscan(ibits, obits, nfd) 379 int (*ibits)[NI], (*obits)[NI]; 380 { 381 register int which, bits, i, j; 382 int flag; 383 struct file *fp; 384 int n = 0; 385 386 for (which = 0; which < 3; which++) { 387 switch (which) { 388 389 case 0: 390 flag = FREAD; break; 391 392 case 1: 393 flag = FWRITE; break; 394 395 case 2: 396 flag = 0; break; 397 } 398 for (i = 0; i < nfd; i += NBI) { 399 bits = ibits[which][i/NBI]; 400 while ((j = ffs(bits)) && i + --j < nfd) { 401 bits &= ~(1 << j); 402 fp = u.u_ofile[i + j]; 403 if (fp == NULL) { 404 u.u_error = EBADF; 405 break; 406 } 407 if ((*fp->f_ops->fo_select)(fp, flag)) { 408 sbit(obits[which], i + j); 409 n++; 410 } 411 } 412 } 413 } 414 return (n); 415 } 416 417 /*ARGSUSED*/ 418 seltrue(dev, flag) 419 dev_t dev; 420 int flag; 421 { 422 423 return (1); 424 } 425 426 selwakeup(p, coll) 427 register struct proc *p; 428 int coll; 429 { 430 431 if (coll) { 432 nselcoll++; 433 wakeup((caddr_t)&selwait); 434 } 435 if (p) { 436 int s = splhigh(); 437 if (p->p_wchan == (caddr_t)&selwait) { 438 if (p->p_stat == SSLEEP) 439 setrun(p); 440 else 441 unsleep(p); 442 } else if (p->p_flag & SSEL) 443 p->p_flag &= ~SSEL; 444 splx(s); 445 } 446 } 447