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