home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume7 / bpatch / bpatch.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-11-30  |  35.1 KB  |  1,750 lines

  1. /*T bpatch - A binary file patch/dump utility */
  2. /*S Introduction */
  3. /*F bpatch ***********************************************************
  4. * bpatch
  5. * by Garry M Johnson - 09/17/84
  6. * (C) Copyright 1984, 1985
  7. *
  8. * Change History:
  9. *  03/05/86 - added further terminal independence
  10. *             added use of ioctl (see main and mstdin)
  11. *             added -D versus -d command line option
  12. *             added use of standard getopt
  13. *             cleaned up code, eliminated function "ikf"
  14. *             added original versions of ezlib functions, such as
  15. *               icc, setterm, cm, mstdin, erase, length, move
  16. *             added ^R, ^Q, ^N, and ^P commands
  17. *             added ^F, !, and ^X (-X) commands
  18. *              changed name to "bpatch"
  19. *              added direct address command (g)
  20. *             added ASCII search capability
  21. *  07/07/86 - converted to use curses
  22. *             modified direct addressing to use suffixes
  23. *             updated HELP function
  24. *
  25. *   Steven List @ Benetics Corporation, Mt. View, CA
  26. *   {cdp,engfocus,idi,oliveb,plx,tolerant}!bene!luke!itkin
  27. *********************************************************************/
  28. /*E*/
  29. /*S includes, globals, and defines */
  30. /*Page Eject*/
  31. #include    <curses.h>
  32. #include <fcntl.h>
  33. #include <signal.h>
  34. #include <ctype.h>
  35. #include <sys/types.h>
  36. #include <sys/stat.h>
  37.  
  38. static int pbrk = 0;
  39. struct stat sb;
  40.  
  41. void icc ();
  42. void copyrec ();
  43. void schwapp ();
  44.  
  45.     /* ------------------------------------------------------------ */
  46.     /* Some defines added by the moderator to get it work on 4.2    */
  47.     /* ------------------------------------------------------------ */
  48. #ifdef    MOD_HAX
  49.     /* Fifos?  We ain't got no steenkin' fifos. */
  50. #define S_IFIFO        123450
  51.     /* "Spelling differences." */
  52. #define beep()        fprintf (stderr, "\007")
  53. #define cbreak()    crmode()
  54.     /* Our curses doesn't translate keypad keys to single characters. */
  55. #define keypad(a, b)    /* null */
  56. #define KEY_UP        '^'
  57. #define KEY_DOWN    'v'
  58. #define KEY_LEFT    '<'
  59. #define KEY_RIGHT    '>'
  60. #define KEY_HOME    '@'
  61. #endif    /* MOD_HAX */
  62.  
  63.  
  64.     /* ------------------------------------------------------------ */
  65.     /* Some convenient defines                                      */
  66.     /* ------------------------------------------------------------ */
  67.  
  68. #define DEL '\177'
  69. #define HEX 1
  70. #define ALPHA 0
  71.  
  72.     /* ------------------------------------------------------------ */
  73.     /* general purpose identification and control variables         */
  74.     /* ------------------------------------------------------------ */
  75.  
  76. char    filename[64];            /* current file being examined        */
  77. char    record[16][16];            /* record (page) buffer                */
  78. char    unch_rec[16][16];        /* record before any changes        */
  79. int     zp;                        /* current input character            */
  80.  
  81. int        block = 0;                /* block size if -b in command        */
  82. int        block_spec;                /* true if file is block special    */
  83. int        bytes = 0;                /* number of bytes from last read    */
  84. int        char_spec;                /* true if file is char special        */
  85. int        debug = 0;                /* true if debug is turned on        */
  86. int        dir_spec;                /* true if file is directory        */
  87. int        dump = 0;                /* nonzero if dump instead of change*/
  88. int        ebcdic = 0;                /* true if -e option                */
  89. int        fifo_spec;                /* true if file is fifo                */
  90. int        honly = 0;                /* true if dump is to be hex only    */
  91. int        mod = 0;                /* true if record has been modified    */
  92. int        pause = 0;                /* true if -p option                */
  93. int        rawfile = 0;            /* true if file is c/b/p            */
  94. int        reclen = 0;                /* record length, if -r                */
  95. int        recno = 0;                /* current record (page) number        */
  96. int        stay = 0;                /* true if no position change         */
  97. int        swab = 0;                /* true if byte swapping is on        */
  98. int        windowed = 0;            /* true if windowing - not dump        */
  99.  
  100. long    position = 0;            /* byte address in file                */
  101.  
  102. WINDOW *hexwin = NULL;
  103. WINDOW *alphawin = NULL;
  104. WINDOW *errwin = NULL;
  105.  
  106. /*S main - control all the work from here */
  107. /*H main *************************************************************
  108. *
  109. *                            main
  110. *
  111. *    set up the globals, initilize the state, and process the file
  112. *
  113. *********************************************************************/
  114. /*E*/
  115. main (argc, argv)
  116. int argc;
  117. char *argv[];
  118. {
  119.     extern WINDOW *subwin ();
  120.     extern WINDOW *newwin ();
  121.  
  122. #ifdef    MOD_HAX
  123. #else    /* use original code... */
  124.     struct termio asis;
  125. #endif    /* MOD_HAX */
  126.  
  127.     register char    *cp;                /* general purpose char ptr    */
  128.     extern   char    *gets ();            /* get string from stdin    */
  129.              char    m = '\017';            /* mask for hex edit        */
  130.              char    response[512];        /* general purpose buffer    */
  131.              int     z;                    /* character read in        */
  132.          
  133.     int        breakp ();            /* signal trapping function            */
  134.     int        c;                    /* current screen column            */
  135.     int        change = 0;            /* true if cmd line option toggled    */
  136.     int        fid;                /* file descriptor                    */
  137.     int        firstfile;            /* arg # of first file in cmd line    */
  138.     int        h;                    /* temp for hex edit                */
  139.     int        i;                    /* general purpose loop index        */
  140.     int        j;                    /* general purpose loop index        */
  141.     int        r;                    /* current screen row                */
  142.     int        hexc;                /* current cursor column in hexwin    */
  143.  
  144.     long    byteaddr;            /* planned byte address for 'G'        */
  145.     long    size;                /* file size in bytes                */
  146.     long    status;                /* EOF if at end of file or error    */
  147.  
  148.     extern int optind;            /* getopt index into argv            */
  149.     extern char *optarg;        /* getopt pointer to opt arg        */
  150.  
  151.     extern long getnum ();
  152.     extern char *instr ();        /* get a string from the cmd line    */
  153.     extern int reset ();        /* exit function - reset terminal    */
  154.  
  155.     /* ------------------------------------------------------------ */
  156.     /* set up signal handling                                       */
  157.     /* ------------------------------------------------------------ */
  158.  
  159.     if (!dump) signal (SIGINT, breakp);
  160.  
  161.     signal (SIGTERM, reset);
  162.  
  163.     /* ------------------------------------------------------------ */
  164.     /* process command line arguments                               */
  165.     /* ------------------------------------------------------------ */
  166.  
  167.     while ((i = getopt (argc, argv, "r:dD:b:pxXse")) != EOF)
  168.     {
  169.         switch (i)
  170.         {
  171.             case    'b':        /* blocking                    */
  172.                 block = atoi (optarg);
  173.                 if (block < 1 || block > 10240)
  174.                 {
  175.                     fprintf (stderr,
  176.                         "invalid block size: %d\n", block);
  177.                     exit (1);
  178.                 }
  179.                 break;
  180.             case    'd':        /* straight dump - no limit    */
  181.                 dump = -1;
  182.                 break;
  183.             case    'D':        /* dump - page count spec    */
  184.                 dump = atoi (optarg);
  185.                 break;
  186.             case    'e':        /* file is ebcdic            */
  187.                 ebcdic = 1;
  188.                 break;
  189.             case    'p':        /* pause between pages - dump    */
  190.                 pause = 1;
  191.                 break;
  192.             case    'r':        /* record length for dump        */
  193.                 reclen = atoi (optarg);
  194.                 break;
  195.             case    's':        /* byte swapping required        */
  196.                 swab = 1;
  197.                 break;
  198.             case    'x':        /* hex dump only                */
  199.                 honly = 1;
  200.                 break;
  201.             case    'X':
  202.                 debug = 1;
  203.                 break;
  204.             default:            /* uhoh                            */
  205.                 fprintf (stderr,
  206. "usage: bpatch [ -b blocksz ] [ -d<ump> ] [ -D pagecnt ] [ -e<bcdic> ]\n");
  207.                 fprintf (stderr,
  208. "              [ -p<ause> ] [ -r reclen ] [ -s<wap bytes> ] [ -x<only> ]\n");
  209.                 exit (1);
  210.         }
  211.     }
  212.  
  213.     /* ------------------------------------------------------------ */
  214.     /* check for valid combinations of options                      */
  215.     /* ------------------------------------------------------------ */
  216.  
  217.     if ((honly || block || reclen || pause ) && !dump)
  218.     {
  219.         fprintf (stderr, "-x|-b|-r|-p requires -d or -D\n");
  220.         exit (2);
  221.     }
  222.  
  223.     /* ------------------------------------------------------------ */
  224.     /* At least one file name must be specified on the cmd line     */
  225.     /* ------------------------------------------------------------ */
  226.  
  227.     if (optind == argc)
  228.     {
  229.         fprintf (stderr, "no file name(s) specified\n");
  230.         exit (2);
  231.     }
  232.  
  233.     /* ------------------------------------------------------------ */
  234.     /* set up the screen, if this is an interactive session         */
  235.     /* ------------------------------------------------------------ */
  236.  
  237.     if (!dump)
  238.     {
  239.         windowed = 1;
  240.         initscr ();
  241.         nonl ();
  242.         noecho ();
  243.         cbreak ();
  244.         keypad (stdscr, TRUE);
  245.         hexwin = subwin (stdscr, 16, 48, 4, 4);
  246.         keypad (hexwin, TRUE);
  247.         alphawin = subwin (stdscr, 16, 16, 4, 57);
  248.         keypad (alphawin, TRUE);
  249.         errwin = subwin (stdscr, 1, 80, 23, 0);
  250.  
  251. #ifdef    MOD_HAX
  252.         /* This is not exactly what the original code does,
  253.            but it's good enough.  -r$ */
  254.         raw();
  255. #else    /* use original code... */
  256.         ioctl (0, TCGETA, &asis);
  257.         asis.c_cc[VINTR] = '\0';
  258.         asis.c_iflag &= ~IXON;
  259.         asis.c_iflag &= ~IXOFF;
  260.         asis.c_iflag &= ~IXANY;
  261.         ioctl (0, TCSETA, &asis);
  262. #endif    /* MOD_HAX */
  263.     }
  264.  
  265.     /* ------------------------------------------------------------ */
  266.     /* save the first file's index for backing up later             */
  267.     /* ------------------------------------------------------------ */
  268.  
  269.     firstfile = optind;
  270.  
  271.     /* ------------------------------------------------------------ */
  272.     /* open the first file                                          */
  273.     /* ------------------------------------------------------------ */
  274.  
  275.     for (fid = -1; fid < 0 && optind < argc;)
  276.     {
  277.         fid = ckfile (argv[optind], &size);
  278.         if (fid < 0) optind++;
  279.     }
  280.     if (fid < 0)
  281.     {
  282.         fprintf (stderr, "could not handle the file list\n");
  283.         exit (2);
  284.     }
  285.  
  286.     strncpy (filename, argv[optind], sizeof filename);
  287.  
  288.     if (block != 0)
  289.     {
  290.         size = -1;
  291.     }
  292.  
  293.     recno = 0;
  294.     stay = 0;
  295.     mod = 0;
  296.     status = 0;
  297.  
  298.     /* ------------------------------------------------------------ */
  299.     /* Until the user exits...                                      */
  300.     /* ------------------------------------------------------------ */
  301.  
  302.     if (!dump) clear ();
  303.  
  304.     while (status != EOF)
  305.     {
  306.     /* ------------------------------------------------------------ */
  307.     /* change of location - read and display                        */
  308.     /* ------------------------------------------------------------ */
  309.         if (stay == 0)
  310.         {
  311.             position = lseek (fid, (long)(recno * 256), 0);
  312.  
  313.             if ((bytes = bread (fid, record, 256, block)) < 0)
  314.             {
  315.                 errmsg ("error on reading file %s", filename);
  316.                 status = EOF;
  317.                 continue;
  318.             }
  319.             if (bytes > 0)
  320.             {
  321.                 if (swab) schwapp (record, 256);
  322.  
  323.                 copyrec (record, unch_rec, sizeof record);
  324.  
  325.                 show (bytes, record, filename, size, recno,
  326.                         position, m,reclen, dump, ebcdic, swab,
  327.                         block, honly);
  328.             }
  329.             mod = 0;
  330.         }
  331.     /* ------------------------------------------------------------ */
  332.     /* not interactive - keep dumping or open next file             */
  333.     /* ------------------------------------------------------------ */
  334.         if (dump)
  335.         {
  336.             if ((dump < 0 && bytes == 0) || (--dump == 0))
  337.             {
  338.                 if (optind == argc) status = EOF;
  339.                 else
  340.                 {
  341.                     close (fid);
  342.                     fid = -1;
  343.                     for (optind++; fid < 0 && optind < argc;)
  344.                     {
  345.                         fid = ckfile (argv[optind], &size);
  346.                         if (fid < 0) optind++;
  347.                     }
  348.  
  349.                     strncpy (filename, argv[optind], sizeof filename);
  350.  
  351.                     if (block != 0)
  352.                     {
  353.                         size = -1;
  354.                     }
  355.                     recno = 0;
  356.                     stay = 0;
  357.                     status = lseek (fid, (long)0, 0);
  358.                 }
  359.             }
  360.             ++recno;
  361.     /* ------------------------------------------------------------ */
  362.     /* if pause, beep and wait                                      */
  363.     /* ------------------------------------------------------------ */
  364.             if (status != EOF && pause)
  365.             {
  366.                 pbrk = 0;
  367.                 fprintf (stderr, "\007");
  368.                 gets (response);
  369.  
  370.                 if (pbrk) status = EOF;
  371.             }
  372.  
  373.             continue;
  374.         }
  375.     /* ------------------------------------------------------------ */
  376.     /* if we got here, this is an interactive session               */
  377.     /* ------------------------------------------------------------ */
  378.         stay = 0;
  379.         move (22, 0);
  380.     /* ------------------------------------------------------------ */
  381.     /* get the user's command                                       */
  382.     /* ------------------------------------------------------------ */
  383.         response[0] = EOF;
  384.         mvaddstr (22, 0, "> ");
  385.         clrtoeol ();
  386.         refresh ();
  387.         zp = getch ();
  388.  
  389.         if (debug && !dump)
  390.         {
  391.             if (isascii (zp) && isprint (zp))
  392.                 errmsg ("command entered is %c", zp);
  393.             else errmsg ("command entered is ^%c (%#x)", zp + '@', zp);
  394.             getch ();
  395.         }
  396.  
  397.         if (isascii (zp) && isalpha (zp) && islower (zp))
  398.             zp = toupper (zp);
  399.     /* ------------------------------------------------------------ */
  400.     /* here we go - what does the user want?                        */
  401.     /* ------------------------------------------------------------ */
  402.         refresh ();
  403.  
  404.         switch (zp)
  405.         { 
  406.             case    '!':            /* shell escape                */
  407.                 echo ();
  408.                 move (23,0);
  409.                 clrtoeol ();
  410.                 addstr ("shell command: ");
  411.                 refresh ();
  412.                 getstr (response);
  413.                 erase ();
  414.                 refresh ();
  415.                 nl ();
  416.                 system (response);
  417.                 noecho ();
  418.                 nonl ();
  419.                 move (23,0);
  420.                 standout ();
  421.                 addstr (" <Press any key> ");
  422.                 standend ();
  423.                 clrtoeol ();
  424.                 refresh ();
  425.                 getch ();
  426.                 clear ();
  427.                 break;
  428.  
  429.             case    '?':            /* HELP                        */
  430.                 dbg_msg ("Help");
  431.                 dohelp ();
  432.                 touchwin (stdscr);
  433.                 refresh ();
  434.                 stay = 1;
  435.                 break;
  436.  
  437.             case    '/':            /* search for a string        */
  438.                 stay = 1;
  439.                 if (mod)
  440.                 {
  441.                     errmsg ("No write since last change");
  442.                 }
  443.                 else search (fid, zp);
  444.                 break;
  445.  
  446.             case '-':                /* toggle options            */
  447.                 zp = getch ();
  448.                 stay = 1;
  449.                 change = 0;
  450.                 switch (zp)
  451.                 {
  452.                     case 'a': /* ascii */
  453.                         if (ebcdic)
  454.                         {
  455.                             dbg_msg ("toggle to ascii");
  456.                             change = 1;
  457.                         }
  458.                         ebcdic = 0;
  459.                         break;
  460.  
  461.                     case 'e': /* ebcdic */
  462.                         if (ebcdic == 0)
  463.                         {
  464.                             dbg_msg ("toggle to ebcdic");
  465.                             change = 1;
  466.                         }
  467.                         ebcdic = 1;
  468.                         break;
  469.  
  470.                     case 's': /* swab */
  471.                         dbg_msg ("toggle byte swap");
  472.                         change = 1;
  473.                         schwapp (record, 256);
  474.                         swab = !swab;
  475.                         break;
  476.                 }
  477.                 if (change)
  478.                 {
  479.                     show (bytes, record, filename, size,
  480.                             recno, position, m,reclen, dump,
  481.                             ebcdic, swab, block, honly);
  482.                 }
  483.  
  484.                 break;
  485.  
  486.             case '\022':            /* redraw screen (^R)        */
  487.                 clear ();
  488.                 show (bytes, record, filename, size, recno,
  489.                       position, m, reclen, dump, ebcdic,
  490.                       swab, block, honly);
  491.                 stay = 1;
  492.                 break;
  493.             
  494.             case    '\030':            /* toggle debug (^X)        */
  495.                 debug = !debug;
  496.                 break;
  497.  
  498.             case    '\006':            /* new file (^F)            */
  499.                 close (fid);
  500.                 fid = ckfile (cp = instr (), &size);
  501.                 if (fid < 0)
  502.                 {
  503.                     fid = ckfile (filename, &size);
  504.                 }
  505.                 else
  506.                 {
  507.                     strncpy (filename, cp, sizeof filename);
  508.                     stay = 0;
  509.                     recno = 0;
  510.                 }
  511.                 break;
  512.  
  513.             case    '\016':            /* next file (^N)            */
  514.                 if (mod)
  515.                 {
  516.                     errmsg ("No write since last change");
  517.                     stay = 1;
  518.                 }
  519.                 else if (optind == (argc - 1))
  520.                 {
  521.                     errmsg ("No more files");
  522.                     stay = 1;
  523.                 }
  524.                 else
  525.                 {
  526.                     close (fid);
  527.                     for (fid = -1, optind++; fid < 0 && optind < argc;)
  528.                     {
  529.                         fid = ckfile (argv[optind], &size);
  530.                         if (fid < 0) optind++;
  531.                     }
  532.                     if (fid < 0)
  533.                     {
  534.                         errmsg ("could not handle the file list");
  535.                         reset (0);
  536.                     }
  537.                     strncpy (filename, argv[optind], sizeof filename);
  538.                     stay = 0;
  539.                     recno = 0;
  540.                 }
  541.                 break;
  542.  
  543.             case    '\020':            /* prev file (^P)            */
  544.                 if (mod)
  545.                 {
  546.                     errmsg ("No write since last change");
  547.                     stay = 1;
  548.                 }
  549.                 else if (optind == firstfile)
  550.                 {
  551.                     errmsg ("No previous file");
  552.                     stay = 1;
  553.                 }
  554.                 else
  555.                 {
  556.                     close (fid);
  557.                     for (fid = -1, optind--; fid < 0 && optind >= firstfile;)
  558.                     {
  559.                         fid = ckfile (argv[optind], &size);
  560.                         if (fid < 0) optind--;
  561.                     }
  562.                     if (fid < 0)
  563.                     {
  564.                         errmsg ("could not handle the file list");
  565.                         reset (0);
  566.                     }
  567.                     strncpy (filename, argv[optind], sizeof filename);
  568.                     stay = 0;
  569.                     recno = 0;
  570.                 }
  571.                 break;
  572.  
  573.             case    '\021':        /* quit absolutely (^Q)        */
  574.                 status = EOF;
  575.                 break;
  576.  
  577.             case DEL:            /* quit with check            */
  578.             case 'Q': /* quit */
  579.                 if (mod)
  580.                 {
  581.                     errmsg ("No write since last change!");
  582.                     stay = 1;
  583.                 }
  584.                 else
  585.                 {
  586.                     status = EOF;
  587.                 }
  588.                 break;
  589.  
  590.             case '\\': /* back up 1 record */
  591.                 if (mod)
  592.                 {
  593.                     errmsg ("No write since last change");
  594.                     stay = 1;
  595.                 }
  596.                 else
  597.                 {
  598.                     if (recno > 0)
  599.                     {
  600.                         --recno;
  601.                         stay = 0;
  602.  
  603.                         status = lseek (fid, (long)recno*256, 0);
  604.                         if (status < 0)
  605.                         {
  606.                             move (22, 0);
  607.                             clrtoeol ();
  608.                             perror (filename);
  609.                             errmsg ("error positioning in file");
  610.                             beep ();
  611.                             ++recno;
  612.                             stay = 1;
  613.                         }
  614.                     }
  615.                     else
  616.                     {
  617.                         errmsg ("No previous records");
  618.                         beep ();
  619.                         stay = 1;
  620.                     }
  621.                 }
  622.                 break; 
  623.  
  624.             case 'F': /* go to first record */
  625.                 if (mod)
  626.                 {
  627.                     errmsg ("No write since last change");
  628.                     stay = 1;
  629.                 }
  630.                 else
  631.                 {
  632.                     status = lseek (fid, (long)0, 0);
  633.                     recno = 0;
  634.                 }
  635.                 break;
  636.  
  637.             case 'L': /* go to last record */
  638.                 if (mod)
  639.                 {
  640.                     errmsg ("No write since last change");
  641.                     stay = 1;
  642.                 }
  643.                 else
  644.                 {
  645.                     position = lseek (fid, (long)0, 2);
  646.                     recno = position / 256;
  647.                     j = position % 256;
  648.                     if (j == 0) --recno;
  649.                     status = lseek (fid, (long)(recno*256), 0);
  650.                 }
  651.                 break;
  652.  
  653.             case 'U':            /* undo changes                    */
  654.                 stay = 1;
  655.                 mod = 0;
  656.                 copyrec (unch_rec, record, sizeof record);
  657.                 show (bytes, record, filename, size, recno,
  658.                         position, m,reclen, dump, ebcdic, swab,
  659.                         block, honly);
  660.                 break;
  661.  
  662.             case 'R': /* re-read record */
  663.                 status = lseek (fid, (long)recno*256, 0);
  664.                 break;
  665.  
  666.             case '0': /* go to some address */
  667.             case '1':
  668.             case '2':
  669.             case '3':
  670.             case '4':
  671.             case '5':
  672.             case '6':
  673.             case '7':
  674.             case '8':
  675.             case '9':
  676.                 if (mod)
  677.                 {
  678.                     errmsg ("No write since last change");
  679.                     stay = 1;
  680.                 }
  681.                 else
  682.                 {
  683.                     byteaddr = getnum (zp, FALSE);
  684.                     stay = 1;
  685.                     errmsg ("Position to byte %ld", byteaddr);
  686.                     if (!rawfile && byteaddr > size)
  687.                     {
  688.                         errmsg ("Address outside file");
  689.                         beep ();
  690.                     }
  691.                     else if (byteaddr / 256 != recno)
  692.                     {
  693.                         recno = byteaddr / 256;
  694.                         status = lseek (fid, (long)recno * 256, 0);
  695.                         stay = 0;
  696.                     }
  697.                 }
  698.                 break;
  699.  
  700.             case 'A': /* alpha modify */
  701.                 stay = 1;
  702.                 r = c = 0;
  703.                 dbg_msg ("edit ascii");
  704.                 if (bytes == 0) break;
  705.                 touchwin (stdscr);
  706.                 refresh ();
  707.                 wmove (alphawin, r, c);
  708.                 wrefresh (alphawin);
  709.  
  710.                 while ((z = wgetch (alphawin)) != DEL)
  711.                 {
  712.                     if (!arrow (z, &r, &c))
  713.                     {
  714.                         if (isascii (z))
  715.                         {
  716.                             if (isprint (z)) waddch (alphawin, z);
  717.                             else             waddch (alphawin, '.');
  718.  
  719.                             if (ebcdic) icc (&z, 1,"AE");
  720.  
  721.                             record[r][c] = z;
  722.                             mod = 1;
  723.  
  724.                             hexc = c * 3;
  725.                             wmove (hexwin, r, hexc);
  726.                             if (record[r][c] < '\0')
  727.                             {
  728.                                 wprintw (hexwin, "%x%x",
  729.                                     (record[r][c] >> 4) & m,
  730.                                     record[r][c] & m);
  731.                             }
  732.                             else
  733.                             {
  734.                                 wprintw (hexwin, "%02x", record[r][c]);
  735.                             }
  736.                             wrefresh (hexwin);
  737.  
  738.                         }
  739.                         else
  740.                         {
  741.                             beep ();
  742.                         }
  743.  
  744.                         if (c == 15)
  745.                         {
  746.                             if (r == 15) beep ();
  747.                             else
  748.                             {
  749.                                 c = 0;
  750.                                 ++r;
  751.                             }
  752.                         }
  753.                         else
  754.                         {
  755.                             c++;
  756.                         }
  757.                     }
  758.                     if (r * 16 + c >= bytes)
  759.                     {
  760.                         beep ();
  761.                         r = (bytes - 1) / 16;
  762.                         c = (bytes - 1) % 16;
  763.                     }
  764.  
  765.                     wmove (alphawin, r, c);
  766.                     wrefresh (alphawin);
  767.                 }
  768.  
  769.                 break;
  770.  
  771.             case 'H': /* hex modify */
  772.                 dbg_msg ("edit hex");
  773.                 stay = 1;
  774.                 r = c = hexc = 0;
  775.                 if (bytes == 0) break;
  776.                 touchwin (stdscr);
  777.                 refresh ();
  778.                 wmove (hexwin, r, hexc);
  779.                 wrefresh (hexwin);
  780.  
  781.                 while ((z = wgetch (hexwin)) != DEL)
  782.                 {
  783.                     if (!arrow (z, &r, &c))
  784.                     {
  785.                         hexc = c * 3;
  786.                         z = toupper (z);
  787.                         if (!isxdigit (z))
  788.                         {
  789.                             beep ();
  790.                         }
  791.                         else
  792.                         {
  793.                             waddch (hexwin, tolower (z));
  794.                             wrefresh (hexwin);
  795.  
  796.                             if (z > '9') z -= 7;
  797.  
  798.                             h = (z & m) << 4;
  799.  
  800.                             while (2)
  801.                             {
  802.                                 z = EOF;
  803.                                 z = getch ();
  804.                                 if (z == EOF)
  805.                                 {
  806.                                     pbrk = 0;
  807.                                     h = -1;
  808.                                     break;
  809.                                 }
  810.                                 z = toupper (z);
  811.                                 if (!isxdigit (z))
  812.                                 {
  813.                                     beep ();
  814.                                 }
  815.                                 else
  816.                                 {
  817.                                     waddch (hexwin, tolower (z));
  818.                                     wrefresh (hexwin);
  819.                                     if (z > '9') z -= 7;
  820.  
  821.                                     h |= z & m;
  822.                                     break;
  823.                                 }
  824.                             }
  825.  
  826.                             if (h < 0)
  827.                             {
  828.                                 wmove (hexwin, r, hexc);
  829.                                 if (record[r][c] < '\0')
  830.                                 {
  831.                                     wprintw (hexwin, "%x%x",
  832.                                         (record[r][c] >> 4) & m,
  833.                                         record[r][c] & m);
  834.                                 }
  835.                                 else
  836.                                 {
  837.                                     wprintw (hexwin, "%02x", record[r][c]);
  838.                                 }
  839.                                 wrefresh (hexwin);
  840.                                 break;
  841.                             }
  842.  
  843.                             record[r][c] = z = h;
  844.                             mod = 1;
  845.  
  846.                             if (ebcdic) icc (&z, 1,"EA");
  847.  
  848.                             wmove (alphawin, r, c);
  849.                             if (isascii (z) && isprint (z))
  850.                                 waddch (alphawin, z);
  851.                             else waddch (alphawin, '.');
  852.                             wrefresh (alphawin);
  853.  
  854.                             if (c == 15)
  855.                             {
  856.                                 if (r == 15) beep ();
  857.                                 else
  858.                                 {
  859.                                     c = 0;
  860.                                     ++r;
  861.                                 }
  862.                             }
  863.                             else
  864.                             {
  865.                                 c++;
  866.                             }
  867.                         }
  868.                     }
  869.  
  870.                     if (r * 16 + c >= bytes)
  871.                     {
  872.                         beep ();
  873.                         r = (bytes - 1) / 16;
  874.                         c = (bytes - 1) % 16;
  875.                     }
  876.  
  877.                     hexc = c * 3;
  878.                     wmove (hexwin, r, hexc);
  879.                     wrefresh (hexwin);
  880.                 }
  881.                 break;
  882.  
  883.             case 'W': /* write record */
  884.                 stay = 1;
  885.                 status = lseek (fid, position, 0);
  886.                 if (status != position)
  887.                 {
  888.                     move (22, 0);
  889.                     clrtoeol ();
  890.                     perror (filename);
  891.                     errmsg ("error positioning in file");
  892.                     beep ();
  893.                 }
  894.                 if (swab) schwapp (record, 256);
  895.                 if (write (fid, record, bytes) != bytes)
  896.                 {
  897.                     errmsg ("error writing to file");
  898.                     sleep (1);
  899.                     reset (0);
  900.                     exit (0);
  901.                 }
  902.                 if (swab) schwapp (record, 256);
  903.                 mod = 0;
  904.                 errmsg ("Record written");
  905.                 break;
  906.  
  907.             case    '\n':        /* newline - next page            */
  908.             case    '\r':
  909.                 if (mod)
  910.                 {
  911.                     errmsg ("No write since last change");
  912.                     stay = 1;
  913.                 }
  914.                 else
  915.                 {
  916.                     ++recno;
  917.                     if (!rawfile && (recno * 256) >= size)
  918.                     {
  919.                         recno--;
  920.                         beep ();
  921.                         errmsg ("No more records in file");
  922.                         stay = 1;
  923.                     }
  924.                     else stay = 0;
  925.                 }
  926.                 break;
  927.  
  928.             default:
  929.                 if (isascii (zp) && isprint (zp))
  930.                     errmsg ("Unknown command: %d", zp);
  931.                 else
  932.                     errmsg ("Unknown command: %d", zp + '@');
  933.                 beep ();
  934.                 stay = 1;
  935.                 break;
  936.         } /* end switch zp */
  937.         refresh ();
  938.     }
  939.  
  940.     if (windowed)
  941.     {
  942.         reset (0);
  943.     }
  944.     status = close (fid);
  945.  
  946.     exit (status);
  947. }
  948. /*S show - display a record on the terminal */
  949. /*H show */
  950. /*E*/
  951. show (bytes, record, filename, size, recno, position,
  952.       m,reclen, dump, ebcdic, swab, block, honly)
  953. int bytes;
  954. int size;
  955. int recno;
  956. int position;
  957. int m;
  958. int reclen;
  959. int dump;
  960. int ebcdic;
  961. int swab;
  962. int honly;
  963. char record[16][16];
  964. char *filename;
  965. {
  966.     int        i;
  967.     int        j;
  968.     char    s;
  969.     char    temp[16];
  970.     char    *look = NULL;
  971.  
  972.     int        row = 0;
  973.     int        col = 0;
  974.  
  975.     if (dump) printf ("\n\n");
  976.  
  977.     if (debug)
  978.     {
  979.         getyx (stdscr, row, col);
  980.         move (23,0);
  981.         printw ("show: %d|%d|%s|%d|%d|%d|%#x|%d|%d|%d|%d|%d|%d",
  982.             bytes, record, filename, size, recno, position,
  983.             m, reclen, dump, ebcdic, swab, block, honly);
  984.         move (row, col);
  985.         row = col = 0;
  986.     }
  987.  
  988.     if (!dump) move (0, 0);
  989.     outstr ("FILE: %s ", filename);
  990.     if (block_spec) outstr ("(block special)");
  991.     else if (char_spec) outstr ("(character special)");
  992.     else if (fifo_spec) outstr ("(fifo (named pipe))");
  993.     else if (dir_spec) outstr ("(directory - %ld)", size);
  994.     else outstr ("(%ld)", size);
  995.  
  996.     if (ebcdic) outstr (" - EBCDIC");
  997.     else outstr (" - ASCII");
  998.     if (swab) outstr (" - SWAP");
  999.     if (block) outstr (" - BLOCK (%d)", block);
  1000.     if (reclen) outstr (" - RECORD (%d)", reclen);
  1001.  
  1002.     if (!dump)
  1003.     {
  1004.         clrtoeol ();
  1005.         move (1,0);
  1006.         printw ("PAGE: %d (%d)", recno, position);
  1007.         clrtoeol ();
  1008.         row = 2;
  1009.     }
  1010.     else
  1011.     {
  1012.         printf ("\nPAGE: %d (%d)\n", recno, position);
  1013.     }
  1014.  
  1015.     if (honly)
  1016.     {
  1017.         look = (char *) record;
  1018.         for (j=0;j<256;++j)
  1019.         {
  1020.             if (*look++ != '\0')
  1021.             {
  1022.                 look = NULL;
  1023.                 break;
  1024.             }
  1025.         }
  1026.     }
  1027.  
  1028.     if (!dump) move (row, col);
  1029.  
  1030.     outstr ("    x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf");
  1031.     outstr ("      0123456789abcdef");
  1032.  
  1033.     if (!dump)
  1034.     {
  1035.         row += 2;
  1036.         move (row, col);
  1037.     }
  1038.     else
  1039.     {
  1040.         printf ("\n\n");
  1041.     }
  1042.     for (i=0; i<=bytes/16; ++i)
  1043.     {
  1044.         if (honly && look != NULL)
  1045.         {
  1046.             i = 16;
  1047.             continue;
  1048.         }
  1049.         if (i*16+1 > bytes) continue;
  1050.  
  1051.         outstr ("%02x: ", i);
  1052.  
  1053.         for (j=0; j<16; ++j)
  1054.         {
  1055.             if (i*16+j < bytes)
  1056.             {
  1057.                 if (record[i][j] < '\0')
  1058.                     outstr ("%x%x ",
  1059.                         (record[i][j] >> 4) & m, record[i][j] & m);
  1060.                 else
  1061.                     outstr ("%02x ", record[i][j]);
  1062.  
  1063.                 s = ' ';
  1064.                 if (reclen > 0 && (position+i*16+j+1)%reclen == 0)
  1065.                     s = ':';
  1066.                 if (block > 0 && (position+i*16+j+1)%block == 0)
  1067.                 {
  1068.                     if (s == ' ')
  1069.                         s = '/';
  1070.                     else
  1071.                         s = '%';
  1072.                 }
  1073.                 if (s != ' ')
  1074.                     outstr ("\b%c", s);
  1075.             }
  1076.             else
  1077.             {
  1078.                 outstr ("   ");
  1079.             }
  1080.         }
  1081.  
  1082.         outstr ("     ");
  1083.  
  1084.         copyrec (record[i], temp, 16);
  1085.  
  1086.         if (ebcdic) icc (temp, 16, "EA");
  1087.  
  1088.         for (j = 0; j < 16 && i*16+j < bytes; ++j)
  1089.         {
  1090.             if (temp[j] < ' ') outch ('.');
  1091.             else outstr ("%c", temp[j]);
  1092.         }
  1093.  
  1094.         if (!dump)
  1095.         {
  1096.             move (++row, col);
  1097.         }
  1098.         else
  1099.         {
  1100.             printf ("\n");
  1101.         }
  1102.     }
  1103.  
  1104.     if (!dump)
  1105.     {
  1106.         clrtobot ();
  1107.         refresh ();
  1108.     }
  1109.  
  1110.     return;
  1111. }
  1112. /*S breakp - set pbrk on interrupt */
  1113. /*H breakp */
  1114. /*E*/
  1115. int breakp (i)
  1116. int i;
  1117. {
  1118.     int s;
  1119.     extern int pbrk;
  1120.     s = (int) signal (SIGINT, breakp);
  1121.     pbrk = i;
  1122. }
  1123. /*S bread - buffered read */
  1124. /*H bread */
  1125. /*E*/
  1126. int bread (fid, record, want, block)
  1127. int fid, want, block;
  1128. char *record;
  1129. {
  1130.     int i, j, k;
  1131.     int what, bytes, orig;
  1132.     static char buffer[10240];
  1133.     static int left, arrow;
  1134.     static int flag = 1;
  1135.  
  1136.     if (flag)
  1137.     {
  1138.         left = 0;
  1139.         arrow = 0;
  1140.         flag = 0;
  1141.     }
  1142.  
  1143.     if (block == 0)
  1144.         return (read (fid, record, want));
  1145.  
  1146.     if (block & 1) ++block;
  1147.  
  1148.     orig = what = want;
  1149.     while (1)
  1150.     {
  1151.         if (left < want)
  1152.         {
  1153.             if (left)
  1154.             {
  1155.                 copyrec (&buffer[arrow], record, left);
  1156.                 record += left;
  1157.                 want -= left;
  1158.             }
  1159.  
  1160.             arrow = 0;
  1161.             left = 0;
  1162.  
  1163.             if ((bytes = read (fid, buffer, block)) < 0)
  1164.             {
  1165.                 what = bytes;
  1166.                 break;
  1167.             }
  1168.  
  1169.             if (bytes == 0)
  1170.             {
  1171.                 what = orig - want;
  1172.                 break;
  1173.             }
  1174.  
  1175.             left = bytes;
  1176.         }
  1177.         else
  1178.         {
  1179.             copyrec (&buffer[arrow], record, want);
  1180.             arrow += want;
  1181.             left -= want;
  1182.             break;
  1183.         }
  1184.     }
  1185.  
  1186.     return (what);
  1187. }
  1188. /*S schwapp - swap bytes in place */
  1189. /*H schwapp */
  1190. /*E*/
  1191. void
  1192. schwapp (ptr, nch)
  1193. register char *ptr;
  1194. register int nch;
  1195. {
  1196.     register int i;
  1197.     register char c;
  1198.     register char *ptra = ptr + 1;
  1199.  
  1200.     if (nch & 1) --nch;
  1201.  
  1202.     for (i = 0; i < nch; i += 2, ptr += 2, ptra += 2)
  1203.     {
  1204.         c = *ptr;
  1205.         *ptr = *ptra;
  1206.         *ptra = c;
  1207.     }
  1208.     return;
  1209. }
  1210. /*S copyrec - transfer bytes from f to t for nbytes bytes */
  1211. /*H copyrec */
  1212. /*E*/
  1213. void
  1214. copyrec (f, t, nbytes)
  1215. register char *f;
  1216. register char *t;
  1217. register int nbytes;
  1218. {
  1219.     register int i;
  1220.  
  1221.     for (i = 0; i < nbytes; i++, f++, t++) *t = *f;
  1222.  
  1223.     return;
  1224. }
  1225. /*S ebcdic codes corresponding to ascii - translation table */
  1226. /*Page Eject*/
  1227. char ebcdic_codes[] = {
  1228. 0, 0x1, 0x2, 0x3, 0x37, 0x2d, 0x2e, 0x2f, 0x16,
  1229. 0x5, 0x25, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11,
  1230. 0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26, 0x18, 0x19, 0x3f,
  1231. 0x27, 0x1c, 0x1d, 0x1e, 0x1f, 0x40, 0x5a, 0x7f, 0x7b,
  1232. 0x5b, 0x6c, 0x50, 0x7d, 0x4d, 0x5d, 0x5c, 0x4e, 0x6b,
  1233. 0x60, 0x4b, 0x61, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5,
  1234. 0xf6, 0xf7, 0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e,
  1235. 0x6f, 0x7c, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
  1236. 0xc8, 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
  1237. 0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
  1238. 0xe9, 0xad, 0xe0, 0xbd, 0x9a, 0x6d, 0x79, 0x81, 0x82,
  1239. 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x91, 0x92,
  1240. 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0xa2, 0xa3,
  1241. 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xc0, 0x4f, 0xd0,
  1242. 0x5f, 0x7 };
  1243. /*S icc - internal code conversion */
  1244. /*H icc */
  1245. /*E*/
  1246. void
  1247. icc (buf, nch, type)
  1248. register char *buf;
  1249. register int nch;
  1250. char *type;
  1251. {
  1252.     register int i;
  1253.     register int j;
  1254.  
  1255.     if (!strcmp (type, "AE"))
  1256.     {
  1257.         for (i = 0; i < nch; i++, buf++)
  1258.         {
  1259.             *buf = ebcdic_codes[*buf];
  1260.         }
  1261.     }
  1262.     else if (!strcmp (type, "EA"))
  1263.     {
  1264.         for (i = 0; i < nch; i++, buf++)
  1265.         {
  1266.             for (j = 0; j < 128; j++)
  1267.             {
  1268.                 if (*buf == ebcdic_codes[j])
  1269.                 {
  1270.                     *buf = j;
  1271.                     break;
  1272.                 }
  1273.             }
  1274.         }
  1275.     }
  1276.  
  1277.     return;
  1278. }
  1279. /*S ckfile - check on existence, accessibility, and type of file */
  1280. /*H ckfile */
  1281. /*E*/
  1282. ckfile (filename, sizep)
  1283. char    *filename;
  1284. long    *sizep;
  1285. {
  1286.     register int fid = 0;
  1287.  
  1288.     if (access (filename, 0) < 0)
  1289.     {
  1290.         errmsg ("file not found (%s)", filename);
  1291.         fid = -1;
  1292.     }
  1293.  
  1294.     if (block || pause || dump)
  1295.     {
  1296.         fid = open (filename, O_RDONLY, 0);
  1297.     }
  1298.     else
  1299.     {
  1300.         fid = open (filename, O_RDWR, 0);
  1301.     }
  1302.  
  1303.     if (fid < 0)
  1304.     {
  1305.         errmsg ("error opening file %s", filename);
  1306.         perror (filename);
  1307.         fid = -1;
  1308.     }
  1309.     else
  1310.     {
  1311.         errmsg ("File %s opened successfully ", filename);
  1312.         if (fstat (fid, &sb) == -1)
  1313.         {
  1314.             fprintf (stderr, "Can't stat\n");
  1315.             perror (filename);
  1316.             fid = -1;
  1317.         }
  1318.         else
  1319.         {
  1320.             block_spec = (sb.st_mode & S_IFMT) == S_IFBLK;
  1321.             char_spec = (sb.st_mode & S_IFMT) == S_IFCHR;
  1322.             fifo_spec = (sb.st_mode & S_IFMT) == S_IFIFO;
  1323.             dir_spec = (sb.st_mode & S_IFMT) == S_IFDIR;
  1324.             rawfile = block_spec || char_spec || fifo_spec;
  1325.  
  1326.             if (rawfile) *sizep = -1;
  1327.             else
  1328.             {
  1329.                 if (sb.st_size == 0)
  1330.                 {
  1331.                     fprintf (stderr,
  1332.                         "file %s is empty (zero bytes)\n",
  1333.                         filename);
  1334.                     fid = -1;
  1335.                 }
  1336.                 *sizep = sb.st_size;
  1337.             }
  1338.         }
  1339.     }
  1340.  
  1341.     return fid;
  1342. }
  1343. /*S dohelp - display help text */
  1344. /*H dohelp */
  1345. /*E*/
  1346. dohelp ()
  1347. {
  1348.     static char *helptxt[] = {
  1349.     "!   - execute command in the shell",    "a   - edit ascii portion",
  1350.     "-x   - toggle command line option",    "f   - display first page of file",
  1351.     "<cr> - display next page",    NULL,
  1352.     "?    - display this help text",    "h   - edit hexadecimal portion",
  1353.     "DEL  - quit the program",        "l   - display last page of file",
  1354.     "\\    - display previous page",        "nnn - direct addressing",
  1355.     "/    - search for ASCII string",        "q   - quit the program",
  1356.     "^f   - select named file",        "r   - reread the current page",
  1357.     "^n   - select next file",        "u   - undo all changes to page",
  1358.     "^p   - select previous file",        "w   - write out changed page",
  1359.     "^q   - quit without writing changes",    NULL,
  1360.     "^r   - redraw the screen",    NULL,
  1361.     "^x   - turn on debug",    NULL,
  1362.     "----------------------------------------------------------------", NULL,
  1363.     "direct addressing: nnnS, where nnn = some number, and", NULL,
  1364.     "                      S = type suffix", "b = block (512)",
  1365.     NULL, "k = kilobyte (1024)",
  1366.     NULL, "l = long word (4)",
  1367.     NULL, "p = page (256)",
  1368.     NULL, "w = word (2)",
  1369.     NULL, "<cr> = byte",
  1370.     };
  1371.  
  1372.     static int nmsg = sizeof helptxt / sizeof (char *);
  1373.     register int row = 0;
  1374.     register int i;
  1375.  
  1376.     register WINDOW *helpwin;
  1377.     extern WINDOW *newwin ();
  1378.  
  1379.     helpwin = newwin (LINES, COLS, 0, 0);
  1380.     werase (helpwin);
  1381.     wrefresh (helpwin);
  1382.  
  1383.     wmove (helpwin, 0, 1);
  1384.     waddstr (helpwin,
  1385. "---------------------------------- HELP ----------------------------------");
  1386.  
  1387.     for (row = 1, i = 0; i < nmsg; i+=2)
  1388.     {
  1389.         if (helptxt[i])
  1390.         {
  1391.             wmove (helpwin, row, 1);
  1392.             waddstr (helpwin, helptxt[i]);
  1393.         }
  1394.         if (i+1 <= nmsg && helptxt[i+1])
  1395.         {
  1396.             wmove (helpwin, row, 41);
  1397.             waddstr (helpwin, helptxt[i+1]);
  1398.         }
  1399.         row++;
  1400.     }
  1401.  
  1402.     wmove (helpwin, 23, 0);
  1403.     wstandout (helpwin);
  1404.     waddstr (helpwin, " <Press any key> ");
  1405.     wstandend (helpwin);
  1406.     wclrtoeol (helpwin);
  1407.     wrefresh (helpwin);
  1408.     wgetch (helpwin);
  1409.     werase (helpwin);
  1410.     wrefresh (helpwin);
  1411.     delwin (helpwin);
  1412.  
  1413.     return;
  1414. }
  1415. /*S reset - reset terminal to original state */
  1416. /*H reset */
  1417. /*E*/
  1418. reset (sig)
  1419. int sig;
  1420. {
  1421.     move (23, 0);
  1422.     refresh ();
  1423.     endwin ();
  1424.     if (sig) fprintf (stderr, "killed with signal %d\n", sig);
  1425.     exit (sig);
  1426. }
  1427. /*S arrow - determine if current character is a cursor control key */
  1428. /*H arrow */
  1429. /*E*/
  1430. arrow (k, r, c, type)
  1431. register int k;
  1432. register int *r;
  1433. register int *c;
  1434. register int type;
  1435. {
  1436.     register ret = 1;
  1437.  
  1438.     if (k == KEY_UP)
  1439.     {
  1440.         if (*r == 0) beep ();
  1441.         else (*r)--;
  1442.     }
  1443.     else if (k == KEY_DOWN || k == '\n')
  1444.     {
  1445.         if (*r == 15) beep ();
  1446.         else (*r)++;
  1447.     }
  1448.     else if (k == KEY_LEFT || k == '\b' )
  1449.     {
  1450.         if (*c == 0)
  1451.         {
  1452.             if (*r == 0) beep ();
  1453.             else
  1454.             {
  1455.                 *c = 15;
  1456.                 (*r)--;
  1457.             }
  1458.         }
  1459.         else (*c)--;
  1460.     }
  1461.     else if (k == KEY_RIGHT)
  1462.     {
  1463.         if (*c == 15)
  1464.         {
  1465.             if (*r == 15) beep ();
  1466.             else
  1467.             {
  1468.                 *c = 0;
  1469.                 (*r)++;
  1470.             }
  1471.         }
  1472.         else (*c)++;
  1473.     }
  1474.     else if (k == KEY_HOME)
  1475.     {
  1476.         *r = *c = 0;
  1477.     }
  1478.     else
  1479.     {
  1480.         ret = 0;
  1481.     }
  1482.  
  1483.     return ret;
  1484. }
  1485. /*S dbg_msg - print a debug message */
  1486. /*H dbg_msg */
  1487. /*E*/
  1488. dbg_msg (msg)
  1489. register char *msg;
  1490. {
  1491.     if (debug && !dump)
  1492.     {
  1493.         errmsg (msg);
  1494.     }
  1495.  
  1496.     return;
  1497. }
  1498. /*S instr - get a character string from the terminal */
  1499. /*H instr */
  1500. /*E*/
  1501. char *
  1502. instr ()
  1503. {
  1504.     static char buf[512];
  1505.  
  1506.     register int c;
  1507.     register char *p = buf;
  1508.     register int col = 0;
  1509.  
  1510.     move (22, 0);
  1511.     clrtoeol ();
  1512.     refresh ();
  1513.  
  1514.     while ((c = getch ()) != '\r')
  1515.     {
  1516.         if (isascii (c) && isprint (c))
  1517.         {
  1518.             move (22, col);
  1519.             addch (c);
  1520.             *p++ = c;
  1521.             col++;
  1522.         }
  1523.         else if (c == '\b')
  1524.         {
  1525.             p--;
  1526.             col--;
  1527.             move (22, col);
  1528.             addch (' ');
  1529.             move (22, col);
  1530.         }
  1531.         refresh ();
  1532.     }
  1533.  
  1534.     refresh ();
  1535.  
  1536.     *p = '\0';
  1537.  
  1538.     return buf;
  1539. }
  1540. /*S getnum - retrieve a number from the terminal */
  1541. /*H getnum */
  1542. /*E*/
  1543. long
  1544. getnum (frst_char, hex)
  1545. register int frst_char;
  1546. register int hex;
  1547. {
  1548.     static char buf[64];
  1549.  
  1550.     register int c;
  1551.     register char *p = buf;
  1552.     register int col = 0;
  1553.  
  1554.     register long retval = 0;
  1555.  
  1556.     move (22, 0);
  1557.     clrtoeol ();
  1558.     if (frst_char)
  1559.     {
  1560.         addch (frst_char);
  1561.         *p++ = frst_char;
  1562.         col++;
  1563.         refresh ();
  1564.     }
  1565.  
  1566.     while ((c = getch()) != '\r')
  1567.     {
  1568.         if (isascii (c))
  1569.         {
  1570.             if ((hex && isxdigit (c)) || isdigit (c))
  1571.             {
  1572.                 move (22, col);
  1573.                 addch (c);
  1574.                 *p++ = c;
  1575.                 col++;
  1576.             }
  1577.             else if (c == '\b')
  1578.             {
  1579.                 p--;
  1580.                 col--;
  1581.                 move (22, col);
  1582.                 addch (' ');
  1583.                 move (22, col);
  1584.             }
  1585.             else
  1586.             {
  1587.                 break;            /* some character typing the value    */
  1588.             }
  1589.             refresh ();
  1590.         }
  1591.     }
  1592.  
  1593.     *p = '\0';
  1594.  
  1595.     retval = atol (buf);
  1596.  
  1597.     mvprintw (22, 0, "%ld", retval);
  1598.     switch (c)
  1599.     {
  1600.         case    'b':            /* block - 512 bytes                */
  1601.             retval *= 512;
  1602.             break;
  1603.         case    'k':            /* 1024 bytes                        */
  1604.             retval *= 1024;
  1605.             break;
  1606.         case    'l':            /* long word - 4 bytes                */
  1607.             retval *= 4;
  1608.             break;
  1609.         case    'p':            /* page - 256 bytes                    */
  1610.             retval *= 256;
  1611.             break;
  1612.         case    'w':            /* word - 2 bytes                    */
  1613.             retval *= 2;
  1614.             break;
  1615.         case    '\r':            /* just clear it for display        */
  1616.             c = '\0';
  1617.             break;
  1618.     }
  1619.  
  1620.     printw ("%c -> %ld byte offset", c, retval);
  1621.     clrtoeol ();
  1622.  
  1623.     refresh ();
  1624.  
  1625.     return retval;
  1626. }
  1627. /*S search - look for an ascii string in the file */
  1628. /*H search */
  1629. /*E*/
  1630. search (fid)
  1631. register int fid;
  1632. {
  1633.     long    curpos = position;
  1634.     long    currec = recno;
  1635.  
  1636.     char    lrecord[sizeof record + 1];
  1637.  
  1638.     register int i;
  1639.     register int matched = 0;
  1640.     register int srch_len;
  1641.  
  1642.     register char *cp = instr ();
  1643.     register char *rp;
  1644.  
  1645.     int row, col;
  1646.  
  1647.     srch_len = strlen (cp);
  1648.     copyrec (record, lrecord, sizeof record);
  1649.     lrecord[256] = '\0';
  1650.  
  1651.     pbrk = 0;
  1652.  
  1653.     wmove (errwin, 0, 0);
  1654.     wstandout (errwin);
  1655.     wmove (errwin, 0, 40);
  1656.     wstandend (errwin);
  1657.     wmove (errwin, 0, 1);
  1658.     waddstr (errwin, "..searching record ");
  1659.     getyx (errwin, row, col);
  1660.  
  1661.     do
  1662.     {
  1663.         mvwprintw (errwin, row, col, "%ld", currec);
  1664.         wrefresh (errwin);
  1665.  
  1666.         for (i = 0, rp = lrecord, matched = 0;
  1667.              !matched && i < 256;
  1668.              rp++, i++)
  1669.         {
  1670.             if (*cp == *rp && !strncmp (cp, rp, srch_len))
  1671.             {
  1672.                 matched = 1;
  1673.                 break;
  1674.             }
  1675.         }
  1676.  
  1677.         if (!matched)
  1678.         {
  1679.             bytes = bread (fid, lrecord, 256, block);
  1680.             currec++;
  1681.             lrecord[256] = '\0';
  1682.         }
  1683.     }    while (!pbrk && bytes && !matched);
  1684.  
  1685.     if (matched)
  1686.     {
  1687.         recno = currec;
  1688.         stay = 0;
  1689.         copyrec (record, unch_rec, sizeof record);
  1690.         werase (errwin);
  1691.         wrefresh (errwin);
  1692.     }
  1693.     else
  1694.     {
  1695.         errmsg ("String %s not found", cp);
  1696.         stay = 1;
  1697.     }
  1698.  
  1699.     return;
  1700. }
  1701. errmsg (fmt, arg1, arg2, arg3, arg4)
  1702. register char *fmt;
  1703. register char *arg1;
  1704. register char *arg2;
  1705. register char *arg3;
  1706. register char *arg4;
  1707. {
  1708.     int y, x;
  1709.  
  1710.     if (!dump)
  1711.     {
  1712.         getyx (stdscr, y, x);
  1713.         wmove (errwin, 0, 0);
  1714.         wstandout (errwin);
  1715.         wprintw (errwin, fmt, arg1, arg2, arg3, arg4);
  1716.         wstandend (errwin);
  1717.         wclrtoeol (errwin);
  1718.         wrefresh (errwin);
  1719.         move (y, x);
  1720.     }
  1721.     else
  1722.     {
  1723.         fprintf (stderr, fmt, arg1, arg2, arg3, arg4);
  1724.     }
  1725.     return;
  1726. }
  1727. outstr (fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
  1728. register char *fmt;
  1729. register char *arg1;
  1730. register char *arg2;
  1731. register char *arg3;
  1732. register char *arg4;
  1733. register char *arg5;
  1734. register char *arg6;
  1735. register char *arg7;
  1736. {
  1737.     if (dump) printf (fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
  1738.     else printw (fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
  1739.  
  1740.     return;
  1741. }
  1742. outch (ch)
  1743. register char ch;
  1744. {
  1745.     if (dump) putchar (ch);
  1746.     else addch (ch);
  1747.  
  1748.     return;
  1749. }
  1750.