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: char    c;
  30: 
  31: char    *connmsg[] = {
  32:     "",
  33:     "line busy",
  34:     "call dropped",
  35:     "no carrier",
  36:     "can't fork",
  37:     "acu access",
  38:     "tty access",
  39:     "tty hung",
  40:     "usage: cu telno [-t] [-s speed] [-l line] [-a acu]"
  41: };
  42: 
  43: rdc(ds) {
  44: 
  45:     ds=read(ds,&c,1);
  46:     c&= 0177;
  47:     return (ds);
  48: }
  49: 
  50: int intr;
  51: 
  52: sig2()
  53: {
  54:     signal(SIGINT, SIG_IGN);
  55:     intr = 1;
  56: }
  57: 
  58: int set14;
  59: 
  60: xsleep(n)
  61: {
  62:     xalarm(n);
  63:     pause();
  64:     xalarm(0);
  65: }
  66: 
  67: xalarm(n)
  68: {
  69:     set14=n;
  70:     alarm(n);
  71: }
  72: 
  73: sig14()
  74: {
  75:     signal(SIGALRM, sig14);
  76:     if (set14) alarm(1);
  77: }
  78: 
  79: int dout;
  80: int nhup;
  81: 
  82: /*
  83:  *	main: get connection, set speed for line.
  84:  *	spawn child to invoke rd to read from line, output to fd 1
  85:  *	main line invokes wr to read tty, write to line
  86:  */
  87: main(ac,av)
  88: char *av[];
  89: {
  90:     int fk;
  91:     int speed;
  92:     char *telno;
  93:     struct sgttyb stbuf;
  94: 
  95:     signal(SIGALRM, sig14);
  96:     if (ac < 2) {
  97:         prf(connmsg[8]);
  98:         exit(8);
  99:     }
 100:     telno = av[1];
 101:     av += 2;
 102:     ac -= 2;
 103:     for (; ac > 0; av++) {
 104:         if (equal(*av, "-t")) {
 105:             dout = 1;
 106:             --ac;
 107:             continue;
 108:         }
 109:         if (ac < 2)
 110:             break;
 111:         if (equal(*av, "-s"))
 112:             lspeed = *++av;
 113:         else if (equal(*av, "-l"))
 114:             devcul = *++av;
 115:         else if (equal(*av, "-a"))
 116:             devcua = *++av;
 117:         else
 118:             break;
 119:         ac -= 2;
 120:     }
 121:     if (!exists(devcua) || !exists(devcul))
 122:         exit(9);
 123:     ln = conn(devcul, devcua, telno);
 124:     if (ln < 0) {
 125:         prf("Connect failed: %s",connmsg[-ln]);
 126:         exit(-ln);
 127:     }
 128:     switch(atoi(lspeed)) {
 129:     case 110:
 130:         speed = B110;break;
 131:     case 150:
 132:         speed = B150;break;
 133:     default:
 134:     case 300:
 135:         speed = B300;break;
 136:     case 1200:
 137:         speed = B1200;break;
 138:     }
 139:     stbuf.sg_ispeed = speed;
 140:     stbuf.sg_ospeed = speed;
 141:     stbuf.sg_flags = EVENP|ODDP;
 142:     if (!dout)
 143:         stbuf.sg_flags |= RAW;
 144:     ioctl(TIOCSETP, ln, &stbuf);
 145:     ioctl(TIOCEXCL, ln, (struct sgttyb *)NULL);
 146:     ioctl(TIOCHPCL, ln, (struct sgttyb *)NULL);
 147:     prf("Connected");
 148:     if (dout)
 149:         fk = -1;
 150:     else
 151:         fk = fork();
 152:     nhup = (int)signal(SIGINT, SIG_IGN);
 153:     if (fk == 0) {
 154:         rd();
 155:         prf("\007Lost carrier");
 156:         exit(3);
 157:     }
 158:     mode(1);
 159:     wr();
 160:     mode(0);
 161:     kill(fk, SIGKILL);
 162:     wait((int *)NULL);
 163:     stbuf.sg_ispeed = 0;
 164:     stbuf.sg_ospeed = 0;
 165:     ioctl(TIOCSETP, ln, &stbuf);
 166:     prf("Disconnected");
 167:     exit(0);
 168: }
 169: 
 170: /*
 171:  *	conn: establish dial-out connection.
 172:  *	Example:  fd = conn("/dev/ttyh","/dev/dn1","4500");
 173:  *	Returns descriptor open to tty for reading and writing.
 174:  *	Negative values (-1...-7) denote errors in connmsg.
 175:  *	Uses alarm and fork/wait; requires sig14 handler.
 176:  *	Be sure to disconnect tty when done, via HUPCL or stty 0.
 177:  */
 178: 
 179: conn(dev,acu,telno)
 180: char *dev, *acu, *telno;
 181: {
 182:     struct sgttyb stbuf;
 183:     extern errno;
 184:     char *p, *q, b[30];
 185:     int er, fk, dn, dh, t;
 186:     er=0;
 187:     fk=(-1);
 188:     if ((dn=open(acu,1))<0) {
 189:         er=(errno == 6? 1:5);
 190:         goto X;
 191:     }
 192:     if ((fk=fork()) == (-1)) {
 193:         er=4;
 194:         goto X;
 195:     }
 196:     if (fk == 0) {
 197:         open(dev,2);
 198:         for (;;) pause();
 199:     }
 200:     xsleep(2);
 201:     /*
 202: 	 *	copy phone #, assure EON
 203: 	 */
 204:     p=b;
 205:     q=telno;
 206:     while (*p++=(*q++))
 207:         ;
 208:     p--;
 209:     if (*(p-1)!='<') {
 210:         if (*(p-1)!='-') *p++='-';
 211:         *p++='<';
 212:     }
 213:     t=p-b;
 214:     xalarm(5*t);
 215:     t=write(dn,b,t);
 216:     xalarm(0);
 217:     if (t<0) {
 218:         er=2;
 219:         goto X;
 220:     }
 221:     /* close(dn) */
 222:     xalarm(40);     /* was 5; sometimes missed carrier */
 223:     dh = open(dev,2);
 224:     xalarm(0);
 225:     if (dh<0) {
 226:         er=(errno == 4? 3:6);
 227:         goto X;
 228:     }
 229:     ioctl(TIOCGETP, ln, &stbuf);
 230:     stbuf.sg_flags &= ~ECHO;
 231:     xalarm(10);
 232:     ioctl(TIOCSETP, dh, &stbuf);
 233:     ioctl(TIOCHPCL, dh, (struct sgttyb *)NULL);
 234:     xalarm(0);
 235: X:
 236:     if (er) close(dn);
 237:     if (fk!=(-1)) {
 238:         kill(fk, SIGKILL);
 239:         xalarm(10);
 240:         while ((t=wait((int *)NULL))!=(-1) && t!=fk);
 241:         xalarm(0);
 242:     }
 243:     return (er? -er:dh);
 244: }
 245: 
 246: /*
 247:  *	wr: write to remote: 0 -> line.
 248:  *	~.	terminate
 249:  *	~<file	send file
 250:  *	~!	local login-style shell
 251:  *	~!cmd	execute cmd locally
 252:  *	~$proc	execute proc locally, send output to line
 253:  *	~%cmd	execute builtin cmd (put and take)
 254:  */
 255: 
 256: wr()
 257: {
 258:     int ds,fk,lcl,x;
 259:     char *p,b[600];
 260:     for (;;) {
 261:         p=b;
 262:         while (rdc(0) == 1) {
 263:             if (p == b) lcl=(c == '~');
 264:             if (p == b+1 && b[0] == '~') lcl=(c!='~');
 265:             if (c == 0) c=0177;
 266:             if (!lcl) {
 267:                 if (wrc(ln) == 0) {
 268:                     prf("line gone"); return;
 269:                 }
 270:             }
 271:             if (lcl) {
 272:                 if (c == 0177) c=tkill;
 273:                 if (c == '\r' || c == '\n') goto A;
 274:                 if (!dout) wrc(0);
 275:             }
 276:             *p++=c;
 277:             if (c == terase) {
 278:                 p=p-2;
 279:                 if (p<b) p=b;
 280:             }
 281:             if (c == tkill || c == 0177 || c == '\r' || c == '\n') p=b;
 282:         }
 283:         return;
 284: A:
 285:         if (!dout) echo("");
 286:         *p=0;
 287:         switch (b[1]) {
 288:         case '.':
 289:         case '\004':
 290:             return;
 291:         case '!':
 292:         case '$':
 293:             fk = fork();
 294:             if (fk == 0) {
 295:                 close(1);
 296:                 dup(b[1] == '$'? ln:2);
 297:                 close(ln);
 298:                 mode(0);
 299:                 if (!nhup) signal(SIGINT, SIG_DFL);
 300:                 if (b[2] == 0) execl("/bin/sh","-",0);
 301:                 else execl("/bin/sh","sh","-c",b+2,0);
 302:                 prf("Can't execute shell");
 303:                 exit(~0);
 304:             }
 305:             if (fk!=(-1)) {
 306:                 while (wait(&x)!=fk);
 307:             }
 308:             mode(1);
 309:             if (b[1] == '!') echo("!");
 310:             else {
 311:                 if (dout) echo("$");
 312:             }
 313:             break;
 314:         case '<':
 315:             if (b[2] == 0) break;
 316:             if ((ds=open(b+2,0))<0) {
 317:                 prf("Can't divert %s",b+1);
 318:                 break;
 319:             }
 320:             intr=x=0;
 321:             mode(2);
 322:             if (!nhup) signal(SIGINT, sig2);
 323:             while (!intr && rdc(ds) == 1) {
 324:                 if (wrc(ln) == 0) {
 325:                     x=1;
 326:                     break;
 327:                 }
 328:             }
 329:             signal(SIGINT, SIG_IGN);
 330:             close(ds);
 331:             mode(1);
 332:             if (x) return;
 333:             if (dout) echo("<");
 334:             break;
 335:         case '%':
 336:             dopercen(&b[2]);
 337:             break;
 338:         default:
 339:             prf("Use `~~' to start line with `~'");
 340:         }
 341:         continue;
 342:     }
 343: }
 344: 
 345: dopercen(line)
 346: register char *line;
 347: {
 348:     char *args[10];
 349:     register narg, f;
 350:     int rcount;
 351:     for (narg = 0; narg < 10;) {
 352:         while(*line == ' ' || *line == '\t')
 353:             line++;
 354:         if (*line == '\0')
 355:             break;
 356:         args[narg++] = line;
 357:         while(*line != '\0' && *line != ' ' && *line != '\t')
 358:             line++;
 359:         if (*line == '\0')
 360:             break;
 361:         *line++ = '\0';
 362:     }
 363:     if (equal(args[0], "take")) {
 364:         if (narg < 2) {
 365:             prf("usage: ~%%take from [to]");
 366:             return;
 367:         }
 368:         if (narg < 3)
 369:             args[2] = args[1];
 370:         wrln("echo '~>:'");
 371:         wrln(args[2]);
 372:         wrln(";tee /dev/null <");
 373:         wrln(args[1]);
 374:         wrln(";echo '~>'\n");
 375:         return;
 376:     } else if (equal(args[0], "put")) {
 377:         if (narg < 2) {
 378:             prf("usage: ~%%put from [to]");
 379:             return;
 380:         }
 381:         if (narg < 3)
 382:             args[2] = args[1];
 383:         if ((f = open(args[1], 0)) < 0) {
 384:             prf("cannot open: %s", args[1]);
 385:             return;
 386:         }
 387:         wrln("stty -echo;cat >");
 388:         wrln(args[2]);
 389:         wrln(";stty echo\n");
 390:         xsleep(5);
 391:         intr = 0;
 392:         if (!nhup)
 393:             signal(SIGINT, sig2);
 394:         mode(2);
 395:         rcount = 0;
 396:         while(!intr && rdc(f) == 1) {
 397:             rcount++;
 398:             if (c == tkill || c == terase)
 399:                 wrln("\\");
 400:             if (wrc(ln) != 1) {
 401:                 xsleep(2);
 402:                 if (wrc(ln) != 1) {
 403:                     prf("character missed");
 404:                     intr = 1;
 405:                     break;
 406:                 }
 407:             }
 408:         }
 409:         signal(SIGINT, SIG_IGN);
 410:         close(f);
 411:         if (intr) {
 412:             wrln("\n");
 413:             prf("stopped after %d bytes", rcount);
 414:         }
 415:         wrln("\004");
 416:         xsleep(5);
 417:         mode(1);
 418:         return;
 419:     }
 420:     prf("~%%%s unknown\n", args[0]);
 421: }
 422: 
 423: equal(s1, s2)
 424: register char *s1, *s2;
 425: {
 426:     while (*s1++ == *s2)
 427:         if (*s2++ == '\0')
 428:             return(1);
 429:     return(0);
 430: }
 431: 
 432: wrln(s)
 433: register char *s;
 434: {
 435:     while (*s)
 436:         write(ln, s++, 1);
 437: }
 438: 
 439: /*
 440:  *	rd: read from remote: line -> 1
 441:  *	catch:
 442:  *	~>[>][:][file]
 443:  *	stuff from file...
 444:  *	~>	(ends diversion)
 445:  */
 446: 
 447: rd()
 448: {
 449:     int ds,slnt;
 450:     char *p,*q,b[600];
 451:     p=b;
 452:     ds=(-1);
 453:     while (rdc(ln) == 1) {
 454:         if (ds<0) slnt=0;
 455:         if (!slnt) wrc(1);
 456:         *p++=c;
 457:         if (c!='\n') continue;
 458:         q=p;
 459:         p=b;
 460:         if (b[0]!='~' || b[1]!='>') {
 461:             if (*(q-2) == '\r') {
 462:                 q--;
 463:                 *(q-1)=(*q);
 464:             }
 465:             if (ds>=0) write(ds,b,q-b);
 466:             continue;
 467:         }
 468:         if (ds>=0) close(ds);
 469:         if (slnt) {
 470:             write(1, b, q - b);
 471:             write(1, CRLF, sizeof(CRLF));
 472:         }
 473:         if (*(q-2) == '\r') q--;
 474:         *(q-1)=0;
 475:         slnt=0;
 476:         q=b+2;
 477:         if (*q == '>') q++;
 478:         if (*q == ':') {
 479:             slnt=1;
 480:             q++;
 481:         }
 482:         if (*q == 0) {
 483:             ds=(-1);
 484:             continue;
 485:         }
 486:         if (b[2]!='>' || (ds=open(q,1))<0) ds=creat(q,0644);
 487:         lseek(ds, (long)0, 2);
 488:         if (ds<0) prf("Can't divert %s",b+1);
 489:     }
 490: }
 491: 
 492: struct {char lobyte; char hibyte;};
 493: mode(f)
 494: {
 495:     struct sgttyb stbuf;
 496:     if (dout) return;
 497:     ioctl(TIOCGETP, 0, &stbuf);
 498:     tkill = stbuf.sg_kill;
 499:     terase = stbuf.sg_erase;
 500:     if (f == 0) {
 501:         stbuf.sg_flags &= ~RAW;
 502:         stbuf.sg_flags |= ECHO|CRMOD;
 503:     }
 504:     if (f == 1) {
 505:         stbuf.sg_flags |= RAW;
 506:         stbuf.sg_flags &= ECHO|CRMOD;
 507:     }
 508:     if (f == 2) {
 509:         stbuf.sg_flags &= ~RAW;
 510:         stbuf.sg_flags &= ~(ECHO|CRMOD);
 511:     }
 512:     ioctl(TIOCSETP, 0, &stbuf);
 513: }
 514: 
 515: echo(s)
 516: char *s;
 517: {
 518:     char *p;
 519:     for (p=s;*p;p++);
 520:     if (p>s) write(0,s,p-s);
 521:     write(0,CRLF, sizeof(CRLF));
 522: }
 523: 
 524: prf(f, s)
 525: char *f;
 526: char *s;
 527: {
 528:     fprintf(stderr, f, s);
 529:     fprintf(stderr, CRLF);
 530: }
 531: 
 532: exists(devname)
 533: char *devname;
 534: {
 535:     if (access(devname, 0)==0)
 536:         return(1);
 537:     prf("%s does not exist", devname);
 538:     return(0);
 539: }

