⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 task.c

📁 开源DOS的C代码源程序
💻 C
📖 第 1 页 / 共 2 页
字号:
    {
      COUNT rc;
      UBYTE UMBstate = uppermem_link;
      UBYTE orig_mem_access = mem_access_mode;
      
      if (mode & 0x80)
      {
        mem_access_mode |= 0x80;
        DosUmbLink(1);            /* link in UMB's */
      }
      
      rc = ChildEnv(exp, &env, namep);
      
      /* COMFILES will always be loaded in largest area. is that true TE */
      /* yes, see RBIL, int21/ah=48 -- Bart */

      if (rc == SUCCESS)
        rc = ExecMemLargest(&asize, com_size);
      
      if (rc == SUCCESS)
        /* Allocate our memory and pass back any errors         */
        rc = ExecMemAlloc(asize, &mem, &asize);

      if (rc != SUCCESS)
        DosMemFree(env);

      if (mode & 0x80)
      {
        DosUmbLink(UMBstate);       /* restore link state */
        mem_access_mode = orig_mem_access;
        mode &= 0x7f;
      }

      if (rc != SUCCESS)
        return rc;

      ++mem;
    }
    else
      mem = exp->load.load_seg;
  }

#ifdef DEBUG
  printf("DosComLoader. Loading '%S' at %04x\n", namep, mem);
#endif
  /* Now load the executable                              */
  {
    BYTE FAR *sp;

    if (mode == OVERLAY)  /* memory already allocated */
      sp = MK_FP(mem, 0);
    else                  /* test the filesize against the allocated memory */
      sp = MK_FP(mem, sizeof(psp));

    /* MS DOS always only loads the very first 64KB - sizeof(psp) bytes.
       -- 1999/04/21 ska */

    /* rewind to start */
    SftSeek(fd, 0, 0);
    /* read everything, but at most 64K - sizeof(PSP)             */
    DosRWSft(fd, 0xff00, sp, XFR_READ);
    DosCloseSft(fd, FALSE);
  }

  if (mode == OVERLAY)
    return SUCCESS;
  
  {
    UWORD fcbcode;
    psp FAR *p;

    /* point to the PSP so we can build it                  */
    setvec(0x22, (intvec)MK_FP(user_r->CS, user_r->IP));
    child_psp(mem, cu_psp, mem + asize);

    fcbcode = patchPSP(mem - 1, env, exp, namep);
    /* set asize to end of segment */
    if (asize > 0x1000)
      asize = 0x1000;
    if (asize < 0x11)
      return DE_NOMEM;
    asize -= 0x11;
    /* CP/M compatibility--size of first segment for .COM files
       while preserving the far call to 0:00c0 +
       copy in HMA at ffff:00d0 */
    p = MK_FP(mem, 0);
    p->ps_reentry = MK_FP(0xc - asize, asize << 4);
    asize <<= 4;
    asize += 0x10e;
    exp->exec.stack = MK_FP(mem, asize);
    exp->exec.start_addr = MK_FP(mem, 0x100);
    *((UWORD FAR *) MK_FP(mem, asize)) = (UWORD) 0;
    load_transfer(mem, exp, fcbcode, mode);
  }
  return SUCCESS;
}

VOID return_user(void)
{
  psp FAR *p, FAR * q;
  REG COUNT i;
  iregs FAR *irp;
/*  long j;*/

  /* 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      */
  network_redirector(REM_PROCESS_END);
  /* might be a good idea to do that after closing
     but doesn't help NET either TE */

  if (!tsr)
  {
    network_redirector(REM_CLOSEALL);
    for (i = 0; i < p->ps_maxfiles; i++)
    {
      DosClose(i);
    }
    FcbCloseAll();
    FreeProcessMem(cu_psp);
  }

  cu_psp = p->ps_parent;
  q = MK_FP(cu_psp, 0);

  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, 0);
}

