1 #include <stdio.h>
2
3 #include <string.h>
4 /* for unlink */
5 #include <dos.h>
6 /* for exit */
7 #include <stdlib.h>
8 /* for tolower */
9 #include <ctype.h>
10
11 /* Conversion error codes */
12 #define BADREAD 1
13 #define BADWRITE 2
14 #define BADSIG 3
15 #define HASRELO 4
16 #define HAS_SS 5
17 #define HAS_CS 6
18 #define BAD_IP 7
19 #define TOO_BIG 8
20
21 /*
22 ** Define structure of fixed-format part of EXE file header
23 */
24 struct exe_header {
25 char exe_sig[2]; /* EXE file signature: "MZ" */
26 unsigned excess, /* Image size mod 512 (valid bytes in last page) */
27 pages, /* # 512-byte pages in image */
28 relo_ct, /* Count of relocation table entries */
29 hdr_size, /* Size of header, in paragraphs */
30 min_mem, /* Min required memory */
31 max_mem, /* Max required memory */
32 ss, /* Stack seg offset in load module */
33 sp, /* Initial value of SP */
34 cksum, /* File checksum */
35 ip, /* Initial value of IP */
36 cs, /* CS offset in load module */
37 relo_start, /* Offset of first relo item */
38 ovl_num; /* Overlay number */
39 } xh;
40
41 FILE *fi, /* Input file stream */
42 *fo; /* Output file stream */
43
44 char fin[129], /* Input file name */
45 fon[129]; /* Output file name */
46
47
48 unsigned long code_start, /* Offset of program image in EXE file */
49 code_size; /* Size of program image, in bytes */
50
51
52 void err_xit (unsigned code);
53 void convert (void);
54 void read_hdr(void);
55 void init (unsigned argc, char *argv[]);
56
57 char *lower (char *cp)
58 {
59 char *cp0;
60 for (cp0=cp; (*cp=tolower (*cp)) != 0; ++cp)
61 ;
62 return cp0;
63 }
64
65 void cdecl main(unsigned argc, char *argv[])
66 {
67 init (argc, argv);
68 read_hdr ();
69 convert ();
70 }
71
72
73 /*
74 ** Initialize - get filenames and open/create files
75 */
76 void init (unsigned argc, char *argv[])
77 {
78 char *cp;
79
80 printf ("exe2com 1.01\n");
81
82 /* Check arg count */
83 if (argc < 2 || argc > 3) {
84 fprintf (stderr, "usage: exe2com file [file]\n");
85 exit (1);
86 }
87
88 /* If argv[1] (the input file) has no extension, add .EXE */
89 strcpy (fin, lower (argv[1]));
90 if (!strchr (fin, '.'))
91 strcat (fin, ".exe");
92
93 /* Get or construct output file name */
94 if (argc == 3)
95 strcpy (fon, lower (argv[2]));
96 else
97 strcpy (fon, fin);
98
99 /* Check output extension--change EXE to COM, or add COM */
100 if (!(cp = strchr (fon, '.')))
101 strcat (fon, ".com");
102 else if (strcmp (cp, ".exe") == 0)
103 strcpy (cp, ".com");
104
105 #ifdef DEBUG
106 printf ("input=%s, output=%s\n", fin, fon);
107 #endif
108
109 /* Try to open input file */
110 if (!(fi = fopen (fin, "rb"))) {
111 fprintf (stderr, "exe2com: can't find input file %s\n", fin);
112 exit (1);
113 }
114
115 /* Try to create output file */
116 if (!(fo = fopen (fon, "wb"))) {
117 fprintf (stderr, "exe2com: can't open output file %s\n", fin);
118 exit (1);
119 }
120 }
121
122
123 /*
124 ** Read and check the EXE file header
125 */
126 void read_hdr(void)
127 {
128
129 /* Read the formatted portion of the header */
130 if (!fread (&xh, sizeof (struct exe_header), 1, fi))
131 err_xit (BADREAD);
132
133 #ifdef DEBUG
134 printf ("EXE file header:\n");
135 printf (" signature %c%c\n", xh.exe_sig[0], xh.exe_sig[1]);
136 printf (" bytes last pg %04x\n", xh.excess);
137 printf (" pages %04x\n", xh.pages);
138 printf (" relo count %04x\n", xh.relo_ct);
139 printf (" header size %04x\n", xh.hdr_size);
140 printf (" min mem %04x\n", xh.min_mem);
141 printf (" max mem %04x\n", xh.max_mem);
142 printf (" ss %04x\n", xh.ss);
143 printf (" sp %04x\n", xh.sp);
144 printf (" checksum %04x\n", xh.cksum);
145 printf (" ip %04x\n", xh.ip);
146 printf (" cs %04x\n", xh.cs);
147 printf (" relo tbl start %04x\n", xh.relo_start);
148 printf (" overlay nbr %04x\n", xh.ovl_num);
149 #endif
150
151 /* Check header; to be convertible, must have:
152 ** -- first two bytes == "MZ"
153 ** -- no relocatable items
154 ** -- no stack segment
155 ** -- no code segment
156 ** -- IP == 0 or 100
157 */
158 if (strncmp (xh.exe_sig, "MZ", 2))
159 err_xit (BADSIG);
160 if (xh.relo_ct)
161 err_xit (HASRELO);
162 if (xh.ss || xh.sp)
163 err_xit (HAS_SS);
164 if (xh.ip != 0 && xh.ip != 0x100)
165 err_xit (BAD_IP);
166
167 /* Compute offset of program image in module, and program size.
168 **
169 ** The program size is computed as follows; it cannot exceed 64K bytes:
170 ** 512 * (# EXE pages - 1)
171 ** + valid bytes in last EXE page
172 ** - offset of program image in EXE file
173 **
174 ** Note that if the IP is nonzero, we will skip the first
175 ** IP bytes of the program image, and copy IP bytes fewer
176 ** than the actual size.
177 */
178 code_start = ((unsigned long) xh.hdr_size) << 4;
179 code_size = (unsigned long) (xh.pages-1) * 512 + xh.excess - code_start;
180 if (code_size >= 65536L)
181 err_xit (TOO_BIG);
182
183 /* Issue a warning if COM file and IP != 0x100 */
184 if (!strcmp (strchr (fon, '.'), ".com") && xh.ip != 0x100)
185 fprintf (stderr, "exe2com warning: COM file, initial IP not 100H\n");
186
187 }
188
189
190
191 /*
192 ** Convert the file. Nothing to do, really, other than
193 ** reading the image (which follows the header), and
194 ** dumping it back out to disk.
195 */
196 void convert (void)
197 {
198 char buffer[512];
199 unsigned wsize;
200
201 /* Seek to start of program image, skipping IP bytes */
202 if (fseek (fi, code_start+xh.ip, 0) != 0)
203 err_xit (BADREAD);
204
205 /* Reduce the "remaining" byte count by IP bytes */
206 code_size -= xh.ip;
207
208 /* Read blocks and copy to output */
209 while (code_size) {
210
211 /* Read block */
212 if (!fread (buffer, 1, 512, fi))
213 err_xit (BADREAD);
214
215 /* Set count of bytes to write, write block */
216 wsize = (unsigned) (code_size > 512 ? 512 : code_size);
217 if (!fwrite (buffer, wsize, 1, fo))
218 err_xit (BADWRITE);
219
220 /* Subtract bytes written from remaining byte count */
221 code_size -= wsize;
222 }
223
224 /* All done, close the two files */
225 fclose (fi);
226 fclose (fo);
227 }
228
229
230 /*
231 ** Display an error message, delete output file, exit.
232 */
233 void err_xit (unsigned code)
234 {
235 char msg[64];
236
237 switch (code) {
238 case BADREAD: strcpy (msg, "error reading EXE header");
239 break;
240 case BADWRITE: strcpy (msg, "error writing output file");
241 break;
242 case BADSIG: strcpy (msg, "invalid EXE file signature");
243 break;
244 case HASRELO: strcpy (msg, "EXE has relocatable items");
245 break;
246 case HAS_SS: strcpy (msg, "EXE has stack segment");
247 break;
248 case HAS_CS: strcpy (msg, "EXE has nonzero CS");
249 break;
250 case BAD_IP: strcpy (msg, "IP not 0 or 100H");
251 break;
252 case TOO_BIG: strcpy (msg, "program exceeds 64K");
253 break;
254 default: strcpy (msg, "unknown error");
255 }
256
257 fprintf (stderr, "exe2com: %s, can't convert\n", msg);
258
259 /* Close two files and delete partial output */
260 fclose (fi);
261 fclose (fo);
262 unlink (fon);
263
264 /* Exit with errorlevel 1 */
265 exit (1);
266 }
2
3 #include <string.h>
4 /* for unlink */
5 #include <dos.h>
6 /* for exit */
7 #include <stdlib.h>
8 /* for tolower */
9 #include <ctype.h>
10
11 /* Conversion error codes */
12 #define BADREAD 1
13 #define BADWRITE 2
14 #define BADSIG 3
15 #define HASRELO 4
16 #define HAS_SS 5
17 #define HAS_CS 6
18 #define BAD_IP 7
19 #define TOO_BIG 8
20
21 /*
22 ** Define structure of fixed-format part of EXE file header
23 */
24 struct exe_header {
25 char exe_sig[2]; /* EXE file signature: "MZ" */
26 unsigned excess, /* Image size mod 512 (valid bytes in last page) */
27 pages, /* # 512-byte pages in image */
28 relo_ct, /* Count of relocation table entries */
29 hdr_size, /* Size of header, in paragraphs */
30 min_mem, /* Min required memory */
31 max_mem, /* Max required memory */
32 ss, /* Stack seg offset in load module */
33 sp, /* Initial value of SP */
34 cksum, /* File checksum */
35 ip, /* Initial value of IP */
36 cs, /* CS offset in load module */
37 relo_start, /* Offset of first relo item */
38 ovl_num; /* Overlay number */
39 } xh;
40
41 FILE *fi, /* Input file stream */
42 *fo; /* Output file stream */
43
44 char fin[129], /* Input file name */
45 fon[129]; /* Output file name */
46
47
48 unsigned long code_start, /* Offset of program image in EXE file */
49 code_size; /* Size of program image, in bytes */
50
51
52 void err_xit (unsigned code);
53 void convert (void);
54 void read_hdr(void);
55 void init (unsigned argc, char *argv[]);
56
57 char *lower (char *cp)
58 {
59 char *cp0;
60 for (cp0=cp; (*cp=tolower (*cp)) != 0; ++cp)
61 ;
62 return cp0;
63 }
64
65 void cdecl main(unsigned argc, char *argv[])
66 {
67 init (argc, argv);
68 read_hdr ();
69 convert ();
70 }
71
72
73 /*
74 ** Initialize - get filenames and open/create files
75 */
76 void init (unsigned argc, char *argv[])
77 {
78 char *cp;
79
80 printf ("exe2com 1.01\n");
81
82 /* Check arg count */
83 if (argc < 2 || argc > 3) {
84 fprintf (stderr, "usage: exe2com file [file]\n");
85 exit (1);
86 }
87
88 /* If argv[1] (the input file) has no extension, add .EXE */
89 strcpy (fin, lower (argv[1]));
90 if (!strchr (fin, '.'))
91 strcat (fin, ".exe");
92
93 /* Get or construct output file name */
94 if (argc == 3)
95 strcpy (fon, lower (argv[2]));
96 else
97 strcpy (fon, fin);
98
99 /* Check output extension--change EXE to COM, or add COM */
100 if (!(cp = strchr (fon, '.')))
101 strcat (fon, ".com");
102 else if (strcmp (cp, ".exe") == 0)
103 strcpy (cp, ".com");
104
105 #ifdef DEBUG
106 printf ("input=%s, output=%s\n", fin, fon);
107 #endif
108
109 /* Try to open input file */
110 if (!(fi = fopen (fin, "rb"))) {
111 fprintf (stderr, "exe2com: can't find input file %s\n", fin);
112 exit (1);
113 }
114
115 /* Try to create output file */
116 if (!(fo = fopen (fon, "wb"))) {
117 fprintf (stderr, "exe2com: can't open output file %s\n", fin);
118 exit (1);
119 }
120 }
121
122
123 /*
124 ** Read and check the EXE file header
125 */
126 void read_hdr(void)
127 {
128
129 /* Read the formatted portion of the header */
130 if (!fread (&xh, sizeof (struct exe_header), 1, fi))
131 err_xit (BADREAD);
132
133 #ifdef DEBUG
134 printf ("EXE file header:\n");
135 printf (" signature %c%c\n", xh.exe_sig[0], xh.exe_sig[1]);
136 printf (" bytes last pg %04x\n", xh.excess);
137 printf (" pages %04x\n", xh.pages);
138 printf (" relo count %04x\n", xh.relo_ct);
139 printf (" header size %04x\n", xh.hdr_size);
140 printf (" min mem %04x\n", xh.min_mem);
141 printf (" max mem %04x\n", xh.max_mem);
142 printf (" ss %04x\n", xh.ss);
143 printf (" sp %04x\n", xh.sp);
144 printf (" checksum %04x\n", xh.cksum);
145 printf (" ip %04x\n", xh.ip);
146 printf (" cs %04x\n", xh.cs);
147 printf (" relo tbl start %04x\n", xh.relo_start);
148 printf (" overlay nbr %04x\n", xh.ovl_num);
149 #endif
150
151 /* Check header; to be convertible, must have:
152 ** -- first two bytes == "MZ"
153 ** -- no relocatable items
154 ** -- no stack segment
155 ** -- no code segment
156 ** -- IP == 0 or 100
157 */
158 if (strncmp (xh.exe_sig, "MZ", 2))
159 err_xit (BADSIG);
160 if (xh.relo_ct)
161 err_xit (HASRELO);
162 if (xh.ss || xh.sp)
163 err_xit (HAS_SS);
164 if (xh.ip != 0 && xh.ip != 0x100)
165 err_xit (BAD_IP);
166
167 /* Compute offset of program image in module, and program size.
168 **
169 ** The program size is computed as follows; it cannot exceed 64K bytes:
170 ** 512 * (# EXE pages - 1)
171 ** + valid bytes in last EXE page
172 ** - offset of program image in EXE file
173 **
174 ** Note that if the IP is nonzero, we will skip the first
175 ** IP bytes of the program image, and copy IP bytes fewer
176 ** than the actual size.
177 */
178 code_start = ((unsigned long) xh.hdr_size) << 4;
179 code_size = (unsigned long) (xh.pages-1) * 512 + xh.excess - code_start;
180 if (code_size >= 65536L)
181 err_xit (TOO_BIG);
182
183 /* Issue a warning if COM file and IP != 0x100 */
184 if (!strcmp (strchr (fon, '.'), ".com") && xh.ip != 0x100)
185 fprintf (stderr, "exe2com warning: COM file, initial IP not 100H\n");
186
187 }
188
189
190
191 /*
192 ** Convert the file. Nothing to do, really, other than
193 ** reading the image (which follows the header), and
194 ** dumping it back out to disk.
195 */
196 void convert (void)
197 {
198 char buffer[512];
199 unsigned wsize;
200
201 /* Seek to start of program image, skipping IP bytes */
202 if (fseek (fi, code_start+xh.ip, 0) != 0)
203 err_xit (BADREAD);
204
205 /* Reduce the "remaining" byte count by IP bytes */
206 code_size -= xh.ip;
207
208 /* Read blocks and copy to output */
209 while (code_size) {
210
211 /* Read block */
212 if (!fread (buffer, 1, 512, fi))
213 err_xit (BADREAD);
214
215 /* Set count of bytes to write, write block */
216 wsize = (unsigned) (code_size > 512 ? 512 : code_size);
217 if (!fwrite (buffer, wsize, 1, fo))
218 err_xit (BADWRITE);
219
220 /* Subtract bytes written from remaining byte count */
221 code_size -= wsize;
222 }
223
224 /* All done, close the two files */
225 fclose (fi);
226 fclose (fo);
227 }
228
229
230 /*
231 ** Display an error message, delete output file, exit.
232 */
233 void err_xit (unsigned code)
234 {
235 char msg[64];
236
237 switch (code) {
238 case BADREAD: strcpy (msg, "error reading EXE header");
239 break;
240 case BADWRITE: strcpy (msg, "error writing output file");
241 break;
242 case BADSIG: strcpy (msg, "invalid EXE file signature");
243 break;
244 case HASRELO: strcpy (msg, "EXE has relocatable items");
245 break;
246 case HAS_SS: strcpy (msg, "EXE has stack segment");
247 break;
248 case HAS_CS: strcpy (msg, "EXE has nonzero CS");
249 break;
250 case BAD_IP: strcpy (msg, "IP not 0 or 100H");
251 break;
252 case TOO_BIG: strcpy (msg, "program exceeds 64K");
253 break;
254 default: strcpy (msg, "unknown error");
255 }
256
257 fprintf (stderr, "exe2com: %s, can't convert\n", msg);
258
259 /* Close two files and delete partial output */
260 fclose (fi);
261 fclose (fo);
262 unlink (fon);
263
264 /* Exit with errorlevel 1 */
265 exit (1);
266 }
浙公网安备 33010602011771号