Defined functions

conn defined in line 179; used 1 times
dopercen defined in line 345; used 1 times
echo defined in line 515; used 4 times
equal defined in line 423; used 6 times
exists defined in line 532; used 2 times
  • in line 121(2)
main defined in line 87; never used
mode defined in line 493; used 8 times
prf defined in line 524; used 17 times
rd defined in line 447; used 1 times
rdc defined in line 43; used 4 times
sig14 defined in line 73; used 2 times
sig2 defined in line 52; used 2 times
wr defined in line 256; used 1 times
wrln defined in line 432; used 11 times
xalarm defined in line 67; used 10 times
xsleep defined in line 60; used 4 times

Defined variables

c defined in line 29; used 21 times
connmsg defined in line 31; used 2 times
devcua defined in line 24; used 3 times
devcul defined in line 23; used 3 times
dout defined in line 79; used 8 times
intr defined in line 50; used 7 times
ln defined in line 27; used 17 times
lspeed defined in line 25; used 2 times
nhup defined in line 80; used 4 times
set14 defined in line 58; used 2 times
terase defined in line 28; used 3 times
tkill defined in line 28; used 4 times

Defined macros

CRLF defined in line 19; used 5 times
wrc defined in line 20; used 6 times
Last modified: 1979-01-10
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1488
Valid CSS Valid XHTML 1.0 Strict