COUNT DosExeLoader(BYTE FAR * namep, exec_blk * exp, COUNT mode, COUNT fd)
{
  UWORD mem, env, start_seg, asize = 0;
  UWORD exe_size;
  {
    UWORD image_size;

    /* compute image size by removing the offset from the   */
    /* number pages scaled to bytes plus the remainder and  */
    /* the psp                                              */
    /*  First scale the size and remove the offset          */
    if (ExeHeader.exPages >= 2048)
      return DE_INVLDDATA; /* we're not able to get >=1MB in dos memory */
    image_size = ExeHeader.exPages * 32 - ExeHeader.exHeaderSize;

    /* 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.
       Jun 11, 2000 - rbc */
    
    if ((mode & 0x7f) != OVERLAY)
    {
      UBYTE UMBstate = uppermem_link;
      UBYTE orig_mem_access = mem_access_mode;
      COUNT rc;
      
      /* and finally add in the psp size                      */
      image_size += sizeof(psp) / 16;        /*TE 03/20/01 */
      exe_size = image_size + ExeHeader.exMinAlloc;
      
      /* Clone the environement and create a memory arena     */
      if (mode & 0x80)
      {
        DosUmbLink(1);          /* link in UMB's */
        mem_access_mode |= 0x80;
      }
      
      rc = ChildEnv(exp, &env, namep);
      
      if (rc == SUCCESS)
        /* Now find out how many paragraphs are available       */
        rc = ExecMemLargest(&asize, exe_size);
      
      exe_size = image_size + ExeHeader.exMaxAlloc;
      /* second test is for overflow (avoiding longs) --
         exMaxAlloc can be high */
      if (exe_size > asize || exe_size < image_size)
        exe_size = asize;
      
      /* TE if ExeHeader.exMinAlloc == ExeHeader.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 ((ExeHeader.exMinAlloc | ExeHeader.exMaxAlloc) == 0)
        exe_size = asize;
      
      /* Allocate our memory and pass back any errors         */
      if (rc == SUCCESS)
        rc = ExecMemAlloc(exe_size, &mem, &asize);
      
      if (rc != SUCCESS)
        DosMemFree(env);
      
      if (mode & 0x80)
      {
        mem_access_mode = orig_mem_access; /* restore old situation */
        DosUmbLink(UMBstate);     /* restore link state */
      }
      if (rc != SUCCESS)
        return rc;
      
      mode &= 0x7f; /* forget about high loading from now on */
      
#ifdef DEBUG
      printf("DosExeLoader. Loading '%S' at %04x\n", namep, mem);
#endif
      
      /* memory found large enough - continue processing      */
      ++mem;
      
/* /// 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 */
    }
    else /* !!OVERLAY */
    {
      mem = exp->load.load_seg;
    }

    /* Now load the executable                              */
    /* offset to start of image                             */
    if (SftSeek(fd, ExeHeader.exHeaderSize * 16UL, 0) != SUCCESS)
    {
      if (mode != OVERLAY)
      {
        DosMemFree(--mem);
        DosMemFree(env);
      }
      return DE_INVLDDATA;
    }
    
    /* create the start seg for later computations          */
    start_seg = mem;
    exe_size = image_size;
    if (mode != OVERLAY)
    {
      exe_size -= sizeof(psp) / 16;
      start_seg += sizeof(psp) / 16;
      if (exe_size > 0 && (ExeHeader.exMinAlloc | ExeHeader.exMaxAlloc) == 0)
      {
        mcb FAR *mp = MK_FP(mem - 1, 0);
        
        /* then the image should be placed as high as possible */
        start_seg += mp->m_size - image_size;
      }
    }
  }

  /* read in the image in 32256 chunks                      */
  {
    int nBytesRead, toRead = CHUNK;
    seg sp = start_seg;

    while (1)
    {
      if (exe_size < CHUNK/16)
        toRead = exe_size*16;
      nBytesRead = (int)DosRWSft(fd, toRead, MK_FP(sp, 0), XFR_READ);
      if (nBytesRead < toRead || exe_size <= CHUNK/16)
        break;
      sp += CHUNK/16;
      exe_size -= CHUNK/16;
    }
  }

  {                             /* relocate the image for new segment                   */
    COUNT i;
    UWORD reloc[2];
    seg FAR *spot;

    SftSeek(fd, ExeHeader.exRelocTable, 0);
    for (i = 0; i < ExeHeader.exRelocItems; i++)
    {
      if (DosRWSft
          (fd, sizeof(reloc), (VOID FAR *) & reloc[0], XFR_READ) != sizeof(reloc))
      {
        if (mode != OVERLAY)
        {
          DosMemFree(--mem);
          DosMemFree(env);
        }
        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;
      }
    }
  }

  /* and finally close the file                           */
  DosCloseSft(fd, FALSE);

  /* exit here for overlay                                */
  if (mode == OVERLAY)
    return SUCCESS;

  {
    UWORD fcbcode;

    /* point to the PSP so we can build it                  */
    setvec(0x22, (intvec)MK_FP(user_r->CS, user_r->IP));
    child_psp(mem, cu_psp, mem + asize);

    fcbcode = patchPSP(mem - 1, env, exp, namep);
    exp->exec.stack =
      MK_FP(ExeHeader.exInitSS + start_seg, ExeHeader.exInitSP);
    exp->exec.start_addr =
      MK_FP(ExeHeader.exInitCS + start_seg, ExeHeader.exInitIP);

    /* Transfer control to the executable                   */
    load_transfer(mem, exp, fcbcode, mode);
  }
  return SUCCESS;
}

