Annotation of 3BSD/cmd/cu.c, revision 1.1.1.1

1.1       root        1: #include <stdio.h>
                      2: #include <signal.h>
                      3: #include <sgtty.h>
                      4: /*
                      5:  *     cu telno [-t] [-s speed] [-l line] [-a acu]
                      6:  *
                      7:  *     -t is for dial-out to terminal.
                      8:  *     speeds are: 110, 134, 150, 300, 1200. 300 is default.
                      9:  *
                     10:  *     Escape with `~' at beginning of line.
                     11:  *     Ordinary diversions are ~<, ~> and ~>>.
                     12:  *     Silent output diversions are ~>: and ~>>:.
                     13:  *     Terminate output diversion with ~> alone.
                     14:  *     Quit is ~. and ~! gives local command or shell.
                     15:  *     Also ~$ for canned procedure pumping remote.
                     16:  *     ~%put from [to]  and  ~%take from [to] invoke builtins
                     17:  */
                     18: 
                     19: #define CRLF "\r\n"
                     20: #define wrc(ds) write(ds,&c,1)
                     21: 
                     22: 
                     23: char   *devcul = "/dev/cul0";
                     24: char   *devcua = "/dev/cua0";
                     25: char   *lspeed = "300";
                     26: 
                     27: int    ln;     /* fd for comm line */
                     28: char   tkill, terase;  /* current input kill & erase */
                     29: int    efk;            /* process of id of listener  */
                     30: char   c;
                     31: 
                     32: char   *connmsg[] = {
                     33:        "",
                     34:        "line busy",
                     35:        "call dropped",
                     36:        "no carrier",
                     37:        "can't fork",
                     38:        "acu access",
                     39:        "tty access",
                     40:        "tty hung",
                     41:        "usage: cu telno [-t] [-s speed] [-l line] [-a acu]"
                     42: };
                     43: 
                     44: rdc(ds) {
                     45: 
                     46:        ds=read(ds,&c,1); 
                     47:        c&= 0177; 
                     48:        return (ds);
                     49: }
                     50: 
                     51: int intr;
                     52: 
                     53: sig2()
                     54: {
                     55:        signal(SIGINT, SIG_IGN); 
                     56:        intr = 1;
                     57: }
                     58: 
                     59: int set14;
                     60: 
                     61: xsleep(n)
                     62: {
                     63:        xalarm(n);
                     64:        pause();
                     65:        xalarm(0);
                     66: }
                     67: 
                     68: xalarm(n)
                     69: {
                     70:        set14=n; 
                     71:        alarm(n);
                     72: }
                     73: 
                     74: sig14()
                     75: {
                     76:        signal(SIGALRM, sig14); 
                     77:        if (set14) alarm(1);
                     78: }
                     79: 
                     80: int    dout;
                     81: int    nhup;
                     82: int    dbflag;
                     83: 
                     84: /*
                     85:  *     main: get connection, set speed for line.
                     86:  *     spawn child to invoke rd to read from line, output to fd 1
                     87:  *     main line invokes wr to read tty, write to line
                     88:  */
                     89: main(ac,av)
                     90: char *av[];
                     91: {
                     92:        int fk;
                     93:        int speed;
                     94:        char *telno;
                     95:        struct sgttyb stbuf;
                     96: 
                     97:        signal(SIGALRM, sig14);
                     98:        if (ac < 2) {
                     99:                prf(connmsg[8]);
                    100:                exit(8);
                    101:        }
                    102:        telno = av[1];
                    103:        av += 2;
                    104:        ac -= 2;
                    105:        for (; ac > 0; av++) {
                    106:                if (equal(*av, "-t")) {
                    107:                        dout = 1;
                    108:                        --ac;
                    109:                        continue;
                    110:                }
                    111:                if (equal(*av, "-d")) {
                    112:                        dbflag++;
                    113:                        continue;
                    114:                }
                    115:                if (ac < 2)
                    116:                        break;
                    117:                if (equal(*av, "-s"))
                    118:                        lspeed = *++av;
                    119:                else if (equal(*av, "-l"))
                    120:                        devcul = *++av;
                    121:                else if (equal(*av, "-a"))
                    122:                        devcua = *++av;
                    123:                else
                    124:                        break;
                    125:                ac -= 2;
                    126:        }
                    127:        if (!exists(devcua) || !exists(devcul))
                    128:                exit(9);
                    129:        ln = conn(devcul, devcua, telno);
                    130:        if (ln < 0) {
                    131:                prf("Connect failed: %s",connmsg[-ln]);
                    132:                exit(-ln);
                    133:        }
                    134:        switch(atoi(lspeed)) {
                    135:        case 110:
                    136:                speed = B110;break;
                    137:        case 150:
                    138:                speed = B150;break;
                    139:        default:
                    140:        case 300:
                    141:                speed = B300;break;
                    142:        case 1200:
                    143:                speed = B1200;break;
                    144:        }
                    145:        stbuf.sg_ispeed = speed;
                    146:        stbuf.sg_ospeed = speed;
                    147:        stbuf.sg_flags = EVENP|ODDP;
                    148:        if (!dout)
                    149:                stbuf.sg_flags |= RAW;
                    150:        ioctl(TIOCSETP, ln, &stbuf);
                    151:        ioctl(TIOCEXCL, ln, (struct sgttyb *)NULL);
                    152:        ioctl(TIOCHPCL, ln, (struct sgttyb *)NULL);
                    153:        prf("Connected");
                    154:        if (dout)
                    155:                fk = -1;
                    156:        else
                    157:                fk = fork();
                    158:        nhup = (int)signal(SIGINT, SIG_IGN);
                    159:        if (fk == 0) {
                    160:                chwrsig();
                    161:                rd();
                    162:                prf("\007Lost carrier");
                    163:                exit(3);
                    164:        }
                    165:        mode(1);
                    166:        efk = fk;
                    167:        wr();
                    168:        mode(0);
                    169:        kill(fk, SIGKILL);
                    170:        wait((int *)NULL);
                    171:        stbuf.sg_ispeed = 0;
                    172:        stbuf.sg_ospeed = 0;
                    173:        ioctl(TIOCSETP, ln, &stbuf);
                    174:        prf("Disconnected");
                    175:        exit(0);
                    176: }
                    177: 
                    178: /*
                    179:  *     conn: establish dial-out connection.
                    180:  *     Example:  fd = conn("/dev/ttyh","/dev/dn1","4500");
                    181:  *     Returns descriptor open to tty for reading and writing.
                    182:  *     Negative values (-1...-7) denote errors in connmsg.
                    183:  *     Uses alarm and fork/wait; requires sig14 handler.
                    184:  *     Be sure to disconnect tty when done, via HUPCL or stty 0.
                    185:  */
                    186: 
                    187: conn(dev,acu,telno)
                    188: char *dev, *acu, *telno;
                    189: {
                    190:        struct sgttyb stbuf;
                    191:        extern errno;
                    192:        char *p, *q, b[30];
                    193:        int er, fk, dn, dh, t;
                    194:        er=0; 
                    195:        fk=(-1);
                    196:        if ((dn=open(acu,1))<0) {
                    197:                er=(errno == 6? 1:5); 
                    198:                goto X;
                    199:        }
                    200:        if ((fk=fork()) == (-1)) {
                    201:                er=4; 
                    202:                goto X;
                    203:        }
                    204:        if (fk == 0) {
                    205:                open(dev,2); 
                    206:                for (;;) pause();
                    207:        }
                    208:        xsleep(2);
                    209:        /*
                    210:         *      copy phone #, assure EON
                    211:         */
                    212:        p=b; 
                    213:        q=telno;
                    214:        while (*p++=(*q++))
                    215:                ;
                    216:        p--;
                    217:        if (*(p-1)!='<') {
                    218:                if (*(p-1)!='-') *p++='-';
                    219:                *p++='<';
                    220:        }
                    221:        t=p-b;
                    222:        xalarm(5*t);
                    223:        t=write(dn,b,t);
                    224:        xalarm(0);
                    225:        if (t<0) {
                    226:                er=2; 
                    227:                goto X;
                    228:        }
                    229:        /* close(dn) */
                    230:        xalarm(40);             /* was 5; sometimes missed carrier */
                    231:        dh = open(dev,2);
                    232:        xalarm(0);
                    233:        if (dh<0) {
                    234:                er=(errno == 4? 3:6); 
                    235:                goto X;
                    236:        }
                    237:        ioctl(TIOCGETP, ln, &stbuf);
                    238:        stbuf.sg_flags &= ~ECHO;
                    239:        xalarm(10);
                    240:        ioctl(TIOCSETP, dh, &stbuf);
                    241:        ioctl(TIOCHPCL, dh, (struct sgttyb *)NULL);
                    242:        xalarm(0);
                    243: X: 
                    244:        if (er) close(dn);
                    245:        if (fk!=(-1)) {
                    246:                kill(fk, SIGKILL);
                    247:                xalarm(10);
                    248:                while ((t=wait((int *)NULL))!=(-1) && t!=fk);
                    249:                xalarm(0);
                    250:        }
                    251:        return (er? -er:dh);
                    252: }
                    253: 
                    254: /*
                    255:  *     wr: write to remote: 0 -> line.
                    256:  *     ~.      terminate
                    257:  *     ~<file  send file
                    258:  *     ~!      local login-style shell
                    259:  *     ~!cmd   execute cmd locally
                    260:  *     ~$proc  execute proc locally, send output to line
                    261:  *     ~%cmd   execute builtin cmd (put and take)
                    262:  */
                    263: 
                    264: wr()
                    265: {
                    266:        int ds,fk,lcl,x;
                    267:        char *p,b[600];
                    268:        for (;;) {
                    269:                p=b;
                    270:                while (rdc(0) == 1) {
                    271:                        if (p == b) lcl=(c == '~');
                    272:                        if (p == b+1 && b[0] == '~') lcl=(c!='~');
                    273:                        if (c == 0) c=0177;
                    274:                        if (!lcl) {
                    275:                                if (wrc(ln) == 0) {
                    276:                                        prf("line gone"); return;
                    277:                                }
                    278:                        }
                    279:                        if (lcl) {
                    280:                                if (c == 0177) c=tkill;
                    281:                                if (c == '\r' || c == '\n') goto A;
                    282:                                if (!dout) wrc(0);
                    283:                        }
                    284:                        *p++=c;
                    285:                        if (c == terase) {
                    286:                                p=p-2; 
                    287:                                if (p<b) p=b;
                    288:                        }
                    289:                        if (c == tkill || c == 0177 || c == '\r' || c == '\n') p=b;
                    290:                }
                    291:                return;
                    292: A: 
                    293:                if (!dout) echo("");
                    294:                *p=0;
                    295:                switch (b[1]) {
                    296:                case '.':
                    297:                case '\004':
                    298:                        return;
                    299:                case '!':
                    300:                case '$':
                    301:                        fk = fork();
                    302:                        if (fk == 0) {
                    303:                                char *shell = getenv("SHELL");
                    304:                                if (shell == 0) shell = "/bin/sh";
                    305:                                close(1);
                    306:                                dup(b[1] == '$'? ln:2);
                    307:                                close(ln);
                    308:                                mode(0);
                    309:                                if (!nhup) signal(SIGINT, SIG_DFL);
                    310:                                if (b[2] == 0) execl(shell,"-",0);
                    311:                                else execl(shell,"sh","-c",b+2,0);
                    312:                                prf("Can't execute shell");
                    313:                                exit(~0);
                    314:                        }
                    315:                        if (fk!=(-1)) {
                    316:                                while (wait(&x)!=fk);
                    317:                        }
                    318:                        mode(1);
                    319:                        if (b[1] == '!') echo("!");
                    320:                        else {
                    321:                                if (dout) echo("$");
                    322:                        }
                    323:                        break;
                    324:                case '<':
                    325:                        if (b[2] == 0) break;
                    326:                        if ((ds=open(b+2,0))<0) {
                    327:                                prf("Can't divert %s",b+1); 
                    328:                                break;
                    329:                        }
                    330:                        intr=x=0;
                    331:                        mode(2);
                    332:                        if (!nhup) signal(SIGINT, sig2);
                    333:                        while (!intr && rdc(ds) == 1) {
                    334:                                if (wrc(ln) == 0) {
                    335:                                        x=1; 
                    336:                                        break;
                    337:                                }
                    338:                        }
                    339:                        signal(SIGINT, SIG_IGN);
                    340:                        close(ds);
                    341:                        mode(1);
                    342:                        if (x) return;
                    343:                        if (dout) echo("<");
                    344:                        break;
                    345:                case '>':
                    346:                case ':':
                    347:                        {
                    348:                        FILE *fp; char tbuff[128]; register char *q;
                    349:                        sprintf(tbuff,"/tmp/cu%d",efk);
                    350:                        if(NULL==(fp = fopen(tbuff,"w"))) {
                    351:                                prf("Can't tell other demon to divert");
                    352:                                break;
                    353:                        }
                    354:                        fprintf(fp,"%s\n",(b[1]=='>'?&b[2]: &b[1] ));
                    355:                        if(dbflag) prf("name to be written in temporary:"),prf(&b[2]);
                    356:                        fclose(fp);
                    357:                        kill(efk,SIGEMT);
                    358:                        }
                    359:                        break;
                    360:                case '%':
                    361:                        dopercen(&b[2]);
                    362:                        break;
                    363:                default:
                    364:                        prf("Use `~~' to start line with `~'");
                    365:                }
                    366:                continue;
                    367:        }
                    368: }
                    369: 
                    370: dopercen(line)
                    371: register char *line;
                    372: {
                    373:        char *args[10];
                    374:        register narg, f;
                    375:        int rcount;
                    376:        for (narg = 0; narg < 10;) {
                    377:                while(*line == ' ' || *line == '\t')
                    378:                        line++;
                    379:                if (*line == '\0')
                    380:                        break;
                    381:                args[narg++] = line;
                    382:                while(*line != '\0' && *line != ' ' && *line != '\t')
                    383:                        line++;
                    384:                if (*line == '\0')
                    385:                        break;
                    386:                *line++ = '\0';
                    387:        }
                    388:        if (equal(args[0], "take")) {
                    389:                if (narg < 2) {
                    390:                        prf("usage: ~%%take from [to]");
                    391:                        return;
                    392:                }
                    393:                if (narg < 3)
                    394:                        args[2] = args[1];
                    395:                wrln("echo '~>:'");
                    396:                wrln(args[2]);
                    397:                wrln(";tee /dev/null <");
                    398:                wrln(args[1]);
                    399:                wrln(";echo '~>'\n");
                    400:                return;
                    401:        } else if (equal(args[0], "put")) {
                    402:                if (narg < 2) {
                    403:                        prf("usage: ~%%put from [to]");
                    404:                        return;
                    405:                }
                    406:                if (narg < 3)
                    407:                        args[2] = args[1];
                    408:                if ((f = open(args[1], 0)) < 0) {
                    409:                        prf("cannot open: %s", args[1]);
                    410:                        return;
                    411:                }
                    412:                wrln("stty -echo;cat >");
                    413:                wrln(args[2]);
                    414:                wrln(";stty echo\n");
                    415:                xsleep(5);
                    416:                intr = 0;
                    417:                if (!nhup)
                    418:                        signal(SIGINT, sig2);
                    419:                mode(2);
                    420:                rcount = 0;
                    421:                while(!intr && rdc(f) == 1) {
                    422:                        rcount++;
                    423:                        if (c == tkill || c == terase)
                    424:                                wrln("\\");
                    425:                        if (wrc(ln) != 1) {
                    426:                                xsleep(2);
                    427:                                if (wrc(ln) != 1) {
                    428:                                        prf("character missed");
                    429:                                        intr = 1;
                    430:                                        break;
                    431:                                }
                    432:                        }
                    433:                }
                    434:                signal(SIGINT, SIG_IGN);
                    435:                close(f);
                    436:                if (intr) {
                    437:                        wrln("\n");
                    438:                        prf("stopped after %d bytes", rcount);
                    439:                }
                    440:                wrln("\004");
                    441:                xsleep(5);
                    442:                mode(1);
                    443:                return;
                    444:        }
                    445:        prf("~%%%s unknown\n", args[0]);
                    446: }
                    447: 
                    448: equal(s1, s2)
                    449: register char *s1, *s2;
                    450: {
                    451:        while (*s1++ == *s2)
                    452:                if (*s2++ == '\0')
                    453:                        return(1);
                    454:        return(0);
                    455: }
                    456: 
                    457: wrln(s)
                    458: register char *s;
                    459: {
                    460:        while (*s)
                    461:                write(ln, s++, 1);
                    462: }
                    463: /*     chwrsig:  Catch orders from wr process 
                    464:  *     to instigate diversion
                    465:  */
                    466: int whoami;
                    467: chwrsig(){
                    468:        int dodiver(); 
                    469:        whoami = getpid();
                    470:        signal(SIGEMT,dodiver);
                    471: }
                    472: int ds,slnt;
                    473: int justrung;
                    474: dodiver(){
                    475:        static char dobuff[128], morejunk[256]; register char *cp; 
                    476:        FILE *fp;
                    477:        justrung = 1;
                    478:        signal(SIGEMT,dodiver);
                    479:        sprintf(dobuff,"/tmp/cu%d",whoami);
                    480:        fp = fopen(dobuff,"r");
                    481:        if(fp==NULL) prf("Couldn't open temporary");
                    482:        unlink(dobuff);
                    483:        if(dbflag) {
                    484:                prf("Name of temporary:");
                    485:                prf(dobuff);
                    486:        }
                    487:        fgets(dobuff,128,fp); fclose(fp);
                    488:        if(dbflag) {
                    489:                prf("Name of target file:");
                    490:                prf(dobuff);
                    491:        }
                    492:        for(cp = dobuff-1; *++cp; ) /* squash newline */
                    493:                if(*cp=='\n') *cp=0;
                    494:        cp = dobuff;
                    495:        if (*cp=='>') cp++;
                    496:        if (*cp==':') {
                    497:                cp++;
                    498:                if(*cp==0) {
                    499:                        slnt ^= 1;
                    500:                        return;
                    501:                } else  {
                    502:                        slnt = 1;
                    503:                }
                    504:        }
                    505:        if (ds >= 0) close(ds);
                    506:        if (*cp==0) {
                    507:                slnt = 0;
                    508:                ds = -1;
                    509:                return;
                    510:        }
                    511:        if (*dobuff!='>' || (ds=open(cp,1))<0) ds=creat(cp,0644);
                    512:        lseek(ds, (long)0, 2);
                    513:        if(ds < 0) prf("Creat failed:"), prf(cp);
                    514:        if (ds<0) prf("Can't divert %s",cp+1);
                    515: }
                    516: 
                    517: 
                    518: /*
                    519:  *     rd: read from remote: line -> 1
                    520:  *     catch:
                    521:  *     ~>[>][:][file]
                    522:  *     stuff from file...
                    523:  *     ~>      (ends diversion)
                    524:  */
                    525: 
                    526: rd()
                    527: {
                    528:        extern int ds,slnt;
                    529:        char *p,*q,b[600];
                    530:        p=b;
                    531:        ds=(-1);
                    532: agin:
                    533:        while (rdc(ln) == 1) {
                    534:                if (!slnt) wrc(1);
                    535:                *p++=c;
                    536:                if (c!='\n') continue;
                    537:                q=p; 
                    538:                p=b;
                    539:                if (b[0]!='~' || b[1]!='>') {
                    540:                        if (*(q-2) == '\r') {
                    541:                                q--; 
                    542:                                *(q-1)=(*q);
                    543:                        }
                    544:                        if (ds>=0) write(ds,b,q-b);
                    545:                        continue;
                    546:                }
                    547:                if (ds>=0) close(ds);
                    548:                if (slnt) {
                    549:                        write(1, b, q - b);
                    550:                        write(1, CRLF, sizeof(CRLF));
                    551:                }
                    552:                if (*(q-2) == '\r') q--;
                    553:                *(q-1)=0;
                    554:                slnt=0;
                    555:                q=b+2;
                    556:                if (*q == '>') q++;
                    557:                if (*q == ':') {
                    558:                        slnt=1; 
                    559:                        q++;
                    560:                }
                    561:                if (*q == 0) {
                    562:                        ds=(-1); 
                    563:                        continue;
                    564:                }
                    565:                if (b[2]!='>' || (ds=open(q,1))<0) ds=creat(q,0644);
                    566:                lseek(ds, (long)0, 2);
                    567:                if (ds<0) prf("Can't divert %s",b+1);
                    568:        }
                    569:        if(justrung) {
                    570:                justrung = 0;
                    571:                goto agin;
                    572:        }
                    573: }
                    574: 
                    575: struct {char lobyte; char hibyte;};
                    576: mode(f)
                    577: {
                    578:        struct sgttyb stbuf;
                    579:        if (dout) return;
                    580:        ioctl(TIOCGETP, 0, &stbuf);
                    581:        tkill = stbuf.sg_kill;
                    582:        terase = stbuf.sg_erase;
                    583:        if (f == 0) {
                    584:                stbuf.sg_flags &= ~RAW;
                    585:                stbuf.sg_flags |= ECHO|CRMOD;
                    586:        }
                    587:        if (f == 1) {
                    588:                stbuf.sg_flags |= RAW;
                    589:                stbuf.sg_flags &= ECHO|CRMOD;
                    590:        }
                    591:        if (f == 2) {
                    592:                stbuf.sg_flags &= ~RAW;
                    593:                stbuf.sg_flags &= ~(ECHO|CRMOD);
                    594:        }
                    595:        ioctl(TIOCSETP, 0, &stbuf);
                    596: }
                    597: 
                    598: echo(s)
                    599: char *s;
                    600: {
                    601:        char *p;
                    602:        for (p=s;*p;p++);
                    603:        if (p>s) write(0,s,p-s);
                    604:        write(0,CRLF, sizeof(CRLF));
                    605: }
                    606: 
                    607: prf(f, s)
                    608: char *f;
                    609: char *s;
                    610: {
                    611:        fprintf(stderr, f, s);
                    612:        fprintf(stderr, CRLF);
                    613: }
                    614: 
                    615: exists(devname)
                    616: char *devname;
                    617: {
                    618:        if (access(devname, 0)==0)
                    619:                return(1);
                    620:        prf("%s does not exist", devname);
                    621:        return(0);
                    622: }

unix.superglobalmegacorp.com

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