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

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

unix.superglobalmegacorp.com

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