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