|
|
1.1 ! root 1: #include <stdio.h> ! 2: #include <signal.h> ! 3: #include <sgtty.h> ! 4: #include <ctype.h> ! 5: /* ! 6: * cu telno [ class ] ! 7: * Escape with `~' at beginning of line. ! 8: * Ordinary diversions are ~<, ~> and ~>>. ! 9: * Silent output diversions are ~>: and ~>>:. ! 10: * Terminate output diversion with ~> alone. ! 11: * Output command requests are ~! and ~:! (silent). ! 12: * Quit is ~. and ~! gives local command or shell. ! 13: * Also ~$ for canned procedure pumping remote. ! 14: * ~%put from [to] and ~%take from [to] invoke builtins ! 15: */ ! 16: ! 17: char CRLF[2] = {'\r', '\n'}; ! 18: #define equal(s1,s2) (strcmp(s1, s2)==0) ! 19: char *cunfile; ! 20: int ln; /* fd for comm line */ ! 21: char tkill, terase; /* current input kill & erase */ ! 22: char c; ! 23: int intr; ! 24: int nhup; ! 25: int nflag; ! 26: int tandm; ! 27: int hduplx; ! 28: int errflg; ! 29: extern int optind, opterr; ! 30: extern char *optarg; ! 31: struct sgttyb realtty; ! 32: struct tchars realtch; ! 33: int sig2(); ! 34: ! 35: char *connmsg[] = { ! 36: "", ! 37: "ACU busy", ! 38: "call dropped", ! 39: "no carrier", ! 40: "can't fork", ! 41: "acu access", ! 42: "tty access", ! 43: "tty hung", ! 44: "usage: cu [-hnt] telno [ class ]", ! 45: "unknown service class", ! 46: }; ! 47: ! 48: struct dial { ! 49: char *telno; ! 50: char *dialtype; ! 51: char *comment; ! 52: }; ! 53: ! 54: char partab[] = { ! 55: 0001,0201,0201,0001,0201,0001,0001,0201, ! 56: 0202,0004,0003,0201,0005,0206,0201,0001, ! 57: 0201,0001,0001,0201,0001,0201,0201,0001, ! 58: 0001,0201,0201,0001,0201,0001,0001,0201, ! 59: 0200,0000,0000,0200,0000,0200,0200,0000, ! 60: 0000,0200,0200,0000,0200,0000,0000,0200, ! 61: 0000,0200,0200,0000,0200,0000,0000,0200, ! 62: 0200,0000,0000,0200,0000,0200,0200,0000, ! 63: 0200,0000,0000,0200,0000,0200,0200,0000, ! 64: 0000,0200,0200,0000,0200,0000,0000,0200, ! 65: 0000,0200,0200,0000,0200,0000,0000,0200, ! 66: 0200,0000,0000,0200,0000,0200,0200,0000, ! 67: 0000,0200,0200,0000,0200,0000,0000,0200, ! 68: 0200,0000,0000,0200,0000,0200,0200,0000, ! 69: 0200,0000,0000,0200,0000,0200,0200,0000, ! 70: 0000,0200,0200,0000,0200,0000,0000,0201 ! 71: }; ! 72: ! 73: /* ! 74: * spawn child to invoke rd to read from line, output to fd 1 ! 75: * main line invokes wr to read tty, write to line ! 76: */ ! 77: ! 78: main(ac, av) ! 79: char *av[]; ! 80: { ! 81: int fk; ! 82: struct sgttyb stbuf; ! 83: struct dial d; ! 84: ! 85: signal(SIGPIPE, SIG_IGN); ! 86: d.telno = NULL; ! 87: d.dialtype = NULL; ! 88: d.comment = ""; ! 89: options(ac, av); ! 90: if (optind >= ac || errflg) { ! 91: prf(connmsg[8]); ! 92: exit(8); ! 93: } ! 94: ioctl(0, TIOCGETP, &realtty); ! 95: ioctl(0, TIOCGETC, &realtch); ! 96: gettelno(av[optind], &d); ! 97: if (optind+1 < ac) ! 98: d.dialtype = av[optind+1]; ! 99: if (d.dialtype==NULL || *d.dialtype=='\0') ! 100: d.dialtype = "D1200"; ! 101: if (equal(d.dialtype, "300")) ! 102: d.dialtype = "D300"; ! 103: else if (equal(d.dialtype, "1200")) ! 104: d.dialtype = "D1200"; ! 105: else if (equal(d.dialtype, "D")) ! 106: d.dialtype = "D1200"; ! 107: else if (equal(d.dialtype, "C")) ! 108: d.dialtype = "C1200"; ! 109: if (nflag) { ! 110: printf("%s %s %s\n", d.telno, d.dialtype, d.comment); ! 111: exit(0); ! 112: } ! 113: if (equal(d.dialtype, "direct")) { ! 114: ln = open(d.telno, 2); ! 115: if (ln>=0) { ! 116: struct tchars tcr; ! 117: ! 118: ioctl(ln, TIOCGETP, &stbuf); ! 119: stbuf.sg_flags &= ~ECHO; ! 120: stbuf.sg_flags |= RAW|EVENP|ODDP; ! 121: stbuf.sg_ispeed = B9600; ! 122: stbuf.sg_ospeed = B9600; ! 123: tcr.t_stopc = '\027'; ! 124: tcr.t_startc = '\031'; ! 125: ioctl(ln, TIOCSETP, &stbuf); ! 126: ioctl(ln, TIOCGETC, &tcr); ! 127: ioctl(ln, TIOCSETC, &tcr); ! 128: ioctl(ln, TIOCHPCL, 0); ! 129: ioctl(ln, TIOCEXCL, 0); ! 130: } ! 131: } else ! 132: ln = dialout(d.telno, d.dialtype); ! 133: if (ln < 0) { ! 134: prf("Connect failed: %s",connmsg[-ln]); ! 135: exit(-ln); ! 136: } ! 137: ioctl(ln, TIOCGETP, &stbuf); ! 138: prf("Connected"); ! 139: if (d.comment && *d.comment && *d.comment!='\n') ! 140: prf(d.comment); ! 141: if (tandm) { ! 142: ioctl(ln, TIOCGETP, &stbuf); ! 143: stbuf.sg_flags = ODDP+EVENP+TANDEM+CBREAK; ! 144: ioctl(ln, TIOCSETN, &stbuf); ! 145: } ! 146: fk = fork(); ! 147: nhup = (int)signal(SIGINT, SIG_IGN); ! 148: if (fk == 0) { ! 149: rd(); ! 150: prf("\007Lost carrier"); ! 151: exit(3); ! 152: } ! 153: mode(1); ! 154: wr(); ! 155: mode(0); ! 156: kill(fk, SIGKILL); ! 157: stbuf.sg_ispeed = 0; ! 158: stbuf.sg_ospeed = 0; ! 159: ioctl(ln, TIOCSETN, &stbuf); ! 160: prf("Disconnected"); ! 161: exit(0); ! 162: } ! 163: ! 164: /* ! 165: * wr: write to remote: 0 -> line. ! 166: * ~. terminate ! 167: * ~<file send file ! 168: * ~! local login-style shell ! 169: * ~!cmd execute cmd locally ! 170: * ~$proc execute proc locally, send output to line ! 171: * ~%cmd execute builtin cmd (put and take) ! 172: */ ! 173: ! 174: wr() ! 175: { ! 176: int ds, fk, lcl, x, nc; ! 177: char *p, b[600]; ! 178: ! 179: for (;;) { ! 180: p = b; ! 181: while (rdc(0) >= 1) { ! 182: if (p == b) ! 183: lcl=(c == '~'); ! 184: if (p == b+1 && b[0] == '~') ! 185: lcl=(c!='~'); ! 186: if (c == 0) ! 187: c = 0177; ! 188: if (!lcl) { ! 189: if (c==0177) ! 190: ioctl(ln, TIOCFLUSH, 0); ! 191: if (wrc(ln, c, 1) <= 0) { ! 192: prf("line gone"); ! 193: return; ! 194: } ! 195: if (c==0177) ! 196: ioctl(0, TIOCFLUSH, 0); ! 197: } ! 198: if (lcl) { ! 199: if (c == 0177) ! 200: c = tkill; ! 201: if (c == '\r' || c == '\n') ! 202: goto A; ! 203: if (!hduplx) ! 204: wrc(1, c, 1); ! 205: } ! 206: *p++ = c; ! 207: if (c == terase) { ! 208: p = p-2; ! 209: if (p<b) ! 210: p = b; ! 211: } ! 212: if (c == tkill || c == 0177 || c == '\r' || c == '\n') ! 213: p = b; ! 214: } ! 215: return; ! 216: A: ! 217: if (!hduplx || realtty.sg_flags&CRMOD) ! 218: echo(""); ! 219: *p = 0; ! 220: switch (b[1]) { ! 221: case '.': ! 222: case '\004': ! 223: return; ! 224: case 'b': ! 225: sendbreak(); ! 226: break; ! 227: ! 228: case '!': ! 229: case '$': ! 230: fk = fork(); ! 231: if (fk == 0) { ! 232: close(1); ! 233: dup(b[1] == '$'? ln:2); ! 234: close(ln); ! 235: mode(0); ! 236: if (!nhup) ! 237: signal(SIGINT, SIG_DFL); ! 238: if (b[2] == 0) ! 239: execl("/bin/sh","sh",0); ! 240: else ! 241: execl("/bin/sh","sh","-c",b+2,(char *)0); ! 242: prf("Can't execute shell"); ! 243: exit(1); ! 244: } ! 245: if (fk!=(-1)) { ! 246: while (wait((int *)0)!=fk) ! 247: ; ! 248: } ! 249: mode(1); ! 250: if (b[1] == '!') ! 251: echo("!"); ! 252: break; ! 253: case '<': ! 254: if (b[2] == 0) break; ! 255: if ((ds = open(b+2,0))<0) { ! 256: prf("Can't divert %s",b+1); ! 257: break; ! 258: } ! 259: intr = x = 0; ! 260: mode(2); ! 261: if (!nhup) ! 262: signal(SIGINT, sig2); ! 263: while (!intr && (nc = rdc(ds)) >= 1) { ! 264: if (wrc(ln, c, nc==1) <= 0) { ! 265: x = 1; ! 266: break; ! 267: } ! 268: } ! 269: signal(SIGINT, SIG_IGN); ! 270: close(ds); ! 271: mode(1); ! 272: if (x) ! 273: return; ! 274: break; ! 275: case '%': ! 276: dopercen(&b[2]); ! 277: break; ! 278: default: ! 279: prf("Use `~~' to start line with `~'"); ! 280: } ! 281: continue; ! 282: } ! 283: } ! 284: ! 285: dopercen(line) ! 286: register char *line; ! 287: { ! 288: char *args[10]; ! 289: register narg, f; ! 290: int rcount, nc; ! 291: ! 292: for (narg = 0; narg < 10;) { ! 293: while(*line == ' ' || *line == '\t') ! 294: line++; ! 295: if (*line == '\0') ! 296: break; ! 297: args[narg++] = line; ! 298: while(*line != '\0' && *line != ' ' && *line != '\t') ! 299: line++; ! 300: if (*line == '\0') ! 301: break; ! 302: *line++ = '\0'; ! 303: } ! 304: if (equal(args[0], "break")) { ! 305: sendbreak(); ! 306: return; ! 307: } else if (equal(args[0], "take")) { ! 308: if (narg < 2) { ! 309: prf("usage: ~%%take from [to]"); ! 310: return; ! 311: } ! 312: if (narg < 3) ! 313: args[2] = args[1]; ! 314: wrln("echo '~>:'"); ! 315: wrln(args[2]); ! 316: wrln(";tee /dev/null <"); ! 317: wrln(args[1]); ! 318: wrln(";echo '~>'\n"); ! 319: return; ! 320: } else if (equal(args[0], "put")) { ! 321: if (narg < 2) { ! 322: prf("usage: ~%%put from [to]"); ! 323: return; ! 324: } ! 325: if (narg < 3) ! 326: args[2] = args[1]; ! 327: if ((f = open(args[1], 0)) < 0) { ! 328: prf("cannot open: %s", args[1]); ! 329: return; ! 330: } ! 331: wrln("stty -echo;cat >"); ! 332: wrln(args[2]); ! 333: wrln(";stty echo\n"); ! 334: sleep(5); ! 335: intr = 0; ! 336: if (!nhup) ! 337: signal(SIGINT, sig2); ! 338: mode(2); ! 339: rcount = 0; ! 340: while(!intr && (nc = rdc(f)) >= 1) { ! 341: rcount++; ! 342: if (c == tkill || c == terase) ! 343: wrc(ln, '\\', 0); ! 344: if (wrc(ln, c, nc == 1) <= 0) ! 345: intr = 1; ! 346: } ! 347: signal(SIGINT, SIG_IGN); ! 348: close(f); ! 349: if (intr) { ! 350: wrc(ln, '\n', 1); ! 351: prf("stopped after %d bytes", rcount); ! 352: } ! 353: wrc(ln, '\004', 1); ! 354: sleep(5); ! 355: mode(1); ! 356: return; ! 357: } ! 358: prf("~%%%s unknown\n", args[0]); ! 359: } ! 360: ! 361: wrln(s) ! 362: register char *s; ! 363: { ! 364: register n = strlen(s); ! 365: ! 366: write(ln, s, n); ! 367: } ! 368: ! 369: /* ! 370: * rd: read from remote: line -> 1 ! 371: * catch: ! 372: * ~>[>][:][file] ! 373: * stuff from file... ! 374: * ~> (ends diversion) ! 375: * ways for remote to run local command: ! 376: * ~!command (run command locally) ! 377: * ~:!command (run silently locally) ! 378: */ ! 379: ! 380: rd() ! 381: { ! 382: int ds, slnt, pid, hold=0, nc; ! 383: char *p, *q, b[600]; ! 384: ! 385: p = b; ! 386: ds = -1; ! 387: while ((nc = rdc(ln)) >= 1) { ! 388: if (ds < 0 && hold==0) ! 389: slnt = 0; ! 390: if (p==b && c=='~') ! 391: hold= ++slnt; ! 392: if (hold && slnt && p==b+1 && c!=':') { ! 393: wrc(1, '~', 1); ! 394: slnt--; ! 395: hold = 0; ! 396: } ! 397: if (!slnt) ! 398: wrc(1, c, nc==1); ! 399: *p++ = c; ! 400: if (c!='\n' && p < &b[599]) ! 401: continue; ! 402: q = p; ! 403: p = b; ! 404: hold = 0; ! 405: if (strncmp(b, "~:!",3)==0||strncmp(b, "~!", 2)==0) { ! 406: *--q= '\0'; ! 407: if (*--q == '\r') ! 408: *q= '\0'; ! 409: mode(0); ! 410: if ((pid=fork())==0) { ! 411: p = b+2; ! 412: if (*p=='!') ! 413: p++; ! 414: execl("/bin/sh", "sh", "-c", p, (char *)0); ! 415: exit(0); ! 416: } ! 417: while (wait((int *)0)!=pid) ! 418: ; ! 419: mode(1); ! 420: continue; ! 421: } ! 422: if (b[0]!='~' || b[1]!='>') { ! 423: if (*(q-2) == '\r') { ! 424: q--; ! 425: *(q-1)=(*q); ! 426: } ! 427: if (ds>=0) ! 428: write(ds, b, q-b); ! 429: continue; ! 430: } ! 431: if (ds>=0) ! 432: close(ds); ! 433: if (slnt) { ! 434: write(1, b, q - b); ! 435: write(1, CRLF, sizeof(CRLF)); ! 436: } ! 437: if (*(q-2) == '\r') ! 438: q--; ! 439: *(q-1) = 0; ! 440: slnt = 0; ! 441: q = b+2; ! 442: if (*q == '>') ! 443: q++; ! 444: if (*q == ':') { ! 445: slnt = 1; ! 446: q++; ! 447: } ! 448: if (*q == 0) { ! 449: ds = -1; ! 450: continue; ! 451: } ! 452: if (b[2]!='>' || (ds = open(q,1))<0) ! 453: ds = creat(q, 0644); ! 454: lseek(ds, (long)0, 2); ! 455: if (ds<0) ! 456: prf("Can't divert %s",b+1); ! 457: } ! 458: } ! 459: ! 460: mode(f) ! 461: { ! 462: struct sgttyb stbuf; ! 463: static struct tchars nochars = { -1, -1, -1, -1, -1, -1}; ! 464: ! 465: ioctl(0, TIOCGETP, &stbuf); ! 466: tkill = stbuf.sg_kill; ! 467: terase = stbuf.sg_erase; ! 468: if (f == 0) { ! 469: ioctl(0, TIOCSETP, &realtty); ! 470: ioctl(0, TIOCSETC, &realtch); ! 471: return; ! 472: } ! 473: if (f == 1) { ! 474: stbuf.sg_flags |= CBREAK; ! 475: stbuf.sg_flags &= ~CRMOD; ! 476: if (!hduplx) ! 477: stbuf.sg_flags &= ~ECHO; ! 478: ioctl(0, TIOCSETP, &stbuf); ! 479: ioctl(0, TIOCSETC, &nochars); ! 480: return; ! 481: } ! 482: if (f == 2) { ! 483: stbuf.sg_flags &= ~(ECHO|CRMOD); ! 484: ioctl(0, TIOCSETP, &stbuf); ! 485: ioctl(0, TIOCSETC, &realtch); ! 486: return; ! 487: } ! 488: } ! 489: ! 490: echo(s) ! 491: char *s; ! 492: { ! 493: register n = strlen(s); ! 494: ! 495: if (n>0) ! 496: write(1, s, n); ! 497: write(1, CRLF, sizeof(CRLF)); ! 498: } ! 499: ! 500: /* VARARGS1 */ ! 501: prf(f, s) ! 502: char *f; ! 503: char *s; ! 504: { ! 505: printf(f, s); ! 506: printf(CRLF); ! 507: } ! 508: ! 509: sendbreak() ! 510: { ! 511: struct sgttyb b; ! 512: int olds; ! 513: ! 514: #ifdef TIOCSBRK ! 515: ioctl(ln, TIOCSBRK, 0); ! 516: #else TIOCSBRK ! 517: ioctl(ln, TIOCGETP, &b); ! 518: olds = b.sg_ispeed; ! 519: b.sg_ispeed = B50; ! 520: b.sg_ospeed = B50; ! 521: ioctl(ln, TIOCSETP, &b); ! 522: write(ln, "\0\0\0", 3); ! 523: b.sg_ispeed = olds; ! 524: b.sg_ospeed = olds; ! 525: ioctl(ln, TIOCSETP, &b); ! 526: #endif TIOCSBRK ! 527: } ! 528: ! 529: /* ! 530: * Symbolic phone numbers ! 531: */ ! 532: gettelno(np, dp) ! 533: char *np; ! 534: register struct dial *dp; ! 535: { ! 536: char cunumber[128]; ! 537: char *hp; ! 538: register char *xnp; ! 539: char *getenv(); ! 540: ! 541: if (cunfile) { ! 542: if (look(np, dp, cunfile)) ! 543: return; ! 544: } else { ! 545: hp = getenv("HOME"); ! 546: if (hp) { ! 547: strcpy(cunumber, hp); ! 548: strcat(cunumber, "/lib/cunumber"); ! 549: if (look(np, dp, cunumber)) ! 550: return; ! 551: } ! 552: if (look(np, dp, "/usr/lib/cunumber")) ! 553: return; ! 554: } ! 555: xnp = np; ! 556: if (*np != '/') ! 557: while (*xnp) { ! 558: if (*xnp!=';' && *xnp!=':' && *xnp!='-' && *xnp!='*' ! 559: && *xnp!='#' && !isdigit(*xnp)) { ! 560: prf("Symbolic number not found"); ! 561: exit(1); ! 562: } ! 563: xnp++; ! 564: } ! 565: dp->telno = np; ! 566: } ! 567: ! 568: look(np, dp, fnp) ! 569: register char *np; ! 570: register struct dial *dp; ! 571: char *fnp; ! 572: { ! 573: FILE *fp; ! 574: static char line[128]; ! 575: register char *lp; ! 576: register i; ! 577: char *opts[8]; ! 578: register char **optp; ! 579: char *w[4]; ! 580: ! 581: if ((fp = fopen(fnp, "r")) == NULL) ! 582: return(0); ! 583: while (fgets(line, sizeof(line), fp)) { ! 584: lp = line; ! 585: optp = opts; ! 586: for (i = 0; i<4; i++) { ! 587: while (isspace(*lp)) ! 588: lp++; ! 589: if (i==1 && *lp=='-') { ! 590: *optp++ = lp; ! 591: i--; ! 592: } else ! 593: w[i] = lp; ! 594: while ((!isspace(*lp) || i==3) && *lp) ! 595: lp++; ! 596: if (*lp) ! 597: *lp++ = '\0'; ! 598: } ! 599: if (strcmp(w[0], np)) ! 600: continue; ! 601: i = optind; ! 602: optind = 0; ! 603: options(optp-opts, opts); ! 604: optind = i; ! 605: dp->telno = w[1]; ! 606: dp->dialtype = w[2]; ! 607: dp->comment = w[3]; ! 608: fclose(fp); ! 609: return(1); ! 610: } ! 611: fclose(fp); ! 612: return(0); ! 613: } ! 614: ! 615: options(ac, av) ! 616: char **av; ! 617: { ! 618: register o; ! 619: ! 620: opterr = 0; ! 621: while ((o = getopt(ac, av, "hntf:")) != EOF) { ! 622: switch(o) { ! 623: ! 624: case '?': ! 625: errflg++; ! 626: continue; ! 627: ! 628: case 'h': ! 629: hduplx++; ! 630: continue; ! 631: ! 632: case 'f': ! 633: cunfile = optarg; ! 634: continue; ! 635: ! 636: case 't': ! 637: tandm++; ! 638: continue; ! 639: ! 640: case 'n': ! 641: nflag++; ! 642: continue; ! 643: } ! 644: } ! 645: } ! 646: ! 647: wrc(f, c, flush) ! 648: register c; ! 649: { ! 650: static char buf[64]; ! 651: static char *bp = buf; ! 652: register r; ! 653: ! 654: c &= 0177; ! 655: if (f==ln) ! 656: c |= (partab[c] & 0200); ! 657: *bp++ = c; ! 658: r = 1; ! 659: if (flush || bp >= &buf[64]) { ! 660: r = write(f, buf, bp-buf); ! 661: bp = buf; ! 662: } ! 663: return(r); ! 664: } ! 665: ! 666: rdc(ds) ! 667: { ! 668: static char buf[64]; ! 669: static nc = 0; ! 670: static char *bp; ! 671: ! 672: if (nc <= 0) { ! 673: nc = read(ds, buf, 64); ! 674: bp = buf; ! 675: } ! 676: if (nc <= 0) ! 677: return(nc); ! 678: nc--; ! 679: c = *bp++ & 0177; ! 680: return(nc+1); ! 681: } ! 682: ! 683: sig2() ! 684: { ! 685: signal(SIGINT, SIG_IGN); ! 686: intr = 1; ! 687: } ! 688:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.