home *** CD-ROM | disk | FTP | other *** search
/ PC Extra Super CD 1998 January / PCPLUS131.iso / DJGPP / V2 / DJLSR201.ZIP / src / stub / stubify.c < prev   
Encoding:
C/C++ Source or Header  |  1996-09-11  |  7.3 KB  |  292 lines

  1. /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
  2. /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <fcntl.h>
  6. #include <sys/stat.h>
  7. #include <string.h>
  8. #include <unistd.h>
  9. #ifdef __DJGPP__
  10. #include <io.h>
  11. #include <libc/dosio.h>
  12. #include <go32.h>
  13. #include <dpmi.h>
  14. #include <errno.h>
  15.  
  16. #define tbsize _go32_info_block.size_of_transfer_buffer
  17. #endif
  18.  
  19. #ifndef O_BINARY
  20. #define O_BINARY 0
  21. #endif
  22.  
  23. const unsigned char stub_bytes[] = {
  24. #include "stub.h"
  25. };
  26.  
  27. #define v_printf if(verbose)printf
  28. int verbose=0;
  29.  
  30. unsigned long
  31. get32(unsigned char *ptr)
  32. {
  33.   return ptr[0] | (ptr[1]<<8) | (ptr[2]<<16) | (ptr[3]<<24);
  34. }
  35.  
  36. unsigned short
  37. get16(unsigned char *ptr)
  38. {
  39.   return ptr[0] | (ptr[1]<<8);
  40. }
  41.  
  42. void coff2exe(char *fname)
  43. {
  44.   char ifilename[256];
  45.   char ofilename[256];
  46.   int ifile;
  47.   int ofile;
  48.   char *ofname, *ofext;
  49.   char buf[4096];
  50.   int rbytes, used_temp, i, n;
  51.   long coffset=0;
  52.   unsigned char filehdr_buf[20];
  53.   int max_file_size = 0;
  54.   int coff_file_size = 0;
  55.   int drop_last_four_bytes = 0;
  56.  
  57.   strcpy(ifilename, fname);
  58.   strcpy(ofilename, fname);
  59.   ofext = 0;
  60.   for (ofname=ofilename; *ofname; ofname++)
  61.   {
  62.     if (strchr("/\\:", *ofname))
  63.       ofext = 0;
  64.     if (*ofname == '.')
  65.       ofext = ofname;
  66.   }
  67.   if (ofext == 0)
  68.     ofext = ofilename + strlen(ofilename);
  69.   strcpy(ofext, ".exe");
  70.   if (access(ofilename, 0) == 0)
  71.     for (ofile=0; ofile<999; ofile++)
  72.     {
  73.       used_temp = 1;
  74.       sprintf(ofext, ".%03d", ofile);
  75.       if (access(ofilename, 0))
  76.     break;
  77.     }
  78.   else
  79.     used_temp = 0;
  80.  
  81.   ifile = open(ifilename, O_RDONLY|O_BINARY);
  82.   if (ifile < 0)
  83.   {
  84.     perror(fname);
  85.     return;
  86.   }
  87.   while (1)
  88.   {
  89.     lseek(ifile, coffset, 0);
  90.     read(ifile, buf, 6);
  91.     if (buf[0] == 'M' && buf[1] == 'Z') /* stubbed already, skip stub */
  92.     {
  93.       int blocks = (unsigned char)buf[4] + (unsigned char)buf[5] * 256;
  94.       int partial = (unsigned char)buf[2] + (unsigned char)buf[3] * 256;
  95.       coffset += blocks * 512;
  96.       if (partial)
  97.     coffset += partial - 512;
  98.     }
  99.     else if (buf[0] == 0x4c && buf[1] == 0x01) /* it's a COFF */
  100.     {
  101.       break;
  102.     }
  103.     else
  104.     {
  105.       fprintf(stderr, "Warning: input file is not COFF or stubbed COFF\n");
  106.       break;
  107.     }
  108.   }
  109.  
  110.   coff_file_size = lseek(ifile, 0, SEEK_END) - coffset;
  111.   lseek(ifile, coffset, 0);
  112.  
  113.   read(ifile, filehdr_buf, 20); /* get the COFF header */
  114.   lseek(ifile, get16(filehdr_buf+16), SEEK_CUR); /* skip optional header */
  115.   n = get16(filehdr_buf + 2);
  116.   for (i=0; i<n; i++) /* for each COFF section */
  117.   {
  118.     int addr, size, flags;
  119.     unsigned char coffsec_buf[40];
  120.     read(ifile, coffsec_buf, 40);
  121.     size = get32(coffsec_buf+16);
  122.     addr = get32(coffsec_buf+20);
  123.     flags = get32(coffsec_buf+36);
  124.     if (flags & 0x60) /* text or data */
  125.     {
  126.       int maybe_file_size = size + addr;
  127.       if (max_file_size < maybe_file_size)
  128.     max_file_size = maybe_file_size;
  129.     }
  130.   }
  131.   if (coff_file_size == max_file_size + 4)
  132.     /* it was built with "gcc -s" and has four too many bytes */
  133.     drop_last_four_bytes = 1;
  134.  
  135.   lseek(ifile, coffset, 0);
  136.  
  137.   ofile = open(ofilename, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0777);
  138.   if (ofile < 0)
  139.   {
  140.     perror(ofname);
  141.     return;
  142.   }
  143.   v_printf("stubify: %s -> %s", ifilename, ofilename);
  144.   if (used_temp)
  145.   {
  146.     strcpy(ifilename, ofilename);
  147.     strcpy(ofext, ".exe");
  148.     v_printf(" -> %s", ofilename);
  149.   }
  150.   v_printf("\n");
  151.  
  152.   write(ofile, stub_bytes, sizeof(stub_bytes));
  153.   
  154. #ifdef __DJGPP__
  155.   /* if 0 bytes are read (or an error occurs, the loop will be broken from */
  156.   while (1) {
  157.     __dpmi_regs r;
  158.     int wb;
  159.     /* bypass the normal read routine to avoid the unnecessary copying of the
  160.      * file contents into extended memory (the data is not actually being
  161.      * used, only copied from one file to another, and so easy access from gcc
  162.      * compiled code is not needed).
  163.      */
  164.     r.x.ax = 0x3f00; /* dos read from file handle function */
  165.     r.x.bx = ifile;
  166.     r.x.cx = tbsize; /* number of bytes to read */
  167.     r.x.dx = __tb & 15; /* transfer buffer offset */
  168.     r.x.ds = __tb / 16; /* transfer buffer segment */
  169.     __dpmi_int(0x21, &r);
  170.     if (r.x.flags & 1)
  171.       errno = __doserr_to_errno(r.x.ax);
  172.     if ((rbytes=(r.x.flags & 1) ? -1 : r.x.ax) <= 0)
  173.       break;
  174. #else
  175.   while ((rbytes=read(ifile, buf, 4096)) > 0)
  176.   {
  177.     int wb;
  178. #endif
  179.  
  180.     if (drop_last_four_bytes && rbytes < 4096)
  181.       rbytes -= 4;
  182.  
  183. #ifdef __DJGPP__
  184.     /* bypass the normal write routine to avoid the unnecessary copying of the
  185.      * file contents from extended memory.
  186.      */
  187.     r.x.ax = 0x4000; /* dos write to file handle function */
  188.     r.x.bx = ofile;
  189.     r.x.cx = rbytes; /* number of bytes to write */
  190.     r.x.dx = __tb & 15; /* transfer buffer offset */
  191.     r.x.ds = __tb / 16; /* transfer buffer segment */
  192.     __dpmi_int(0x21, &r);
  193.     wb = (r.x.flags & 1) ? -1 : r.x.ax;
  194.     if (r.x.flags & 1)
  195.       errno = __doserr_to_errno(r.x.ax);
  196. #else
  197.     wb = write(ofile, buf, rbytes);
  198. #endif
  199.     if (wb < 0)
  200.     {
  201.       perror(ofname);
  202.       close(ifile);
  203.       close(ofile);
  204.       unlink(ofilename);
  205.       exit(1);
  206.     }
  207.     if (wb < rbytes)
  208.     {
  209.       fprintf(stderr, "%s: disk full\n", ofname);
  210.       close(ifile);
  211.       close(ofile);
  212.       unlink(ofilename);
  213.       exit(1);
  214.     }
  215.   }
  216.  
  217.   close(ifile);
  218.   close(ofile);
  219.  
  220.   if (used_temp)
  221.   {
  222.     unlink(ofilename);
  223. #ifdef __DJGPP__
  224.     if (_rename(ifilename, ofilename))
  225. #else
  226.     if (rename(ifilename, ofilename))
  227. #endif
  228.     {
  229.       printf("rename of %s to %s failed.\n", ifilename, ofilename);
  230.       perror("The error was");
  231.     }
  232.   }
  233. }
  234.  
  235. int main(int argc, char **argv)
  236. {
  237.   int i;
  238.   if (argc > 1 && strcmp(argv[1], "-v")==0)
  239.   {
  240.     verbose = 1;
  241.     argv++;
  242.     argc--;
  243.   }
  244.   v_printf("stubify for djgpp V2.X executables, Copyright (C) 1995 DJ Delorie\n");
  245.   if (argc < 2)
  246.   {
  247.     fprintf(stderr, "Usage: stubify [-g] <program>  (program may be COFF or stubbed .exe,\n");
  248.     fprintf(stderr, "  and may be COFF with .exe extension.  Resulting file will have .exe)\n");
  249.  
  250.     fprintf(stderr, "\nThis program is NOT shareware or public domain.  It is copyrighted.\n");
  251.     fprintf(stderr, "It is redistributable but only as part of a complete package.  If you\n");
  252.     fprintf(stderr, "have a copy of this program, the place that you got it from is\n");
  253.     fprintf(stderr, "responsible for making sure you are able to get it's sources as well.\n");
  254.  
  255.     exit(1);
  256.   }
  257.   if (argc > 2 && strcmp(argv[1], "-g") == 0)
  258.   {
  259.     char ofilename[256], *ofname, *ofext=0;
  260.     int ofile;
  261.  
  262.     strcpy(ofilename, argv[2]);
  263.     for (ofname=ofilename; *ofname; ofname++)
  264.     {
  265.       if (strchr("/\\:", *ofname))
  266.     ofext = 0;
  267.       if (*ofname == '.')
  268.     ofext = ofname;
  269.     }
  270.     if (ofext == 0)
  271.       ofext = ofilename + strlen(ofilename);
  272.     strcpy(ofext, ".exe");
  273.     
  274.     ofile = open(ofilename, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666);
  275.     if (ofile < 0)
  276.     {
  277.       printf("Cannot open output file to generate\n");
  278.       perror(ofilename);
  279.       return 1;
  280.     }
  281.     v_printf("stubify: generate %s\n", argv[2]);
  282.  
  283.     write(ofile, stub_bytes, sizeof(stub_bytes));
  284.     close(ofile);
  285.   }
  286.   else
  287.     for (i=1; i<argc; i++)
  288.       coff2exe(argv[i]);
  289.   return 0;
  290. }
  291.  
  292.