/* 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)
{
  COUNT rc;
  COUNT fd;

  if ((mode & 0x7f) > 3 || (mode & 0x7f) == 2)
    return DE_INVLDFMT; 

  fmemcpy(&TempExeBlock, ep, sizeof(exec_blk));
  /* If file not found - free ram and return error        */

  if (IsDevice(lp) ||        /* we don't want to execute C:>NUL */
      (fd = (short)DosOpenSft(lp, O_LEGACY | O_OPEN | O_RDONLY, 0)) < 0)
  {
    return DE_FILENOTFND;
  }
  
  rc = (int)DosRWSft(fd, sizeof(exe_header), (BYTE FAR *)&ExeHeader, XFR_READ);

  if (rc == sizeof(exe_header) &&
      (ExeHeader.exSignature == MAGIC || ExeHeader.exSignature == OLD_MAGIC))
  {
    rc = DosExeLoader(lp, &TempExeBlock, mode, fd);
  }
  else if (rc != 0)
  {
    rc = DosComLoader(lp, &TempExeBlock, mode, fd);
  }

  DosCloseSft(fd, FALSE);

  if (mode == LOAD && rc == SUCCESS)
    fmemcpy(ep, &TempExeBlock, sizeof(exec_blk));

  return rc;
}

#include "config.h" /* config structure definition */

/* start process 0 (the shell) */
VOID ASMCFUNC P_0(struct config FAR *Config)
{
  BYTE *tailp, *endp;
  exec_blk exb;
  UBYTE mode = Config->cfgP_0_startmode;

  /* build exec block and save all parameters here as init part will vanish! */
  exb.exec.fcb_1 = exb.exec.fcb_2 = (fcb FAR *)-1L;
  exb.exec.env_seg = DOS_PSP + 8;
  fstrcpy(Shell, MK_FP(FP_SEG(Config), Config->cfgInit));
  /* join name and tail */
  fstrcpy(Shell + strlen(Shell), MK_FP(FP_SEG(Config), Config->cfgInitTail));
  endp =  Shell + strlen(Shell);

  for ( ; ; )   /* endless shell load loop - reboot or shut down to exit it! */
  {
    BYTE *p;
    /* if there are no parameters, point to end without "\r\n" */
    if((tailp = strchr(Shell,'\t')) == NULL &&
       (tailp = strchr(Shell, ' ')) == NULL)
        tailp = endp - 2;
    /* shift tail to right by 2 to make room for '\0', ctCount */
    for (p = endp - 1; p >= tailp; p--)
      *(p + 2) = *p;
    /* terminate name and tail */
    *tailp =  *(endp + 2) = '\0';
    /* ctCount: just past '\0' do not count the "\r\n" */
    exb.exec.cmd_line = (CommandTail *)(tailp + 1);
    exb.exec.cmd_line->ctCount = endp - tailp - 2;
#ifdef DEBUG
    printf("Process 0 starting: %s%s\n\n", Shell, tailp + 2);
#endif
    res_DosExec(mode, &exb, Shell);
    put_string("Bad or missing Command Interpreter: "); /* failure _or_ exit */
    put_string(Shell);
    put_string(tailp + 2);
    put_string(" Enter the full shell command line: ");
    endp = Shell + res_read(STDIN, Shell, NAMEMAX);
    *endp = '\0';                             /* terminate string for strchr */
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -