|
|
1.1 root 1: #include <ctype.h>
2: #include <pads.pri>
3: #include <CC/sys/types.h>
4: #include <CC/sys/stat.h>
5: #ifdef BSD
6: #include <sys/socket.h>
7: #endif BSD
8: SRCFILE("term.c")
9:
10: void Pick( char *s, Action a, long o )
11: {
12: Index ix;
13:
14: trace("Pick(%d,%d)", a, o);
15: ix = ICache->place(Item(s, a, o));
16: R->pktstart( P_PICK );
17: R->sendshort( ix.sht() );
18: R->pktend();
19: }
20:
21: char *JerqTERM[] = { "/usr/jerq/bin/32ld /usr/jerq/mbin/pads.m",
22: "5620", "jerq", "JERQ", "Jerq", "DMD", "DMD5620",
23: 0 };
24:
25: char *BlitTERM[] = { "/usr/blit/bin/68ld /usr/blit/mbin/pads.m",
26: "blit", "BLIT", "Blit",
27: 0 };
28:
29: char *XTERM[] = { "pads",
30: "xterm", "sun",
31: 0 };
32:
33: char **MapTERM[] = { JerqTERM, BlitTERM, XTERM, 0 };
34:
35: int pipe(int[2]), fork(), _exit(int);
36: #ifdef BSD
37: int socketpair(int,int,int,int[2]);
38: #endif BSD
39:
40: char *PadsInit(char *loadcmd)
41: {
42: trace( "PadsInit(%s)", loadcmd );
43: if( !loadcmd ){
44: char *getenv(char*), *TERM = getenv("TERM"), ***map, **term;
45: loadcmd = MapTERM[0][0];
46: for( map = MapTERM; TERM && *map; ++map )
47: for( term = *map, ++term; *term; ++term )
48: if( !strcmp(TERM, *term) )
49: loadcmd = **map;
50: }
51: if( loadcmd == XTERM[0] ){
52: int afildes[2], pid;
53: #ifdef BSD
54: if( socketpair(AF_UNIX, SOCK_STREAM, 0, afildes)==-1 )
55: #else
56: if( pipe(afildes)==-1 )
57: #endif BSD
58: return "can't open pipe\n";
59: if( (pid=fork())==0 ){
60: dup2(afildes[0], 0);
61: dup2(afildes[0], 1);
62: close(afildes[0]);
63: close(afildes[1]);
64: execlp(loadcmd, "pads", (char *)0);
65: _exit(1);
66: }
67: if(pid==-1)
68: return "terminal fork failed";
69: close(afildes[0]);
70: R = new Remote(afildes[1]);
71: }
72: else {
73: if ( system(loadcmd) ) return "terminal download failed";
74: R = new Remote("/dev/tty");
75: }
76: R->pktstart(P_VERSION); R->sendlong(PADS_VERSION); R->pktend();
77: R->pktstart(P_BUSY); R->pktend();
78: ICache = new ItemCache;
79: CCache = new CarteCache;
80: close(2);
81: return 0;
82: }
83:
84: char *PadsTermInit(char *machine)
85: {
86: char *loadcmd = XTERM[0];
87: int afildes[2], pid;
88: #ifdef BSD
89: if( socketpair(AF_UNIX, SOCK_STREAM, 0, afildes)==-1 )
90: #else
91: if( pipe(afildes)==-1 )
92: #endif BSD
93: return "can't open pipe\n";
94: if( (pid=fork())==0 ){
95: dup2(afildes[0], 0);
96: dup2(afildes[0], 1);
97: close(afildes[0]);
98: close(afildes[1]);
99: execlp(loadcmd, "pads", (char *)0);
100: _exit(1);
101: }
102: if(pid==-1)
103: return "terminal fork failed";
104: dup2(afildes[1], 0);
105: dup2(afildes[1], 1);
106: dup2(afildes[1], 2);
107: close(afildes[0]);
108: close(afildes[1]);
109: execlp("rsh", machine, "exec /usr/jerq/bin/pi -R", 0);
110: exit(127);
111: return 0;
112: }
113:
114: void PadsRemInit()
115: {
116: R = new Remote(0);
117: R->pktstart(P_VERSION); R->sendlong(PADS_VERSION); R->pktend();
118: R->pktstart(P_BUSY); R->pktend();
119: ICache = new ItemCache;
120: CCache = new CarteCache;
121: }
122:
123: char *TapTo;
124: void WireTap(PRINTF_ARGS)
125: {
126: static int fd = -1;
127: static long t0;
128: struct stat s;
129: char *ctime(long*);
130: long t, time(long*);
131:
132: if( !TapTo ) return;
133: t = time(0);
134: if( ::stat("/usr/jerq/lib/.logpads", &s) || ctime(&t)[23]!='6' )
135: goto BailOut;
136: if( t0 )
137: t -= t0;
138: else
139: t0 = t;
140: char buf[256];
141: sprintf(buf, "%x:", t);
142: sprintf(buf+strlen(buf), PRINTF_COPY);
143: if( fd < 0 ){
144: if( ::stat(TapTo, &s) )
145: creat(TapTo, 0777);
146: fd = open(TapTo, 1);
147: }
148: #define PILOGSIZE 32000
149: if( fd<0
150: || fstat(fd, &s)
151: || s.st_size > PILOGSIZE )
152: goto BailOut;
153: lseek(fd, s.st_size, 0);
154: write(fd, buf, strlen(buf));
155: return;
156: BailOut:
157: TapTo = 0;
158: }
159:
160: int BothValid(PadRcv *p, PadRcv *o)
161: {
162: return p && o;
163: }
164:
165: void TermAction(PadRcv *parent, PadRcv *obj, int pick)
166: {
167: Item *item;
168: Index ix(R->rcvshort());
169:
170: trace( "TermAction(%d,%d,%d)", parent, obj, pick );
171: if( ix.null() ) return;
172: item = ICache->take(ix);
173: if( !BothValid(parent,obj)
174: || (pick && !obj->accept(item->action)) )
175: return;
176: Action a = item->action;
177: long faddr, ixorf = (int) a; // yuk: can't say
178: if( ixorf & (~127) ) // &(obj->*item->action)
179: faddr = ixorf; //
180: else //
181: faddr = ((long**) obj)[1][ixorf-1]; //
182: WireTap("%x->%x(%x)\n", obj, faddr, item->opand);
183: if( item->action ) (obj->*item->action)(item->opand, 0, 0);
184: }
185:
186: char *DoKbd(PadRcv *obj, char *buf)
187: {
188: WireTap("%x->%x(%x) %s\n", obj, &obj->kbd, strlen(buf), buf);
189: char *e = obj->kbd(buf);
190: if( e ) PadsWarn("%s", e);
191: return e;
192: }
193:
194: void Shell()
195: {
196: char cmd[256];
197: R->rcvstring(cmd);
198: FILE *fp = Popen(cmd, "w");
199: for( long lines = R->rcvlong(); lines>0; --lines ){
200: char data[256];
201: if( fp ) fprintf(fp, "%s\n", R->rcvstring(data));
202: }
203: if( !fp ){
204: PadsWarn("cannot write to pipe");
205: return;
206: }
207: int x = Pclose(fp);
208: if( x ) PadsWarn( "exit(%d): %s", x, cmd );
209: }
210:
211: void ShKbd(PadRcv *obj, char *cmd)
212: {
213: trace( "ShKbd(%d,%s)", obj, buf );
214: FILE *fp = Popen(cmd, "r");
215: if( !fp ){
216: PadsWarn("cannot read from pipe");
217: return;
218: }
219: char buf[256];
220: while( fgets(buf, sizeof buf, fp) ){
221: buf[strlen(buf)-1] = 0;
222: if( DoKbd(obj, buf) ) break;
223: }
224: int x = Pclose(fp);
225: if( x ) PadsWarn( "exit(%d): %s", x, cmd );
226: }
227:
228: void Kbd(PadRcv *parent, PadRcv *obj)
229: {
230: char buf[256];
231: R->rcvstring(buf);
232: trace( "Kbd %d %s", obj, buf );
233: if( !BothValid(parent,obj) ) return;
234: if( !strcmp( buf, "?" ) ){
235: char *h = obj->help();
236: PadsWarn( "%s", (h && *h) ? h : "error: null help string" );
237: } else if( buf[0] == '<' ){
238: ShKbd(obj, buf+1);
239: } else
240: DoKbd(obj, buf);
241: }
242:
243: void TermServe()
244: {
245: Protocol p;
246: long n, to, pick = 0;
247:
248: trace("TermServe()");
249: R->writesize = 0;
250: R->pktstart(P_IDLE); R->pktend(); /* flush */
251: p = (Protocol) R->get();
252: if( p == P_PICK ) {
253: pick = 1;
254: p = (Protocol) R->get();
255: }
256: PadRcv *par = R->rcvobj();
257: PadRcv *obj = R->rcvobj();
258: if( p != P_CYCLE ) { R->writesize = 0; R->pktstart(P_BUSY); R->pktend(); }
259: switch( (int) p ){
260: case P_ACTION:
261: TermAction(par, obj, pick);
262: break;
263: case P_KBDSTR:
264: Kbd(par, obj);
265: break;
266: case P_SHELL:
267: Shell();
268: break;
269: case P_NUMERIC:
270: case P_CYCLE:
271: case P_USERCLOSE:
272: case P_USERCUT:
273: n = R->rcvshort();
274: if( !BothValid(par,obj) ) return;
275: switch( (int) p ){
276: case P_NUMERIC:
277: WireTap("%x->%x(%x)\n", obj, &obj->numeric, n);
278: obj->numeric(n); break;
279: case P_CYCLE:
280: obj->cycle(); break;
281: case P_USERCLOSE:
282: WireTap("%x->%x(0)\n", obj, &obj->userclose);
283: obj->userclose(); break;
284: case P_USERCUT :
285: WireTap("%x->%x(0)\n", obj, &obj->usercut);
286: obj->usercut(); break;
287: default: R->err();
288: }
289: break;
290: case P_LINEREQ:
291: n = R->rcvlong();
292: to = R->rcvlong();
293: trace("P_LINEREQ %d %d %d", p, n, to);
294: if( !BothValid(par,obj) ) return;
295: // WireTap("%x->%x(%x)", obj, &obj->linereq, to-n+1);
296: while( n <= to )
297: obj->linereq((long) n++, 0);
298: break;
299: default:
300: R->err();
301: }
302: }
303:
304: void PadsServe(long n)
305: {
306: if( n ){
307: while( n-->0 ) TermServe();
308: } else {
309: for( ;; ) TermServe();
310: }
311: }
312:
313: void PadsWarn(PRINTF_ARGS)
314: {
315: char t[256];
316: sprintf( t, PRINTF_COPY );
317: R->pktstart( P_HELPSTR );
318: R->sendstring( t );
319: R->pktend();
320: }
321:
322: void PadsError(PRINTF_ARGS)
323: {
324: char t[256];
325: sprintf(t, PRINTF_COPY);
326: int fd = open("/dev/tty", 1);
327: write(fd, " ", 2);
328: write(fd, t, strlen(t));
329: abort();
330: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.