Annotation of 43BSDTahoe/new/X/hacks/misc/vrogue.c, revision 1.1.1.1

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, "", 3);
                    219: }
                    220: 
                    221: special_font() {
                    222:     write (1, "", 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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.