1: #include "param.h"
   2: #include <sys/systm.h>
   3: #include <sys/dir.h>
   4: #include <sys/user.h>
   5: #include <sys/reg.h>
   6: #include <sys/proc.h>
   7: #include <sys/tty.h>
   8: #include <sys/inode.h>
   9: #include <sys/mx.h>
  10: #include <sys/file.h>
  11: #include <sys/conf.h>
  12: 
  13: /*
  14:  *	SCCS id	@(#)mx1.c	2.1 (Berkeley)	8/5/83
  15:  */
  16: 
  17: /*
  18:  * Multiplexor:   clist version
  19:  *
  20:  * installation:
  21:  *	requires a line in cdevsw -
  22:  *		mxopen, mxclose, mxread, mxwrite, mxioctl, 0,
  23:  *
  24:  *	also requires a line in linesw -
  25:  *		mxopen, mxclose, mcread, mcwrite, mxioctl, nulldev, nulldev,
  26:  *
  27:  *	The linesw entry for mpx should be the last one in the table.
  28: 						 *	'nldisp' (number of line disciplines) should not include the
  29:  *	mpx line.  This is to prevent mpx from being enabled by an ioctl.
  30: 
  31:  *	mxtty.c must be loaded instead of tty.c so that certain
  32:  *	sleeps will not be done if a typewriter is connected to
  33:  *	a channel and so that sdata will be called from ttyinput.
  34:  *
  35:  */
  36: struct  chan    chans[NCHANS];
  37: struct  schan   schans[NPORTS];
  38: struct  group   *groups[NGROUPS];
  39: int mpxline;
  40: struct chan *xcp();
  41: dev_t   mpxdev  = -1;
  42: 
  43: 
  44: char    mcdebugs[NDEBUGS];
  45: 
  46: 
  47: /*
  48:  * Allocate a channel, set c_index to index.
  49:  */
  50: struct  chan *
  51: challoc(index, isport)
  52: {
  53: register s,i;
  54: register struct chan *cp;
  55: 
  56:     s = spl6();
  57:     for(i=0;i<((isport)?NPORTS:NCHANS);i++) {
  58:         cp = (isport)? (struct chan *)(schans+i): chans+i;
  59:         if(cp->c_group == NULL) {
  60:             cp->c_index = index;
  61:             cp->c_pgrp = 0;
  62:             cp->c_flags = 0;
  63:             splx(s);
  64:             return(cp);
  65:         }
  66:     }
  67:     splx(s);
  68:     return(NULL);
  69: }
  70: 
  71: 
  72: 
  73: /*
  74:  * Allocate a group table cell.
  75:  */
  76: gpalloc()
  77: {
  78:     register i;
  79: 
  80:     for (i=NGROUPS-1; i>=0; i--)
  81:         if (groups[i]==NULL) {
  82:             groups[i]++;
  83:             return(i);
  84:         }
  85:     u.u_error = ENXIO;
  86:     return(i);
  87: }
  88: 
  89: 
  90: /*
  91:  * Add a channel to the group in
  92:  * inode ip.
  93:  */
  94: struct chan *
  95: addch(ip, isport)
  96: struct inode *ip;
  97: {
  98: register struct chan *cp;
  99: register struct group *gp;
 100: register i;
 101: 
 102:     plock(ip);
 103:     gp = &ip->i_un.i_group;
 104:     for(i=0;i<NINDEX;i++) {
 105:         cp = (struct chan *)gp->g_chans[i];
 106:         if (cp == NULL) {
 107:             if ((cp=challoc(i, isport)) != NULL) {
 108:                 gp->g_chans[i] = cp;
 109:                 cp->c_group = gp;
 110:             }
 111:             break;
 112:         }
 113:         cp = NULL;
 114:     }
 115:     prele(ip);
 116:     return(cp);
 117: }
 118: 
 119: /*
 120:  * Mpxchan system call.
 121:  */
 122: 
 123: mpxchan()
 124: {
 125:     extern  mxopen(), mcread(), sdata(), scontrol();
 126:     struct  inode   *ip, *gip;
 127:     struct  tty *tp;
 128:     struct  file    *fp, *chfp, *gfp;
 129:     struct  chan    *cp;
 130:     struct  group   *gp, *ngp;
 131:     struct  mx_args vec;
 132:     struct  a   {
 133:         int cmd;
 134:         int *argvec;
 135:     } *uap;
 136:     dev_t   dev;
 137:     register int i;
 138: 
 139:     /*
 140: 	 * Common setup code.
 141: 	 */
 142: 
 143:     uap = (struct a *)u.u_ap;
 144:     (void) copyin((caddr_t)uap->argvec, (caddr_t)&vec, sizeof vec);
 145:     gp = NULL; gfp = NULL; cp = NULL;
 146: 
 147:     switch(uap->cmd) {
 148: 
 149:     case NPGRP:
 150:         if (vec.m_arg[1] < 0)
 151:             break;
 152:     case CHAN:
 153:     case JOIN:
 154:     case EXTR:
 155:     case ATTACH:
 156:     case DETACH:
 157:     case CSIG:
 158:         gfp = getf(vec.m_arg[1]);
 159:         if (gfp==NULL)
 160:             return;
 161:         gip = gfp->f_inode;
 162:         gp = &gip->i_un.i_group;
 163:         if (gp->g_inode != gip) {
 164:             u.u_error = ENXIO;
 165:             return;
 166:         }
 167:     }
 168: 
 169:     switch(uap->cmd) {
 170: 
 171:     /*
 172: 	 * Create an MPX file.
 173: 	 */
 174: 
 175:     case MPX:
 176:     case MPXN:
 177:         if (mpxdev < 0) {
 178:             for (i=0; linesw[i].l_open; i++) {
 179:                 if (linesw[i].l_read==mcread) {
 180:                     mpxline = i;
 181:                     for (i=0; cdevsw[i].d_open; i++) {
 182:                         if (cdevsw[i].d_open==mxopen) {
 183:                             mpxdev = (dev_t)(i<<8);
 184:                         }
 185:                     }
 186:                 }
 187:             }
 188:             if (mpxdev < 0) {
 189:                 u.u_error = ENXIO;
 190:                 return;
 191:             }
 192:         }
 193:         if (uap->cmd==MPXN) {
 194:             if ((ip=ialloc(pipedev))==NULL)
 195:                 return;
 196:             ip->i_mode = ((vec.m_arg[1]&0777)+IFMPC) & ~u.u_cmask;
 197:             ip->i_flag = IACC|IUPD|ICHG;
 198:         } else {
 199:             u.u_dirp = vec.m_name;
 200:             ip = namei(uchar,1);
 201:             if (ip != NULL) {
 202:                 i = ip->i_mode&IFMT;
 203:                 u.u_error = EEXIST;
 204:                 if (i==IFMPC || i==IFMPB) {
 205:                     i = minor(ip->i_un.i_rdev);
 206:                     gp = groups[i];
 207:                     if (gp && gp->g_inode==ip)
 208:                         u.u_error = EBUSY;
 209:                 }
 210:                 iput(ip);
 211:                 return;
 212:             }
 213:             if (u.u_error)
 214:                 return;
 215:             ip = maknode((vec.m_arg[1]&0777)+IFMPC);
 216:             if (ip == NULL)
 217:                 return;
 218:         }
 219:         if ((i=gpalloc()) < 0) {
 220:             iput(ip);
 221:             return;
 222:         }
 223:         if ((fp=falloc()) == NULL) {
 224:             iput(ip);
 225:             groups[i] = NULL;
 226:             return;
 227:         }
 228:         ip->i_un.i_rdev = (daddr_t)(mpxdev+i);
 229:         ip->i_count++;
 230:         prele(ip);
 231: 
 232:         gp = &ip->i_un.i_group;
 233:         groups[i] = gp;
 234:         gp->g_inode = ip;
 235:         gp->g_state = INUSE|ISGRP;
 236:         gp->g_group = NULL;
 237:         gp->g_file = fp;
 238:         gp->g_index = 0;
 239:         gp->g_rotmask = 1;
 240:         gp->g_rot = 0;
 241:         gp->g_datq = 0;
 242:         for(i=0;i<NINDEX;)
 243:             gp->g_chans[i++] = NULL;
 244: 
 245:         fp->f_flag = FREAD|FWRITE|FMP;
 246:         fp->f_inode = ip;
 247:         fp->f_un.f_chan = NULL;
 248:         return;
 249: 
 250:     /*
 251: 	 * join file descriptor (arg 0) to group (arg 1)
 252: 	 * return channel number
 253: 	 */
 254: 
 255:     case JOIN:
 256:         if ((fp=getf(vec.m_arg[0]))==NULL)
 257:             return;
 258:         ip = fp->f_inode;
 259:         switch (ip->i_mode & IFMT) {
 260: 
 261:         case IFMPC:
 262:             if ((fp->f_flag&FMP) != FMP) {
 263:                 u.u_error = ENXIO;
 264:                 return;
 265:             }
 266:             ngp = &ip->i_un.i_group;
 267:             if (mtree(ngp, gp) == NULL)
 268:                 return;
 269:             fp->f_count++;
 270:             u.u_r.r_val1 = cpx((struct chan *)ngp);
 271:             return;
 272: 
 273:         case IFCHR:
 274:             dev = (dev_t)ip->i_un.i_rdev;
 275:             tp = cdevsw[major(dev)].d_ttys;
 276:             if (tp==NULL) {
 277:                 u.u_error = ENXIO;
 278:                 return;
 279:             }
 280:             tp = &tp[minor(dev)];
 281:             if (tp->t_chan) {
 282:                 u.u_error = ENXIO;
 283:                 return;
 284:             }
 285:             if ((cp=addch(gip, 1))==NULL) {
 286:                 u.u_error = ENXIO;
 287:                 return;
 288:             }
 289:             tp->t_chan = cp;
 290:             cp->c_fy = fp;
 291:             fp->f_count++;
 292:             cp->c_ttyp = tp;
 293:             cp->c_line = tp->t_line;
 294:             cp->c_flags = XGRP+PORT;
 295:             u.u_r.r_val1 = cpx(cp);
 296:             return;
 297: 
 298:         default:
 299:             u.u_error = ENXIO;
 300:             return;
 301: 
 302:         }
 303: 
 304:     /*
 305: 	 * Attach channel (arg 0) to group (arg 1).
 306: 	 */
 307: 
 308:     case ATTACH:
 309:         cp = xcp(gp, vec.m_arg[0]);
 310:         if (cp==NULL || cp->c_flags&ISGRP) {
 311:             u.u_error = ENXIO;
 312:             return;
 313:         }
 314:         u.u_r.r_val1 = cpx(cp);
 315:         wakeup((caddr_t)cp);
 316:         return;
 317: 
 318:     case DETACH:
 319:         cp = xcp(gp, vec.m_arg[0]);
 320:         if (cp==NULL) {
 321:             u.u_error = ENXIO;
 322:             return;
 323:         }
 324:         (void) detach(cp);
 325:         return;
 326: 
 327:     /*
 328: 	 * Extract channel (arg 0) from group (arg 1).
 329: 	 */
 330: 
 331:     case EXTR:
 332:         cp = xcp(gp, vec.m_arg[0]);
 333:         if (cp==NULL) {
 334:             u.u_error = ENXIO;
 335:             return;
 336:         }
 337:         if (cp->c_flags & ISGRP) {
 338:             (void) mxfalloc(((struct group *)cp)->g_file);
 339:             return;
 340:         }
 341:         if ((fp=cp->c_fy) != NULL) {
 342:             (void) mxfalloc(fp);
 343:             return;
 344:         }
 345:         if ((fp=falloc()) == NULL)
 346:             return;
 347:         fp->f_inode = gip;
 348:         gip->i_count++;
 349:         fp->f_un.f_chan = cp;
 350:         fp->f_flag = (vec.m_arg[2]) ?
 351:                 (FREAD|FWRITE|FMPY) : (FREAD|FWRITE|FMPX);
 352:         cp->c_fy = fp;
 353:         return;
 354: 
 355:     /*
 356: 	 * Make new chan on group (arg 1).
 357: 	 */
 358: 
 359:     case CHAN:
 360:         if((gfp->f_flag&FMP)==FMP)cp = addch(gip, 0);
 361:             if(cp == NULL){
 362:             u.u_error = ENXIO;
 363:             return;
 364:             }
 365:         cp->c_flags = XGRP;
 366:         cp->c_fy = NULL;
 367:         cp->c_ttyp = cp->c_ottyp = (struct tty *)cp;
 368:         cp->c_line = cp->c_oline = mpxline;
 369:         u.u_r.r_val1 = cpx(cp);
 370:         return;
 371: 
 372:     /*
 373: 	 * Connect fd (arg 0) to channel fd (arg 1).
 374: 	 * (arg 2 <  0) => fd to chan only
 375: 	 * (arg 2 >  0) => chan to fd only
 376: 	 * (arg 2 == 0) => both directions
 377: 	 */
 378: 
 379:     case CONNECT:
 380:         if ((fp=getf(vec.m_arg[0]))==NULL)
 381:             return;
 382:         if ((chfp=getf(vec.m_arg[1]))==NULL)
 383:             return;
 384:         ip = fp->f_inode;
 385:         i = ip->i_mode&IFMT;
 386:         if (i!=IFCHR) {
 387:             u.u_error = ENXIO;
 388:             return;
 389:         }
 390:         dev = (dev_t)ip->i_un.i_rdev;
 391:         tp = cdevsw[major(dev)].d_ttys;
 392:         if (tp==NULL) {
 393:             u.u_error = ENXIO;
 394:             return;
 395:         }
 396:         tp = &tp[minor(dev)];
 397:         if (!(chfp->f_flag&FMPY)) {
 398:             u.u_error = ENXIO;
 399:             return;
 400:         }
 401:         cp = chfp->f_un.f_chan;
 402:         if (cp==NULL || cp->c_flags&PORT) {
 403:             u.u_error = ENXIO;
 404:             return;
 405:         }
 406:         i = vec.m_arg[2];
 407:         if (i>=0) {
 408:             cp->c_ottyp = tp;
 409:             cp->c_oline = tp->t_line;
 410:         }
 411:         if (i<=0)  {
 412:             tp->t_chan = cp;
 413:             cp->c_ttyp = tp;
 414:             cp->c_line = tp->t_line;
 415:         }
 416:         u.u_r.r_val1 = 0;
 417:         return;
 418: 
 419:     case NPGRP: {
 420:         register struct proc *pp;
 421: 
 422:         if (gp != NULL) {
 423:             cp = xcp(gp, vec.m_arg[0]);
 424:             if (cp==NULL) {
 425:                 u.u_error = ENXIO;
 426:                 return;
 427:             }
 428:         }
 429:         pp = u.u_procp;
 430:         pp->p_pgrp = pp->p_pid;
 431:         if (vec.m_arg[2])
 432:             pp->p_pgrp = vec.m_arg[2];
 433:         if (gp != NULL)
 434:             cp->c_pgrp = pp->p_pgrp;
 435:         u.u_r.r_val1 = pp->p_pgrp;
 436:         return;
 437:     }
 438: 
 439:     case CSIG:
 440:         cp = xcp(gp, vec.m_arg[0]);
 441:         if (cp==NULL) {
 442:             u.u_error = ENXIO;
 443:             return;
 444:         }
 445:         gsignal(cp->c_pgrp, vec.m_arg[2]);
 446:         u.u_r.r_val1 = vec.m_arg[2];
 447:         return;
 448: 
 449:     case DEBUG:
 450:         i = vec.m_arg[0];
 451:         if (i<0 || i>NDEBUGS)
 452:             return;
 453:         mcdebugs[i] = vec.m_arg[1];
 454:         if (i==ALL)
 455:             for(i=0;i<NDEBUGS;i++)
 456:                 mcdebugs[i] = vec.m_arg[1];
 457:         return;
 458: 
 459:     default:
 460:         u.u_error = ENXIO;
 461:         return;
 462:     }
 463: 
 464: }
 465: 
 466: detach(cp)
 467: register struct chan *cp;
 468: {
 469:     register struct group *master,*sub;
 470:     register index;
 471: 
 472:     if (cp==NULL)
 473:         return(0);
 474:     if (cp->c_flags&ISGRP) {
 475:         sub = (struct group *)cp;
 476:         master = sub->g_group;  index = sub->g_index;
 477:         closef(sub->g_file);
 478:         if (master != NULL)
 479:             master->g_chans[index] = NULL;
 480:         else
 481:             printf("detach: master null\n");
 482:         return(0);
 483:     } else if (cp->c_flags&PORT && cp->c_ttyp != NULL) {
 484:         closef(cp->c_fy);
 485:         chdrain(cp);
 486:         chfree(cp);
 487:         return(0);
 488:     }
 489:     if (cp->c_flags & WCLOSE) {
 490:         if (cp->c_fy) {
 491:             if (cp->c_fy->f_count)
 492:                 return(1);
 493:             chdrain(cp);
 494:             chfree(cp);
 495:             return(0);
 496:         }
 497:     }
 498:     cp->c_flags |= WCLOSE;
 499:     chwake(cp);
 500:     return(1);
 501: }
 502: 
 503: mxfalloc(fp)
 504: register struct file *fp;
 505: {
 506: register i;
 507: 
 508:     if (fp==NULL) {
 509:         u.u_error = ENXIO;
 510:         return(-1);
 511:     }
 512:     i = ufalloc();
 513:     if (i < 0)
 514:         return(i);
 515:     u.u_ofile[i] = fp;
 516:     fp->f_count++;
 517:     u.u_r.r_val1 = i;
 518:     return(i);
 519: }
 520: 
 521: /*
 522:  * Grow a branch on a tree.
 523:  */
 524: 
 525: mtree(sub,master)
 526: register struct group *sub, *master;
 527: {
 528:     register i;
 529:     int mtresiz, stresiz;
 530: 
 531:     if ((mtresiz=mup(master,sub)) == NULL) {
 532:         u.u_error = ENXIO;
 533:         return(NULL);
 534:     }
 535:     if ((stresiz=mdown(sub,master)) <= 0) {
 536:         u.u_error = ENXIO;
 537:         return(NULL);
 538:     }
 539:     if (sub->g_group != NULL) {
 540:         u.u_error = ENXIO;
 541:         return(NULL);
 542:     }
 543:     if (stresiz+mtresiz > NLEVELS) {
 544:         u.u_error = ENXIO;
 545:         return(NULL);
 546:     }
 547:     for (i=0;i<NINDEX;i++) {
 548:         if (master->g_chans[i] != NULL)
 549:             continue;
 550:         master->g_chans[i] = (struct chan *)sub;
 551:         sub->g_group = master;
 552:         sub->g_index = i;
 553:         return(1);
 554:     }
 555:     u.u_error = ENXIO;
 556:     return(NULL);
 557: }
 558: 
 559: mup(master,sub)
 560: struct group *master, *sub;
 561: {
 562:     register struct group *top;
 563:     register int depth;
 564: 
 565:     depth = 1;  top = master;
 566:     while (top->g_group) {
 567:         depth++;
 568:         top = top->g_group;
 569:     }
 570:     if(top == sub)
 571:         return(NULL);
 572:     return(depth);
 573: }
 574: 
 575: 
 576: mdown(sub,master)
 577: struct group *sub, *master;
 578: {
 579:     register int maxdepth, i, depth;
 580: 
 581:     if(sub == (struct group *)NULL || (sub->g_state&ISGRP) == 0)
 582:         return(0);
 583:     if(sub == master)
 584:         return(-1);
 585:     maxdepth = 0;
 586:     for(i=0; i<NINDEX; i++) {
 587:         if((depth=mdown((struct group *)sub->g_chans[i],master)) == -1)
 588:             return(-1);
 589:         maxdepth = (depth>maxdepth) ? depth: maxdepth;
 590:     }
 591:     return(maxdepth+1);
 592: }

Defined functions

addch defined in line 94; used 4 times
challoc defined in line 50; used 1 times
detach defined in line 466; used 1 times
gpalloc defined in line 76; used 1 times
mdown defined in line 576; used 2 times
mpxchan defined in line 123; never used
mtree defined in line 525; used 1 times
mup defined in line 559; used 1 times
mxfalloc defined in line 503; used 2 times

Defined variables

chans defined in line 36; used 1 times
  • in line 58
groups defined in line 38; used 5 times
mcdebugs defined in line 44; used 2 times
mpxdev defined in line 41; used 4 times
mpxline defined in line 39; used 2 times
schans defined in line 37; used 1 times
  • in line 58

Defined struct's

a defined in line 132; used 2 times
  • in line 143(2)
Last modified: 1983-08-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1586
Valid CSS Valid XHTML 1.0 Strict