Annotation of 41BSD/4.0.upgrade/sys/dev/mx1.c, revision 1.1.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.