]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/doscmd/exe.c
Enable the new libmp in the build, and disable libgmp and its
[FreeBSD/FreeBSD.git] / usr.bin / doscmd / exe.c
1 /*
2  * Copyright (c) 1992, 1993, 1996
3  *      Berkeley Software Design, Inc.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by Berkeley Software
16  *      Design, Inc.
17  *
18  * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  *      BSDI exe.c,v 2.2 1996/04/08 19:32:34 bostic Exp
31  * $FreeBSD$
32  */
33
34 #include <sys/types.h>
35 #include <sys/uio.h>
36 #include <ctype.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <unistd.h>
40
41 #include "doscmd.h"
42
43 /* exports */
44 int     pspseg;
45 int     curpsp = 0;
46
47 /* locals */
48 static int              psp_s[10] = { 0 };
49 static int              env_s[10];
50 static regcontext_t     frames[10];
51
52 static int
53 make_environment (char *cmdname, char **env)
54 {
55     int i;
56     int total;
57     int len;
58     int envseg;
59     char *p;
60     char *env_block;
61
62     total = 0;
63     for (i = 0; env[i]; i++) {
64         debug (D_EXEC,"env: %s\n", env[i]);
65         len = strlen (env[i]);
66         if (total + len >= 32 * 1024)
67             break;
68         total += len + 1;
69     }
70
71     total++; /* terminating null */
72     total += 2; /* word count */
73     total += strlen (cmdname) + 1;
74     total += 4; /* some more zeros, just in case */
75
76     if ((envseg = mem_alloc(total/16 + 1, 1, NULL)) == 0)
77         fatal("out of memory for env\n");
78
79     env_block = (char *)MAKEPTR(envseg, 0);
80     memset (env_block, 0, total);
81
82     p = env_block;
83     total = 0;
84     for (i = 0; env[i]; i++) {
85         len = strlen (env[i]);
86         if (total + len >= 32 * 1024)
87             break;
88         total += len + 1;
89         strcpy (p, env[i]);
90         p += strlen (p) + 1;
91     }   
92     *p++ = 0;
93     *(short *)p = strlen(cmdname);
94     p += 2;
95     strcpy (p, cmdname);
96     while(*p) {
97         if (*p == '/')
98             *p = '\\';
99         else if (islower(*p))
100             *p = toupper(*p);
101         p++;
102     }
103     *p = '\0';
104     return(envseg);
105 }
106
107 static void
108 load_com(int fd, int start_segment)
109 {
110     char *start_addr;
111     int i;
112
113     start_addr = (char *)MAKEPTR(start_segment, 0);
114
115     lseek (fd, 0, 0);
116     i = read (fd, start_addr, 0xff00);
117
118     debug(D_EXEC, "Read %05x into %04x\n",
119           i, start_segment);
120 }
121
122 static void
123 load_exe(int fd, int start_segment, int reloc_segment, struct exehdr *hdr, int text_size)
124 {
125     char *start_addr;
126     int reloc_size;
127     struct reloc_entry *reloc_tbl, *rp;
128     u_short *segp;
129     int i;
130
131     start_addr = (char *)MAKEPTR(start_segment, 0);
132
133     lseek (fd, hdr->hdr_size * 16, 0);
134     if (read (fd, start_addr, text_size) != text_size)
135         fatal ("error reading program text\n");
136     debug(D_EXEC, "Read %05x into %04x\n",
137           text_size, start_segment);
138
139     if (hdr->nreloc) {
140         reloc_size = hdr->nreloc * sizeof (struct reloc_entry);
141
142         if ((reloc_tbl = (struct reloc_entry *)malloc (reloc_size)) == NULL)
143             fatal ("out of memory for program\n");
144
145         lseek (fd, hdr->reloc_offset, 0);
146         if (read (fd, reloc_tbl, reloc_size) != reloc_size)
147             fatal ("error reading reloc table\n");
148
149         for (i = 0, rp = reloc_tbl; i < hdr->nreloc; i++, rp++) {
150             segp = (u_short *)MAKEPTR(start_segment + rp->seg, rp->off);
151             *segp += start_segment;
152         }
153         free((char *)reloc_tbl);
154     }
155 }
156
157 void
158 load_command(regcontext_t *REGS, int run, int fd, char *cmdname, 
159              u_short *param, char **argv, char **envs)
160 {
161     struct exehdr hdr;
162     int min_memory, max_memory;
163     int biggest;
164     int envseg;
165     char *psp;
166     int text_size;
167     int i;
168     int start_segment;
169     int exe_file;
170     char *p;
171     int used, n;
172     char *fcb;
173     int newpsp;
174     u_short init_cs, init_ip, init_ss, init_sp, init_ds, init_es;
175
176     if (envs)
177         envseg = make_environment(cmdname, envs);
178     else
179         envseg = env_s[curpsp];
180
181     /* read exe header */
182     if (read (fd, &hdr, sizeof hdr) != sizeof hdr)
183         fatal ("can't read header\n");
184     
185     /* proper header ? */
186     if (hdr.magic == 0x5a4d) {
187         exe_file = 1;
188         text_size = (hdr.size - 1) * 512 + hdr.bytes_on_last_page
189             - hdr.hdr_size * 16;
190         min_memory = hdr.min_memory + (text_size + 15)/16;
191         max_memory = hdr.max_memory + (text_size + 15)/16;
192     } else {
193         exe_file = 0;
194         min_memory = 64 * (1024/16);
195         max_memory = 0xffff;
196     }
197     
198     /* alloc mem block */
199     pspseg = mem_alloc(max_memory, 1, &biggest);
200     if (pspseg == 0) {
201         if (biggest < min_memory ||
202             (pspseg = mem_alloc(biggest, 1, NULL)) == 0)
203             fatal("not enough memory: needed %d have %d\n",
204                   min_memory, biggest);
205         
206         max_memory = biggest;
207     }
208     
209     mem_change_owner(pspseg, pspseg);
210     mem_change_owner(envseg, pspseg);
211     
212     /* create psp */
213     newpsp = curpsp + 1;
214     psp_s[newpsp] = pspseg;
215     env_s[newpsp] = envseg;
216     
217     psp = (char *)MAKEPTR(pspseg, 0);
218     memset(psp, 0, 256);
219     
220     psp[0] = 0xcd;
221     psp[1] = 0x20;
222
223     *(u_short *)&psp[2] = pspseg + max_memory;
224     
225     /*
226      * this is supposed to be a long call to dos ... try to fake it
227      */
228     psp[5] = 0xcd;
229     psp[6] = 0x99;
230     psp[7] = 0xc3;
231     
232     *(u_short *)&psp[0x16] = psp_s[curpsp];
233     psp[0x18] = 1;
234     psp[0x19] = 1;
235     psp[0x1a] = 1;
236     psp[0x1b] = 0;
237     psp[0x1c] = 2;
238     memset(psp + 0x1d, 0xff, 15);
239     
240     *(u_short *)&psp[0x2c] = envseg;
241     
242     *(u_short *)&psp[0x32] = 20;
243     *(u_long *)&psp[0x34] = MAKEVEC(pspseg, 0x18);
244     *(u_long *)&psp[0x38] = 0xffffffff;
245     
246     psp[0x50] = 0xcd;
247     psp[0x51] = 0x98;
248     psp[0x52] = 0xc3;
249     
250     p = psp + 0x81;
251     *p = 0;
252     used = 0;
253     for (i = 0; argv[i]; i++) {
254         n = strlen(argv[i]);
255         if (used + 1 + n > 0x7d)
256             break;
257         *p++ = ' ';
258         memcpy(p, argv[i], n);
259         p += n;
260         used += n;
261     }
262
263     psp[0x80] = strlen(psp + 0x81);
264     psp[0x81 + psp[0x80]] = 0x0d;
265     psp[0x82 + psp[0x80]] = 0;
266     
267     p = psp + 0x81;
268     parse_filename(0x00, p, psp + 0x5c, &n);
269     p += n;
270     parse_filename(0x00, p, psp + 0x6c, &n);
271     
272     if (param[4]) {
273         fcb = (char *)MAKEPTR(param[4], param[3]);
274         memcpy(psp + 0x5c, fcb, 16);
275     }
276     if (param[6]) {
277         fcb = (char *)MAKEPTR(param[6], param[5]);
278         memcpy(psp + 0x6c, fcb, 16);
279     }
280
281 #if 0
282     printf("005c:");
283     for (n = 0; n < 16; n++)
284         printf(" %02x", psp[0x5c + n]);
285     printf("\n");
286     printf("006c:");
287     for (n = 0; n < 16; n++)
288         printf(" %02x", psp[0x6c + n]);
289     printf("\n");
290 #endif
291
292     disk_transfer_addr = MAKEVEC(pspseg, 0x80);
293     
294     start_segment = pspseg + 0x10;
295     
296     if (!exe_file) {
297         load_com(fd, start_segment);
298
299         init_cs = pspseg;
300         init_ip = 0x100;
301         init_ss = init_cs;
302         init_sp = 0xfffe;
303         init_ds = init_cs;
304         init_es = init_cs;
305     } else {
306         load_exe(fd, start_segment, start_segment, &hdr, text_size);
307         
308         init_cs = hdr.init_cs + start_segment;
309         init_ip = hdr.init_ip;
310         init_ss = hdr.init_ss + start_segment;
311         init_sp = hdr.init_sp;
312         init_ds = pspseg;
313         init_es = init_ds;
314     }
315
316     debug(D_EXEC, "cs:ip = %04x:%04x, ss:sp = %04x:%04x, "
317           "ds = %04x, es = %04x\n",
318           init_cs, init_ip, init_ss, init_sp, init_ds, init_es);
319     
320     if (run) {
321         frames[newpsp] = *REGS;
322         curpsp = newpsp;
323         
324         R_EFLAGS = 0x20202;
325         R_CS = init_cs;
326         R_IP = init_ip;
327         R_SS = init_ss;
328         R_SP = init_sp;
329         R_DS = init_ds;
330         R_ES = init_es;
331
332         R_AX = R_BX = R_CX = R_DX = R_SI = R_DI = R_BP = 0;
333
334     } else {
335         param[7] = init_sp;
336         param[8] = init_ss;
337         param[9] = init_ip;
338         param[10] = init_cs;
339     }
340 }
341
342 void
343 load_overlay(int fd, int start_segment, int reloc_segment)
344 {
345     struct exehdr hdr;
346     int text_size;
347     int exe_file;
348
349     /* read exe header */
350     if (read (fd, &hdr, sizeof hdr) != sizeof hdr)
351         fatal ("can't read header\n");
352     
353     /* proper header ? */
354     if (hdr.magic == 0x5a4d) {
355         exe_file = 1;
356         text_size = (hdr.size - 1) * 512 + hdr.bytes_on_last_page
357             - hdr.hdr_size * 16;
358     } else {
359         exe_file = 0;
360     }
361
362     if (!exe_file)
363         load_com(fd, start_segment);
364     else
365         load_exe(fd, start_segment, reloc_segment, &hdr, text_size);
366 }
367
368 int
369 get_env(void)
370 {
371     return(env_s[curpsp]);
372 }
373
374 void
375 exec_command(regcontext_t *REGS, int run,
376              int fd, char *cmdname, u_short *param)
377 {
378     char *arg;
379     char *env;
380     char *argv[2];
381     char *envs[100];
382
383     env = (char *)MAKEPTR(param[0], 0);
384     arg = (char *)MAKEPTR(param[2], param[1]);
385
386     if (arg) {
387         int nbytes = *arg++;
388         arg[nbytes] = 0;
389         if (!*arg)
390             arg = NULL;
391     }
392     argv[0] = arg;
393     argv[1] = NULL;
394
395     debug (D_EXEC, "exec_command: cmdname = %s\n"
396                    "env = 0x0%x, arg = %04x:%04x(%s)\n",
397         cmdname, param[0], param[2], param[1], arg);
398
399     if (env) {
400         int i;
401         for ( i=0; i < 99 && *env; ++i ) {
402             envs[i] = env;
403             env += strlen(env)+1;
404         }
405         envs[i] = NULL;
406         load_command(REGS, run, fd, cmdname, param, argv, envs);
407     } else
408         load_command(REGS, run, fd, cmdname, param, argv, NULL);
409 }
410
411 void
412 exec_return(regcontext_t *REGS, int code)
413 {
414     debug(D_EXEC, "Returning from exec\n");
415     mem_free_owner(psp_s[curpsp]);
416     *REGS = frames[curpsp--];
417     R_AX = code;
418     R_FLAGS &= ~PSL_C;          /* It must have worked */
419 }