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