|
|
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.