1: /*
   2:  * Copyright (c) 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	1.8 (2.11BSD) 2000/2/28
   7:  */
   8: 
   9: #include "param.h"
  10: #include "../machine/seg.h"
  11: 
  12: #include "user.h"
  13: #include "proc.h"
  14: #include "signalvar.h"
  15: #include "inode.h"
  16: #include "file.h"
  17: #include "ioctl.h"
  18: #include "conf.h"
  19: #include "uio.h"
  20: #include "pty.h"
  21: #include "kernel.h"
  22: #include "systm.h"
  23: 
  24: /*
  25:  * this is consolidated here rather than being scattered all over the
  26:  * place.  the socketops table has to be in kernel space, but since
  27:  * networking might not be defined an appropriate error has to be set
  28: */
  29: 
  30:     int sorw(), soctl(), sosel(), socls();
  31:     struct  fileops socketops =
  32:         { sorw, soctl, sosel, socls };
  33: extern  struct  fileops inodeops, pipeops;
  34:     struct  fileops *Fops[] = { NULL, &inodeops, &socketops, &pipeops };
  35: 
  36: /*
  37:  * Read system call.
  38:  */
  39: read()
  40: {
  41:     register struct a {
  42:         int fdes;
  43:         char    *cbuf;
  44:         unsigned count;
  45:     } *uap = (struct a *)u.u_ap;
  46:     struct uio auio;
  47:     struct iovec aiov;
  48: 
  49:     aiov.iov_base = (caddr_t)uap->cbuf;
  50:     aiov.iov_len = uap->count;
  51:     auio.uio_iov = &aiov;
  52:     auio.uio_iovcnt = 1;
  53:     auio.uio_rw = UIO_READ;
  54:     rwuio(&auio);
  55: }
  56: 
  57: readv()
  58: {
  59:     register struct a {
  60:         int fdes;
  61:         struct  iovec *iovp;
  62:         unsigned iovcnt;
  63:     } *uap = (struct a *)u.u_ap;
  64:     struct uio auio;
  65:     struct iovec aiov[16];      /* XXX */
  66: 
  67:     if (uap->iovcnt > sizeof(aiov)/sizeof(aiov[0])) {
  68:         u.u_error = EINVAL;
  69:         return;
  70:     }
  71:     auio.uio_iov = aiov;
  72:     auio.uio_iovcnt = uap->iovcnt;
  73:     auio.uio_rw = UIO_READ;
  74:     u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)aiov,
  75:         uap->iovcnt * sizeof (struct iovec));
  76:     if (u.u_error)
  77:         return;
  78:     rwuio(&auio);
  79: }
  80: 
  81: /*
  82:  * Write system call
  83:  */
  84: write()
  85: {
  86:     register struct a {
  87:         int fdes;
  88:         char    *cbuf;
  89:         unsigned count;
  90:     } *uap = (struct a *)u.u_ap;
  91:     struct uio auio;
  92:     struct iovec aiov;
  93: 
  94:     auio.uio_iov = &aiov;
  95:     auio.uio_iovcnt = 1;
  96:     auio.uio_rw = UIO_WRITE;
  97:     aiov.iov_base = uap->cbuf;
  98:     aiov.iov_len = uap->count;
  99:     rwuio(&auio);
 100: }
 101: 
 102: writev()
 103: {
 104:     register struct a {
 105:         int fdes;
 106:         struct  iovec *iovp;
 107:         unsigned iovcnt;
 108:     } *uap = (struct a *)u.u_ap;
 109:     struct uio auio;
 110:     struct iovec aiov[16];      /* XXX */
 111: 
 112:     if (uap->iovcnt > sizeof(aiov)/sizeof(aiov[0])) {
 113:         u.u_error = EINVAL;
 114:         return;
 115:     }
 116:     auio.uio_iov = aiov;
 117:     auio.uio_iovcnt = uap->iovcnt;
 118:     auio.uio_rw = UIO_WRITE;
 119:     u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)aiov,
 120:         uap->iovcnt * sizeof (struct iovec));
 121:     if (u.u_error)
 122:         return;
 123:     rwuio(&auio);
 124: }
 125: 
 126: static
 127: rwuio(uio)
 128:     register struct uio *uio;
 129: {
 130:     struct a {
 131:         int fdes;
 132:     };
 133:     register struct file *fp;
 134:     register struct iovec *iov;
 135:     u_int i, count;
 136:     off_t   total;
 137: 
 138:     GETF(fp, ((struct a *)u.u_ap)->fdes);
 139:     if ((fp->f_flag & (uio->uio_rw == UIO_READ ? FREAD : FWRITE)) == 0) {
 140:         u.u_error = EBADF;
 141:         return;
 142:     }
 143:     total =(off_t)0;
 144:     uio->uio_resid = 0;
 145:     uio->uio_segflg = UIO_USERSPACE;
 146:     for (iov = uio->uio_iov, i = 0; i < uio->uio_iovcnt; i++, iov++)
 147:         total += iov->iov_len;
 148: 
 149:     uio->uio_resid = total;
 150:     if  (uio->uio_resid != total)   /* check wraparound */
 151:         return(u.u_error = EINVAL);
 152: 
 153:     count = uio->uio_resid;
 154:     if  (setjmp(&u.u_qsave))
 155:         {
 156: /*
 157:  * The ONLY way we can get here is via the longjump in sleep.  Thus signals
 158:  * have been checked and u_error set accordingly.  If no bytes have been
 159:  * transferred then all that needs to be done now is 'return'; the system
 160:  * call will either be restarted or reported as interrupted.  If bytes have
 161:  * been transferred then we need to calculate the number of bytes transferred.
 162: */
 163:         if  (uio->uio_resid == count)
 164:             return;
 165:         else
 166:             u.u_error = 0;
 167:         }
 168:     else
 169:         u.u_error = (*Fops[fp->f_type]->fo_rw)(fp, uio);
 170:     u.u_r.r_val1 = count - uio->uio_resid;
 171: }
 172: 
 173: /*
 174:  * Ioctl system call
 175:  */
 176: ioctl()
 177: {
 178:     register struct file *fp;
 179:     register struct a {
 180:         int fdes;
 181:         long    cmd;
 182:         caddr_t cmarg;
 183:     } *uap;
 184:     long com;
 185:     u_int k_com;
 186:     register u_int size;
 187:     char data[IOCPARM_MASK+1];
 188: 
 189:     uap = (struct a *)u.u_ap;
 190:     if ((fp = getf(uap->fdes)) == NULL)
 191:         return;
 192:     if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
 193:         u.u_error = EBADF;
 194:         return;
 195:     }
 196:     com = uap->cmd;
 197: 
 198:     /* THE 2.11 KERNEL STILL THINKS THAT IOCTL COMMANDS ARE 16 BITS */
 199:     k_com = (u_int)com;
 200: 
 201:     if (k_com == FIOCLEX) {
 202:         u.u_pofile[uap->fdes] |= UF_EXCLOSE;
 203:         return;
 204:     }
 205:     if (k_com == FIONCLEX) {
 206:         u.u_pofile[uap->fdes] &= ~UF_EXCLOSE;
 207:         return;
 208:     }
 209: 
 210:     /*
 211: 	 * Interpret high order word to find
 212: 	 * amount of data to be copied to/from the
 213: 	 * user's address space.
 214: 	 */
 215:     size = (com &~ (IOC_INOUT|IOC_VOID)) >> 16;
 216:     if (size > sizeof (data)) {
 217:         u.u_error = EFAULT;
 218:         return;
 219:     }
 220:     if (com&IOC_IN) {
 221:         if (size) {
 222:             if (((u_int)uap->cmarg|size)&1)
 223:                 u.u_error =
 224:                 vcopyin(uap->cmarg, (caddr_t)data, size);
 225:             else
 226:                 u.u_error =
 227:                 copyin(uap->cmarg, (caddr_t)data, size);
 228:             if (u.u_error)
 229:                 return;
 230:         } else
 231:             *(caddr_t *)data = uap->cmarg;
 232:     } else if ((com&IOC_OUT) && size)
 233:         /*
 234: 		 * Zero the buffer on the stack so the user
 235: 		 * always gets back something deterministic.
 236: 		 */
 237:         bzero((caddr_t)data, size);
 238:     else if (com&IOC_VOID)
 239:         *(caddr_t *)data = uap->cmarg;
 240: 
 241:     switch (k_com) {
 242: 
 243:     case FIONBIO:
 244:         u.u_error = fset(fp, FNONBLOCK, *(int *)data);
 245:         return;
 246: 
 247:     case FIOASYNC:
 248:         u.u_error = fset(fp, FASYNC, *(int *)data);
 249:         return;
 250: 
 251:     case FIOSETOWN:
 252:         u.u_error = fsetown(fp, *(int *)data);
 253:         return;
 254: 
 255:     case FIOGETOWN:
 256:         u.u_error = fgetown(fp, (int *)data);
 257:         return;
 258:     }
 259:     u.u_error = (*Fops[fp->f_type]->fo_ioctl)(fp, k_com, data);
 260:     /*
 261: 	 * Copy any data to user, size was
 262: 	 * already set and checked above.
 263: 	 */
 264:     if (u.u_error == 0 && (com&IOC_OUT) && size)
 265:         if (((u_int)uap->cmarg|size)&1)
 266:             u.u_error = vcopyout(data, uap->cmarg, size);
 267:         else
 268:             u.u_error = copyout(data, uap->cmarg, size);
 269: }
 270: 
 271: int nselcoll;
 272: 
 273: struct  pselect_args
 274:     {
 275:     int     nd;
 276:     fd_set      *in;
 277:     fd_set      *ou;
 278:     fd_set      *ex;
 279:     struct  timespec *ts;
 280:     sigset_t    *maskp;
 281:     };
 282: 
 283: /*
 284:  * Select system call.
 285: */
 286: int
 287: select()
 288:     {
 289:     struct uap
 290:         {
 291:         int nd;
 292:         fd_set  *in, *ou, *ex;
 293:         struct  timeval *tv;
 294:         } *uap = (struct uap *)u.u_ap;
 295:     register struct pselect_args *pselargs = (struct pselect_args *)uap;
 296: 
 297:     /*
 298: 	 * Fake the 6th parameter of pselect.  See the comment below about the
 299: 	 * number of parameters!
 300: 	*/
 301:     pselargs->maskp = 0;
 302:     return(u.u_error = select1(pselargs, 0));
 303:     }
 304: 
 305: /*
 306:  * pselect (posix select)
 307:  *
 308:  * N.B.  There is only room for 6 arguments - see user.h - so pselect() is
 309:  *       at the maximum!  See user.h
 310: */
 311: int
 312: pselect()
 313:     {
 314:     register struct pselect_args *uap = (struct pselect_args *)u.u_ap;
 315: 
 316:     return(u.u_error = select1(uap, 1));
 317:     }
 318: 
 319: /*
 320:  * Select helper function common to both select() and pselect()
 321:  */
 322: static int
 323: select1(uap, is_pselect)
 324:     register struct pselect_args *uap;
 325:     int is_pselect;
 326:     {
 327:     fd_set ibits[3], obits[3];
 328:     struct timeval atv;
 329:     sigset_t sigmsk;
 330:     unsigned int timo = 0;
 331:     register int error, ni;
 332:     int ncoll, s;
 333: 
 334:     bzero((caddr_t)ibits, sizeof(ibits));
 335:     bzero((caddr_t)obits, sizeof(obits));
 336:     if (uap->nd > NOFILE)
 337:         uap->nd = NOFILE;   /* forgiving, if slightly wrong */
 338:     ni = howmany(uap->nd, NFDBITS);
 339: 
 340: #define getbits(name, x) \
 341:     if (uap->name) { \
 342:         error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \
 343:             (unsigned)(ni * sizeof(fd_mask))); \
 344:         if (error) \
 345:             goto done; \
 346:     }
 347:     getbits(in, 0);
 348:     getbits(ou, 1);
 349:     getbits(ex, 2);
 350: #undef  getbits
 351: 
 352:     if  (uap->maskp)
 353:         {
 354:         error = copyin(uap->maskp, &sigmsk, sizeof(sigmsk));
 355:         sigmsk &= ~sigcantmask;
 356:         if  (error)
 357:             goto done;
 358:         }
 359:     if  (uap->ts)
 360:         {
 361:         error = copyin((caddr_t)uap->ts, (caddr_t)&atv, sizeof (atv));
 362:         if  (error)
 363:             goto done;
 364: /*
 365:  * nanoseconds ('struct timespec') on a PDP-11 are stupid since a 50 or 60 hz
 366:  * clock is all we have.   Keeping the names and logic made porting easier
 367:  * though.
 368: */
 369:         if  (is_pselect)
 370:             {
 371:             struct  timespec *ts = (struct timespec *)&atv;
 372: 
 373:             if  (ts->tv_sec == 0 && ts->tv_nsec < 1000)
 374:                     atv.tv_usec = 1;
 375:                 else
 376:                     atv.tv_usec = ts->tv_nsec / 1000;
 377:             }
 378:         if  (itimerfix(&atv))
 379:             {
 380:             error = EINVAL;
 381:             goto done;
 382:             }
 383:         s = splhigh();
 384:         time.tv_usec = lbolt * mshz;
 385:         timevaladd(&atv, &time);
 386:         splx(s);
 387:         }
 388: retry:
 389:     ncoll = nselcoll;
 390:     u.u_procp->p_flag |= P_SELECT;
 391:     error = selscan(ibits, obits, uap->nd, &u.u_r.r_val1);
 392:     if  (error || u.u_r.r_val1)
 393:         goto done;
 394:     s = splhigh();
 395:     if  (uap->ts)
 396:         {
 397:         /* this should be timercmp(&time, &atv, >=) */
 398:         if  ((time.tv_sec > atv.tv_sec || (time.tv_sec == atv.tv_sec
 399:                     && lbolt * mshz >= atv.tv_usec)))
 400:             {
 401:             splx(s);
 402:             goto done;
 403:             }
 404:         timo = hzto(&atv);
 405:         if  (timo == 0)
 406:             timo = 1;
 407:         }
 408:     if  ((u.u_procp->p_flag & P_SELECT) == 0 || nselcoll != ncoll)
 409:         {
 410:         u.u_procp->p_flag &= ~P_SELECT;
 411:         splx(s);
 412:         goto retry;
 413:         }
 414:     u.u_procp->p_flag &= ~P_SELECT;
 415: /*
 416:  * If doing a pselect() need to set a temporary mask while in tsleep.
 417:  * Returning from pselect after catching a signal the old mask has to be
 418:  * restored.  Save it here and set the appropriate flag.
 419: */
 420:     if  (uap->maskp)
 421:         {
 422:         u.u_oldmask = u.u_procp->p_sigmask;
 423:         u.u_psflags |= SAS_OLDMASK;
 424:         u.u_procp->p_sigmask = sigmsk;
 425:         }
 426:     error = tsleep(&selwait, PSOCK | PCATCH, timo);
 427:     if  (uap->maskp)
 428:         u.u_procp->p_sigmask = u.u_oldmask;
 429:     splx(s);
 430:     if  (error == 0)
 431:         goto retry;
 432: done:
 433:     u.u_procp->p_flag &= ~P_SELECT;
 434:     /* select is not restarted after signals... */
 435:     if  (error == ERESTART)
 436:         error = EINTR;
 437:     if  (error == EWOULDBLOCK)
 438:         error = 0;
 439: #define putbits(name, x) \
 440:     if (uap->name && \
 441:         (error2 = copyout(&obits[x],uap->name,(ni*sizeof(fd_mask))))) \
 442:             error = error2;
 443: 
 444:     if  (error == 0)
 445:         {
 446:         int error2;
 447: 
 448:         putbits(in, 0);
 449:         putbits(ou, 1);
 450:         putbits(ex, 2);
 451: #undef putbits
 452:         }
 453:     return(error);
 454:     }
 455: 
 456: selscan(ibits, obits, nfd, retval)
 457:     fd_set *ibits, *obits;
 458:     int nfd, *retval;
 459: {
 460:     register int i, j, flag;
 461:     fd_mask bits;
 462:     struct file *fp;
 463:     int which, n = 0;
 464: 
 465:     for (which = 0; which < 3; which++) {
 466:         switch (which) {
 467: 
 468:         case 0:
 469:             flag = FREAD; break;
 470: 
 471:         case 1:
 472:             flag = FWRITE; break;
 473: 
 474:         case 2:
 475:             flag = 0; break;
 476:         }
 477:         for (i = 0; i < nfd; i += NFDBITS) {
 478:             bits = ibits[which].fds_bits[i/NFDBITS];
 479:             while ((j = ffs(bits)) && i + --j < nfd) {
 480:                 bits &= ~(1L << j);
 481:                 fp = u.u_ofile[i + j];
 482:                 if (fp == NULL)
 483:                     return(EBADF);
 484:                 if ((*Fops[fp->f_type]->fo_select)(fp,flag)) {
 485:                     FD_SET(i + j, &obits[which]);
 486:                     n++;
 487:                 }
 488:             }
 489:         }
 490:     }
 491:     *retval = n;
 492:     return(0);
 493: }
 494: 
 495: /*ARGSUSED*/
 496: seltrue(dev, flag)
 497:     dev_t dev;
 498:     int flag;
 499: {
 500: 
 501:     return (1);
 502: }
 503: 
 504: selwakeup(p, coll)
 505:     register struct proc *p;
 506:     long coll;
 507: {
 508:     mapinfo map;
 509: 
 510:     savemap(map);
 511:     if (coll) {
 512:         nselcoll++;
 513:         wakeup((caddr_t)&selwait);
 514:     }
 515:     if (p) {
 516:         register int s = splhigh();
 517:         if (p->p_wchan == (caddr_t)&selwait) {
 518:             if (p->p_stat == SSLEEP)
 519:                 setrun(p);
 520:             else
 521:                 unsleep(p);
 522:         } else if (p->p_flag & P_SELECT)
 523:             p->p_flag &= ~P_SELECT;
 524:         splx(s);
 525:     }
 526:     restormap(map);
 527: }
 528: 
 529: sorw(fp, uio)
 530:     register struct file *fp;
 531:     register struct uio *uio;
 532: {
 533: #ifdef  INET
 534:     if (uio->uio_rw == UIO_READ)
 535:         return(SORECEIVE((struct socket *)fp->f_socket, 0, uio, 0, 0));
 536:     return(SOSEND((struct socket *)fp->f_socket, 0, uio, 0, 0));
 537: #else
 538:     return (EOPNOTSUPP);
 539: #endif
 540: }
 541: 
 542: soctl(fp, com, data)
 543:     struct file *fp;
 544:     u_int   com;
 545:     char    *data;
 546:     {
 547: #ifdef  INET
 548:     return (SOO_IOCTL(fp, com, data));
 549: #else
 550:     return (EOPNOTSUPP);
 551: #endif
 552: }
 553: 
 554: sosel(fp, flag)
 555:     struct file *fp;
 556:     int flag;
 557: {
 558: #ifdef  INET
 559:     return (SOO_SELECT(fp, flag));
 560: #else
 561:     return (EOPNOTSUPP);
 562: #endif
 563: }
 564: 
 565: socls(fp)
 566:     register struct file *fp;
 567: {
 568:     register int error = 0;
 569: 
 570: #ifdef  INET
 571:     if  (fp->f_data)
 572:         error = SOCLOSE((struct socket *)fp->f_data);
 573:     fp->f_data = 0;
 574: #else
 575:     error = EOPNOTSUPP;
 576: #endif
 577:     return(error);
 578: }

Defined functions

ioctl defined in line 176; used 2 times
pselect defined in line 311; used 3 times
read defined in line 39; used 2 times
readv defined in line 57; used 2 times
rwuio defined in line 126; used 4 times
select defined in line 286; used 3 times
select1 defined in line 322; used 2 times
selscan defined in line 456; used 1 times
seltrue defined in line 496; used 16 times
socls defined in line 565; used 2 times
soctl defined in line 542; used 2 times
sorw defined in line 529; used 2 times
sosel defined in line 554; used 2 times
write defined in line 84; used 2 times
writev defined in line 102; used 2 times

Defined variables

Fops defined in line 34; used 5 times
nselcoll defined in line 271; used 3 times
socketops defined in line 31; used 1 times
  • in line 34

Defined struct's

a defined in line 179; used 12 times
pselect_args defined in line 273; used 10 times
uap defined in line 289; used 2 times
  • in line 294(2)

Defined macros

getbits defined in line 340; used 4 times
putbits defined in line 439; used 4 times
Last modified: 2000-02-29
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 6104
Valid CSS Valid XHTML 1.0 Strict