1、TASK.C
/*
TASK.C
Teacher: Wang Xiaoniu
program by Wang Xiaozhi & Zhao Tingzhe
CopyRight Northwest Normal Univeristy Computer Department 1995.4
*/
/*
TCC -mc -1 -f- -d -k- -O -Z task.c
Usage:task [DRIVE:\PATH\]
*/
#include <stdlib.h>
#include <io.h>
#include <fcntl.h>
#include <dos.h>
#include <mem.h>
#include <conio.h>
#include <process.h>
/*
Use BIOS correspondence areas
0:0x4f0 Software flag
0:0x4f4 Menu Return
*/
/*
Change Vector includes 1CH,2AH,9H,5H,7DH,
1CH:Timer;
2AH:DOS critical section;
9H:Keyboard hardware interrupt;
*/
#define SOFTWAREFLAG 0x575a
#define NDEBUG
#ifndef NDEBUG
void _Assert(char *,int);
void DeleteTask(void);
#define Assert(f) if(f) ; else _Assert(__FILE__,__LINE__)
void _Assert(char *s,int line)
{
cprintf("Assert failed :FILE :%s LINE:%d",
s,line);
DeleteTask();
}
#else
#define Assert(f)
#endif
#define INTERRUPT void interrupt
typedef unsigned int WORD;
typedef unsigned char BYTE;
#define STACKSIZE 2048 /* Itself stack */
char sStack[STACKSIZE];
#define MAXUSERS 6 /* Max Task Number */
#define F10_KEY 68 /* This is F10 */ /* Hot Key */
#define CTRL_ALT_KEY 12 /* This is ctrl 0x8 && alt 0x4*/ /* Crtl_ALT Key */
#define SDA_SWAPSIZE 0x7c0
extern WORD _stklen=2048;
int WantPopUp=0; /* Menu pop_up flag */
int Int2ABusy=0; /* Dos Enter flag */
int nExe=0; /* Now Task Id */
int uTask=0;
INTERRUPT (*OldInt9)();
INTERRUPT NewInt9();
/*
INTERRUPT (*OldInt1C)();
INTERRUPT NewInt1C();
*/
INTERRUPT (*OldInt2A)();
INTERRUPT NewInt2A();
void main(int argc,char *argv[]);
void TaskMain(void);
void ChangeVect(void);
void TestInstall(void);
void End(void);
void TaskChange(void);
void Menu(void);
void SaveAllMem(void);
void SaveMem(WORD seg);
void SetMemFree(WORD seg);
void LoadMem(WORD seg);
WORD GetMem(void);
void DeleteTask(void);
void SubDos(void);
int MakeMapName(char *s,int mode);
#define READ 0
#define READ_AND_NOT_DIRECT_PUT 2
#define WRITE 1
void IOFile(char *s,char *buf,WORD size,int ctrl);
typedef struct {
WORD es,ds,di,si,bp,sp,bx,dx,cx,ax,ip,cs,flags;
} INTERRUPT_REGS; /* Interrupt parameters */
typedef struct {
WORD psp;
struct SAVE_REGS {
WORD sp,ss; /* Task RESG */
} save_regs;
char swapsave[SDA_SWAPSIZE]; /* DosSwapArea */
} PCB; /* PCB For Task */
PCB nPCB[2];
BYTE IsTask[MAXUSERS+1]; /* For Task 1 to 6 */
/* 0 noused */
int fp;
#define VECTMAP "vect"
#define SDAMAP "sda"
#define BLOCKSIZE 512
#define MEMORYMAP "mem" /* memory map file */
typedef struct {
char attr;
WORD owner;
WORD size;
} MCB; /* Memory Crtl Block */
MCB mcbdesc={ /* Last,size,nouse */
'Z',0,0
};
char sPath[32]; /* Owner's path and swapdisk */
char sDisk[32];
char sNameBuffer[82];
char temp2[48];
/*_______________________________________________________________________*/
/*
DOSSWAP.C-Functions to manage DOS swap areas
*/
/*
INT21h 5D06
DS:SI -points to DOS swappable data area
DX -size of area to swap when InDOS>0
CX -size of area to always swap
*/
#define GET_DOSSWAP3 0X5D06
/* variables for 3.x swap work*/
char far *pDosSwapArea; /* DosSwapArea Addr */
int DosSwapSize;
/*
Function:InitDosSwap
Initialize pointers and sizes of DOS swap area.
*/
void InitDosSwap(void)
{
WORD save_ds;
WORD tmp_ds,tmp_si,tmp_cx;
save_ds=_DS;
_AX=GET_DOSSWAP3;
geninterrupt(0x21); /* Must save DS */
tmp_cx=_CX;
tmp_ds=_DS;
tmp_si=_SI;
_DS=save_ds;
pDosSwapArea=MK_FP(tmp_ds,tmp_si);
Assert(pDosSwapArea);
DosSwapSize=tmp_cx;
}
/*
Function:SaveDosSwap
This function will save the dos swap area to a local buffer
*/
void SaveDosSwap(void)
{
movedata( FP_SEG(pDosSwapArea),
FP_OFF(pDosSwapArea),
_DS,
FP_OFF(nPCB[nExe].swapsave),
DosSwapSize);
}
/*
Function:RestoreDosSwap
This function will restore a previously swapped dos data area
*/
void RestoreDosSwap(void)
{
movedata( _DS,
FP_OFF(nPCB[nExe].swapsave),
FP_SEG(pDosSwapArea),
FP_OFF(pDosSwapArea),
DosSwapSize);
}
/*_______________________________________________________________________*/
/*
MAIN.C-Main program for Task DOS
*/
void TaskMain(void)
{
TestInstall();
InitDosSwap();
SaveDosSwap();
ChangeVect();
/* Save raw vector table */
IOFile(VECTMAP,(char far *)0l,1024,WRITE);
uTask=1;
IsTask[1]=1;
SubDos();
End();
}
void ChangeVect(void) /* Set owner hook intr */
{
/*
OldInt1C=getvect(0x1c);
*/
OldInt2A=getvect(0x2a);
OldInt9=getvect(0x9);
/*
setvect(0x1c,NewInt1C);
*/
setvect(0x2a,NewInt2A);
setvect(0x9,NewInt9);
}
/*
The function TestInstall first check is also installed!
Then makeup pop_up stack,save task's DTA for use.
*/
void TestInstall(void)
{
if(peek(0,0x4f0)==SOFTWAREFLAG) /* If also exist, exit */
exit(1);
else
poke(0,0x4f0,SOFTWAREFLAG); /* Exist flag */
nPCB[0].save_regs.ss=_DS;
/* We not sure if sp is a odd */
nPCB[0].save_regs.sp=FP_OFF(&sStack[STACKSIZE-2]);
nPCB[0].psp=_psp;
}
void End(void) /* Restore old intr and clear */
{
IOFile(VECTMAP,(char far *)0l,1024,READ_AND_NOT_DIRECT_PUT);
/*
setvect(0x1c,OldInt1C);
*/
setvect(0x2a,OldInt2A);
setvect(0x9,OldInt9);
poke(0,0x4f0,0); /* Clear softflag */
}
INTERRUPT NewInt9() /* CTRL_ALT_F10 to pop up. */
{
static char far *pKey=MK_FP(0,0x417);
static int key;
if(inportb(0x60)==F10_KEY) /* Hot key */
{ /* CTRL and ALT */
if((*pKey&CTRL_ALT_KEY)==CTRL_ALT_KEY)
{
key=inportb(0x61);
outportb(0x61,key);
outportb(0x20,0x20);
/*
if also pop up, or if dos_error,or dos busy,
can not pop up.
*/
if(WantPopUp||*pDosSwapArea||Int2ABusy)
return;
else
{
WantPopUp=1;
disable();
nPCB[1].save_regs.ss=_SS; /* save old stack */
nPCB[1].save_regs.sp=_SP;
_SP=nPCB[0].save_regs.sp; /* set new stack */
_SS=nPCB[0].save_regs.ss;
enable();
TaskChange(); /* enter task */
disable();
_SP=nPCB[1].save_regs.sp; /* restore old stack */
_SS=nPCB[1].save_regs.ss;
enable();
WantPopUp=0;
}
}
else
(*OldInt9)();
}
else
(*OldInt9)();
}
/*
INTERRUPT NewInt1C()
{
static int i=0;
static char str[12],*sptr;
char far *p;
static char h,m,s;
(*OldInt1C)();
if(i++<4)
return;
else
{
i=0;
_AH=2;
geninterrupt(0x1a);
h=_CH;
m=_CL;
s=_DH;
#ifndef NDEBUG
sprintf(str,"%d %d ",*(pDosSwapArea),
*(pDosSwapArea+1));
#else
sprintf(str,"%02d %02x:%02x:%02x",
uTask,h,m,s);
#endif
sptr=str;
p=MK_FP(0xb800,160-22);
while(*sptr)
{
*(p++)=*(sptr++);
*(p++)=RED;
}
}
}
*/
INTERRUPT NewInt2A(INTERRUPT_REGS r) /* Check DOS busy. */
{
switch(r.ax&0xff00)
{
case 0x8000:
Int2ABusy++;
break;
case 0x8001:
case 0x8002:
if(Int2ABusy)
Int2ABusy--;
break;
default:
break;
}
_AX=r.ax;
(*OldInt2A)();
}
void TaskChange(void) /* Task Change Procedure */
{
nExe=1;
SaveDosSwap(); /* save SDA */
nExe=0;
RestoreDosSwap(); /* set new SDA */
IOFile(SDAMAP,(char *)&nPCB[1].psp,sizeof(PCB),WRITE);
Menu(); /* sub route */
IOFile(SDAMAP,(char *)&nPCB[1].psp,sizeof(PCB),READ);
SaveDosSwap();
nExe=1;
RestoreDosSwap(); /* restore old SDA */
}
void cccp(char *temp)
{
sprintf(sNameBuffer,"%s%s",sPath,temp);
spawnl(P_WAIT,sNameBuffer,sNameBuffer,temp2,NULL);
}
/* Define Sub program */
#define MENU "menu"
#define SAVEDISP "savedisp"
#define LOADDISP "loaddisp"
/* Define display filename */
#define DISPMAP "disp"
void Menu(void)
{
int nTmpTask;
/* Save Task's Vector */
IOFile(VECTMAP,(char far *)0l,1024,WRITE);
nTmpTask=uTask;
uTask=0;
/* restore raw vect for another task */
IOFile(VECTMAP,(char far *)0l,1024,READ_AND_NOT_DIRECT_PUT);
uTask=nTmpTask;
SaveAllMem(); /* save and clear memory */
sprintf(temp2," %s%s%d.map",sDisk,DISPMAP,uTask);/* sDisk is SwapDisk */
cccp(SAVEDISP); /* save and load display for menu to do.*/
sprintf(temp2," %s",sDisk);
poke(0,0x4f4,uTask);
cccp(MENU);
if((uTask=(int)peek(0,0x4f4))==-1) /* menu return value in this address.*/
DeleteTask(); /* all task exit memory */
Assert(uTask<=MAXUSERS);
if(IsTask[uTask]==0) /* Build a new task. */
{
IsTask[uTask]=1;
WantPopUp=0;
SubDos();
}
sprintf(temp2," %s%s%d.map",sDisk,DISPMAP,uTask);
cccp(LOADDISP); /* restore display */
LoadMem(GetMem()); /* restore memory */
/* Restore Task Vector */
IOFile(VECTMAP,(char far *)0l,1024,READ_AND_NOT_DIRECT_PUT);
}
/*
Memory MAP
___________
| intr |
| bios |
| dos |
| command |
| t a s k | _______ first swap seg
| |
| . |
| . |
| . |
| . |
| . |
| . |
___________ A000h
*/
void SaveAllMem(void)
{
WORD firstseg;
firstseg=GetMem();
SaveMem(firstseg);
SetMemFree(firstseg);
}
void SaveMem(WORD seg) /* from seg to 0xa000 save to file */
{
char huge *tmpptr;
tmpptr=(char huge *)MK_FP(seg,0);
MakeMapName(MEMORYMAP,1);
Assert(fp!=-1);
while(seg<=0xa000)
{
_write(fp,(char far *)tmpptr,BLOCKSIZE);
tmpptr+=BLOCKSIZE;
seg+=BLOCKSIZE/16;
}
_close(fp);
}
void SetMemFree(WORD seg) /* Let from seg to 0xa000 is */
{
mcbdesc.size=0xa000-seg-1; /* a free MCB */
movedata(_DS,FP_OFF(&(mcbdesc.attr)),
seg,0,16);
}
void LoadMem(WORD seg) /* load memory map from file */
{
char huge *tmpptr;
MakeMapName(MEMORYMAP,0);
tmpptr=(char huge *)MK_FP(seg,0);
Assert(fp!=-1);
while(seg<0xa000)
{
if((0xa000-seg)<32)
_read(fp,(char far *)tmpptr,(0xa000-seg)*16);
else
_read(fp,(char far *)tmpptr,BLOCKSIZE);
tmpptr+=BLOCKSIZE;
seg+=BLOCKSIZE/16;
}
_close(fp);
}
/*
Cation :
The next MCB is
first swap memory seg.
*/
/*
GetMem return's seg is next MCB,
It belone's sub command.com.
*/
WORD GetMem()
{
MCB far *p;
p=MK_FP(nPCB[0].psp-1,0);
return(nPCB[0].psp+p->size);
}
/*
Cation:
DeleteTask free DOS memory,restore raw vector,
but it not close other task's opening files. You
can use it, But remember this.
*/
void DeleteTask(void)
{
uTask=0;
SetMemFree(GetMem());
End();
exit(1);
}
#define WELLCOMEFILE "sptmap" /* PAGE */
#define HELPFILE "help" /* HELP */
void main(int argc,char *argv[])
{
char *s,*t;
Assert(argv[0]);
s=argv[0]; /* get task's path */
t=0;
for(;*s;s++)
{
if(*s=='\\')
t=s;
}
*(t+1)=0;
sprintf(sPath,"%s",argv[0]);
*t=0;
if(argc==2) /* get task's swapdisk */
sprintf(sDisk,"%s",argv[1]);
else
sprintf(sDisk,"%s",sPath);
temp2[0]=0;
cccp(WELLCOMEFILE); /* Page */
TaskMain(); /* MAIN ROUTE */
}
int MakeMapName(char *s,int mode) /* open a task's file */
{
sprintf(sNameBuffer,"%s%s%d.map",sDisk,s,uTask);
if(mode)
fp=_creat(sNameBuffer,FA_ARCH);
else
fp=_open(sNameBuffer,O_RDWR);
}
/* ctrl 0:read,1:write */
void IOFile(char *s,char *buf,WORD size,int ctrl)
{
int i;
long vector;
Assert(size<0x800);
if(ctrl==READ_AND_NOT_DIRECT_PUT)
{
i=1;
ctrl=READ;
}
else
i=0;
MakeMapName(s,ctrl);
Assert(fp!=-1);
if(ctrl==WRITE)
{
_write(fp,buf,size);
}
else
{
if(i) /* Can't direct put to Vectable */
{
for(i=0;i<256;i++)
{
_read(fp,(char far *)(&vector),4);
setvect(i,vector);
}
}
else
_read(fp,buf,size);
}
_close(fp);
}
void SubDos(void)
{
char *p;
p=getenv("COMSPEC");
spawnl(P_WAIT,p,p,"/p",NULL);
}