|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.