home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
- /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
- #include <stdio.h>
- #include <stdlib.h>
- #include <fcntl.h>
- #include <sys/stat.h>
- #include <string.h>
- #include <unistd.h>
- #ifdef __DJGPP__
- #include <io.h>
- #include <libc/dosio.h>
- #include <go32.h>
- #include <dpmi.h>
- #include <errno.h>
-
- #define tbsize _go32_info_block.size_of_transfer_buffer
- #endif
-
- #ifndef O_BINARY
- #define O_BINARY 0
- #endif
-
- const unsigned char stub_bytes[] = {
- #include "stub.h"
- };
-
- #define v_printf if(verbose)printf
- int verbose=0;
-
- unsigned long
- get32(unsigned char *ptr)
- {
- return ptr[0] | (ptr[1]<<8) | (ptr[2]<<16) | (ptr[3]<<24);
- }
-
- unsigned short
- get16(unsigned char *ptr)
- {
- return ptr[0] | (ptr[1]<<8);
- }
-
- void coff2exe(char *fname)
- {
- char ifilename[256];
- char ofilename[256];
- int ifile;
- int ofile;
- char *ofname, *ofext;
- char buf[4096];
- int rbytes, used_temp, i, n;
- long coffset=0;
- unsigned char filehdr_buf[20];
- int max_file_size = 0;
- int coff_file_size = 0;
- int drop_last_four_bytes = 0;
-
- strcpy(ifilename, fname);
- strcpy(ofilename, fname);
- ofext = 0;
- for (ofname=ofilename; *ofname; ofname++)
- {
- if (strchr("/\\:", *ofname))
- ofext = 0;
- if (*ofname == '.')
- ofext = ofname;
- }
- if (ofext == 0)
- ofext = ofilename + strlen(ofilename);
- strcpy(ofext, ".exe");
- if (access(ofilename, 0) == 0)
- for (ofile=0; ofile<999; ofile++)
- {
- used_temp = 1;
- sprintf(ofext, ".%03d", ofile);
- if (access(ofilename, 0))
- break;
- }
- else
- used_temp = 0;
-
- ifile = open(ifilename, O_RDONLY|O_BINARY);
- if (ifile < 0)
- {
- perror(fname);
- return;
- }
- while (1)
- {
- lseek(ifile, coffset, 0);
- read(ifile, buf, 6);
- if (buf[0] == 'M' && buf[1] == 'Z') /* stubbed already, skip stub */
- {
- int blocks = (unsigned char)buf[4] + (unsigned char)buf[5] * 256;
- int partial = (unsigned char)buf[2] + (unsigned char)buf[3] * 256;
- coffset += blocks * 512;
- if (partial)
- coffset += partial - 512;
- }
- else if (buf[0] == 0x4c && buf[1] == 0x01) /* it's a COFF */
- {
- break;
- }
- else
- {
- fprintf(stderr, "Warning: input file is not COFF or stubbed COFF\n");
- break;
- }
- }
-
- coff_file_size = lseek(ifile, 0, SEEK_END) - coffset;
- lseek(ifile, coffset, 0);
-
- read(ifile, filehdr_buf, 20); /* get the COFF header */
- lseek(ifile, get16(filehdr_buf+16), SEEK_CUR); /* skip optional header */
- n = get16(filehdr_buf + 2);
- for (i=0; i<n; i++) /* for each COFF section */
- {
- int addr, size, flags;
- unsigned char coffsec_buf[40];
- read(ifile, coffsec_buf, 40);
- size = get32(coffsec_buf+16);
- addr = get32(coffsec_buf+20);
- flags = get32(coffsec_buf+36);
- if (flags & 0x60) /* text or data */
- {
- int maybe_file_size = size + addr;
- if (max_file_size < maybe_file_size)
- max_file_size = maybe_file_size;
- }
- }
- if (coff_file_size == max_file_size + 4)
- /* it was built with "gcc -s" and has four too many bytes */
- drop_last_four_bytes = 1;
-
- lseek(ifile, coffset, 0);
-
- ofile = open(ofilename, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0777);
- if (ofile < 0)
- {
- perror(ofname);
- return;
- }
- v_printf("stubify: %s -> %s", ifilename, ofilename);
- if (used_temp)
- {
- strcpy(ifilename, ofilename);
- strcpy(ofext, ".exe");
- v_printf(" -> %s", ofilename);
- }
- v_printf("\n");
-
- write(ofile, stub_bytes, sizeof(stub_bytes));
-
- #ifdef __DJGPP__
- /* if 0 bytes are read (or an error occurs, the loop will be broken from */
- while (1) {
- __dpmi_regs r;
- int wb;
- /* bypass the normal read routine to avoid the unnecessary copying of the
- * file contents into extended memory (the data is not actually being
- * used, only copied from one file to another, and so easy access from gcc
- * compiled code is not needed).
- */
- r.x.ax = 0x3f00; /* dos read from file handle function */
- r.x.bx = ifile;
- r.x.cx = tbsize; /* number of bytes to read */
- r.x.dx = __tb & 15; /* transfer buffer offset */
- r.x.ds = __tb / 16; /* transfer buffer segment */
- __dpmi_int(0x21, &r);
- if (r.x.flags & 1)
- errno = __doserr_to_errno(r.x.ax);
- if ((rbytes=(r.x.flags & 1) ? -1 : r.x.ax) <= 0)
- break;
- #else
- while ((rbytes=read(ifile, buf, 4096)) > 0)
- {
- int wb;
- #endif
-
- if (drop_last_four_bytes && rbytes < 4096)
- rbytes -= 4;
-
- #ifdef __DJGPP__
- /* bypass the normal write routine to avoid the unnecessary copying of the
- * file contents from extended memory.
- */
- r.x.ax = 0x4000; /* dos write to file handle function */
- r.x.bx = ofile;
- r.x.cx = rbytes; /* number of bytes to write */
- r.x.dx = __tb & 15; /* transfer buffer offset */
- r.x.ds = __tb / 16; /* transfer buffer segment */
- __dpmi_int(0x21, &r);
- wb = (r.x.flags & 1) ? -1 : r.x.ax;
- if (r.x.flags & 1)
- errno = __doserr_to_errno(r.x.ax);
- #else
- wb = write(ofile, buf, rbytes);
- #endif
- if (wb < 0)
- {
- perror(ofname);
- close(ifile);
- close(ofile);
- unlink(ofilename);
- exit(1);
- }
- if (wb < rbytes)
- {
- fprintf(stderr, "%s: disk full\n", ofname);
- close(ifile);
- close(ofile);
- unlink(ofilename);
- exit(1);
- }
- }
-
- close(ifile);
- close(ofile);
-
- if (used_temp)
- {
- unlink(ofilename);
- #ifdef __DJGPP__
- if (_rename(ifilename, ofilename))
- #else
- if (rename(ifilename, ofilename))
- #endif
- {
- printf("rename of %s to %s failed.\n", ifilename, ofilename);
- perror("The error was");
- }
- }
- }
-
- int main(int argc, char **argv)
- {
- int i;
- if (argc > 1 && strcmp(argv[1], "-v")==0)
- {
- verbose = 1;
- argv++;
- argc--;
- }
- v_printf("stubify for djgpp V2.X executables, Copyright (C) 1995 DJ Delorie\n");
- if (argc < 2)
- {
- fprintf(stderr, "Usage: stubify [-g] <program> (program may be COFF or stubbed .exe,\n");
- fprintf(stderr, " and may be COFF with .exe extension. Resulting file will have .exe)\n");
-
- fprintf(stderr, "\nThis program is NOT shareware or public domain. It is copyrighted.\n");
- fprintf(stderr, "It is redistributable but only as part of a complete package. If you\n");
- fprintf(stderr, "have a copy of this program, the place that you got it from is\n");
- fprintf(stderr, "responsible for making sure you are able to get it's sources as well.\n");
-
- exit(1);
- }
- if (argc > 2 && strcmp(argv[1], "-g") == 0)
- {
- char ofilename[256], *ofname, *ofext=0;
- int ofile;
-
- strcpy(ofilename, argv[2]);
- for (ofname=ofilename; *ofname; ofname++)
- {
- if (strchr("/\\:", *ofname))
- ofext = 0;
- if (*ofname == '.')
- ofext = ofname;
- }
- if (ofext == 0)
- ofext = ofilename + strlen(ofilename);
- strcpy(ofext, ".exe");
-
- ofile = open(ofilename, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666);
- if (ofile < 0)
- {
- printf("Cannot open output file to generate\n");
- perror(ofilename);
- return 1;
- }
- v_printf("stubify: generate %s\n", argv[2]);
-
- write(ofile, stub_bytes, sizeof(stub_bytes));
- close(ofile);
- }
- else
- for (i=1; i<argc; i++)
- coff2exe(argv[i]);
- return 0;
- }
-
-