home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / nethack-3.1 / sys / msdos / exesmurf.c next >
Encoding:
C/C++ Source or Header  |  1993-01-18  |  13.3 KB  |  385 lines

  1. /*    SCCS Id: @(#)exesmurf.c     3.1     91/01/29              */
  2. /* Copyright (c) Pierre Martineau and Stephen Spackman 1991, 1992, 1993.  */
  3. /* NetHack may be freely redistributed.  See license for details.      */
  4.  
  5. /******************************************************************************
  6. *                                                                             *
  7. *                         EXE header list and modify                          *
  8. *                                                                             *
  9. *                        by Pierre Martineau, 91/01/29                        *
  10. *                                                                             *
  11. *                                Version 1.2                                  *
  12. *                                                                             *
  13. >*****************************************************************************<
  14. * Modified (stephen@estragon.uchicago.edu):                                   *
  15. * 1990oct23 sps Overlay splitter-outer first cut                              *
  16. *        31     Error handling; some #defines                                 *
  17. *     nov01     /l                                                            *
  18. *   91jan29     Changed default overlay file names to conform to ovlmgr 30a0  *
  19. ******************************************************************************/
  20.  
  21. #include <string.h>
  22. #include <stdlib.h>
  23. #include <stdio.h>
  24. #include <math.h>
  25.  
  26. /** parameters ***************************************************************/
  27. #define MAXFILENAME 128   /* Probably overkill - theoretical limit is 80     */
  28. #define NPARTS        36      /* Maximum # of overlay files (excluding root .EXE)*/
  29. #define COPYBUFSIZE 32768 /* Fair sized buffer for file copy                 */
  30. #define BAKEXT      ".BAK"/* Extension for .exe backups                      */
  31. #define OVLEXT      ".OVL"/* Default extension for overlay files             */
  32. /* #define MANYZEROES */  /* Old style default: foo00001.ovl, not foo0.ovl   */
  33. /*****************************************************************************/
  34.  
  35. #define BOOLEAN int
  36. #define TRUE    1
  37. #define FALSE   0
  38.  
  39. int sstrccnt(register char const *s, register char c)
  40.   { int n = 0;
  41.  
  42.     while (*s) if (*s++ == c) n++;
  43.     return n;
  44.   }
  45.  
  46. FILE *wrkfile, *outfile;
  47. long min, max, stk;
  48. BOOLEAN listflg = FALSE;
  49. BOOLEAN verbose = FALSE;
  50. BOOLEAN minflg = FALSE;
  51. BOOLEAN maxflg = FALSE;
  52. BOOLEAN stkflg = FALSE;
  53.  
  54. int column = 0;
  55.  
  56. struct exehdr {
  57. unsigned signature;
  58. unsigned mod512;
  59. unsigned pages;
  60. unsigned relocitems;
  61. unsigned headerparas;
  62. unsigned minalloc;
  63. unsigned maxalloc;
  64. unsigned ss;
  65. unsigned sp;
  66. unsigned checksum;
  67. unsigned ip;
  68. unsigned cs;
  69. unsigned relocptr;
  70. unsigned ovlnum;
  71. } exehdr_area;
  72.  
  73. main(argc, argv)
  74. int argc;
  75. char *argv[];
  76. {
  77. char *dot, *slash;
  78. char fname[MAXFILENAME], oname[MAXFILENAME], zname[MAXFILENAME];
  79. char *jname = NULL;
  80. char *args;
  81. int i;
  82. long offset, oldstk;
  83. unsigned nparts = 0, part = 0, partstart[NPARTS + 2];
  84.  
  85.     printf("EXE list and modify V1.1s, by Pierre Martineau, 90/05/20.\n");
  86.     printf("This program may be freely distributed.\n");
  87.  
  88.     if ((argc < 2) || (argc > NPARTS + 2)) {
  89.         usage();
  90.         return;
  91.     }
  92.  
  93. /*  Process any remaining arguments  */
  94.  
  95.     if (argc == 2) {
  96.         listflg = TRUE;
  97.         verbose = TRUE; /* ??? */
  98.     }
  99.     else {
  100.         i = 2;
  101.         while (argc-- > 2) {
  102.             args = argv[i];
  103.         if ('0' <= args[0] && args[0] <= '9') { /* File split request */
  104.             if (nparts >= NPARTS) {
  105.             printf("\nToo many .OVL files requested (max. %d)\n", NPARTS);
  106.             usage();
  107.             return;
  108.         }
  109.         else if (!atoi(args)) {
  110.             printf("\nCan't relocate the root overlay (#0)\n");
  111.             usage();
  112.             return;
  113.         }
  114.         else if (nparts && partstart[nparts - 1] >= atoi(args)) {
  115.             printf("\nOverlay starts must be in ascending order\n");
  116.             usage();
  117.             return;
  118.         }
  119.         partstart[nparts++] = atoi(args);
  120.         } else {
  121.         if ((args[0] != '-') && (args[0] != '/')) {
  122.             printf("\nInvalid switch in paramater %s!\n", argv[i]);
  123.             usage();
  124.             return;
  125.         }
  126.         args++;
  127.         if (strnicmp(args, "min", 3) == 0) {
  128.             args += 3;
  129.             min = atol(args);
  130.             minflg = TRUE;
  131.         }
  132.         else if (strnicmp(args, "max", 3) == 0) {
  133.             args += 3;
  134.             max = atol(args);
  135.             maxflg = TRUE;
  136.         }
  137.         else if (strnicmp(args, "stk", 3) == 0) {
  138.             args += 3;
  139.             stk = atol(args);
  140.             stkflg = TRUE;
  141.         }
  142.         else if (strnicmp(args, "v", 1) == 0) {
  143.             listflg = TRUE;
  144.                     verbose = TRUE;
  145.                 }
  146.                 else if (strnicmp(args, "l", 1) == 0)
  147.                     listflg = TRUE;
  148.                 else if (strnicmp(args, "p", 1) == 0) {
  149.                     args++;
  150.                     jname = args;
  151.                 }
  152.         else {
  153.             printf("\nInvalid paramater %s!\n", argv[i]);
  154.             usage();
  155.             return;
  156.         }
  157.             }
  158.             i++;
  159.         }
  160.     }
  161.  
  162. /*  Extract filename from first argumemt  */
  163.  
  164.     strcpy(fname, argv[1]);
  165.     dot = strrchr(fname, '.');
  166.     slash = strrchr(fname, '\\');
  167.     if ((dot == NULL) || (slash > dot))
  168.         strcat(fname, ".exe");
  169.  
  170.     if (nparts) {
  171.     strcpy(oname,fname);
  172.     *strrchr(fname, '.') = '\0';
  173.     strcat(fname,BAKEXT);
  174.     if (!stricmp(oname,fname)) {
  175.         printf(
  176.                 "\nI refuse to split a file with extension "BAKEXT": %s\n",
  177.                 oname
  178.             );
  179.         return;
  180.     }
  181.         if (!jname || nparts > 1 && !sstrccnt(jname, '?')) {
  182.             char ext[5];
  183.             char *t;
  184.  
  185.             if (!jname) {
  186.                 strcpy(zname, oname);
  187.                 *strrchr(zname, '.') = '\0';
  188.                 strcpy(ext, OVLEXT);
  189.             } else {
  190.                 if (strrchr(jname, '.') &&
  191.                      (!strrchr(jname, '\\') ||
  192.                          strrchr(jname, '.') > strrchr(jname, '\\')
  193.                      )
  194.                 ) {
  195.                     strncpy(ext, strrchr(jname, '.'), sizeof(ext));
  196.                     ext[sizeof(ext) - 1] = '\0';
  197.                     strncpy(zname, jname, strrchr(jname, '.') - jname);
  198.                     zname[strrchr(jname, '.') - jname] = '\0';
  199.                 } else {
  200.                     strcpy(zname, jname);
  201.                     strcpy(ext, OVLEXT);
  202.                 }
  203.             }
  204.             t = strrchr(zname, '\\') ? strrchr(zname, '\\') + 1:
  205.                 strrchr(zname, ':') ? strrchr(zname, ':') + 1:
  206.                 zname;
  207.             if (strlen(t) >= 8)
  208.                 t[7] = '\0';
  209. #if defined(MANYZEROES)
  210.         while (strlen(t) < 8)
  211. #endif
  212.           strcat(t, "?");
  213.             strcat(zname, ext);
  214.             jname = zname;
  215.         }
  216.     if (rename(oname,fname)) { /* This assumes oldname, newname.
  217.                       There's some confusion. OK for TC2.0 */
  218.         printf("\nCouldn't rename (original) %s to %s\n", oname, fname);
  219.         return;
  220.     }
  221.     if ((outfile = fopen(oname, "wb")) == NULL) {
  222.             printf("\nCouldn't create file %s\n",oname);
  223.             return;
  224.         }
  225.     }
  226.  
  227.     if ((wrkfile = fopen(fname, "r+b")) == NULL) {
  228.         printf("\nCouldn't open file %s\n", fname);
  229.         return;
  230.     }
  231.  
  232.     fread(&exehdr_area, sizeof (struct exehdr), 1, wrkfile);
  233.     if (exehdr_area.signature != 0x5a4d) {
  234.         printf("\nNot an EXE file!\n");
  235.         return;
  236.     }
  237.  
  238.     while(!feof(wrkfile)) {
  239.         if (nparts) {
  240.         if (exehdr_area.ovlnum == partstart[part]) {
  241.              fclose(outfile);
  242.                  {
  243.                      int p = part + 1;
  244.                      strcpy(oname, jname);
  245.                      while (sstrccnt(oname, '?') > 1) {
  246.                          *strrchr(oname, '?') = '0' + p % 10;
  247.                          p /= 10;
  248.                      }
  249.                      *strchr(oname, '?') = (p > 9 ? 'a' - 10 : '0') + p;
  250.                  }
  251.                  part++;
  252.          if ((outfile = fopen(oname, "wb")) == NULL) {
  253.                      printf("\nCan't open file %s\n", oname);
  254.                      return;
  255.                  }
  256.         }
  257.             fwrite(&exehdr_area, sizeof (struct exehdr), 1, outfile);
  258.             if (ferror(outfile)) {
  259.                 printf("\nWrite error while moving overlay header in %s\n", oname);
  260.                 return;
  261.             }
  262.     }
  263.         if (listflg)
  264.             show_hdr();
  265.         else if (nparts)
  266.             printf("[overlay %d]\r", exehdr_area.ovlnum); /* Keep talking... */
  267.         if ((minflg || maxflg || stkflg) && (exehdr_area.ovlnum == 0) && (exehdr_area.signature == 0x5a4d)) {
  268.             if (minflg)
  269.                 exehdr_area.minalloc = min;
  270.             if (maxflg)
  271.                 exehdr_area.maxalloc = max;
  272.             if (stkflg) {
  273.                 oldstk = exehdr_area.sp;
  274.                 exehdr_area.sp = stk;
  275.                 if (!minflg) {
  276.                     exehdr_area.minalloc += ((stk - oldstk) / 16);
  277.                     printf("\nAdjusting size of minalloc!\n");
  278.                 }
  279.             }
  280.             fseek(nparts ? outfile : wrkfile, ftell(wrkfile) - sizeof (struct exehdr), SEEK_SET);
  281.             fwrite(&exehdr_area, sizeof (struct exehdr), 1, nparts ? outfile : wrkfile);
  282.             if (ferror(nparts ? outfile : wrkfile)) {
  283.                 printf("Write error while trying to update header!\n");
  284.                 fclose(nparts ? outfile : wrkfile);
  285.                 return;
  286.             }
  287.         }
  288.         offset = exehdr_area.pages;
  289.         offset *= 512L;
  290.         offset -= sizeof(struct exehdr);
  291.         if (nparts) { /* Copy the stuff across */
  292.         static char buffer[COPYBUFSIZE];
  293.         while (offset > sizeof(buffer)) {
  294.              fread(buffer, sizeof(buffer), 1, wrkfile);
  295.                  if (ferror(wrkfile)) {
  296.                      printf("\nRead error in overlay body\n");
  297.                      return;
  298.                  }
  299.          fwrite(buffer, sizeof(buffer), 1, outfile);
  300.                  if (ferror(outfile)) {
  301.                      printf("\nWrite error moving overlay body, file %s\n", oname);
  302.                      return;
  303.                  }
  304.          offset -= sizeof(buffer);
  305.         }
  306.         fread(buffer, (unsigned)offset, 1, wrkfile);
  307.             if (ferror(wrkfile)) {
  308.                 printf("\nRead error in overlay body\n");
  309.                 return;
  310.             }
  311.             fwrite(buffer, (unsigned)offset, 1, outfile);
  312.             if (ferror(outfile)) {
  313.                 printf("\nWrite error moving overlay body, file %s\n", oname);
  314.                 return;
  315.             }
  316.         } else fseek(wrkfile, offset, SEEK_CUR);
  317.         fread(&exehdr_area, sizeof (struct exehdr), 1, wrkfile);
  318.         if (ferror(wrkfile)) {
  319.             printf("Read error while trying to get a header!\n");
  320.             fclose(wrkfile);
  321.             return;
  322.         }
  323.     }
  324.     if (nparts) {
  325.         fclose(outfile);
  326.         if (!listflg) printf("                    \r");
  327.     }
  328.     fclose(wrkfile);
  329.     if (listflg && !verbose && column % 4) printf("\n");
  330. }
  331.  
  332. show_hdr()
  333. {
  334. long lsize;
  335.  
  336.     lsize = exehdr_area.pages;
  337.     if (exehdr_area.mod512 != 0)
  338.         lsize--;
  339.     lsize *= 512L;
  340.     lsize += exehdr_area.minalloc * 16;
  341.     lsize += exehdr_area.mod512;
  342.     lsize -= exehdr_area.headerparas * 16;
  343.  
  344.     if (verbose) {
  345.         printf("\nOverlay: %d\n", exehdr_area.ovlnum);
  346.         printf("Size (512 byte pages)\t-%6x\t\t%6u\n", exehdr_area.pages, exehdr_area.pages);
  347.         printf("Remainder (last page)\t-%6x\t\t%6u\n", exehdr_area.mod512, exehdr_area.mod512);
  348.         printf("Header size (in paras)\t-%6x\t\t%6u\n", exehdr_area.headerparas, exehdr_area.headerparas);
  349.         printf("Minalloc (in paras)\t-%6x\t\t%6u\n", exehdr_area.minalloc, exehdr_area.minalloc);
  350.         printf("Maxalloc (in paras)\t-%6x\t\t%6u\n", exehdr_area.maxalloc, exehdr_area.maxalloc);
  351.         printf("Load size (in bytes)\t-%6lx\t\t%6lu\n", lsize, lsize);
  352.         printf("Relocation items\t-%6x\t\t%6u\n", exehdr_area.relocitems, exehdr_area.relocitems);
  353.         printf("Relocation table offset\t-%6x\t\t%6u\n", exehdr_area.relocptr, exehdr_area.relocptr);
  354.         printf("Checksum\t\t-%6x\t\t%6u\n", exehdr_area.checksum, exehdr_area.checksum);
  355.         printf("Initial CS:IP\t\t-  %04x:%04x\n", exehdr_area.cs, exehdr_area.ip);
  356.         printf("Initial SS:SP\t\t-  %04x:%04x\n", exehdr_area.ss, exehdr_area.sp);
  357.     } else {
  358.         if (!exehdr_area.ovlnum) {
  359.             printf("\nOverlay: %d\n", exehdr_area.ovlnum);
  360.             printf("Minalloc (in paras)\t-%6x\t\t%6u\n", exehdr_area.minalloc, exehdr_area.minalloc);
  361.             printf("Maxalloc (in paras)\t-%6x\t\t%6u\n", exehdr_area.maxalloc, exehdr_area.maxalloc);
  362.             printf("Stored size (in bytes)\t-%6lx\t\t%6lu\n", exehdr_area.pages * 512L, exehdr_area.pages * 512L);
  363.             printf("Load size (in bytes)\t-%6lx\t\t%6lu\n", lsize, lsize);
  364.             printf("Initial CS:IP, SS:SP\t-  %04x:%04x\t  %04x:%04x\n", exehdr_area.cs, exehdr_area.ip, exehdr_area.ss, exehdr_area.sp);
  365.     } else {
  366.         static bis = 0;
  367.         if (!bis++)
  368.                 printf("\nOvl StrdSz LoadSz | Ovl StrdSz LoadSz | Ovl StrdSz LoadSz | Ovl StrdSz LoadSz\n");
  369.             printf("%3d:%6lu %6lu%s", exehdr_area.ovlnum, exehdr_area.pages * 512L, lsize, ++column % 4 ? " | " : "\n");
  370.         }
  371.     }
  372. }
  373.  
  374. usage()
  375. {
  376.     printf("\nUsage: exesmurf exe_file [/l] [/v] [/min#####] [/max#####] [/stk#####]\n");
  377.     printf("                [n1 n2...nn] [/p????????.???]\n");
  378.     printf("       where: min   = minalloc\n");
  379.     printf("              max   = maxalloc\n");
  380.     printf("              stk   = stack size\n");
  381.     printf("              ##### = decimal number of paragraphs\n");
  382.     printf("              ni    = overlay starting each new .OVL file, n1 < n2 <...< nn\n");
  383.     printf("              p     = DOS filename, maybe with ?s, for overlay files.\n");
  384. }
  385.