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