Annotation of 43BSDTahoe/new/X/hacks/misc/vrogue.c, revision 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.