Annotation of researchv10no/ipc/bin/con.c, revision 1.1.1.1

1.1       root        1: #include <sys/types.h>
                      2: #include <sys/stream.h>
                      3: #include <sys/stat.h>
                      4: #include <sys/ttyio.h>
                      5: #include <sys/filio.h>
                      6: #include <sys/dkio.h>
                      7: #include <stdio.h>
                      8: #include <errno.h>
                      9: #include <signal.h>
                     10: #include <ipc.h>
                     11: #include <libc.h>
                     12: #include <utsname.h>
                     13: 
                     14: /*
                     15:  * program to connect to
                     16:  * another cpu on Datakit w/ transparent ioctls
                     17:  */
                     18: 
                     19: int     rem=-1;                /* remote file descriptor */
                     20: extern int mesg_ld;
                     21: struct sgttyb sgbuf;
                     22: struct tchars tcbuf;
                     23: int    ttyrem=0;       /* true if tty ld is remote */
                     24: char   *ttyn;
                     25: int    perms;
                     26: 
                     27: struct sigmsg {
                     28:        struct  mesg m;
                     29:        char    sig[1];
                     30: };
                     31: 
                     32: struct buffer {
                     33:        int     rfd,wfd;
                     34:        int     rmesgld;
                     35:        int     wmesgld;
                     36:        char    *rptr;
                     37:        char    *wptr;
                     38:        char    data[4096+MSGHLEN];
                     39: };
                     40: static struct buffer ttyb;
                     41: static struct buffer netb;
                     42: 
                     43: struct mesg *getmsg();
                     44: int fillbuf();
                     45: 
                     46: #define        msglen(mp)      ((mp)->losize + ((mp)->hisize<<8))
                     47: 
                     48: int lfd;
                     49: char *av0;
                     50: int notdef;
                     51: int (*quitsig)();
                     52: int debug;
                     53: 
                     54: usage()
                     55: {
                     56:        fprintf(stderr, "usage: %s [-l] host\n", av0);
                     57:        exit(1);
                     58: }
                     59: 
                     60: main(argc, argv)
                     61: char **argv;
                     62: {
                     63:        char *host;
                     64:        struct stat sb;
                     65:        int all, ld, nold;
                     66:        extern int hupcatch();
                     67:        char *ttyname();
                     68: 
                     69:        nold = 0;
                     70:        av0 = strrchr(argv[0], '/');
                     71:        av0 = av0==NULL ? argv[0] : av0+1;
                     72:                while(argc>1 && argv[1][0]=='-'){
                     73:                char *cp;
                     74:                for(cp=&argv[1][1]; *cp; cp++)
                     75:                        switch (*cp) {
                     76:                        case 'l':
                     77:                                av0 = "con -l";
                     78:                                break;
                     79:                        case 'd':
                     80:                                debug = 1;
                     81:                                close(2);
                     82:                                creat("/tmp/con.debug", 0666);
                     83:                                break;
                     84:                        case 'n':
                     85:                                nold = 1;
                     86:                                break;
                     87:                        default:
                     88:                                usage(); 
                     89:                        }
                     90:                argv++;
                     91:                argc--;
                     92:        }
                     93:        host=argv[1];
                     94:        if(strcmp(host, "helix")==0
                     95:        || strcmp(host, "spindle")==0
                     96:        || strcmp(host, "hobocpu")==0
                     97:        || strcmp(host, "fornax")==0)
                     98:                av0 = "dcon";
                     99: /*
                    100:        if (host==NULL)
                    101:                usage();
                    102: */
                    103:        ioctl(0, TIOCGETP, &sgbuf);
                    104:        ioctl(0, TIOCGETC, &tcbuf);
                    105:        quitsig = signal(SIGQUIT, hupcatch);
                    106: 
                    107:        all = strcmp(av0, "con")==0;
                    108:        if (strcmp(av0, "nogin")==0)
                    109:                rem = trynogin(host);
                    110:        if (all || strcmp(av0, "ndcon")==0)
                    111:                rem = trymesg(host);
                    112:        if (rem<0 && (all || strcmp(av0, "dcon")==0))
                    113:                rem = trynomesg(host);
                    114: /*
                    115:        if (rem<0 && (all || strcmp(av0, "9con")==0))
                    116:                rem = try9con(host);
                    117: */
                    118:        if (rem<0 && (all || strcmp(av0, "rogin")==0 || strcmp(av0, "rlogin")==0))
                    119:                rem = tryrogin(host);
                    120:        if (rem<0 && (all || strcmp(av0, "con -l")==0))
                    121:                rem = trysimple(host);
                    122:        if (rem<0) {
                    123:                fprintf(stderr, "%s: %s connecting to %s\n", av0, errstr, host);
                    124:                exit(1);
                    125:        }
                    126: 
                    127:        /*
                    128:         *  we really have to avoid leaving mesg_ld's pushed
                    129:         */
                    130:        signal(SIGHUP, hupcatch);
                    131:        signal(SIGPIPE, hupcatch);
                    132:        if ((ttyn = ttyname(0)) != NULL
                    133:        &&   stat(ttyn, &sb) >= 0) {
                    134:                perms = sb.st_mode & ~S_IFMT;
                    135:                chmod(ttyn, 0);
                    136:        }
                    137: 
                    138:        /*
                    139:         *  push mesg_ld onto stdin and stdout if possible
                    140:         */
                    141:        ttyb.rmesgld = ttyb.wmesgld = netb.rmesgld = netb.wmesgld = 0;
                    142:        if (!nold){
                    143:                /* race ahead possible */
                    144:                ioctl(0, TIOCFLUSH, (char *)0);
                    145:                if(ioctl(0, FIOPUSHLD, &mesg_ld)>=0)
                    146:                        ttyb.rmesgld=1;
                    147:                if(ioctl(1, FIOLOOKLD, &ld)>=0
                    148:                && (ld==mesg_ld || ioctl(1, FIOPUSHLD, &mesg_ld)>=0))
                    149:                        ttyb.wmesgld=1;
                    150:        }
                    151: 
                    152:        /*
                    153:         * see if remote side accepts mesg_ld packets
                    154:         */
                    155:        netb.rmesgld = netb.wmesgld = ttyrem==0;
                    156:        if(debug)
                    157:                fprintf(stderr, "connected\n");
                    158:        go(rem);
                    159:        finish(0);
                    160:        /* NOTREACHED */
                    161: }
                    162: 
                    163: /* try to set up a message line discipline connection */
                    164: trymesg(host)
                    165:        char *host;
                    166: {
                    167:        int fd;
                    168: 
                    169:        fd = ipcopen(ipcpath(host, "dk", "mesgdcon"), "light hup");
                    170:        if (fd<0)
                    171:                return fd;
                    172:        if (ipclogin(fd)<0) {
                    173:                fprintf(stderr, "%s: can't log in\n", av0);
                    174:                exit(1);
                    175:        }
                    176:        return fd;
                    177: }
                    178: 
                    179: /* try to set up a no line discipline connection */
                    180: trynomesg(host)
                    181:        char *host;
                    182: {
                    183:        int fd;
                    184: 
                    185:        fd = ipcopen(ipcpath(host, "dk", "dcon"), "light hup");
                    186:        if (fd<0)
                    187:                return fd;
                    188:        if (ipclogin(fd)<0) {
                    189:                fprintf(stderr, "%s: can't log in\n", av0);
                    190:                exit(1);
                    191:        }
                    192:        remtty(fd);
                    193:        return fd;
                    194: }
                    195: 
                    196: /*
                    197:  *  try to set up an dcon-like connection with local echo
                    198:  */
                    199: try9con(host)
                    200:        char *host;
                    201: {
                    202:        int fd;
                    203:        char service[256];
                    204: 
                    205:        sprintf(service, "nonet!%s", host);
                    206:        fd = ipcopen(ipcpath("r70", "dk", service), "light hup bsdauth");
                    207:        if (fd<0)
                    208:                return fd;
                    209:        ttyrem = 1;
                    210:        return fd;
                    211: }
                    212: 
                    213: /*
                    214:  *  try to set up an rlogin-like connection with local echo
                    215:  *
                    216:  *  the authentication string is passwd by ipcopen because of the bsdauth
                    217:  *  parameter.   The ipcrogin passes the terminal type and gets the authentication
                    218:  *  reply.
                    219:  */
                    220: trynogin(host)
                    221:        char *host;
                    222: {
                    223:        int fd;
                    224:        char *term;
                    225: 
                    226:        fd = ipcopen(ipcpath(host, "tcp", "login"), "light hup bsdauth");
                    227:        if (fd<0)
                    228:                return fd;
                    229:        term = getenv("TERM");
                    230:        ipcrogin(fd, term?term:"");
                    231:        ttyrem = 1;
                    232:        return fd;
                    233: }
                    234: 
                    235: /*
                    236:  *  try to set up a rlogin-like connection with remote echo
                    237:  */
                    238: tryrogin(host)
                    239:        char *host;
                    240: {
                    241:        int fd;
                    242:        char *term;
                    243: 
                    244:        fd = ipcopen(ipcpath(host, "tcp", "login"), "light hup bsdauth");
                    245:        if (fd<0)
                    246:                return fd;
                    247:        term = getenv("TERM");
                    248:        ipcrogin(fd, term?term:"");
                    249:        remtty(fd);
                    250:        return fd;
                    251: }
                    252: 
                    253: /* try to set up a non-authenticated connection */
                    254: trysimple(host)
                    255:        char *host;
                    256: {
                    257:        int fd;
                    258: 
                    259:        fd = ipcopen(ipcpath(host, "dk", ""), "light hup 1200");
                    260:        if (fd<0)
                    261:                return fd;
                    262:        remtty(fd);
                    263:        return fd;
                    264: }
                    265: 
                    266: /* set up for tty control to be remote */
                    267: remtty(fd)
                    268: {
                    269:        struct  sgttyb sg;
                    270:        struct  tchars tc;
                    271: 
                    272:        sg = sgbuf;
                    273:        sg.sg_flags &= ~(CRMOD|ECHO|XTABS);
                    274:        sg.sg_flags |= CBREAK;
                    275:        ioctl(0, TIOCSETP, &sg);
                    276:        tc.t_quitc = tcbuf.t_quitc;
                    277:        tc.t_intrc = tc.t_startc = tc.t_stopc = tc.t_eofc = tc.t_brkc = -1;
                    278:        ioctl(0, TIOCSETC, &tc);
                    279:        ttyrem = 1;
                    280:        /*
                    281:         *  HACK!!!! to make select work when connected to a
                    282:         *  delimited stream --- turn off delimiters.
                    283:         */
                    284:        ioctl(fd, DIOCSTREAM, 0);
                    285: }
                    286:        
                    287: 
                    288: go(fd)
                    289: {
                    290:        int rbits, wbits;
                    291:        struct mesg *mp;
                    292:        int dgenerated=0;
                    293:        int lasttype=0;
                    294: 
                    295:        wbits = 0;
                    296:        ttyb.rptr = ttyb.wptr = ttyb.data;
                    297:        ttyb.rfd = 0;
                    298:        ttyb.wfd = 1;
                    299:        netb.rptr = netb.wptr = netb.data;
                    300:        netb.rfd = fd;
                    301:        netb.wfd = fd;
                    302:        while(1){
                    303:                rbits = 1 | (1<<fd);
                    304:                if(select(20, (fd_set*)&rbits, (fd_set*)&wbits, 20000) < 0){
                    305:                        if(errno != EINTR)
                    306:                                return;
                    307:                        continue;
                    308:                }
                    309:                if(rbits & 1)
                    310:                        if (fillbuf(&ttyb)<0)
                    311:                                return;
                    312:                if(rbits & (1<<fd))
                    313:                        if (fillbuf(&netb)<0)
                    314:                                return;
                    315:                while(mp = getmsg(&ttyb)) {
                    316:                        if (mp->type==M_DELIM) {
                    317:                                if (ttyrem && lasttype==M_DELIM) {
                    318:                                        sendmsg(&netb, M_DATA, &tcbuf.t_eofc, 1);
                    319:                                        continue;
                    320:                                }
                    321:                        }
                    322:                        lasttype = mp->type;
                    323:                        if (mp->type==M_SIGNAL)
                    324:                                switch(((struct sigmsg *)mp)->sig[0]) {
                    325:                                case SIGQUIT:
                    326:                                        dolocal(mp);
                    327:                                        continue;
                    328:                                case SIGINT:
                    329:                                        if(!ttyrem)
                    330:                                                break;
                    331:                                        sendmsg(&netb, M_DATA, &tcbuf.t_intrc, 1);
                    332:                                        continue;
                    333:                                }
                    334:                        mp->magic = MSGMAGIC;   /* temp safety */
                    335:                        if(writemsg(&netb, mp)<0)
                    336:                                return;
                    337:                        if(!ttyrem && mp->type == M_FLUSH) {
                    338:                                remflush();
                    339:                                rbits = 0;
                    340:                        }
                    341:                }
                    342:                while(mp = getmsg(&netb)){
                    343:                        if(mp->type == M_HANGUP)
                    344:                                return;
                    345:                        if(mp->type == M_IOCTL){
                    346:                                doioctl(mp);
                    347:                        } else if(dgenerated && mp->type==M_DELIM){
                    348:                                dgenerated = 0;
                    349:                        } else {
                    350:                                if(writemsg(&ttyb, mp)<0)
                    351:                                        return;
                    352:                                if(mp->type==M_DATA) {
                    353:                                        sendmsg(&ttyb, M_DELIM, (char *)mp, 0);
                    354:                                        dgenerated = 1;
                    355:                                }
                    356:                        }
                    357:                }
                    358:        }
                    359: }
                    360: 
                    361: /* read in at least a complete message */
                    362: fillbuf(bp)
                    363:        register struct buffer *bp;
                    364: {
                    365:        register int n;
                    366:        struct mesg *mp;
                    367:        static int neofs;       
                    368: 
                    369:        if(!bp->rmesgld) {
                    370:                bp->rptr = bp->data;
                    371:                bp->wptr = bp->data+MSGHLEN;
                    372:                mp = (struct mesg *)bp->rptr;
                    373:        } else {
                    374:                /* compact */
                    375:                n = bp->wptr-bp->rptr;
                    376:                if (n > 0 && bp->rptr!=bp->data)
                    377:                        memcpy(bp->data, bp->rptr, n);
                    378:                bp->rptr = bp->data;
                    379:                bp->wptr = bp->rptr + n;
                    380:        }
                    381: 
                    382:        /* try reading */
                    383:        n = bp->data+sizeof(bp->data) - bp->wptr;
                    384:        if (n > 0) {
                    385:                if(debug)
                    386:                        fprintf(stderr, "read(%d)\n", bp->rfd);
                    387:                n = read(bp->rfd, bp->wptr, n);
                    388:                if(debug){
                    389:                        char *cp;
                    390:                        fprintf(stderr, "read(%d) returns %d\n", bp->rfd, n);
                    391:                        for(cp = bp->wptr; cp < bp->wptr+n; cp++)
                    392:                                fprintf(stderr, "<%o>\n", *cp);
                    393:                }
                    394:                if(n<=0){
                    395:                        if(n<0 || ++neofs>4)
                    396:                                return -1;
                    397:                        if(!bp->rmesgld)
                    398:                                bp->wptr-=MSGHLEN;
                    399:                }
                    400:                bp->wptr += n;
                    401:        } else
                    402:                neofs = 0;
                    403: 
                    404:        if(!bp->rmesgld) {
                    405:                mp->type = M_DATA;
                    406:                mp->magic = MSGMAGIC;
                    407:                setmsgl(mp, n);
                    408:        }
                    409:        return 0;
                    410: }
                    411: 
                    412: /* get the next (buffered) message */
                    413: struct mesg *
                    414: getmsg(bp)
                    415:        struct buffer *bp;
                    416: {
                    417:        struct mesg *mp = (struct mesg *)bp->rptr;
                    418:        int n = bp->wptr - bp->rptr;
                    419: 
                    420:        if (n<MSGHLEN || n<MSGHLEN+msglen(mp)) {
                    421:                if (msglen(mp)+MSGHLEN > sizeof(bp->data))
                    422:                        bp->rptr = bp->wptr = bp->data;
                    423:                return NULL;
                    424:        }
                    425:        bp->rptr += MSGHLEN + msglen(mp);
                    426:        mp->magic = MSGMAGIC;
                    427:        return mp;
                    428: }
                    429: 
                    430: int
                    431: writemsg(bp, mp)
                    432:        struct buffer *bp;
                    433:        struct mesg *mp;
                    434: {
                    435:        int len,n;
                    436:        char *cp;
                    437: 
                    438:        if(bp->wmesgld) {
                    439:                len = MSGHLEN + msglen(mp);
                    440:                cp = (char *)mp;
                    441:        } else if(mp->type==M_DATA){
                    442:                len = msglen(mp);
                    443:                cp = ((char *)mp)+MSGHLEN;
                    444:        } else
                    445:                return 0;
                    446:        if(debug)
                    447:                fprintf(stderr, "write(%d)\n", bp->wfd);
                    448:        n=write(bp->wfd, cp, len);
                    449:        if(debug)
                    450:                fprintf(stderr, "write(%d) returns %d\n", bp->wfd, n);
                    451:        if(n!=len)
                    452:                return -1;
                    453:        return 0;
                    454: }
                    455: 
                    456: doioctl(mp)
                    457:        struct mesg *mp;
                    458: {
                    459:        struct iofoo{
                    460:                int cmd;
                    461:                union{
                    462:                        int i;
                    463:                        char errno;
                    464:                        struct insld insld;
                    465:                } u;
                    466:        } *iop;
                    467:        int cmd, ld;
                    468:        int n;
                    469: 
                    470:        iop = (struct iofoo *)(((char*)mp) + MSGHLEN);
                    471:        cmd = iop->cmd;
                    472:        n = msglen(mp);
                    473:        n -= sizeof(iop->cmd);
                    474:        switch(cmd){
                    475:        case FIOLOOKLD:
                    476:                if(n > 0)
                    477:                        ld = iop->u.i;
                    478:                else
                    479:                        ld = 0;
                    480:                ld++;
                    481:                if(ioctl(1, FIOLOOKLD, &ld) < 0)
                    482:                        goto bad;
                    483:                iop->cmd = ld;
                    484:                n = sizeof(iop->cmd);
                    485:                break;
                    486: 
                    487:        case FIOPOPLD:
                    488:                if(n > 0)
                    489:                        ld = iop->u.i;
                    490:                else
                    491:                        ld = 0;
                    492:                ld++;
                    493:                if(ioctl(1, FIOPOPLD, &ld) < 0)
                    494:                        goto bad;
                    495:                n = 0;
                    496:                break;
                    497: 
                    498:        case FIOPUSHLD:
                    499:                iop->u.insld.level = 0;
                    500:                /* fall through... */
                    501:        case FIOINSLD:
                    502:                iop->u.insld.level++;
                    503:                if(ioctl(1, FIOINSLD, &(iop->u.insld)) < 0)
                    504:                        goto bad;
                    505:                n = 0;
                    506:                break;
                    507: 
                    508:        default:
                    509:                mp->magic = MSGMAGIC;   /* safety */
                    510:                writemsg(&ttyb, mp);
                    511:                return;
                    512:        }
                    513:        /* locally successful */
                    514:        mp->type = M_IOCACK;
                    515:        mp->magic = MSGMAGIC;
                    516:        setmsgl(mp, n);
                    517:        writemsg(&netb, mp);
                    518:        return;
                    519: bad:
                    520:        mp->type = M_IOCNAK;
                    521:        mp->magic = MSGMAGIC;
                    522:        setmsgl(mp, sizeof(struct iofoo));
                    523:        iop->u.errno = errno;
                    524:        writemsg(&netb, mp);
                    525: }
                    526: 
                    527: remflush()
                    528: {
                    529:        char buf[5000];
                    530:        struct mesg *mp;
                    531: 
                    532:        mp = (struct mesg *) buf;
                    533:        mp->type = M_IOCTL;
                    534:        setmsgl(mp, sizeof(int));
                    535:        mp->magic = MSGMAGIC;
                    536:        writemsg(&netb, (struct mesg *)buf);
                    537: 
                    538:        while(read(rem, buf, sizeof(buf)) > 0){
                    539:                if(mp->type == M_HANGUP){
                    540:                        close(rem);
                    541:                        return;
                    542:                }
                    543:                if(mp->type == M_IOCNAK || mp->type == M_IOCACK)
                    544:                        return;
                    545:        }
                    546: }
                    547: 
                    548: setmsgl(mp, n)
                    549:        register struct mesg *mp;
                    550:        int n;
                    551: {
                    552:        mp->losize = n;
                    553:        mp->hisize = n >> 8;
                    554: }
                    555: 
                    556: hupcatch()
                    557: {
                    558:        finish(0);
                    559: }
                    560: 
                    561: finish(sts)
                    562: {
                    563:        struct mesg m;
                    564: 
                    565:        if(ioctl(0, FIOLOOKLD, 0) == mesg_ld) {
                    566:                ioctl(0, FIOPOPLD, 0);
                    567:                ioctl(0, TIOCFLUSH, (char *)0);
                    568:        }
                    569:        if(ioctl(1, FIOLOOKLD, 0) == mesg_ld)
                    570:                ioctl(1, FIOPOPLD, 0);
                    571:        if (ttyn)
                    572:                chmod(ttyn, perms);
                    573:        ioctl(0, TIOCSETP, &sgbuf);
                    574:        ioctl(0, TIOCSETC, &tcbuf);
                    575:        signal(SIGQUIT, quitsig);
                    576:        if(sts==0)
                    577:                write(2, "Eof\n", 4);
                    578:        exit(sts);
                    579: }
                    580: 
                    581: dolocal(mp)
                    582:        register struct mesg *mp;
                    583: {
                    584:        char lbuf[128+1];
                    585:        register char *lp;
                    586:        struct sgttyb nsgbuf;
                    587:        struct tchars ntcbuf;
                    588:        int done;
                    589:        static char prompt[32];
                    590:        struct utsname uts;
                    591: 
                    592:        
                    593:        ioctl(0, FIOPOPLD, (char *)0);
                    594:        signal(SIGQUIT, quitsig);
                    595:        ioctl(0, TIOCFLUSH, (char *)0);
                    596:        ioctl(0, TIOCGETP, &nsgbuf);
                    597:        ioctl(0, TIOCSETP, &sgbuf);
                    598:        ioctl(0, TIOCGETC, &ntcbuf);
                    599:        ioctl(0, TIOCSETC, &tcbuf);
                    600:        if(prompt[0]==0){
                    601:                uname(&uts);
                    602:                strncpy(prompt, uts.nodename, sizeof(uts.nodename));
                    603:                prompt[sizeof(uts.nodename)] = 0;
                    604:                strcat(prompt, ">> ");
                    605:        }
                    606:        if (ttyn)
                    607:                chmod(ttyn, perms);
                    608:        for (done=0;!done;) {
                    609:                lp = lbuf;
                    610:                printf(prompt);
                    611:                fflush(stdout);
                    612:                while (lp < &lbuf[128] && read(0, lp, 1)>0 && *lp!='\n')
                    613:                        lp++;
                    614:                *lp = '\0';
                    615:                switch(*lbuf) {
                    616:                case 'b':
                    617:                        if (ttyrem)
                    618:                                ioctl(netb.wfd, TIOCSBRK, 0);
                    619:                        else
                    620:                                sendmsg(&netb, M_BREAK, (char *)NULL, 0);
                    621:                        mp->type = 0;
                    622:                        done = 1;
                    623:                        break;
                    624:                case 'i':
                    625:                        if (ttyrem) {
                    626:                                sendmsg(&netb, M_DATA, &tcbuf.t_quitc, 1);
                    627:                                mp->type = 0;
                    628:                        }
                    629:                        done = 1;
                    630:                        break;
                    631:                case 'q':
                    632:                case 'x':
                    633:                case '.':
                    634:                        finish(1);
                    635:                case '!':
                    636:                        system(lbuf+1);
                    637:                        printf("!!\n");
                    638:                        fflush(stdout);
                    639:                        mp->type = 0;
                    640:                        done = 1;
                    641:                        break;
                    642:                case '\0':
                    643:                        mp->type = 0;
                    644:                        done = 1;
                    645:                        break;
                    646:                default:
                    647:                        printf("[qx.] to exit, i for quit signal, b for break, !cmd for shell\n");
                    648:                        fflush(stdout);
                    649:                }
                    650:        }
                    651:        ioctl(0, TIOCSETP, &nsgbuf);
                    652:        ioctl(0, TIOCSETC, &ntcbuf);
                    653:        signal(SIGQUIT, hupcatch);
                    654:        ioctl(0, FIOPUSHLD, &mesg_ld);
                    655:        if (ttyn)
                    656:                chmod(ttyn, 0);
                    657:        if (mp->type) {
                    658:                mp->magic = MSGMAGIC;   /* safety */
                    659:                writemsg(&netb, mp);
                    660:        }
                    661: }
                    662: 
                    663: sendmsg(bp, type, cp, len)
                    664:        struct buffer *bp;
                    665:        int type, len;
                    666:        char *cp;
                    667: {
                    668:        struct amesg {
                    669:                struct mesg m;
                    670:                char body[128];
                    671:        } am;
                    672: 
                    673:        am.m.magic = MSGMAGIC;
                    674:        am.m.type = type;
                    675:        setmsgl(&am.m, len);
                    676:        if (cp!=NULL && len>0)
                    677:                memcpy(am.body, cp, len);
                    678:        writemsg(bp, (struct mesg *)&am);
                    679: }

unix.superglobalmegacorp.com

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