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

📄 task.c

📁 用C语言实现的DOS操作系统的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************/
/*                                                              */
/*                           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 "../../hdr/portab.h"
#include "globals.h"

/* $Logfile:   C:/dos-c/src/kernel/task.c_v  $ */
#ifdef VERSION_STRINGS
static BYTE *RcsId = "$Header:   C:/dos-c/src/kernel/task.c_v   1.14   07 Feb 1998 20:38:32   patv  $";
#endif

/* $Log:   C:/dos-c/src/kernel/task.c_v  $
 * 
 *    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.
 */
/* $EndLog$ */

#define LOADNGO 0
#define LOAD    1
#define OVERLAY 3

static exe_header header;

#define CHUNK 16384
#define MAXENV 32768

#ifndef PROTO
COUNT ChildEnv(exec_blk FAR *, UWORD *, char far *);
#else
COUNT ChildEnv();
#endif

#ifndef IPL
COUNT 
ChildEnv (exec_blk FAR *exp, UWORD *pChildEnvSeg, char far *pathname)
{
        BYTE FAR *pSrc;
        BYTE FAR *pDest;
        UWORD nEnvSize;
        COUNT RetCode;
        UWORD MaxEnvSize;
        psp FAR *ppsp = MK_FP( cu_psp, 0);
       
        /* create a new environment for the process             */
        /* copy parent's environment if exec.env_seg == 0       */

        pSrc = exp -> exec.env_seg ? 
                        MK_FP(exp -> exec.env_seg, 0) :
                        MK_FP(ppsp -> ps_environ, 0);
                   
        if (!pSrc)    /* no environment to copy */
        {
                *pChildEnvSeg = 0;
                return SUCCESS;
        }

        for(nEnvSize = 0; *pSrc != '\0'; )
        {
                while(*pSrc != '\0')
                {
                        ++pSrc;
                        ++nEnvSize;
                }
                /* account for terminating null         */
                ++nEnvSize;
                ++pSrc;
        }

        /* Test env size and abort if greater than max          */
        if(nEnvSize >= MAXENV)
                return DE_INVLDENV;

        /* allocate enough space for env + path                 */
        if((RetCode = DosMemAlloc(long2para(nEnvSize + 65), 
          FIRST_FIT, (seg FAR *)pChildEnvSeg,
          (UWORD FAR *)MaxEnvSize)) < 0)
                return RetCode;
        else
                pDest = MK_FP(*pChildEnvSeg + 1, 0);

        /* fill the new env and inform the process of its       */
        /* location throught the psp                            */
        pSrc = exp -> exec.env_seg ? 
                        MK_FP(exp -> exec.env_seg, 0) :
                        MK_FP(ppsp -> ps_environ, 0);
        
        /* copy the environment */
        for( ; *pSrc != '\0'; )
        {
                while (*pSrc) 
                {
                        *pDest++ = *pSrc++;  
                } 
                pSrc++;
                *pDest++ = 0;
        }
        *pDest++ = 0;
        /* initialize 'extra strings' count */
        *pDest++ = 1;
        *pDest++ = 0;
        
        /* copy complete pathname */
        truename(pathname, pDest);
        return SUCCESS;
}

#endif


/* The following code is 8086 dependant                         */
VOID 
new_psp (psp FAR *p, int psize)
{
        REG COUNT i;
        BYTE FAR *lpPspBuffer;
        psp FAR *q = MK_FP(cu_psp, 0);

        /* Clear out new psp first                              */
        for(lpPspBuffer = (BYTE FAR *)p, i = 0; i < sizeof(psp) ; ++i)
                *lpPspBuffer = 0;
        
        /* 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;
#ifndef IPL
        p -> ps_reentry = cpm_entry;
#endif
        /* 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;

#ifndef IPL
        /* 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                                    */
        p -> ps_isv22 = (VOID(interrupt FAR *)(void))getvec(0x22);
        /* break address                                        */
        p -> ps_isv23 = (VOID(interrupt FAR *)(void))getvec(0x23);
        /* critical error address                               */
        p -> ps_isv24 = (VOID(interrupt FAR *)(void))getvec(0x24);
#endif

        /* File System parameters                               */
        /* user stack pointer - int 21                          */
        p -> ps_stack = (BYTE FAR *)-1;
        /* file table - 0xff is unused                          */
        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;

#ifndef IPL
        /* clone the file table                                 */
        if(InDOS > 0)
        {
                REG COUNT i;
                
                for(i = 0; i < 20; i++)
                {
                        REG COUNT ret;

                        if(q -> ps_filetab[i] != 0xff
                         && ((ret = CloneHandle(q -> ps_filetab[i])) >= 0))
                        {        
                                p -> ps_filetab[i] = ret;
                        }
                        else
                                p -> ps_filetab[i] = 0xff;
                }
        }
        else
        {
                /* initialize stdin, stdout, etc                        */
                p -> ps_files[STDIN] = 0;       /* stdin                */
                p -> ps_files[STDOUT] = 1;      /* stdout               */
                p -> ps_files[STDERR] = 2;      /* stderr               */
                p -> ps_files[STDAUX] = 3;      /* stdaux               */
                p -> ps_files[STDPRN] = 4;      /* stdprn               */
       }
#else
        /* initialize stdin, stdout, etc                        */
        p -> ps_files[STDIN] = 0;       /* stdin                */
        p -> ps_files[STDOUT] = 1;      /* stdout               */
        p -> ps_files[STDERR] = 2;      /* stderr               */
        p -> ps_files[STDAUX] = 3;      /* stdaux               */
        p -> ps_files[STDPRN] = 4;      /* stdprn               */
#endif

        /* first command line argument                          */
        p -> ps_fcb1.fcb_drive = 0;
        /* second command line argument                         */
        p -> ps_fcb2.fcb_drive = 0;

        /* local command line                                   */
        p -> ps_cmd_count = 0;  /* command tail                 */
        p -> ps_cmd[0] = 0;     /* command tail                 */
}


