1 /* sys_generic.c 5.36 83/05/27 */ 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 } 130 count = uio->uio_resid; 131 uio->uio_offset = fp->f_offset; 132 if ((u.u_procp->p_flag&SNUSIG) && setjmp(&u.u_qsave)) { 133 if (uio->uio_resid == count) 134 u.u_eosys = RESTARTSYS; 135 } else 136 u.u_error = (*fp->f_ops->fo_rw)(fp, rw, uio); 137 u.u_r.r_val1 = count - uio->uio_resid; 138 fp->f_offset += u.u_r.r_val1; 139 } 140 141 /* 142 * Ioctl system call 143 */ 144 ioctl() 145 { 146 register struct file *fp; 147 struct a { 148 int fdes; 149 int cmd; 150 caddr_t cmarg; 151 } *uap; 152 register int com; 153 register u_int size; 154 char data[IOCPARM_MASK+1]; 155 156 uap = (struct a *)u.u_ap; 157 if ((fp = getf(uap->fdes)) == NULL) 158 return; 159 if ((fp->f_flag & (FREAD|FWRITE)) == 0) { 160 u.u_error = EBADF; 161 return; 162 } 163 com = uap->cmd; 164 165 #if defined(vax) && !defined(NOCOMPAT) 166 /* 167 * Map old style ioctl's into new for the 168 * sake of backwards compatibility (sigh). 169 */ 170 if ((com&~0xffff) == 0) { 171 com = mapioctl(com); 172 if (com == 0) { 173 u.u_error = EINVAL; 174 return; 175 } 176 } 177 #endif 178 if (com == FIOCLEX) { 179 u.u_pofile[uap->fdes] |= UF_EXCLOSE; 180 return; 181 } 182 if (com == FIONCLEX) { 183 u.u_pofile[uap->fdes] &= ~UF_EXCLOSE; 184 return; 185 } 186 187 /* 188 * Interpret high order word to find 189 * amount of data to be copied to/from the 190 * user's address space. 191 */ 192 size = (com &~ (IOC_INOUT|IOC_VOID)) >> 16; 193 if (size > sizeof (data)) { 194 u.u_error = EFAULT; 195 return; 196 } 197 if (com&IOC_IN) { 198 if (size) { 199 u.u_error = 200 copyin(uap->cmarg, (caddr_t)data, (u_int)size); 201 if (u.u_error) 202 return; 203 } else 204 *(caddr_t *)data = uap->cmarg; 205 } else if ((com&IOC_OUT) && size) 206 /* 207 * Zero the buffer on the stack so the user 208 * always gets back something deterministic. 209 */ 210 bzero((caddr_t)data, size); 211 else if (com&IOC_VOID) 212 *(caddr_t *)data = uap->cmarg; 213 214 switch (com) { 215 216 case FIONBIO: 217 u.u_error = fset(fp, FNDELAY, *(int *)data); 218 return; 219 220 case FIOASYNC: 221 u.u_error = fset(fp, FASYNC, *(int *)data); 222 return; 223 224 case FIOSETOWN: 225 u.u_error = fsetown(fp, *(int *)data); 226 return; 227 228 case FIOGETOWN: 229 u.u_error = fgetown(fp, (int *)data); 230 return; 231 } 232 u.u_error = (*fp->f_ops->fo_ioctl)(fp, com, data); 233 /* 234 * Copy any data to user, size was 235 * already set and checked above. 236 */ 237 if (u.u_error == 0 && (com&IOC_OUT) && size) 238 u.u_error = copyout(data, uap->cmarg, (u_int)size); 239 } 240 241 int unselect(); 242 int nselcoll; 243 /* 244 * Select system call. 245 */ 246 select() 247 { 248 register struct uap { 249 int nd; 250 long *in, *ou, *ex; 251 struct timeval *tv; 252 } *uap = (struct uap *)u.u_ap; 253 int ibits[3], obits[3]; 254 struct timeval atv; 255 int s, ncoll; 256 label_t lqsave; 257 258 obits[0] = obits[1] = obits[2] = 0; 259 if (uap->nd > NOFILE) 260 uap->nd = NOFILE; /* forgiving, if slightly wrong */ 261 262 #define getbits(name, x) \ 263 if (uap->name) { \ 264 u.u_error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \ 265 sizeof (ibits[x])); \ 266 if (u.u_error) \ 267 goto done; \ 268 } else \ 269 ibits[x] = 0; 270 getbits(in, 0); 271 getbits(ou, 1); 272 getbits(ex, 2); 273 #undef getbits 274 275 if (uap->tv) { 276 u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv, 277 sizeof (atv)); 278 if (u.u_error) 279 goto done; 280 if (itimerfix(&atv)) { 281 u.u_error = EINVAL; 282 goto done; 283 } 284 s = spl7(); timevaladd(&atv, &time); splx(s); 285 } 286 retry: 287 ncoll = nselcoll; 288 u.u_procp->p_flag |= SSEL; 289 u.u_r.r_val1 = selscan(ibits, obits); 290 if (u.u_error || u.u_r.r_val1) 291 goto done; 292 s = spl6(); 293 if (uap->tv && timercmp(&time, &atv, >=)) { 294 splx(s); 295 goto done; 296 } 297 if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { 298 u.u_procp->p_flag &= ~SSEL; 299 splx(s); 300 goto retry; 301 } 302 u.u_procp->p_flag &= ~SSEL; 303 if (uap->tv) { 304 lqsave = u.u_qsave; 305 if (setjmp(&u.u_qsave)) { 306 untimeout(unselect, (caddr_t)u.u_procp); 307 u.u_error = EINTR; 308 splx(s); 309 goto done; 310 } 311 timeout(unselect, (caddr_t)u.u_procp, hzto(&atv)); 312 } 313 sleep((caddr_t)&selwait, PZERO+1); 314 if (uap->tv) { 315 u.u_qsave = lqsave; 316 untimeout(unselect, (caddr_t)u.u_procp); 317 } 318 splx(s); 319 goto retry; 320 done: 321 #define putbits(name, x) \ 322 if (uap->name) { \ 323 int error = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \ 324 sizeof (obits[x])); \ 325 if (error) \ 326 u.u_error = error; \ 327 } 328 putbits(in, 0); 329 putbits(ou, 1); 330 putbits(ex, 2); 331 #undef putbits 332 } 333 334 unselect(p) 335 register struct proc *p; 336 { 337 register int s = spl6(); 338 339 switch (p->p_stat) { 340 341 case SSLEEP: 342 setrun(p); 343 break; 344 345 case SSTOP: 346 unsleep(p); 347 break; 348 } 349 splx(s); 350 } 351 352 selscan(ibits, obits) 353 int *ibits, *obits; 354 { 355 register int which, bits, i; 356 int flag; 357 struct file *fp; 358 int n = 0; 359 360 for (which = 0; which < 3; which++) { 361 bits = ibits[which]; 362 obits[which] = 0; 363 switch (which) { 364 365 case 0: 366 flag = FREAD; break; 367 368 case 1: 369 flag = FWRITE; break; 370 371 case 2: 372 flag = 0; break; 373 } 374 while (i = ffs(bits)) { 375 bits &= ~(1<<(i-1)); 376 fp = u.u_ofile[i-1]; 377 if (fp == NULL) { 378 u.u_error = EBADF; 379 break; 380 } 381 if ((*fp->f_ops->fo_select)(fp, flag)) { 382 obits[which] |= (1<<(i-1)); 383 n++; 384 } 385 } 386 } 387 return (n); 388 } 389 390 /*ARGSUSED*/ 391 seltrue(dev, flag) 392 dev_t dev; 393 int flag; 394 { 395 396 return (1); 397 } 398 399 selwakeup(p, coll) 400 register struct proc *p; 401 int coll; 402 { 403 404 if (coll) { 405 nselcoll++; 406 wakeup((caddr_t)&selwait); 407 } 408 if (p) { 409 int s = spl6(); 410 if (p->p_wchan == (caddr_t)&selwait) 411 setrun(p); 412 else if (p->p_flag & SSEL) 413 p->p_flag &= ~SSEL; 414 splx(s); 415 } 416 } 417 418 fstat() 419 { 420 register struct file *fp; 421 register struct a { 422 int fdes; 423 struct stat *sb; 424 } *uap; 425 struct stat ub; 426 427 uap = (struct a *)u.u_ap; 428 fp = getf(uap->fdes); 429 if (fp == 0) 430 return; 431 u.u_error = (*fp->f_ops->fo_stat)(fp, &ub); 432 if (u.u_error == 0) 433 u.u_error = copyout(&ub, uap->sb, sizeof (ub)); 434 } 435