|
|
1.1 root 1: #include <signal.h>
2: #include <stdio.h>
3: #include <sgtty.h>
4: #include <sys/wait.h>
5: #include <sys/time.h>
6: #define BUFLEN 1024
7:
8: int got_a_signal;
9:
10: main(argc,argv)
11: int argc;
12: char *argv[];
13: {
14: extern int tstp_handler (), quit_handler (), chld_handler (),
15: int_handler ();
16: extern int got_a_signal;
17: struct ltchars new_ltc, old_ltc;
18: struct sigvec vec;
19: int topipe[2], frompipe[2];
20: int pipeflag, nfds, from_rogue, to_rogue, readfds;
21: int num, rogue_pid, old_mask;
22:
23: /* Since this IS a game, reduce our priority. */
24: setpriority(0, getpid(), 4);
25:
26: /* Create the pipes that will connect us to rogue. */
27: if (pipe (topipe) != 0) {
28: printf ("Couldn't open pipe to rogue\n");
29: exit (1);
30: }
31: if (pipe (frompipe) != 0) {
32: printf ("Couldn't open pipe to rogue\n");
33: exit (1);
34: }
35:
36: if (rogue_pid = vfork ()) {
37: /* Close the ends of the pipes that we don't need, and make better
38: names for the ones we do. */
39: close (topipe[0]);
40: close (frompipe[1]);
41: from_rogue = frompipe[0];
42: to_rogue = topipe[1];
43:
44: /* Get the old interrupt chars and save them. */
45: if (ioctl (0, TIOCGLTC, &old_ltc))
46: printf("Couldn't get old_ltc.\n");
47:
48: /* Copy the old interrupt chars and make the rest of them
49: correspond to what rogue uses. */
50: new_ltc = old_ltc;
51: new_ltc.t_dsuspc = -1;
52: if (ioctl (0, TIOCSLTC, &new_ltc))
53: printf("Couldn't remove ^Y.\n");
54:
55: /* Install our interrupt handlers */
56: vec.sv_mask = 0;
57: vec.sv_onstack = 0;
58: vec.sv_handler = tstp_handler;
59: if (sigvec (SIGTSTP, &vec, 0))
60: printf("Couldn't install TSTP handler.\n");
61: vec.sv_handler = quit_handler;
62: if (sigvec (SIGQUIT, &vec, 0))
63: printf("Couldn't install QUIT handler.\n");
64: vec.sv_handler = int_handler;
65: if (sigvec (SIGINT, &vec, 0))
66: printf("Couldn't install INT handler.\n");
67: vec.sv_handler = chld_handler;
68: if (sigvec (SIGCHLD, &vec, 0))
69: printf("Couldn't install CHLD handler.\n");
70:
71: pipeflag = 1 << from_rogue;
72: nfds = from_rogue + 1;
73: while (1) {
74: readfds = pipeflag | 1;
75: num = select (nfds, &readfds, 0, 0, 0);
76: if (num > 0)
77: if (readfds & pipeflag) process_output(from_rogue);
78: else process_input(to_rogue);
79:
80: if (got_a_signal) {
81: handle_signal(got_a_signal, rogue_pid, from_rogue, &old_ltc);
82: got_a_signal = 0;
83: }
84: }
85: }
86: else {
87: /* We are the child process, so attach our ends of the pipe to stdin
88: and stdout. */
89: if ((dup2 (topipe[0], 0)) == -1) {
90: printf ("couldn't dup2 stdin pipe\n\n");
91: exit (1);
92: }
93: if ((dup2 (frompipe[1], 1)) == -1) {
94: printf ("couldn't dup2 stdout pipe\n\n");
95: exit (1);
96: }
97:
98: /* Close the ends of the pipe we don't need. */
99: close (topipe[1]);
100: close (frompipe[0]);
101:
102: /* Do it. */
103: execv ("/usr/games/rogue", argv);
104: printf ("Couldn't execv rogue!\n");
105: exit (1);
106: }
107: }
108:
109: handle_signal(the_signal, rogue_pid, from_rogue, old_ltc)
110: int the_signal, rogue_pid, from_rogue;
111: struct ltchars *old_ltc;
112: {
113: switch (the_signal) {
114: case SIGQUIT:
115: if (kill(rogue_pid, SIGQUIT)) {
116: normal_font();
117: printf("Couldn't QUIT rogue!\n");
118: exit(1);
119: }
120: break;
121: case SIGTSTP:
122: if (kill(rogue_pid, SIGTSTP)) {
123: normal_font();
124: printf("Couldn't TSTP rogue!\n");
125: exit(1);
126: }
127: break;
128: case SIGINT:
129: if (kill(rogue_pid, SIGINT)) {
130: normal_font();
131: printf("Couldn't INT rogue!\n");
132: exit(1);
133: }
134: break;
135: case SIGCHLD:
136: {
137: union wait status;
138: int nfds, pipeflag;
139: int num, readfds;
140: struct timeval timeout;
141:
142: /* For some reason, our child has stopped. There is no need
143: (I think) to send it any more characters, so just finish
144: processing its output, and decide how we should stop. */
145:
146:
147: nfds = from_rogue + 1;
148: pipeflag = 1 << from_rogue;
149: timeout.tv_sec = 0;
150: timeout.tv_usec = 100000;
151: do {
152: readfds = pipeflag;
153: num = select (nfds, &readfds, 0, 0, &timeout);
154: if (num > 0)
155: num = process_output(from_rogue);
156: }
157: while(num > 0);
158:
159: normal_font();
160:
161: if (wait3(&status, WNOHANG | WUNTRACED, 0) > 0) {
162: if (WIFSTOPPED(status)) {
163: if (kill(getpid(), SIGSTOP)) {
164: printf("Couldn't STOP myself!\n");
165: exit(1);
166: }
167: if (kill(rogue_pid, SIGCONT)) {
168: printf("Couldn't CONT rogue!\n");
169: exit(1);
170: }
171: }
172: else if (WIFEXITED(status)) {
173: ioctl(0,TIOCSLTC,old_ltc);
174: exit(status.w_retcode);
175: }
176: else if (WIFSIGNALED(status)) {
177: ioctl(0,TIOCSLTC,old_ltc);
178: printf("Rogue terminated.\n");
179: printf("termsig: %d\n",status.w_termsig);
180: printf("coredump: %d\n",status.w_coredump);
181: printf("retcode: %d\n",status.w_retcode);
182: exit(-1);
183: }
184: else {
185: ioctl(0,TIOCSLTC,old_ltc);
186: printf("Rogue's status is bizzare!\n");
187: exit(1);
188: }
189: }
190: }
191: break;
192: default:
193: break;
194: }
195: }
196:
197: quit_handler() {
198: extern int got_a_signal;
199: got_a_signal = SIGQUIT;
200: }
201:
202: tstp_handler() {
203: extern int got_a_signal;
204: got_a_signal = SIGTSTP;
205: }
206:
207: int_handler() {
208: extern int got_a_signal;
209: got_a_signal = SIGINT;
210: }
211:
212: chld_handler() {
213: extern int got_a_signal;
214: got_a_signal = SIGCHLD;
215: }
216:
217: normal_font() {
218: write(1, "[m", 3);
219: }
220:
221: special_font() {
222: write (1, "[4m", 4);
223: }
224:
225: int process_input(to_rogue)
226: int to_rogue;
227: {
228: static char buf[BUFLEN];
229: register int num, old_mask;
230:
231: old_mask = sigblock(1 << (SIGCHLD - 1));
232: num = read (0, buf, BUFLEN);
233: if (num <= 0) {
234: printf("Error reading keyboard!\n");
235: exit(1);
236: }
237: write (to_rogue, buf, num);
238: sigsetmask(old_mask);
239: return(num);
240: }
241:
242: int process_output(from_rogue)
243: int from_rogue;
244: {
245: static char buf[BUFLEN];
246: static int state = 0;
247: static int linenum = 1;
248: static int special = 0;
249: static int force = 0;
250: static int accum = 0;
251: int chr, i, start, num, something_changed, old_mask;
252:
253: old_mask = sigblock(1 << (SIGCHLD - 1));
254: num = read (from_rogue, buf, BUFLEN);
255:
256: if (num <= 0) {
257: sigsetmask(old_mask);
258: return(num);
259: }
260:
261: start = 0;
262: for (i = 0; i < num; i++) {
263: chr = buf[i];
264: switch (state) {
265: case 0:
266: /* State 0 is the normal idle state. */
267: switch (chr) {
268: case '':
269: state = 1;
270: break;
271: case '\n':
272: linenum++;
273: something_changed = 1;
274: break;
275: case 'a':
276: case 'b':
277: case 'c':
278: case 'd': /* e is left out on purpose */
279: case 'f':
280: case 'g':
281: case 'h':
282: case 'i':
283: case 'j':
284: case 'k':
285: case 'l':
286: case 'm':
287: case 'n':
288: case 'o':
289: case 'p':
290: case 'q':
291: case 'r':
292: case 's':
293: case 't':
294: case 'u':
295: case 'v':
296: case 'w':
297: case 'x':
298: case 'y':
299: case 'z':
300: if ((linenum > 1) && (linenum < 24) && (!force)) {
301: force = 1;
302: something_changed = 1;
303: }
304: break;
305: case 'e':
306: if (force) {
307: state = 5;
308: }
309: if ((linenum > 1) && (linenum < 24) && (!force)) {
310: state = 5;
311: force = 1;
312: something_changed = 1;
313: }
314: break;
315: default:
316: break;
317: }
318: break;
319: case 1:
320: /* We've begun an escape sequence. */
321: switch (chr) {
322: case '[':
323: state = 2;
324: break;
325: default:
326: state = 0;
327: break;
328: }
329: break;
330: case 2:
331: /* We've seen "<esc>[" */
332: switch (chr) {
333: case '0':
334: case '1':
335: case '2':
336: case '3':
337: case '4':
338: case '5':
339: case '6':
340: case '7':
341: case '8':
342: case '9':
343: state = 3;
344: accum = chr - '0';
345: break;
346: case ';':
347: state = 4;
348: accum = 1;
349: break;
350: case 'A':
351: state = 0;
352: linenum--;
353: something_changed = 1;
354: break;
355: case 'H':
356: state = 0;
357: linenum = 1;
358: something_changed = 1;
359: break;
360: case 'm':
361: /* We've seen "<esc>[m"
362: Rogue is trying to get out of reverse video. */
363: state = 0;
364: break;
365: default:
366: state = 0;
367: break;
368: }
369: break;
370: case 3:
371: /* We've seen "<esc>[n"
372: Continue parsing the argument. */
373: switch (chr) {
374: case '0':
375: case '1':
376: case '2':
377: case '3':
378: case '4':
379: case '5':
380: case '6':
381: case '7':
382: case '8':
383: case '9':
384: accum = (10 * accum) + chr - '0';
385: break;
386: case ';':
387: state = 4;
388: break;
389: case 'm':
390: /* Rogue is trying to use reverse video or something. */
391: state = 0;
392: break;
393: default:
394: state = 0;
395: break;
396: }
397: break;
398: case 4:
399: /* We've seen "<esc>[nn;"
400: Ignore the rest of the digits until the magic H completes the
401: sequence. */
402: switch (chr) {
403: case 'H':
404: state = 0;
405: linenum = accum;
406: something_changed = 1;
407: break;
408: case '0':
409: case '1':
410: case '2':
411: case '3':
412: case '4':
413: case '5':
414: case '6':
415: case '7':
416: case '8':
417: case '9':
418: break;
419: default:
420: state = 0;
421: break;
422: }
423: break;
424: case 5:
425: /* We've seen an "e" on lines 2-23. This means that we're in
426: an inventory or something. We're hoping for "e--", the end of
427: "--more--" or "--Press space to continue--". */
428: switch (chr) {
429: case '-':
430: state = 6;
431: break;
432: case '':
433: state = 1;
434: break;
435: case '\n':
436: state = 0;
437: linenum++;
438: something_changed = 1;
439: break;
440: default:
441: break;
442: }
443: break;
444: case 6:
445: /* We've seen "e-". If we see another "-" we can stop forcing. */
446: switch (chr) {
447: case '-':
448: state = 0;
449: force = 0;
450: something_changed = 1;
451: break;
452: case '':
453: state = 1;
454: break;
455: case '\n':
456: state = 0;
457: linenum++;
458: something_changed = 1;
459: break;
460: default:
461: break;
462: }
463: break;
464: default:
465: break;
466: }
467: if (something_changed) {
468: something_changed = 0;
469: if (force) {
470: /* Since we're just starting for force, force before outputting
471: the character just looked at. */
472: if (special) {
473: write(1, buf + start, i - start);
474: normal_font();
475: start = i;
476: special = 0;
477: }
478: }
479: else if ((linenum == 1) || (linenum >= 24)) {
480: if (special) {
481: write (1, buf + start, i - start + 1);
482: normal_font();
483: start = i + 1;
484: special = 0;
485: }
486: }
487: else {
488: if (!special) {
489: write (1, buf + start, i - start + 1);
490: special_font();
491: start = i + 1;
492: special = 1;
493: }
494: }
495: }
496: }
497:
498: /* Output any characters remaining in the buffer. */
499: if (i != start)
500: write (1, buf + start, i - start);
501:
502: sigsetmask(old_mask);
503:
504: return(num);
505: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.