#ifndef IPL
static COUNT 
DosComLoader (BYTE FAR *namep, exec_blk FAR *exp, COUNT mode)
{
        COUNT rc, env_size, nread;
        UWORD mem;
        UWORD env, asize;
        BYTE FAR *sp, FAR *dp;
        psp FAR *p;
        psp FAR *q = MK_FP(cu_psp, 0);
        mcb FAR *mp, FAR *envp = 0;
        iregs FAR *irp;
        LONG com_size;
        
        if(mode != OVERLAY)
        {
                
                if((rc = ChildEnv(exp, &env, namep)) != SUCCESS)
                {        
                        return rc;
                }
                /* Allocate our memory and pass back any errors         */
                if((rc = DosMemAlloc(0, LARGEST, (seg FAR *)&mem, (UWORD FAR *)&asize)) < 0)
                {
                        if(env != 0)
                           DosMemFree(env);
                        
                        return rc;
                }
                mp = MK_FP(mem, 0);
                ++mem;
                envp = MK_FP(env, 0);
        }
        else mem = exp -> load.load_seg;

        /* Now load the executable                              */
        /* If file not found - error                            */
        /* NOTE - this is fatal because we lost it in transit   */
        /* from DosExec!                                        */
        if((rc = dos_open(namep, 0)) < 0)
                fatal("(DosComLoader) com file lost in transit");
        /* do it in 32K chunks                                  */
        sp = MK_FP(mem, mode == OVERLAY? 0 : sizeof(psp));
        for(com_size = dos_getfsize(rc), nread = 0; com_size > 0; )
        {
                nread = dos_read(rc, sp, CHUNK);
                sp = add_far((VOID FAR *)sp, (ULONG)nread);
                com_size -= nread;
                if(nread < CHUNK)
                        break;
        }
        dos_close(rc);

        if(mode == OVERLAY)
                 return SUCCESS;

        /* point to the PSP so we can build it                  */
        p = MK_FP(mem, 0);
        setvec(0x22, (VOID (INRPT FAR *)(VOID))MK_FP(user_r -> CS, user_r -> IP));
        new_psp(p, mem + asize);

        p -> ps_environ = env == 0 ? 0 : env + 1;

        /* complete the psp by adding the command line          */
        p -> ps_cmd_count = exp -> exec.cmd_line -> ctCount;
        fbcopy(exp -> exec.cmd_line -> ctBuffer, p -> ps_cmd, 127);
#if 0
        /* stick a new line on the end for safe measure         */
        p -> ps_cmd[p -> ps_cmd_count] = '\r';
#endif
        /* identify the mcb as this functions'                  */
        /* use the file name less extension - left adjusted and */
        /* space filled                                         */
        mp -> m_psp = mem;
        if (envp) envp -> m_psp = mem;   

        for(asize = 0; asize < 8; asize++)
        {
                if(namep[asize] != '.')
                        mp -> m_name[asize] = namep[asize];
                else
                        break;
        }
        for(; asize < 8; asize++)
                        mp -> m_name[asize] = ' ';

        /* 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;
        irp -> AX = 0xffff; /* for now, until fcb code is in    */
        irp -> BX =
        irp -> CX =
        irp -> DX =
        irp -> SI =
        irp -> DI =
        irp -> BP = 0;
        irp -> FLAGS = 0x200;

        /* 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;
        
        switch(mode)
        {
        case LOADNGO:
        {        
                cu_psp = mem;
                dta = p -> ps_dta;
                if (InDOS)
                	--InDOS;
                exec_user(irp);

                /* We should never be here                      */
                fatal("KERNEL RETURNED!!!");
                break;
        }
        case LOAD:
                cu_psp = mem;
                exp -> exec.stack = (BYTE FAR *)irp;
                exp -> exec.start_addr = MK_FP(irp -> CS, irp -> IP);
                return SUCCESS;
        }

        return DE_INVLDFMT;
}


VOID 
return_user (void)
{
        psp FAR *p, FAR *q;
        REG COUNT i;

⌨️ 快捷键说明

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