2000-05-06 21:34:20 +02:00
|
|
|
/****************************************************************/
|
|
|
|
/* */
|
|
|
|
/* task.c */
|
|
|
|
/* */
|
|
|
|
/* Task Manager for DOS Processes */
|
|
|
|
/* */
|
|
|
|
/* Copyright (c) 1995 */
|
|
|
|
/* Pasquale J. Villani */
|
|
|
|
/* All Rights Reserved */
|
|
|
|
/* */
|
|
|
|
/* This file is part of DOS-C. */
|
|
|
|
/* */
|
|
|
|
/* DOS-C is free software; you can redistribute it and/or */
|
|
|
|
/* modify it under the terms of the GNU General Public License */
|
|
|
|
/* as published by the Free Software Foundation; either version */
|
|
|
|
/* 2, or (at your option) any later version. */
|
|
|
|
/* */
|
|
|
|
/* DOS-C is distributed in the hope that it will be useful, but */
|
|
|
|
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
|
|
|
|
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
|
|
|
|
/* the GNU General Public License for more details. */
|
|
|
|
/* */
|
|
|
|
/* You should have received a copy of the GNU General Public */
|
|
|
|
/* License along with DOS-C; see the file COPYING. If not, */
|
|
|
|
/* write to the Free Software Foundation, 675 Mass Ave, */
|
|
|
|
/* Cambridge, MA 02139, USA. */
|
|
|
|
/****************************************************************/
|
|
|
|
|
|
|
|
#include "portab.h"
|
|
|
|
#include "globals.h"
|
|
|
|
|
|
|
|
#ifdef VERSION_STRINGS
|
2001-11-18 15:01:12 +01:00
|
|
|
static BYTE *RcsId =
|
|
|
|
"$Id$";
|
2000-05-06 21:34:20 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#define toupper(c) ((c) >= 'a' && (c) <= 'z' ? (c) + ('A' - 'a') : (c))
|
|
|
|
|
|
|
|
#define LOADNGO 0
|
|
|
|
#define LOAD 1
|
|
|
|
#define OVERLAY 3
|
|
|
|
|
2001-03-30 21:30:06 +02:00
|
|
|
#define LOAD_HIGH 0x80
|
|
|
|
|
2000-05-06 21:34:20 +02:00
|
|
|
static exe_header header;
|
|
|
|
|
|
|
|
#define CHUNK 32256
|
2001-04-15 05:21:50 +02:00
|
|
|
#define MAXENV 32768u
|
2000-05-06 21:34:20 +02:00
|
|
|
#define ENV_KEEPFREE 83 /* keep unallocated by environment variables */
|
2001-11-18 15:01:12 +01:00
|
|
|
/* The '65' added to nEnvSize does not cover the additional stuff:
|
|
|
|
+ 2 bytes: number of strings
|
|
|
|
+ 80 bytes: maximum absolute filename
|
|
|
|
+ 1 byte: '\0'
|
|
|
|
-- 1999/04/21 ska */
|
2000-05-06 21:34:20 +02:00
|
|
|
|
|
|
|
#ifndef PROTO
|
|
|
|
COUNT ChildEnv(exec_blk FAR *, UWORD *, char far *);
|
|
|
|
#else
|
|
|
|
COUNT ChildEnv();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
LONG doslseek(COUNT fd, LONG foffset, COUNT origin)
|
|
|
|
{
|
|
|
|
LONG set_pos;
|
|
|
|
DosSeek(fd, foffset, origin, (ULONG *) & set_pos);
|
|
|
|
return set_pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
LONG DosGetFsize(COUNT hndl)
|
|
|
|
{
|
|
|
|
sft FAR *s;
|
2001-03-30 21:30:06 +02:00
|
|
|
/* sfttbl FAR *sp;*/
|
2000-05-06 21:34:20 +02:00
|
|
|
|
|
|
|
/* Get the SFT block that contains the SFT */
|
|
|
|
if ((s = get_sft(hndl)) == (sft FAR *) - 1)
|
|
|
|
return DE_INVLDHNDL;
|
|
|
|
|
|
|
|
/* If this is not opened another error */
|
|
|
|
if (s->sft_count == 0)
|
|
|
|
return DE_ACCESS;
|
|
|
|
|
|
|
|
/* If SFT entry refers to a device, return the date and time of opening */
|
|
|
|
if (s->sft_flags & (SFT_FDEVICE | SFT_FSHARED))
|
|
|
|
{
|
|
|
|
return s->sft_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* call file system handler */
|
|
|
|
return dos_getfsize(s->sft_status);
|
|
|
|
}
|
|
|
|
|
2001-11-18 15:01:12 +01:00
|
|
|
COUNT ChildEnv(exec_blk FAR * exp, UWORD * pChildEnvSeg,
|
|
|
|
char far * pathname)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
|
|
|
BYTE FAR *pSrc;
|
|
|
|
BYTE FAR *pDest;
|
|
|
|
UWORD nEnvSize;
|
|
|
|
COUNT RetCode;
|
|
|
|
/* UWORD MaxEnvSize; not used -- 1999/04/21 ska */
|
|
|
|
psp FAR *ppsp = MK_FP(cu_psp, 0);
|
|
|
|
|
|
|
|
/* create a new environment for the process */
|
|
|
|
/* copy parent's environment if exec.env_seg == 0 */
|
|
|
|
|
2001-06-03 16:16:18 +02:00
|
|
|
pSrc = exp->exec.env_seg ?
|
2001-11-18 15:01:12 +01:00
|
|
|
MK_FP(exp->exec.env_seg, 0) : MK_FP(ppsp->ps_environ, 0);
|
2000-05-06 21:34:20 +02:00
|
|
|
|
|
|
|
#if 0
|
|
|
|
/* Every process requires an environment because of argv[0]
|
|
|
|
-- 1999/04/21 ska */
|
2001-11-18 15:01:12 +01:00
|
|
|
*/if (!pSrc) /* no environment to copy */
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
|
|
|
*pChildEnvSeg = 0;
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
nEnvSize = 1;
|
|
|
|
/* This loop had not counted the very last '\0'
|
|
|
|
-- 1999/04/21 ska */
|
|
|
|
if (pSrc)
|
|
|
|
{ /* if no environment is available, one byte is required */
|
2001-11-18 15:01:12 +01:00
|
|
|
|
|
|
|
for (nEnvSize = 0;; nEnvSize++)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2001-11-18 15:01:12 +01:00
|
|
|
/* Test env size and abort if greater than max */
|
|
|
|
if (nEnvSize >= MAXENV - ENV_KEEPFREE)
|
|
|
|
return DE_INVLDENV;
|
|
|
|
|
|
|
|
if (*(UWORD FAR *) (pSrc + nEnvSize) == 0)
|
|
|
|
break;
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
2001-06-03 16:16:18 +02:00
|
|
|
nEnvSize += 2; /* account for trailing \0\0 */
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* allocate enough space for env + path */
|
|
|
|
if ((RetCode = DosMemAlloc(long2para(nEnvSize + ENV_KEEPFREE),
|
2001-03-19 05:50:56 +01:00
|
|
|
mem_access_mode, (seg FAR *) pChildEnvSeg,
|
2001-11-18 15:01:12 +01:00
|
|
|
NULL /*(UWORD FAR *) MaxEnvSize ska */ )) < 0)
|
2000-05-06 21:34:20 +02:00
|
|
|
return RetCode;
|
|
|
|
pDest = MK_FP(*pChildEnvSeg + 1, 0);
|
|
|
|
|
|
|
|
/* fill the new env and inform the process of its */
|
|
|
|
/* location throught the psp */
|
|
|
|
|
|
|
|
/* copy the environment */
|
|
|
|
if (pSrc)
|
|
|
|
{
|
2001-11-18 00:26:45 +01:00
|
|
|
fmemcpy(pDest, pSrc, nEnvSize);
|
2000-05-06 21:34:20 +02:00
|
|
|
pDest += nEnvSize;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
*pDest++ = '\0'; /* create an empty environment */
|
|
|
|
|
2001-11-18 15:01:12 +01:00
|
|
|
/* initialize 'extra strings' count */
|
2001-11-18 00:26:45 +01:00
|
|
|
*((UWORD FAR *) pDest) = 1;
|
2001-11-18 15:01:12 +01:00
|
|
|
pDest += sizeof(UWORD) / sizeof(BYTE);
|
2000-05-06 21:34:20 +02:00
|
|
|
|
|
|
|
/* copy complete pathname */
|
2001-11-18 15:01:12 +01:00
|
|
|
if ((RetCode = truename(pathname, pDest, TRUE)) != SUCCESS)
|
|
|
|
{
|
2000-05-08 06:30:00 +02:00
|
|
|
return RetCode;
|
|
|
|
}
|
2000-05-06 21:34:20 +02:00
|
|
|
|
|
|
|
/* Theoretically one could either:
|
|
|
|
+ resize the already allocated block to best-fit behind the pathname, or
|
|
|
|
+ generate the filename into a temporary buffer to allocate only the
|
|
|
|
minimum required environment -- 1999/04/21 ska */
|
|
|
|
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The following code is 8086 dependant */
|
|
|
|
VOID new_psp(psp FAR * p, int psize)
|
|
|
|
{
|
2001-11-18 15:01:12 +01:00
|
|
|
REG COUNT i;
|
2000-05-06 21:34:20 +02:00
|
|
|
psp FAR *q = MK_FP(cu_psp, 0);
|
|
|
|
|
|
|
|
/* Clear out new psp first */
|
2001-04-15 05:21:50 +02:00
|
|
|
fmemset(p, 0, sizeof(psp));
|
2000-05-06 21:34:20 +02:00
|
|
|
|
|
|
|
/* initialize all entries and exits */
|
|
|
|
/* CP/M-like exit point */
|
|
|
|
p->ps_exit = 0x20cd;
|
|
|
|
|
|
|
|
/* CP/M-like entry point - jump to special entry */
|
|
|
|
p->ps_farcall = 0xea;
|
2002-01-23 23:29:41 +01:00
|
|
|
p->ps_reentry = cpm_entry;
|
2000-05-06 21:34:20 +02:00
|
|
|
/* unix style call - 0xcd 0x21 0xcb (int 21, retf) */
|
|
|
|
p->ps_unix[0] = 0xcd;
|
|
|
|
p->ps_unix[1] = 0x21;
|
|
|
|
p->ps_unix[2] = 0xcb;
|
|
|
|
|
|
|
|
/* Now for parent-child relationships */
|
|
|
|
/* parent psp segment */
|
|
|
|
p->ps_parent = cu_psp;
|
|
|
|
/* previous psp pointer */
|
|
|
|
p->ps_prevpsp = q;
|
|
|
|
|
|
|
|
/* Environment and memory useage parameters */
|
|
|
|
/* memory size in paragraphs */
|
|
|
|
p->ps_size = psize;
|
|
|
|
/* environment paragraph */
|
|
|
|
p->ps_environ = 0;
|
|
|
|
/* process dta */
|
|
|
|
p->ps_dta = (BYTE FAR *) (&p->ps_cmd_count);
|
|
|
|
|
|
|
|
/* terminate address */
|
2002-01-23 23:29:41 +01:00
|
|
|
p->ps_isv22 = getvec(0x22);
|
2000-05-06 21:34:20 +02:00
|
|
|
/* break address */
|
2002-01-23 23:29:41 +01:00
|
|
|
p->ps_isv23 = getvec(0x23);
|
2000-05-06 21:34:20 +02:00
|
|
|
/* critical error address */
|
2002-01-23 23:29:41 +01:00
|
|
|
p->ps_isv24 = getvec(0x24);
|
2000-05-06 21:34:20 +02:00
|
|
|
|
|
|
|
/* File System parameters */
|
|
|
|
/* user stack pointer - int 21 */
|
2001-08-19 14:58:36 +02:00
|
|
|
p->ps_stack = q->ps_stack;
|
2000-05-06 21:34:20 +02:00
|
|
|
/* file table - 0xff is unused */
|
2001-11-04 20:47:39 +01:00
|
|
|
|
2000-05-06 21:34:20 +02:00
|
|
|
for (i = 0; i < 20; i++)
|
|
|
|
p->ps_files[i] = 0xff;
|
|
|
|
|
|
|
|
/* maximum open files */
|
|
|
|
p->ps_maxfiles = 20;
|
|
|
|
/* open file table pointer */
|
|
|
|
p->ps_filetab = p->ps_files;
|
|
|
|
|
|
|
|
/* clone the file table */
|
2001-11-18 15:01:12 +01:00
|
|
|
if (p != q)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
|
|
|
REG COUNT i;
|
|
|
|
|
|
|
|
for (i = 0; i < 20; i++)
|
|
|
|
{
|
|
|
|
if (q->ps_filetab[i] != 0xff && CloneHandle(i) >= 0)
|
|
|
|
p->ps_filetab[i] = q->ps_filetab[i];
|
|
|
|
else
|
|
|
|
p->ps_filetab[i] = 0xff;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* first command line argument */
|
|
|
|
p->ps_fcb1.fcb_drive = 0;
|
2002-05-09 00:49:35 +02:00
|
|
|
fmemset(p->ps_fcb1.fcb_fname, ' ', FNAME_SIZE + FEXT_SIZE);
|
2000-05-06 21:34:20 +02:00
|
|
|
/* second command line argument */
|
|
|
|
p->ps_fcb2.fcb_drive = 0;
|
2002-05-09 00:49:35 +02:00
|
|
|
fmemset(p->ps_fcb2.fcb_fname, ' ', FNAME_SIZE + FEXT_SIZE);
|
2000-05-06 21:34:20 +02:00
|
|
|
|
|
|
|
/* local command line */
|
|
|
|
p->ps_cmd_count = 0; /* command tail */
|
|
|
|
p->ps_cmd[0] = 0; /* command tail */
|
|
|
|
if (RootPsp == (seg) ~ 0)
|
|
|
|
RootPsp = FP_SEG(p);
|
|
|
|
}
|
|
|
|
|
2001-11-18 15:01:12 +01:00
|
|
|
STATIC UWORD patchPSP(UWORD pspseg, UWORD envseg, exec_blk FAR * exb,
|
2001-07-23 14:47:42 +02:00
|
|
|
BYTE FAR * fnam)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
|
|
|
psp FAR *psp;
|
|
|
|
mcb FAR *pspmcb;
|
|
|
|
int i;
|
|
|
|
BYTE FAR *np;
|
|
|
|
|
|
|
|
pspmcb = MK_FP(pspseg, 0);
|
|
|
|
++pspseg;
|
|
|
|
psp = MK_FP(pspseg, 0);
|
|
|
|
|
2001-07-23 14:47:42 +02:00
|
|
|
/* complete the psp by adding the command line and FCBs */
|
2001-11-18 00:26:45 +01:00
|
|
|
fmemcpy(psp->ps_cmd, exb->exec.cmd_line->ctBuffer, 127);
|
2002-05-09 00:49:35 +02:00
|
|
|
if (FP_OFF(exb->exec.fcb_1) != 0xffff)
|
|
|
|
{
|
|
|
|
fmemcpy(&psp->ps_fcb1, exb->exec.fcb_1, 16);
|
|
|
|
fmemcpy(&psp->ps_fcb2, exb->exec.fcb_2, 16);
|
|
|
|
}
|
2001-07-23 14:47:42 +02:00
|
|
|
psp->ps_cmd_count = exb->exec.cmd_line->ctCount;
|
2000-05-06 21:34:20 +02:00
|
|
|
|
|
|
|
/* identify the mcb as this functions' */
|
|
|
|
pspmcb->m_psp = pspseg;
|
|
|
|
/* Patch in environment segment, if present, also adjust its MCB */
|
|
|
|
if (envseg)
|
|
|
|
{
|
|
|
|
psp->ps_environ = envseg + 1;
|
|
|
|
((mcb FAR *) MK_FP(envseg, 0))->m_psp = pspseg;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
psp->ps_environ = 0;
|
|
|
|
|
|
|
|
/* use the file name less extension - left adjusted and */
|
|
|
|
np = fnam;
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
switch (*fnam++)
|
|
|
|
{
|
|
|
|
case '\0':
|
|
|
|
goto set_name;
|
|
|
|
case ':':
|
|
|
|
case '/':
|
|
|
|
case '\\':
|
|
|
|
np = fnam;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
set_name:
|
|
|
|
for (i = 0; i < 8 && np[i] != '.' && np[i] != '\0'; i++)
|
|
|
|
{
|
|
|
|
pspmcb->m_name[i] = toupper(np[i]);
|
|
|
|
}
|
|
|
|
if (i < 8)
|
|
|
|
pspmcb->m_name[i] = '\0';
|
|
|
|
|
2001-07-23 14:47:42 +02:00
|
|
|
/* return value: AX value to be passed based on FCB values */
|
2001-11-18 15:01:12 +01:00
|
|
|
return ((psp->ps_fcb1.fcb_drive < lastdrive &&
|
|
|
|
CDSp->cds_table[psp->ps_fcb1.fcb_drive].
|
|
|
|
cdsFlags & CDSVALID) ? 0 : 0xff) + ((psp->ps_fcb2.fcb_drive <
|
|
|
|
lastdrive
|
|
|
|
&& CDSp->cds_table[psp->
|
|
|
|
ps_fcb2.
|
|
|
|
fcb_drive].
|
|
|
|
cdsFlags & CDSVALID) ? 0 :
|
|
|
|
0xff) * 0x100;
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
|
2001-03-21 03:56:26 +01:00
|
|
|
COUNT DosComLoader(BYTE FAR * namep, exec_blk FAR * exp, COUNT mode)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2001-04-22 00:32:53 +02:00
|
|
|
COUNT rc
|
2001-11-18 15:01:12 +01:00
|
|
|
/* err */
|
|
|
|
/*,env_size */ ;
|
2000-05-06 21:34:20 +02:00
|
|
|
COUNT nread;
|
|
|
|
UWORD mem;
|
2001-11-18 15:01:12 +01:00
|
|
|
UWORD env, asize;
|
2000-05-06 21:34:20 +02:00
|
|
|
BYTE FAR *sp;
|
|
|
|
psp FAR *p;
|
|
|
|
psp FAR *q = MK_FP(cu_psp, 0);
|
|
|
|
iregs FAR *irp;
|
|
|
|
LONG com_size;
|
|
|
|
|
2001-11-18 15:01:12 +01:00
|
|
|
int ModeLoadHigh = mode & 0x80;
|
|
|
|
UBYTE UMBstate = uppermem_link;
|
2001-03-30 21:30:06 +02:00
|
|
|
|
|
|
|
mode &= 0x7f;
|
|
|
|
|
2000-05-06 21:34:20 +02:00
|
|
|
if (mode != OVERLAY)
|
|
|
|
{
|
|
|
|
|
|
|
|
if ((rc = ChildEnv(exp, &env, namep)) != SUCCESS)
|
|
|
|
{
|
|
|
|
return rc;
|
|
|
|
}
|
2001-11-18 15:01:12 +01:00
|
|
|
|
|
|
|
/* COMFILES will always be loaded in largest area. is that true TE */
|
|
|
|
|
2001-03-19 05:50:56 +01:00
|
|
|
/* Now find out how many paragraphs are available */
|
|
|
|
if ((rc = DosMemLargest((seg FAR *) & asize)) != SUCCESS)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2001-03-19 05:50:56 +01:00
|
|
|
DosMemFree(env);
|
2000-05-06 21:34:20 +02:00
|
|
|
return rc;
|
|
|
|
}
|
2001-03-19 05:50:56 +01:00
|
|
|
com_size = asize;
|
2001-11-18 15:01:12 +01:00
|
|
|
|
|
|
|
if (ModeLoadHigh)
|
|
|
|
{
|
|
|
|
DosUmbLink(1); /* link in UMB's */
|
|
|
|
}
|
|
|
|
|
2001-03-19 05:50:56 +01:00
|
|
|
/* Allocate our memory and pass back any errors */
|
2001-11-18 15:01:12 +01:00
|
|
|
if ((rc =
|
|
|
|
DosMemAlloc((seg) com_size, mem_access_mode, (seg FAR *) & mem,
|
|
|
|
(UWORD FAR *) & asize)) < 0)
|
2001-03-19 05:50:56 +01:00
|
|
|
{
|
2001-11-18 15:01:12 +01:00
|
|
|
if (rc == DE_NOMEM)
|
|
|
|
{
|
|
|
|
if ((rc =
|
|
|
|
DosMemAlloc(0, LARGEST, (seg FAR *) & mem,
|
|
|
|
(UWORD FAR *) & asize)) < 0)
|
2001-03-19 05:50:56 +01:00
|
|
|
{
|
2001-11-18 15:01:12 +01:00
|
|
|
DosMemFree(env);
|
|
|
|
return rc;
|
2001-03-19 05:50:56 +01:00
|
|
|
}
|
2001-11-18 15:01:12 +01:00
|
|
|
/* This should never happen, but ... */
|
|
|
|
if (asize < com_size)
|
2001-03-19 05:50:56 +01:00
|
|
|
{
|
2001-11-18 15:01:12 +01:00
|
|
|
DosMemFree(mem);
|
|
|
|
DosMemFree(env);
|
|
|
|
return rc;
|
2001-03-19 05:50:56 +01:00
|
|
|
}
|
2001-11-18 15:01:12 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DosMemFree(env); /* env may be 0 */
|
|
|
|
return rc;
|
|
|
|
}
|
2001-03-19 05:50:56 +01:00
|
|
|
}
|
2000-05-06 21:34:20 +02:00
|
|
|
++mem;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
mem = exp->load.load_seg;
|
2001-11-18 15:01:12 +01:00
|
|
|
|
|
|
|
if (ModeLoadHigh)
|
|
|
|
{
|
|
|
|
DosUmbLink(UMBstate); /* restore link state */
|
|
|
|
}
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2002-01-23 23:29:41 +01:00
|
|
|
#ifdef DEBUG
|
|
|
|
printf("DosComLoader. Loading '%S' at %04x\n", namep, mem);
|
|
|
|
#endif
|
2000-05-06 21:34:20 +02:00
|
|
|
/* Now load the executable */
|
|
|
|
/* If file not found - error */
|
|
|
|
/* NOTE - this is fatal because we lost it in transit */
|
|
|
|
/* from DosExec! */
|
|
|
|
if ((rc = DosOpen(namep, 0)) < 0)
|
|
|
|
fatal("(DosComLoader) com file lost in transit");
|
|
|
|
|
|
|
|
/* do it in 32K chunks */
|
|
|
|
if ((com_size = DosGetFsize(rc)) != 0)
|
|
|
|
{
|
|
|
|
if (mode == OVERLAY) /* memory already allocated */
|
|
|
|
sp = MK_FP(mem, 0);
|
|
|
|
else
|
2001-11-18 15:01:12 +01:00
|
|
|
{ /* test the filesize against the allocated memory */
|
|
|
|
|
2000-05-06 21:34:20 +02:00
|
|
|
sp = MK_FP(mem, sizeof(psp));
|
|
|
|
|
|
|
|
/* This is a potential problem, what to do with .COM files larger than
|
|
|
|
the allocated memory?
|
|
|
|
MS DOS always only loads the very first 64KB - sizeof(psp) bytes.
|
|
|
|
-- 1999/04/21 ska */
|
2001-11-18 15:01:12 +01:00
|
|
|
|
|
|
|
/* BUG !! in case of LH, memory may be smaller then 64K TE */
|
|
|
|
|
|
|
|
if (com_size > ((LONG) asize << 4)) /* less memory than the .COM file has */
|
|
|
|
com_size = (LONG) asize << 4;
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
do
|
|
|
|
{
|
2001-04-22 00:32:53 +02:00
|
|
|
nread = DosRead(rc, CHUNK, sp, &UnusedRetVal);
|
2000-05-06 21:34:20 +02:00
|
|
|
sp = add_far((VOID FAR *) sp, (ULONG) nread);
|
|
|
|
}
|
|
|
|
while ((com_size -= nread) > 0 && nread == CHUNK);
|
|
|
|
}
|
|
|
|
DosClose(rc);
|
|
|
|
|
|
|
|
if (mode == OVERLAY)
|
|
|
|
return SUCCESS;
|
|
|
|
|
|
|
|
/* point to the PSP so we can build it */
|
|
|
|
p = MK_FP(mem, 0);
|
2002-01-23 23:29:41 +01:00
|
|
|
setvec(0x22, MK_FP(user_r->CS, user_r->IP));
|
2000-05-06 21:34:20 +02:00
|
|
|
new_psp(p, mem + asize);
|
|
|
|
|
2001-11-18 15:01:12 +01:00
|
|
|
asize = patchPSP(mem - 1, env, exp, namep); /* asize=fcbcode for ax */
|
2000-05-06 21:34:20 +02:00
|
|
|
|
|
|
|
/* Transfer control to the executable */
|
|
|
|
p->ps_parent = cu_psp;
|
|
|
|
p->ps_prevpsp = (BYTE FAR *) MK_FP(cu_psp, 0);
|
|
|
|
q->ps_stack = (BYTE FAR *) user_r;
|
|
|
|
user_r->FLAGS &= ~FLG_CARRY;
|
2001-07-23 14:47:42 +02:00
|
|
|
cu_psp = mem;
|
|
|
|
dta = p->ps_dta;
|
2000-05-06 21:34:20 +02:00
|
|
|
|
|
|
|
switch (mode)
|
|
|
|
{
|
|
|
|
case LOADNGO:
|
|
|
|
{
|
2001-11-18 15:01:12 +01:00
|
|
|
/* BUG !!
|
|
|
|
this works only, if COMSIZE >= 64K
|
|
|
|
in case of LH, this is not necessarily true
|
|
|
|
*/
|
|
|
|
|
2001-07-23 14:47:42 +02:00
|
|
|
*((UWORD FAR *) MK_FP(mem, 0xfffe)) = (UWORD) 0;
|
2001-11-18 15:01:12 +01:00
|
|
|
|
2001-07-23 14:47:42 +02:00
|
|
|
/* build the user area on the stack */
|
|
|
|
irp = MK_FP(mem, (0xfffe - sizeof(iregs)));
|
|
|
|
|
|
|
|
/* start allocating REGs */
|
|
|
|
irp->ES = irp->DS = mem;
|
|
|
|
irp->CS = mem;
|
|
|
|
irp->IP = 0x100;
|
2001-11-18 15:01:12 +01:00
|
|
|
irp->AX = asize; /* fcbcode */
|
|
|
|
irp->BX = irp->CX = irp->DX = irp->SI = irp->DI = irp->BP = 0;
|
2001-07-23 14:47:42 +02:00
|
|
|
irp->FLAGS = 0x200;
|
2001-04-15 05:21:50 +02:00
|
|
|
|
2000-05-06 21:34:20 +02:00
|
|
|
if (InDOS)
|
|
|
|
--InDOS;
|
|
|
|
exec_user(irp);
|
|
|
|
|
2001-11-04 20:47:39 +01:00
|
|
|
/* We should never be here
|
2001-11-18 15:01:12 +01:00
|
|
|
fatal("KERNEL RETURNED!!!"); */
|
2000-05-06 21:34:20 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case LOAD:
|
2001-07-23 14:47:42 +02:00
|
|
|
exp->exec.stack = MK_FP(mem, 0xfffe);
|
2001-11-18 15:01:12 +01:00
|
|
|
*((UWORD FAR *) exp->exec.stack) = asize;
|
2001-07-23 14:47:42 +02:00
|
|
|
exp->exec.start_addr = MK_FP(mem, 0x100);
|
2000-05-06 21:34:20 +02:00
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return DE_INVLDFMT;
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID return_user(void)
|
|
|
|
{
|
2001-11-18 15:01:12 +01:00
|
|
|
psp FAR *p, FAR * q;
|
2000-05-06 21:34:20 +02:00
|
|
|
REG COUNT i;
|
|
|
|
iregs FAR *irp;
|
2001-03-30 21:30:06 +02:00
|
|
|
/* long j;*/
|
2000-05-06 21:34:20 +02:00
|
|
|
|
|
|
|
/* restore parent */
|
|
|
|
p = MK_FP(cu_psp, 0);
|
|
|
|
|
|
|
|
/* When process returns - restore the isv */
|
|
|
|
setvec(0x22, p->ps_isv22);
|
|
|
|
setvec(0x23, p->ps_isv23);
|
|
|
|
setvec(0x24, p->ps_isv24);
|
|
|
|
|
|
|
|
/* And free all process memory if not a TSR return */
|
2001-11-18 15:01:12 +01:00
|
|
|
remote_process_end(); /* might be a good idea to do that after closing
|
|
|
|
but doesn't help NET either TE */
|
2000-05-06 21:34:20 +02:00
|
|
|
if (!tsr)
|
|
|
|
{
|
2001-11-04 20:47:39 +01:00
|
|
|
remote_close_all();
|
2000-05-06 21:34:20 +02:00
|
|
|
for (i = 0; i < p->ps_maxfiles; i++)
|
|
|
|
{
|
|
|
|
DosClose(i);
|
|
|
|
}
|
2001-07-23 14:47:42 +02:00
|
|
|
FcbCloseAll();
|
2000-05-06 21:34:20 +02:00
|
|
|
FreeProcessMem(cu_psp);
|
|
|
|
}
|
|
|
|
|
|
|
|
cu_psp = p->ps_parent;
|
|
|
|
q = MK_FP(cu_psp, 0);
|
|
|
|
dta = q->ps_dta;
|
|
|
|
|
|
|
|
irp = (iregs FAR *) q->ps_stack;
|
|
|
|
|
|
|
|
irp->CS = FP_SEG(p->ps_isv22);
|
|
|
|
irp->IP = FP_OFF(p->ps_isv22);
|
|
|
|
|
|
|
|
if (InDOS)
|
|
|
|
--InDOS;
|
|
|
|
exec_user((iregs FAR *) q->ps_stack);
|
|
|
|
}
|
|
|
|
|
2001-03-30 21:30:06 +02:00
|
|
|
COUNT DosExeLoader(BYTE FAR * namep, exec_blk FAR * exp, COUNT mode)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2001-11-18 15:01:12 +01:00
|
|
|
COUNT rc;
|
|
|
|
/*err, */
|
|
|
|
/*env_size, */
|
|
|
|
|
|
|
|
UWORD mem, env, asize, start_seg;
|
|
|
|
|
|
|
|
int ModeLoadHigh = mode & 0x80;
|
2001-09-23 22:39:44 +02:00
|
|
|
UBYTE UMBstate = uppermem_link;
|
2001-03-30 21:30:06 +02:00
|
|
|
|
|
|
|
mode &= 0x7f;
|
|
|
|
|
2000-05-06 21:34:20 +02:00
|
|
|
/* Clone the environement and create a memory arena */
|
|
|
|
if (mode != OVERLAY)
|
|
|
|
{
|
|
|
|
if ((rc = ChildEnv(exp, &env, namep)) != SUCCESS)
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
mem = exp->load.load_seg;
|
2001-11-04 20:47:39 +01:00
|
|
|
|
|
|
|
{
|
2001-11-18 15:01:12 +01:00
|
|
|
ULONG image_size;
|
|
|
|
ULONG image_offset;
|
|
|
|
LONG exe_size;
|
|
|
|
mcb FAR *mp;
|
|
|
|
|
|
|
|
/* compute image offset from the header */
|
|
|
|
image_offset = (ULONG) header.exHeaderSize * 16;
|
|
|
|
|
|
|
|
/* compute image size by removing the offset from the */
|
|
|
|
/* number pages scaled to bytes plus the remainder and */
|
|
|
|
/* the psp */
|
|
|
|
/* First scale the size */
|
|
|
|
image_size = (ULONG) header.exPages * 512;
|
|
|
|
/* remove the offset */
|
|
|
|
image_size -= image_offset;
|
|
|
|
|
|
|
|
/* and finally add in the psp size */
|
|
|
|
if (mode != OVERLAY)
|
|
|
|
image_size += sizeof(psp); /*TE 03/20/01 */
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2001-11-18 15:01:12 +01:00
|
|
|
if (mode != OVERLAY)
|
2001-04-16 16:28:32 +02:00
|
|
|
{
|
2001-11-18 15:01:12 +01:00
|
|
|
if (ModeLoadHigh)
|
|
|
|
{
|
|
|
|
DosUmbLink(1); /* link in UMB's */
|
|
|
|
mem_access_mode |= ModeLoadHigh;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Now find out how many paragraphs are available */
|
|
|
|
if ((rc = DosMemLargest((seg FAR *) & asize)) != SUCCESS)
|
2001-04-16 16:28:32 +02:00
|
|
|
{
|
|
|
|
DosMemFree(env);
|
|
|
|
return rc;
|
|
|
|
}
|
2001-03-30 21:30:06 +02:00
|
|
|
|
2001-11-18 15:01:12 +01:00
|
|
|
exe_size = (LONG) long2para(image_size) + header.exMinAlloc;
|
2001-03-30 21:30:06 +02:00
|
|
|
|
2001-11-18 15:01:12 +01:00
|
|
|
/* + long2para((LONG) sizeof(psp)); ?? see above
|
|
|
|
image_size += sizeof(psp) -- 1999/04/21 ska */
|
|
|
|
if (exe_size > asize && (mem_access_mode & 0x80))
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2001-11-18 15:01:12 +01:00
|
|
|
/* First try low memory */
|
|
|
|
mem_access_mode &= ~0x80;
|
|
|
|
rc = DosMemLargest((seg FAR *) & asize);
|
|
|
|
mem_access_mode |= 0x80;
|
|
|
|
if (rc != SUCCESS)
|
|
|
|
{
|
|
|
|
DosMemFree(env);
|
|
|
|
return rc;
|
|
|
|
}
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
2001-11-18 15:01:12 +01:00
|
|
|
if (exe_size > asize)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
|
|
|
DosMemFree(env);
|
2001-11-18 15:01:12 +01:00
|
|
|
return DE_NOMEM;
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
2001-11-18 15:01:12 +01:00
|
|
|
exe_size = (LONG) long2para(image_size) + header.exMaxAlloc;
|
|
|
|
/* + long2para((LONG) sizeof(psp)); ?? -- 1999/04/21 ska */
|
|
|
|
if (exe_size > asize)
|
|
|
|
exe_size = asize;
|
|
|
|
|
|
|
|
/* TE if header.exMinAlloc == header.exMaxAlloc == 0,
|
|
|
|
DOS will allocate the largest possible memory area
|
|
|
|
and load the image as high as possible into it.
|
|
|
|
discovered (and after that found in RBIL), when testing NET */
|
|
|
|
|
|
|
|
if ((header.exMinAlloc | header.exMaxAlloc) == 0)
|
|
|
|
exe_size = asize;
|
|
|
|
|
|
|
|
/* /// Removed closing curly brace. We should not attempt to allocate
|
|
|
|
memory if we are overlaying the current process, because the new
|
|
|
|
process will simply re-use the block we already have allocated.
|
|
|
|
This was causing execl() to fail in applications which use it to
|
|
|
|
overlay (replace) the current exe file with a new one.
|
|
|
|
Jun 11, 2000 - rbc
|
|
|
|
} */
|
|
|
|
|
|
|
|
/* Allocate our memory and pass back any errors */
|
|
|
|
/* We can still get an error on first fit if the above */
|
|
|
|
/* returned size was a bet fit case */
|
|
|
|
/* ModeLoadHigh = 80 = try high, then low */
|
|
|
|
if ((rc =
|
|
|
|
DosMemAlloc((seg) exe_size, mem_access_mode | ModeLoadHigh,
|
|
|
|
(seg FAR *) & mem, (UWORD FAR *) & asize)) < 0)
|
|
|
|
{
|
|
|
|
if (rc == DE_NOMEM)
|
|
|
|
{
|
|
|
|
if ((rc =
|
|
|
|
DosMemAlloc(0, LARGEST, (seg FAR *) & mem,
|
|
|
|
(UWORD FAR *) & asize)) < 0)
|
|
|
|
{
|
|
|
|
DosMemFree(env);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
/* This should never happen, but ... */
|
|
|
|
if (asize < exe_size)
|
|
|
|
{
|
|
|
|
DosMemFree(mem);
|
|
|
|
DosMemFree(env);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DosMemFree(env);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
/* with no error, we got exactly what we asked for */
|
|
|
|
asize = exe_size;
|
2000-08-06 07:50:17 +02:00
|
|
|
|
2001-11-18 15:01:12 +01:00
|
|
|
#ifdef DEBUG
|
2002-01-23 23:29:41 +01:00
|
|
|
printf("DosExeLoader. Loading '%S' at %04x\n", namep, mem);
|
2001-11-18 15:01:12 +01:00
|
|
|
#endif
|
2001-03-30 21:30:06 +02:00
|
|
|
|
2000-08-06 07:50:17 +02:00
|
|
|
/* /// Added open curly brace and "else" clause. We should not attempt
|
|
|
|
to allocate memory if we are overlaying the current process, because
|
|
|
|
the new process will simply re-use the block we already have allocated.
|
|
|
|
This was causing execl() to fail in applications which use it to
|
|
|
|
overlay (replace) the current exe file with a new one.
|
|
|
|
Jun 11, 2000 - rbc */
|
2001-11-18 15:01:12 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
asize = exe_size;
|
2000-08-06 07:50:17 +02:00
|
|
|
/* /// End of additions. Jun 11, 2000 - rbc */
|
2001-03-30 21:30:06 +02:00
|
|
|
|
2001-11-18 15:01:12 +01:00
|
|
|
if (ModeLoadHigh)
|
2001-03-30 21:30:06 +02:00
|
|
|
{
|
2001-11-18 15:01:12 +01:00
|
|
|
mem_access_mode &= ~ModeLoadHigh; /* restore old situation */
|
|
|
|
DosUmbLink(UMBstate); /* restore link state */
|
2001-03-30 21:30:06 +02:00
|
|
|
}
|
|
|
|
|
2000-05-06 21:34:20 +02:00
|
|
|
if (mode != OVERLAY)
|
|
|
|
{
|
2001-11-18 15:01:12 +01:00
|
|
|
/* memory found large enough - continue processing */
|
|
|
|
mp = MK_FP(mem, 0);
|
|
|
|
++mem;
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
2001-11-18 15:01:12 +01:00
|
|
|
else
|
|
|
|
mem = exp->load.load_seg;
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2001-11-18 15:01:12 +01:00
|
|
|
/* create the start seg for later computations */
|
|
|
|
if (mode == OVERLAY)
|
|
|
|
start_seg = mem;
|
|
|
|
else
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2001-11-18 15:01:12 +01:00
|
|
|
start_seg = mem + long2para((LONG) sizeof(psp));
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
|
2001-11-18 15:01:12 +01:00
|
|
|
/* Now load the executable */
|
|
|
|
/* If file not found - error */
|
|
|
|
/* NOTE - this is fatal because we lost it in transit */
|
|
|
|
/* from DosExec! */
|
|
|
|
if ((rc = DosOpen(namep, 0)) < 0)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2001-11-18 15:01:12 +01:00
|
|
|
fatal("(DosExeLoader) exe file lost in transit");
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
2001-11-18 15:01:12 +01:00
|
|
|
/* offset to start of image */
|
|
|
|
if (doslseek(rc, image_offset, 0) != image_offset)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2001-11-18 15:01:12 +01:00
|
|
|
if (mode != OVERLAY)
|
|
|
|
{
|
|
|
|
DosMemFree(--mem);
|
|
|
|
DosMemFree(env);
|
|
|
|
}
|
2000-05-06 21:34:20 +02:00
|
|
|
return DE_INVLDDATA;
|
|
|
|
}
|
2001-11-18 15:01:12 +01:00
|
|
|
|
|
|
|
/* read in the image in 32K chunks */
|
|
|
|
if (mode != OVERLAY)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2001-11-18 15:01:12 +01:00
|
|
|
exe_size = image_size - sizeof(psp);
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
else
|
2001-11-18 15:01:12 +01:00
|
|
|
exe_size = image_size;
|
|
|
|
|
|
|
|
if (exe_size > 0)
|
2000-05-06 21:34:20 +02:00
|
|
|
{
|
2001-11-18 15:01:12 +01:00
|
|
|
UCOUNT nBytesRead;
|
|
|
|
BYTE FAR *sp;
|
|
|
|
|
|
|
|
if (mode != OVERLAY)
|
|
|
|
{
|
|
|
|
if ((header.exMinAlloc == 0) && (header.exMaxAlloc == 0))
|
|
|
|
{
|
|
|
|
/* then the image should be placed as high as possible */
|
|
|
|
start_seg = start_seg + mp->m_size - (image_size + 15) / 16;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sp = MK_FP(start_seg, 0x0);
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
nBytesRead =
|
|
|
|
DosRead((COUNT) rc,
|
|
|
|
(COUNT) (exe_size < CHUNK ? exe_size : CHUNK),
|
|
|
|
(VOID FAR *) sp, &UnusedRetVal);
|
|
|
|
sp = add_far((VOID FAR *) sp, (ULONG) nBytesRead);
|
|
|
|
exe_size -= nBytesRead;
|
|
|
|
}
|
|
|
|
while (nBytesRead && exe_size > 0);
|
2000-05-06 21:34:20 +02:00
|
|
|
}
|
|
|
|
}
|
2001-11-18 15:01:12 +01:00
|
|
|
|
|
|
|
{ /* relocate the image for new segment */
|
|
|
|
COUNT i;
|
|
|
|
UWORD reloc[2];
|
|
|
|
seg FAR *spot;
|
|
|
|
|
|
|
|
doslseek(rc, (LONG) header.exRelocTable, 0);
|
|
|
|
for (i = 0; i < header.exRelocItems; i++)
|
|
|
|
{
|
|
|
|
if (DosRead
|
|
|
|
(rc, sizeof(reloc), (VOID FAR *) & reloc[0],
|
|
|
|
&UnusedRetVal) != sizeof(reloc))
|
|
|
|
{
|
|
|
|
return DE_INVLDDATA;
|
|
|
|
}
|
|
|
|
if (mode == OVERLAY)
|
|
|
|
{
|
|
|
|
spot = MK_FP(reloc[1] + mem, reloc[0]);
|
|
|
|
*spot += exp->load.reloc;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* spot = MK_FP(reloc[1] + mem + 0x10, reloc[0]); */
|
|
|
|
spot = MK_FP(reloc[1] + start_seg, reloc[0]);
|
|
|
|
*spot += start_seg;
|
|
|
|
}
|
|
|
|
}
|
2001-11-04 20:47:39 +01:00
|
|
|
}
|
2001-11-18 15:01:12 +01:00
|
|
|
|
2000-05-06 21:34:20 +02:00
|
|
|
/* and finally close the file */
|
|
|
|
DosClose(rc);
|
|
|
|
|
|
|
|
/* exit here for overlay */
|
|
|
|
if (mode == OVERLAY)
|
|
|
|
return SUCCESS;
|
|
|
|
|
2001-11-04 20:47:39 +01:00
|
|
|
{
|
2001-11-18 15:01:12 +01:00
|
|
|
psp FAR *p;
|
|
|
|
psp FAR *q = MK_FP(cu_psp, 0);
|
2001-11-04 20:47:39 +01:00
|
|
|
|
2001-11-18 15:01:12 +01:00
|
|
|
/* point to the PSP so we can build it */
|
|
|
|
p = MK_FP(mem, 0);
|
2002-01-23 23:29:41 +01:00
|
|
|
setvec(0x22, MK_FP(user_r->CS, user_r->IP));
|
2001-11-18 15:01:12 +01:00
|
|
|
new_psp(p, mem + asize);
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2001-11-18 15:01:12 +01:00
|
|
|
asize = patchPSP(mem - 1, env, exp, namep); /* asize = fcbcode */
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2001-11-18 15:01:12 +01:00
|
|
|
/* Transfer control to the executable */
|
|
|
|
p->ps_parent = cu_psp;
|
|
|
|
p->ps_prevpsp = (BYTE FAR *) MK_FP(cu_psp, 0);
|
|
|
|
q->ps_stack = (BYTE FAR *) user_r;
|
|
|
|
user_r->FLAGS &= ~FLG_CARRY;
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2001-11-18 15:01:12 +01:00
|
|
|
switch (mode)
|
2001-11-04 20:47:39 +01:00
|
|
|
{
|
2001-11-18 15:01:12 +01:00
|
|
|
case LOADNGO:
|
|
|
|
{
|
|
|
|
/* build the user area on the stack */
|
|
|
|
iregs FAR *irp = MK_FP(header.exInitSS + start_seg,
|
|
|
|
((header.exInitSP -
|
|
|
|
sizeof(iregs)) & 0xffff));
|
|
|
|
|
|
|
|
/* start allocating REGs */
|
|
|
|
/* Note: must match es & ds memory segment */
|
|
|
|
irp->ES = irp->DS = mem;
|
|
|
|
irp->CS = header.exInitCS + start_seg;
|
|
|
|
irp->IP = header.exInitIP;
|
|
|
|
irp->AX = asize; /* asize = fcbcode */
|
|
|
|
irp->BX = irp->CX = irp->DX = irp->SI = irp->DI = irp->BP = 0;
|
|
|
|
irp->FLAGS = 0x200;
|
|
|
|
|
|
|
|
cu_psp = mem;
|
|
|
|
dta = p->ps_dta;
|
|
|
|
|
|
|
|
if (InDOS)
|
|
|
|
--InDOS;
|
|
|
|
exec_user(irp);
|
|
|
|
/* We should never be here
|
|
|
|
fatal("KERNEL RETURNED!!!"); */
|
|
|
|
break;
|
|
|
|
}
|
2000-05-06 21:34:20 +02:00
|
|
|
|
2001-11-18 15:01:12 +01:00
|
|
|
case LOAD:
|
|
|
|
cu_psp = mem;
|
|
|
|
exp->exec.stack =
|
|
|
|
MK_FP(header.exInitSS + start_seg, header.exInitSP);
|
|
|
|
*((UWORD FAR *) exp->exec.stack) = asize; /* fcbcode */
|
|
|
|
exp->exec.start_addr =
|
|
|
|
MK_FP(header.exInitCS + start_seg, header.exInitIP);
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
2001-11-04 20:47:39 +01:00
|
|
|
}
|
2000-05-06 21:34:20 +02:00
|
|
|
return DE_INVLDFMT;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* mode = LOAD or EXECUTE
|
|
|
|
ep = EXE block
|
|
|
|
lp = filename to load (string)
|
|
|
|
|
|
|
|
leb = local copy of exe block
|
|
|
|
*/
|
|
|
|
COUNT DosExec(COUNT mode, exec_blk FAR * ep, BYTE FAR * lp)
|
|
|
|
{
|
2001-04-22 00:32:53 +02:00
|
|
|
COUNT rc;
|
2001-04-15 05:21:50 +02:00
|
|
|
exec_blk leb;
|
|
|
|
|
2001-03-30 21:30:06 +02:00
|
|
|
/* BYTE FAR *cp;*/
|
2000-05-06 21:34:20 +02:00
|
|
|
BOOL bIsCom = FALSE;
|
|
|
|
|
2001-04-15 05:21:50 +02:00
|
|
|
fmemcpy(&leb, ep, sizeof(exec_blk));
|
2000-05-06 21:34:20 +02:00
|
|
|
/* If file not found - free ram and return error */
|
|
|
|
|
|
|
|
if ((rc = DosOpen(lp, 0)) < 0)
|
|
|
|
{
|
|
|
|
return DE_FILENOTFND;
|
|
|
|
}
|
|
|
|
|
2001-04-22 00:32:53 +02:00
|
|
|
if (DosRead(rc, sizeof(exe_header), (VOID FAR *) & header, &UnusedRetVal)
|
2000-05-06 21:34:20 +02:00
|
|
|
!= sizeof(exe_header))
|
|
|
|
{
|
|
|
|
bIsCom = TRUE;
|
|
|
|
}
|
|
|
|
DosClose(rc);
|
|
|
|
|
|
|
|
if (bIsCom || header.exSignature != MAGIC)
|
|
|
|
{
|
|
|
|
rc = DosComLoader(lp, &leb, mode);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rc = DosExeLoader(lp, &leb, mode);
|
|
|
|
}
|
|
|
|
if (mode == LOAD && rc == SUCCESS)
|
2001-04-15 05:21:50 +02:00
|
|
|
fmemcpy(ep, &leb, sizeof(exec_blk));
|
2000-05-06 21:34:20 +02:00
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2001-11-18 00:26:45 +01:00
|
|
|
/*
|
|
|
|
* Log: task.c,v - for newer log entries do "cvs log task.c"
|
|
|
|
*
|
|
|
|
* Revision 1.8 2000/03/31 05:40:09 jtabor
|
|
|
|
* Added Eric W. Biederman Patches
|
|
|
|
*
|
|
|
|
* Revision 1.7 2000/03/09 06:07:11 kernel
|
|
|
|
* 2017f updates by James Tabor
|
|
|
|
*
|
|
|
|
* Revision 1.6 1999/08/25 03:18:10 jprice
|
|
|
|
* ror4 patches to allow TC 2.01 compile.
|
|
|
|
*
|
|
|
|
* Revision 1.5 1999/04/23 04:24:39 jprice
|
|
|
|
* Memory manager changes made by ska
|
|
|
|
*
|
|
|
|
* Revision 1.4 1999/04/16 00:53:33 jprice
|
|
|
|
* Optimized FAT handling
|
|
|
|
*
|
|
|
|
* Revision 1.3 1999/04/11 04:33:39 jprice
|
|
|
|
* ror4 patches
|
|
|
|
*
|
|
|
|
* Revision 1.2 1999/03/29 17:05:09 jprice
|
|
|
|
* ror4 changes
|
|
|
|
*
|
|
|
|
* Revision 1.1.1.1 1999/03/29 15:41:41 jprice
|
|
|
|
* New version without IPL.SYS
|
|
|
|
*
|
|
|
|
* Revision 1.5 1999/02/08 05:55:58 jprice
|
|
|
|
* Added Pat's 1937 kernel patches
|
|
|
|
*
|
|
|
|
* Revision 1.4 1999/02/04 03:14:07 jprice
|
|
|
|
* Formating. Added comments.
|
|
|
|
*
|
|
|
|
* Revision 1.3 1999/02/01 01:48:41 jprice
|
|
|
|
* Clean up; Now you can use hex numbers in config.sys. added config.sys screen function to change screen mode (28 or 43/50 lines)
|
|
|
|
*
|
|
|
|
* Revision 1.2 1999/01/22 04:13:27 jprice
|
|
|
|
* Formating
|
|
|
|
*
|
|
|
|
* Revision 1.1.1.1 1999/01/20 05:51:01 jprice
|
|
|
|
* Imported sources
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* Rev 1.15 06 Dec 1998 8:46:28 patv
|
|
|
|
* Bug fixes.
|
|
|
|
*
|
|
|
|
* Rev 1.14 07 Feb 1998 20:38:32 patv
|
|
|
|
* Modified stack fram to match DOS standard
|
|
|
|
*
|
|
|
|
* Rev 1.13 31 Jan 1998 14:39:20 patv
|
|
|
|
* Corrected type in load high code.
|
|
|
|
*
|
|
|
|
* Rev 1.12 31 Jan 1998 14:02:52 patv
|
|
|
|
* Added load high in memory option in DosExeLoader.
|
|
|
|
*
|
|
|
|
* Rev 1.11 22 Jan 1998 22:17:14 patv
|
|
|
|
* Eliminated warnings.
|
|
|
|
*
|
|
|
|
* Rev 1.10 22 Jan 1998 21:31:36 patv
|
|
|
|
* Corrected short .COM problem.
|
|
|
|
*
|
|
|
|
* Rev 1.9 04 Jan 1998 23:15:16 patv
|
|
|
|
* Changed Log for strip utility
|
|
|
|
*
|
|
|
|
* Rev 1.8 22 Jan 1997 13:18:14 patv
|
|
|
|
* pre-0.92 Svante Frey bug fixes.
|
|
|
|
*
|
|
|
|
* Rev 1.7 16 Jan 1997 12:46:56 patv
|
|
|
|
* pre-Release 0.92 feature additions
|
|
|
|
*
|
|
|
|
* Rev 1.5 29 Aug 1996 13:07:22 patv
|
|
|
|
* Bug fixes for v0.91b
|
|
|
|
*
|
|
|
|
* Rev 1.4 29 May 1996 21:03:36 patv
|
|
|
|
* bug fixes for v0.91a
|
|
|
|
*
|
|
|
|
* Rev 1.3 19 Feb 1996 3:21:48 patv
|
|
|
|
* Added NLS, int2f and config.sys processing
|
|
|
|
*
|
|
|
|
* Rev 1.2 01 Sep 1995 17:54:22 patv
|
|
|
|
* First GPL release.
|
|
|
|
*
|
|
|
|
* Rev 1.1 30 Jul 1995 20:51:58 patv
|
|
|
|
* Eliminated version strings in ipl
|
|
|
|
*
|
|
|
|
* Rev 1.0 02 Jul 1995 8:34:06 patv
|
|
|
|
* Initial revision.
|
|
|
|
*/
|