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