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