📄 multtest.c
字号:
/* MULTI.C */
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <dos.h>
#include <io.h>
#include "tsr.h"
#define SEARCH_DIR "C:\\SPOOL\\"
#define STACK_SIZE 4096 /* must be 16 byte boundaray */
#define SET_DTA 0x1a /* SET Disk Transfer Address */
#define GET_DTA 0x2f /* GET Disk Transfer Address */
#define STAY_RES 0x31 /* DOS Term & Stay Reg */
#define ALTER_BLOCK 0x4a /* DOS Alter Mem BLock */
#define BACKGROUND_TICS 2
#define FOREGROUND_TICS 16
#define BACKGROUND_YIELD 0
#define FOREGROUND_YIELD 0
struct prReq
{
char level;
char far *fname;
};
char far *stack_ptr; /* stack for our background TSR */
char far *ptr;
unsigned ss_save; /* slot for stack segment register */
unsigned sp_save; /* slot for stack pointer register */
unsigned unsafe_flag = 0; /* set true by variouse interrupts */
int first_time = 1; /* flag for first time in running background */
int my_psp; /* our TSR's psp */
int foreground_psp; /* PSP of foreground process we've interrupted */
int foreground_dta_seg; /* DTA of foreground process we've interrupted */
int foreground_dta_off;
int ctr=0;
int tic_count = 0; /* counts timer tices */
int in_progress = 0; /* true if we're in background process */
/* various work variables */
int ax,bx,cx,dx,bp,si,di,ss,sp,cs,es;
int cs_ip;
union REGS regs;
struct SREGS sregs;
char search_work[65];
struct ExtErr my_ErrInfo;
struct ExtErr foreground_ErrInfo;
int foreground_limit = FOREGROUND_TICS; /* limit of foreground cycle */
int background_limit = BACKGROUND_TICS; /* limit of background cycle */
char search_dir[65] = {SEARCH_DIR}; /* directory to search for spool files */
volatile int int_28_active = 0; /* true if activated by INT 28 */
/* old interrupt pointers are stored here */
INTVECT old_int8, old_int9, old_int10, old_int13;
INTVECT old_int1B, old_int23, old_int24, old_int25;
INTVECT old_int26, old_int28;
/* prototypes for this module */
void main_loop();
void interrupt far new_int8(INTERRUPT_REGS);
void interrupt far new_int9(INTERRUPT_REGS);
void interrupt far new_int10(void);
void interrupt far new_int13(void);
void interrupt far new_int1B(INTERRUPT_REGS);
void interrupt far new_int23(INTERRUPT_REGS);
void interrupt far new_int24(INTERRUPT_REGS);
void interrupt far new_int25(void);
void interrupt far new_int26(void);
void interrupt far new_int28(INTERRUPT_REGS);
int spooler_active(void);
int search_spl_que(char * fname);
void suspend_foreground(void);
void suspend_background(void);
/* returns nonzero if spooler active */
int spooler_active()
{
union REGS regs;
regs.x.ax = 0x0100; /* spooler active request */
int86(0x2f,®s,®s); /* call multiplex interrupt */
return(regs.h.al == 0xff); /* FF if spooler active */
}
/* returns nonzero if string pointed to by fname is in the spooler queue */
int search_spl_que(char * fname)
{
union REGS regs;
struct SREGS sregs;
char far * que_ptr;
char que_name[65];
int ii;
int found;
found = 0;
if (spooler_active())
{
regs.x.ax = 0x0104; /* get spooler status */
int86x(0x2f,®s,®s,&sregs);
/* on return from call DS:SI points to print queue */
(long) que_ptr = (sregs.ds * 0x10000L) | regs.x.si;
regs.x.ax = 0x0105; /* release hold on spooler, side effect of status*/
int86x(0x2f,®s,®s,&sregs);
while (*que_ptr && !found) /* while items in queue */
{
for (ii = 0; ii < 65; ii++)
que_name[ii] = *(que_ptr + ii);
found = !strcmpi(que_name,fname);
que_ptr += 65;
}
}
return(found);
}
void main_loop()
{
struct find_t c_file;
union REGS regs;
struct SREGS sregs;
struct prReq prRequest;
struct prReq far * ptr;
int sleep_cntr;
while (1)
{
strcpy(search_work,search_dir);
strcat(search_work,"*.SPL"); /* create dir search string */
sleep_cntr = 20000;
while (sleep_cntr) /* wait a while between each dir search */
{
sleep_cntr-= 1;
}
printf("Background Active!\n");
}
}
void suspend_foreground()
{
/* SWAP TO BACKGROUND */
tic_count = 0;
/* save old interrupt-CTRL-BREAK, CTRL-C and CRIT ERROR */
old_int1B= _dos_getvect(0x1B);
old_int23= _dos_getvect(0x23);
old_int24= _dos_getvect(0x24);
/* set our interrupts functions */
_dos_setvect(0x1b,new_int1B);
_dos_setvect(0x23,new_int23);
_dos_setvect(0x24,new_int24);
/* save current PSP and set to ours */
foreground_psp = GetPSP();
SetPSP(my_psp);
/* get foreground DTA */
regs.h.ah = GET_DTA;
intdosx(®s, ®s, &sregs);
foreground_dta_seg = sregs.es;
foreground_dta_off = regs.x.bx;
/* set up our DTA */
regs.h.ah = SET_DTA;
regs.x.dx = 0x80; /* use default in PSP area */
sregs.ds = my_psp;
intdosx(®s, ®s, &sregs);
/* save error info */
GetExtErr(&foreground_ErrInfo);
if (! first_time)
SetExtErr(&my_ErrInfo);
in_progress = 1;
background_limit = BACKGROUND_TICS; /* set default limit */
}
void suspend_background()
{
/* SWAP TO FOREGROUND */
/* put back original DTA */
regs.h.ah = SET_DTA;
regs.x.dx = foreground_dta_off;
sregs.ds = foreground_dta_seg;
intdosx(®s, ®s, &sregs);
/* put back original PSP */
SetPSP(foreground_psp);
/* put back original INTS */
_dos_setvect(0x1b,old_int1B);
_dos_setvect(0x23,old_int23);
_dos_setvect(0x24,old_int24);
/* get error info */
GetExtErr(&my_ErrInfo);
SetExtErr(&foreground_ErrInfo);
tic_count = 0;
in_progress = 0;
int_28_active = 0;
foreground_limit = FOREGROUND_TICS; /* set default limit */
}
/**********
* TIMER TICK INTERRUPT HANDLER
**********/
void interrupt far new_int8(INTERRUPT_REGS r)
{
tic_count++;
if ((in_progress && (tic_count >= background_limit) &&
!DosBusy() && !unsafe_flag) ||
(in_progress && int_28_active && !Int28DosBusy() &&
(tic_count >=background_limit)))
{
suspend_background();
restore_stack();
}
else if ((!in_progress && (tic_count >= foreground_limit) &&
!DosBusy() && !unsafe_flag) ||
(!in_progress && int_28_active && !Int28DosBusy() &&
(tic_count >=foreground_limit)))
{
set_stack();
suspend_foreground();
if (first_time)
{
first_time = 0;
timer_int_chain();
}
}
old_int8(); /* call old handler */
}
/**********
* KEYBOARD INTERRUPT HANDLER
**********/
void interrupt far new_int9(INTERRUPT_REGS r)
{
unsafe_flag++;
old_int9();
if (in_progress)
background_limit = BACKGROUND_YIELD; /* set to swap to foreground */
foreground_limit = 18; /* since user hit keyboard */
unsafe_flag--;
}
/*********
* CTRL-BREAK INTERRUPT HANDLER
*********/
void interrupt far new_int1B(INTERRUPT_REGS r)
{
/* do nothing */
}
/**********
* CTRL-C INTERRUPT HANDLER
**********/
void interrupt far new_int23(INTERRUPT_REGS r)
{
/* do nothing */
}
/**********
* CRTITICAL ERROR INTERRUPT HANDLER
**********/
void interrupt far new_int24(INTERRUPT_REGS r)
{
if (_osmajor >= 3)
r.ax = 3; /* fail dos function */
else
r.ax = 0;
}
/**********
* DOS IDLE INTERRUPT HANDLER
**********/
void interrupt far new_int28(INTERRUPT_REGS r)
{
if (!in_progress && !Int28DosBusy() && !unsafe_flag &&
tic_count > foreground_limit)
{
foreground_limit = FOREGROUND_YIELD; /* stop foreground */
int_28_active = 1;
_enable(); /* STI */
while (int_28_active); /*spin waiting for task swap to background*/
}
old_int28(); /* call old handler */
}
main()
{
union REGS regs;
struct SREGS sregs;
unsigned memtop;
void far* far* tmpptr;
puts("Multi-Tasking PRINT spooler installing");
if (_osmajor < 3)
{
puts("Error: MS-DOS version 3.00 or greater required");
exit(1);
}
if (! spooler_active())
puts("Warning: Print Spooler not active");
InitInDos();
my_psp = GetPSP();
/* MALLOC a stack for our TSR section */
stack_ptr = malloc(STACK_SIZE);
stack_ptr += STACK_SIZE;
ptr = stack_ptr;
*(--stack_ptr) = 0xF2; /* set up stack to look like an IRET was done*/
*(--stack_ptr) = 0x02;
stack_ptr -= 4;
tmpptr = stack_ptr;
*(tmpptr) = main_loop;
/* get interrupt vectors */
old_int8 = _dos_getvect(0x08); /* timer int */
old_int9 = _dos_getvect(0x09); /* keyboard int */
old_int10 = _dos_getvect(0x10); /* video int */
old_int13 = _dos_getvect(0x13); /* disk int */
old_int25 = _dos_getvect(0x25); /* sector read int */
old_int26 = _dos_getvect(0x26); /* sector write int */
old_int28 = _dos_getvect(0x28); /* dos idle int */
init_intr(); /* init asm variables */
_dos_setvect(0x08,new_int8);
_dos_setvect(0x09,new_int9);
_dos_setvect(0x10,new_int10);
_dos_setvect(0x13,new_int13);
_dos_setvect(0x25,new_int25);
_dos_setvect(0x26,new_int26);
_dos_setvect(0x28,new_int28);
/* release unused heap to MS-DOS */
/* All MALLOCS for TSR section must be done in TSR_INIT() */
segread(&sregs);
/* calculate top of memory and shrink block*/
regs.h.ah = ALTER_BLOCK;
memtop = sregs.ds + ((FP_OFF(ptr)+15) >> 4) - _psp;
regs.x.bx = memtop;
sregs.es = _psp;
intdosx(®s, ®s, &sregs);
bdos( STAY_RES, memtop, 0); /* Make TSR */
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -