Annotation of 41BSD/sys/dev/mx1.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.