TASK.C
上传用户:dcs7469208
上传日期:2010-01-02
资源大小:443k
文件大小:28k
源码类别:

操作系统开发

开发平台:

DOS

  1. /****************************************************************/
  2. /*                                                              */
  3. /*                           task.c                             */
  4. /*                                                              */
  5. /*                 Task Manager for DOS Processes               */
  6. /*                                                              */
  7. /*                      Copyright (c) 1995                      */
  8. /*                      Pasquale J. Villani                     */
  9. /*                      All Rights Reserved                     */
  10. /*                                                              */
  11. /* This file is part of DOS-C.                                  */
  12. /*                                                              */
  13. /* DOS-C is free software; you can redistribute it and/or       */
  14. /* modify it under the terms of the GNU General Public License  */
  15. /* as published by the Free Software Foundation; either version */
  16. /* 2, or (at your option) any later version.                    */
  17. /*                                                              */
  18. /* DOS-C is distributed in the hope that it will be useful, but */
  19. /* WITHOUT ANY WARRANTY; without even the implied warranty of   */
  20. /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See    */
  21. /* the GNU General Public License for more details.             */
  22. /*                                                              */
  23. /* You should have received a copy of the GNU General Public    */
  24. /* License along with DOS-C; see the file COPYING.  If not,     */
  25. /* write to the Free Software Foundation, 675 Mass Ave,         */
  26. /* Cambridge, MA 02139, USA.                                    */
  27. /****************************************************************/
  28. #include "../../hdr/portab.h"
  29. #include "globals.h"
  30. /* $Logfile:   C:/dos-c/src/kernel/task.c_v  $ */
  31. #ifdef VERSION_STRINGS
  32. static BYTE *RcsId = "$Header:   C:/dos-c/src/kernel/task.c_v   1.14   07 Feb 1998 20:38:32   patv  $";
  33. #endif
  34. /* $Log:   C:/dos-c/src/kernel/task.c_v  $
  35.  * 
  36.  *    Rev 1.14   07 Feb 1998 20:38:32   patv
  37.  * Modified stack fram to match DOS standard
  38.  * 
  39.  *    Rev 1.13   31 Jan 1998 14:39:20   patv
  40.  * Corrected type in load high code.
  41.  * 
  42.  *    Rev 1.12   31 Jan 1998 14:02:52   patv
  43.  * Added load high in memory option in DosExeLoader.
  44.  * 
  45.  *    Rev 1.11   22 Jan 1998 22:17:14   patv
  46.  * Eliminated warnings.
  47.  * 
  48.  *    Rev 1.10   22 Jan 1998 21:31:36   patv
  49.  * Corrected short .COM problem.
  50.  * 
  51.  *    Rev 1.9   04 Jan 1998 23:15:16   patv
  52.  * Changed Log for strip utility
  53.  * 
  54.  *    Rev 1.8   22 Jan 1997 13:18:14   patv
  55.  * pre-0.92 Svante Frey bug fixes.
  56.  * 
  57.  *    Rev 1.7   16 Jan 1997 12:46:56   patv
  58.  * pre-Release 0.92 feature additions
  59.  * 
  60.  *    Rev 1.5   29 Aug 1996 13:07:22   patv
  61.  * Bug fixes for v0.91b
  62.  * 
  63.  *    Rev 1.4   29 May 1996 21:03:36   patv
  64.  * bug fixes for v0.91a
  65.  * 
  66.  *    Rev 1.3   19 Feb 1996  3:21:48   patv
  67.  * Added NLS, int2f and config.sys processing
  68.  * 
  69.  *    Rev 1.2   01 Sep 1995 17:54:22   patv
  70.  * First GPL release.
  71.  * 
  72.  *    Rev 1.1   30 Jul 1995 20:51:58   patv
  73.  * Eliminated version strings in ipl
  74.  * 
  75.  *    Rev 1.0   02 Jul 1995  8:34:06   patv
  76.  * Initial revision.
  77.  */
  78. /* $EndLog$ */
  79. #define LOADNGO 0
  80. #define LOAD    1
  81. #define OVERLAY 3
  82. static exe_header header;
  83. #define CHUNK 16384
  84. #define MAXENV 32768
  85. #ifndef PROTO
  86. COUNT ChildEnv(exec_blk FAR *, UWORD *, char far *);
  87. #else
  88. COUNT ChildEnv();
  89. #endif
  90. #ifndef IPL
  91. COUNT 
  92. ChildEnv (exec_blk FAR *exp, UWORD *pChildEnvSeg, char far *pathname)
  93. {
  94.         BYTE FAR *pSrc;
  95.         BYTE FAR *pDest;
  96.         UWORD nEnvSize;
  97.         COUNT RetCode;
  98.         UWORD MaxEnvSize;
  99.         psp FAR *ppsp = MK_FP( cu_psp, 0);
  100.        
  101.         /* create a new environment for the process             */
  102.         /* copy parent's environment if exec.env_seg == 0       */
  103.         pSrc = exp -> exec.env_seg ? 
  104.                         MK_FP(exp -> exec.env_seg, 0) :
  105.                         MK_FP(ppsp -> ps_environ, 0);
  106.                    
  107.         if (!pSrc)    /* no environment to copy */
  108.         {
  109.                 *pChildEnvSeg = 0;
  110.                 return SUCCESS;
  111.         }
  112.         for(nEnvSize = 0; *pSrc != ''; )
  113.         {
  114.                 while(*pSrc != '')
  115.                 {
  116.                         ++pSrc;
  117.                         ++nEnvSize;
  118.                 }
  119.                 /* account for terminating null         */
  120.                 ++nEnvSize;
  121.                 ++pSrc;
  122.         }
  123.         /* Test env size and abort if greater than max          */
  124.         if(nEnvSize >= MAXENV)
  125.                 return DE_INVLDENV;
  126.         /* allocate enough space for env + path                 */
  127.         if((RetCode = DosMemAlloc(long2para(nEnvSize + 65), 
  128.           FIRST_FIT, (seg FAR *)pChildEnvSeg,
  129.           (UWORD FAR *)MaxEnvSize)) < 0)
  130.                 return RetCode;
  131.         else
  132.                 pDest = MK_FP(*pChildEnvSeg + 1, 0);
  133.         /* fill the new env and inform the process of its       */
  134.         /* location throught the psp                            */
  135.         pSrc = exp -> exec.env_seg ? 
  136.                         MK_FP(exp -> exec.env_seg, 0) :
  137.                         MK_FP(ppsp -> ps_environ, 0);
  138.         
  139.         /* copy the environment */
  140.         for( ; *pSrc != ''; )
  141.         {
  142.                 while (*pSrc) 
  143.                 {
  144.                         *pDest++ = *pSrc++;  
  145.                 } 
  146.                 pSrc++;
  147.                 *pDest++ = 0;
  148.         }
  149.         *pDest++ = 0;
  150.         /* initialize 'extra strings' count */
  151.         *pDest++ = 1;
  152.         *pDest++ = 0;
  153.         
  154.         /* copy complete pathname */
  155.         truename(pathname, pDest);
  156.         return SUCCESS;
  157. }
  158. #endif
  159. /* The following code is 8086 dependant                         */
  160. VOID 
  161. new_psp (psp FAR *p, int psize)
  162. {
  163.         REG COUNT i;
  164.         BYTE FAR *lpPspBuffer;
  165.         psp FAR *q = MK_FP(cu_psp, 0);
  166.         /* Clear out new psp first                              */
  167.         for(lpPspBuffer = (BYTE FAR *)p, i = 0; i < sizeof(psp) ; ++i)
  168.                 *lpPspBuffer = 0;
  169.         
  170.         /* initialize all entries and exits                     */
  171.         /* CP/M-like exit point                                 */
  172.         p -> ps_exit = 0x20cd;     
  173.         
  174.         /* CP/M-like entry point - jump to special entry        */
  175.         p -> ps_farcall= 0xea;
  176. #ifndef IPL
  177.         p -> ps_reentry = cpm_entry;
  178. #endif
  179.         /* unix style call - 0xcd 0x21 0xcb (int 21, retf)      */
  180.         p -> ps_unix[0] = 0xcd;
  181.         p -> ps_unix[1] = 0x21; 
  182.         p -> ps_unix[2] = 0xcb; 
  183.         /* Now for parent-child relationships                   */
  184.         /* parent psp segment                                   */
  185.         p -> ps_parent = cu_psp;
  186.         /* previous psp pointer                                 */
  187.         p -> ps_prevpsp = q;
  188. #ifndef IPL
  189.         /* Environment and memory useage parameters             */
  190.         /* memory size in paragraphs                            */
  191.         p -> ps_size = psize;
  192.         /* environment paragraph                                */
  193.         p -> ps_environ = 0;
  194.         /* process dta                                          */
  195.         p -> ps_dta = (BYTE FAR *)(&p -> ps_cmd_count);
  196.         
  197.         /* terminate address                                    */
  198.         p -> ps_isv22 = (VOID(interrupt FAR *)(void))getvec(0x22);
  199.         /* break address                                        */
  200.         p -> ps_isv23 = (VOID(interrupt FAR *)(void))getvec(0x23);
  201.         /* critical error address                               */
  202.         p -> ps_isv24 = (VOID(interrupt FAR *)(void))getvec(0x24);
  203. #endif
  204.         /* File System parameters                               */
  205.         /* user stack pointer - int 21                          */
  206.         p -> ps_stack = (BYTE FAR *)-1;
  207.         /* file table - 0xff is unused                          */
  208.         for(i = 0; i < 20; i++)
  209.                 p -> ps_files[i] = 0xff;
  210.         
  211.         /* maximum open files                                   */
  212.         p -> ps_maxfiles = 20;
  213.         /* open file table pointer                              */
  214.         p -> ps_filetab = p -> ps_files;
  215. #ifndef IPL
  216.         /* clone the file table                                 */
  217.         if(InDOS > 0)
  218.         {
  219.                 REG COUNT i;
  220.                 
  221.                 for(i = 0; i < 20; i++)
  222.                 {
  223.                         REG COUNT ret;
  224.                         if(q -> ps_filetab[i] != 0xff
  225.                          && ((ret = CloneHandle(q -> ps_filetab[i])) >= 0))
  226.                         {        
  227.                                 p -> ps_filetab[i] = ret;
  228.                         }
  229.                         else
  230.                                 p -> ps_filetab[i] = 0xff;
  231.                 }
  232.         }
  233.         else
  234.         {
  235.                 /* initialize stdin, stdout, etc                        */
  236.                 p -> ps_files[STDIN] = 0;       /* stdin                */
  237.                 p -> ps_files[STDOUT] = 1;      /* stdout               */
  238.                 p -> ps_files[STDERR] = 2;      /* stderr               */
  239.                 p -> ps_files[STDAUX] = 3;      /* stdaux               */
  240.                 p -> ps_files[STDPRN] = 4;      /* stdprn               */
  241.        }
  242. #else
  243.         /* initialize stdin, stdout, etc                        */
  244.         p -> ps_files[STDIN] = 0;       /* stdin                */
  245.         p -> ps_files[STDOUT] = 1;      /* stdout               */
  246.         p -> ps_files[STDERR] = 2;      /* stderr               */
  247.         p -> ps_files[STDAUX] = 3;      /* stdaux               */
  248.         p -> ps_files[STDPRN] = 4;      /* stdprn               */
  249. #endif
  250.         /* first command line argument                          */
  251.         p -> ps_fcb1.fcb_drive = 0;
  252.         /* second command line argument                         */
  253.         p -> ps_fcb2.fcb_drive = 0;
  254.         /* local command line                                   */
  255.         p -> ps_cmd_count = 0;  /* command tail                 */
  256.         p -> ps_cmd[0] = 0;     /* command tail                 */
  257. }
  258. #ifndef IPL
  259. static COUNT 
  260. DosComLoader (BYTE FAR *namep, exec_blk FAR *exp, COUNT mode)
  261. {
  262.         COUNT rc, env_size, nread;
  263.         UWORD mem;
  264.         UWORD env, asize;
  265.         BYTE FAR *sp, FAR *dp;
  266.         psp FAR *p;
  267.         psp FAR *q = MK_FP(cu_psp, 0);
  268.         mcb FAR *mp, FAR *envp = 0;
  269.         iregs FAR *irp;
  270.         LONG com_size;
  271.         
  272.         if(mode != OVERLAY)
  273.         {
  274.                 
  275.                 if((rc = ChildEnv(exp, &env, namep)) != SUCCESS)
  276.                 {        
  277.                         return rc;
  278.                 }
  279.                 /* Allocate our memory and pass back any errors         */
  280.                 if((rc = DosMemAlloc(0, LARGEST, (seg FAR *)&mem, (UWORD FAR *)&asize)) < 0)
  281.                 {
  282.                         if(env != 0)
  283.                            DosMemFree(env);
  284.                         
  285.                         return rc;
  286.                 }
  287.                 mp = MK_FP(mem, 0);
  288.                 ++mem;
  289.                 envp = MK_FP(env, 0);
  290.         }
  291.         else mem = exp -> load.load_seg;
  292.         /* Now load the executable                              */
  293.         /* If file not found - error                            */
  294.         /* NOTE - this is fatal because we lost it in transit   */
  295.         /* from DosExec!                                        */
  296.         if((rc = dos_open(namep, 0)) < 0)
  297.                 fatal("(DosComLoader) com file lost in transit");
  298.         /* do it in 32K chunks                                  */
  299.         sp = MK_FP(mem, mode == OVERLAY? 0 : sizeof(psp));
  300.         for(com_size = dos_getfsize(rc), nread = 0; com_size > 0; )
  301.         {
  302.                 nread = dos_read(rc, sp, CHUNK);
  303.                 sp = add_far((VOID FAR *)sp, (ULONG)nread);
  304.                 com_size -= nread;
  305.                 if(nread < CHUNK)
  306.                         break;
  307.         }
  308.         dos_close(rc);
  309.         if(mode == OVERLAY)
  310.                  return SUCCESS;
  311.         /* point to the PSP so we can build it                  */
  312.         p = MK_FP(mem, 0);
  313.         setvec(0x22, (VOID (INRPT FAR *)(VOID))MK_FP(user_r -> CS, user_r -> IP));
  314.         new_psp(p, mem + asize);
  315.         p -> ps_environ = env == 0 ? 0 : env + 1;
  316.         /* complete the psp by adding the command line          */
  317.         p -> ps_cmd_count = exp -> exec.cmd_line -> ctCount;
  318.         fbcopy(exp -> exec.cmd_line -> ctBuffer, p -> ps_cmd, 127);
  319. #if 0
  320.         /* stick a new line on the end for safe measure         */
  321.         p -> ps_cmd[p -> ps_cmd_count] = 'r';
  322. #endif
  323.         /* identify the mcb as this functions'                  */
  324.         /* use the file name less extension - left adjusted and */
  325.         /* space filled                                         */
  326.         mp -> m_psp = mem;
  327.         if (envp) envp -> m_psp = mem;   
  328.         for(asize = 0; asize < 8; asize++)
  329.         {
  330.                 if(namep[asize] != '.')
  331.                         mp -> m_name[asize] = namep[asize];
  332.                 else
  333.                         break;
  334.         }
  335.         for(; asize < 8; asize++)
  336.                         mp -> m_name[asize] = ' ';
  337.         /* build the user area on the stack                     */
  338.         irp = MK_FP(mem, (0xfffe - sizeof(iregs)));
  339.         /* start allocating REGs                                */
  340.         irp -> ES = irp -> DS = mem;
  341.         irp -> CS = mem;
  342.         irp -> IP = 0x100;
  343.         irp -> AX = 0xffff; /* for now, until fcb code is in    */
  344.         irp -> BX =
  345.         irp -> CX =
  346.         irp -> DX =
  347.         irp -> SI =
  348.         irp -> DI =
  349.         irp -> BP = 0;
  350.         irp -> FLAGS = 0x200;
  351.         /* Transfer control to the executable                   */
  352.         p -> ps_parent = cu_psp;
  353.         p -> ps_prevpsp = (BYTE FAR *)MK_FP(cu_psp, 0);
  354.         q -> ps_stack = (BYTE FAR *)user_r;
  355.         user_r -> FLAGS &= ~FLG_CARRY;
  356.         
  357.         switch(mode)
  358.         {
  359.         case LOADNGO:
  360.         {        
  361.                 cu_psp = mem;
  362.                 dta = p -> ps_dta;
  363.                 if (InDOS)
  364.                  --InDOS;
  365.                 exec_user(irp);
  366.                 /* We should never be here                      */
  367.                 fatal("KERNEL RETURNED!!!");
  368.                 break;
  369.         }
  370.         case LOAD:
  371.                 cu_psp = mem;
  372.                 exp -> exec.stack = (BYTE FAR *)irp;
  373.                 exp -> exec.start_addr = MK_FP(irp -> CS, irp -> IP);
  374.                 return SUCCESS;
  375.         }
  376.         return DE_INVLDFMT;
  377. }
  378. VOID 
  379. return_user (void)
  380. {
  381.         psp FAR *p, FAR *q;
  382.         REG COUNT i;
  383.         iregs FAR *irp;
  384.         long j;
  385.         /* restore parent                                       */
  386.         p = MK_FP(cu_psp, 0);
  387.         /* When process returns - restore the isv               */
  388.         setvec(0x22, p -> ps_isv22);
  389.         setvec(0x23, p -> ps_isv23);
  390.         setvec(0x24, p -> ps_isv24);
  391.         /* And free all process memory if not a TSR return      */
  392.         if(!tsr)
  393.         {
  394.                 for(i = 0; i < p -> ps_maxfiles; i++)
  395.                 {    
  396.                         DosClose(i);
  397.                 }
  398.                 FreeProcessMem(cu_psp);
  399.         }
  400.         cu_psp = p -> ps_parent;
  401.         q = MK_FP(cu_psp, 0);
  402.         dta = q -> ps_dta;
  403.         irp = (iregs FAR *)q -> ps_stack;
  404.         irp -> CS = FP_SEG(p -> ps_isv22);
  405.         irp -> IP = FP_OFF(p -> ps_isv22);
  406.         
  407.         if (InDOS)
  408.          --InDOS;
  409.         exec_user((iregs FAR *)q -> ps_stack);
  410. }
  411. #endif
  412. static COUNT 
  413. DosExeLoader (BYTE FAR *namep, exec_blk FAR *exp, COUNT mode)
  414. {
  415.         COUNT rc, env_size, i, nBytesRead;
  416.         UWORD mem, env, asize, start_seg;
  417.         ULONG image_size;
  418.         ULONG image_offset;
  419.         BYTE FAR *sp, FAR * dp;
  420.         psp FAR *p;
  421.         psp FAR *q = MK_FP(cu_psp, 0);
  422.         mcb FAR *mp, FAR *envp = 0;
  423.         iregs FAR *irp;
  424.         UWORD reloc[2];
  425.         seg FAR *spot;
  426.         LONG exe_size;
  427. #ifdef IPL
  428.         BYTE szNameBuffer[64];
  429. #endif
  430. #ifndef IPL
  431.         /* Clone the environement and create a memory arena     */
  432.         if(mode != OVERLAY)
  433.         {
  434.                 if((rc = ChildEnv(exp, &env, namep)) != SUCCESS)
  435.                         return rc;
  436.         }
  437.         else
  438.                 mem = exp -> load.load_seg;
  439.         envp = MK_FP(env, 0);
  440. #endif
  441.         /* compute image offset from the header                 */
  442. #ifdef IPL
  443.         fscopy(namep, (BYTE FAR *)szNameBuffer);
  444.         printf("nEXE loader loading: %s", szNameBuffer);
  445. #endif
  446.         image_offset = (ULONG)header.exHeaderSize * 16l;
  447.         /* compute image size by removing the offset from the   */
  448.         /* number pages scaled to bytes plus the remainder and  */
  449.         /* the psp                                              */
  450.         /*  First scale the size                                */
  451.         image_size = (ULONG)(header.exPages) * 512l;
  452.         /* remove the offset                                    */
  453.         image_size -= image_offset;
  454. #if 0
  455.         /* add in the remainder bytes                           */
  456.         if(header.exExtraBytes != 0)
  457.                 image_size -= (ULONG)(512 - header.exExtraBytes);
  458. #endif
  459.         /* and finally add in the psp size                      */
  460.         if(mode != OVERLAY)
  461.                 image_size += (ULONG)long2para((LONG)sizeof(psp));
  462. #ifndef IPL
  463.         
  464.         if(mode != OVERLAY)
  465.         {
  466.                 
  467.                 /* Now find out how many paragraphs are available       */
  468.                 if((rc = DosMemLargest((seg FAR *)&asize)) != SUCCESS)
  469.                 {         
  470.                         return rc;
  471.                 }
  472.                 else
  473.                 {
  474.                         exe_size = (LONG)long2para(image_size) + header.exMinAlloc + long2para((LONG)sizeof(psp));
  475.                         if(exe_size > asize)
  476.                                 return DE_NOMEM;
  477.                         else if(((LONG)long2para(image_size) + header.exMaxAlloc + long2para((LONG)sizeof(psp))) < asize)
  478.                                 exe_size = (LONG)long2para(image_size) + header.exMaxAlloc + long2para((LONG)sizeof(psp));
  479.                         else
  480.                                 exe_size = asize;
  481.                 }
  482.                 /* Allocate our memory and pass back any errors         */
  483.                 /* We can still get an error on first fit if the above  */
  484.                 /* returned size was a bet fit case                     */
  485.                 if((rc = DosMemAlloc((seg)exe_size, FIRST_FIT, (seg FAR *)&mem, (UWORD FAR *)&asize)) < 0)
  486.                 {
  487.                         if(rc == DE_NOMEM)
  488.                         {
  489.                                 if((rc = DosMemAlloc(0, LARGEST, (seg FAR *)&mem, (UWORD FAR *)&asize)) < 0)
  490.                                 {
  491.                                         if(env != 0)
  492.                                                 DosMemFree(env);
  493.                                         return rc;
  494.                                 }
  495.                                 /* This should never happen, but ...    */
  496.                                 if(asize < exe_size)
  497.                                 {
  498.                                         if(env != 0)
  499.                                                 DosMemFree(env);
  500.                                         DosMemFree(mem);
  501.                                         return rc;
  502.                                 }
  503.                         }
  504.                         else
  505.                         {
  506.                                 if(env != 0)
  507.                                         DosMemFree(env);
  508.                                 return rc;
  509.                         }
  510.                 }
  511.                 else
  512.                 /* with no error, we got exactly what we asked for      */
  513.                         asize = exe_size;
  514.         }
  515. #else
  516.         mem = KERNSEG;
  517. #endif
  518. #ifndef IPL
  519.         if(mode != OVERLAY)
  520.         {
  521. #endif
  522.                 /* memory found large enough - continue processing      */
  523.                 mp = MK_FP(mem, 0);
  524.                 ++mem;
  525. #ifndef IPL
  526.         }
  527.         else
  528.                 mem = exp -> load.load_seg;
  529. #endif
  530. #ifdef IPL
  531.         printf(".");
  532. #endif
  533.         /* create the start seg for later computations          */
  534.         if(mode == OVERLAY)
  535.                 start_seg = mem;
  536.         else
  537.         {
  538.                 start_seg = mem + long2para((LONG)sizeof(psp));
  539. }
  540.         /* Now load the executable                              */
  541.         /* If file not found - error                            */
  542.         /* NOTE - this is fatal because we lost it in transit   */
  543.         /* from DosExec!                                        */
  544.         if((rc = dos_open(namep, 0)) < 0)
  545.         {        
  546.                 fatal("(DosExeLoader) exe file lost in transit");
  547.         }
  548. #ifdef IPL
  549.         printf(".");
  550. #endif
  551.         /* offset to start of image                             */
  552.         if (dos_lseek(rc, image_offset, 0) != image_offset)
  553.         {
  554. #ifndef IPL
  555.                 if(mode != OVERLAY)
  556.                 {
  557.                         DosMemFree(--mem);
  558.                         if(env != 0)
  559.                                 DosMemFree(env);
  560.                 }
  561. #endif
  562.                 return DE_INVLDDATA;
  563.         }
  564. #ifdef IPL
  565.         printf(".");
  566. #endif
  567.         /* read in the image in 32K chunks                      */
  568.         if(mode != OVERLAY)
  569.         {
  570.                 exe_size = image_size - long2para((LONG)sizeof(psp));
  571.         }
  572.         else
  573.                 exe_size = image_size;
  574.         sp = MK_FP(start_seg, 0x0);
  575.         if(mode != OVERLAY)
  576. {
  577. if((header.exMinAlloc == 0) && (header.exMaxAlloc == 0))
  578. {
  579. sp = MK_FP(start_seg + mp -> m_size
  580.  - (image_size + 15) /16, 0);
  581. }
  582. }
  583.         while(exe_size > 0)
  584.         {
  585.                 nBytesRead = dos_read((COUNT)rc, (VOID FAR *)sp, (COUNT)(exe_size < CHUNK ? exe_size : CHUNK));
  586.                 sp = add_far((VOID FAR *)sp, (ULONG)CHUNK);
  587.                 exe_size -= nBytesRead;
  588.                 if(nBytesRead == 0 || exe_size <= 0)
  589.                         break;
  590. #ifdef IPL
  591.                 printf(".");
  592. #endif
  593.         }
  594. #if 0
  595.         /* Error if we did not read the entire image            */
  596.         if(exe_size != 0)
  597.                 fatal("Broken exe loader (exe_size != 0)");
  598. #endif
  599.         /* relocate the image for new segment                   */
  600.         dos_lseek(rc, (LONG)header.exRelocTable, 0);
  601.         for (i=0; i < header.exRelocItems; i++)
  602.         {
  603.                 if (dos_read(rc, (VOID FAR *)&reloc[0], sizeof(reloc)) != sizeof(reloc))
  604.                 {
  605.                         return DE_INVLDDATA;
  606.                 }
  607.                 if(mode == OVERLAY)
  608.                 {
  609.                         spot = MK_FP(reloc[1] + mem, reloc[0]);
  610.                         *spot = *spot + exp -> load.reloc;
  611.                 }
  612.                 else
  613.                 {
  614.                 /*      spot = MK_FP(reloc[1] + mem + 0x10, reloc[0]);*/
  615.                         spot = MK_FP(reloc[1] + start_seg, reloc[0]);
  616.                         *spot = *spot + start_seg;
  617.                 }
  618.         }
  619. #ifdef IPL
  620.         printf(".");
  621. #endif
  622.         /* and finally close the file                           */
  623.         dos_close(rc);
  624.         /* exit here for overlay                                */
  625.         if(mode == OVERLAY)
  626.                 return SUCCESS;
  627.         /* point to the PSP so we can build it                  */
  628.         p = MK_FP(mem, 0);   
  629.         setvec(0x22, (VOID (INRPT FAR *)(VOID))MK_FP(user_r -> CS, user_r -> IP));
  630.         new_psp(p, mem + asize);
  631. #ifndef IPL
  632.         p -> ps_environ = env == 0 ? 0 : env + 1;
  633. #else
  634.         p -> ps_environ = 0;
  635. #endif
  636.         /* complete the psp by adding the command line          */
  637.         p -> ps_cmd_count = exp -> exec.cmd_line -> ctCount;
  638.         fbcopy(exp -> exec.cmd_line -> ctBuffer, p -> ps_cmd, 127);
  639. #if 0        
  640.         /* stick a new line on the end for safe measure         */
  641.         p -> ps_cmd[p -> ps_cmd_count] = 'r';
  642. #endif
  643.         /* identify the mcb as this functions'                  */
  644.         /* use the file name less extension - left adjusted and */
  645.         /* space filled                                         */
  646.         mp -> m_psp = mem;
  647.         if (envp) envp -> m_psp = mem;
  648.         for(i = 0; i < 8; i++)
  649.         {
  650.                 if(namep[i] != '.')
  651.                         mp -> m_name[i] = namep[i];
  652.                 else
  653.                         break;
  654.         }
  655.         for(; i < 8; i++)
  656.                         mp -> m_name[i] = ' ';
  657.         /* build the user area on the stack                     */
  658.         irp = MK_FP(header.exInitSS + start_seg, ((header.exInitSP - sizeof(iregs)) & 0xffff));
  659. #ifdef IPL
  660.         printf(".n");
  661. #endif
  662.         /* start allocating REGs                                */
  663.         /* Note: must match es & ds memory segment              */
  664.         irp -> ES = irp -> DS = mem;
  665.         irp -> CS = header.exInitCS + start_seg;
  666.         irp -> IP = header.exInitIP;
  667.         irp -> AX = 0xffff; /* for now, until fcb code is in    */
  668. #ifdef IPL
  669.         irp -> BX = BootDrive;
  670.         irp -> CX = NumFloppies;
  671. #else
  672.         irp -> BX =
  673.         irp -> CX =
  674. #endif
  675.         irp -> DX =
  676.         irp -> SI =
  677.         irp -> DI =
  678.         irp -> BP = 0;
  679.         irp -> FLAGS = 0x200; 
  680.                                         
  681.         /* Transfer control to the executable                   */
  682.         p -> ps_parent = cu_psp;
  683.         p -> ps_prevpsp = (BYTE FAR *)MK_FP(cu_psp, 0);
  684.         q -> ps_stack = (BYTE FAR *)user_r;
  685.         user_r -> FLAGS &= ~FLG_CARRY;
  686. #ifdef IPL
  687.         printf("Starting kernel ...n");
  688. #endif
  689.         
  690.         switch(mode)
  691.         {
  692.         case LOADNGO:
  693.                 cu_psp = mem;
  694.                 dta = p -> ps_dta;
  695.                 if (InDOS) --InDOS;
  696.                 exec_user(irp);
  697.                 /* We should never be here                      */
  698.                 fatal("KERNEL RETURNED!!!");
  699.                 break;
  700. #ifndef IPL
  701.         case LOAD:
  702.                 cu_psp = mem;
  703.                 exp -> exec.stack = (BYTE FAR *)irp;
  704.                 exp -> exec.start_addr = MK_FP(irp -> CS, irp -> IP);
  705.                 return SUCCESS;
  706. #endif
  707.         }
  708.         return DE_INVLDFMT;
  709. }
  710. COUNT 
  711. DosExec (COUNT mode, exec_blk FAR *ep, BYTE FAR *lp)
  712. {
  713.         COUNT rc;
  714.         exec_blk leb = *ep;
  715.         BYTE FAR *cp;
  716. BOOL bIsCom = FALSE;
  717.         /* If file not found - free ram and return error        */
  718. #ifdef IPL
  719.         printf(".");
  720. #endif
  721.         if((rc = dos_open(lp, 0)) < 0)
  722.         {
  723.                 return DE_FILENOTFND;
  724.         }
  725.         
  726.         if(dos_read(rc, (VOID FAR *)&header, sizeof(exe_header))
  727.          != sizeof(exe_header))
  728.         {
  729. #ifdef IPL
  730.                 printf("Internal IPL error - Read failure");
  731.                 return DE_INVLDDATA;
  732. #else
  733. bIsCom = TRUE;
  734. #endif
  735.         }
  736.         dos_close(rc);
  737. #ifdef IPL
  738.         printf(".");
  739. #endif
  740.         if(bIsCom || header.exSignature != MAGIC)
  741. #ifndef IPL
  742.         {
  743.                 rc = DosComLoader(lp, &leb, mode);
  744.         }
  745. #else
  746.         {
  747.                 char szFileName[32];
  748.                 fmemcpy((BYTE FAR *)szFileName, lp);
  749.                 printf("nFile: %s (MAGIC = %04x)", szFileName, header.exSignature);
  750.                 fatal("IPL can't load .com files!");
  751.         }
  752. #endif
  753.         else
  754.         {
  755.                 rc = DosExeLoader(lp, &leb, mode);
  756.         }
  757.         if (mode == LOAD && rc == SUCCESS)
  758.                 *ep = leb;
  759.         return rc;
  760. }