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

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

unix.superglobalmegacorp.com

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