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