📄 multi.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 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 interrupted foreground process */
int foreground_dta_seg; /* DTA of interrupted foreground process */
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 */
char search_work[65];
struct ExtErr my_ErrInfo;
struct ExtErr foreground_ErrInfo;
int foreground_limit = FOREGROUND_TICS; /* foreground cycle limit */
int background_limit = BACKGROUND_TICS; /* background cycle limit */
char search_dir[65] = {SEARCH_DIR}; /* dir to search for spool files */
volatile int int_28_active = 0; /* true if activated by INT 28 */
volatile int interval_timer; /* for sleeping a number of tics */
/* 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 PRINT installed */
int spooler_active()
{
union REGS regs;
regs.x.ax = 0x0100; /* PRINT install check */
int86(0x2f,®s,®s); /* call multiplex interrupt */
return(regs.h.al == 0xff); /* FF if installed */
}
/* returns nonzero if file 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 i;
int 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 */
FP_SEG(que_ptr) = sregs.ds;
FP_OFF(que_ptr) = regs.x.si;
/* release hold on spooler, side effect of status*/
regs.x.ax = 0x0105;
int86x(0x2f,®s,®s,&sregs);
while (*que_ptr && !found) /* while items in queue */
{
for (i = 0; i < 65; i++)
que_name[i] = *(que_ptr + i);
if (found = !strcmpi(que_name,fname))
break;
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;
while (1)
{
strcpy(search_work,search_dir);
strcat(search_work,"*.SPL"); /* create dir search string */
interval_timer = 18 * 30; /* search every 30 seconds */
while (interval_timer) /* wait between each dir search */
background_limit = BACKGROUND_YIELD; /* yield for fgrnd */
if (!_dos_findfirst(search_work,_A_NORMAL,&c_file))
{
/* if spooler installed, dos 3.xx+ and file size > 0 */
if (spooler_active() && _osmajor >= 3 && c_file.size)
{
strcpy(search_work,search_dir);
strcat(search_work,c_file.name); /* full pathname */
prRequest.level = 0;
prRequest.fname = search_work;
regs.x.ax = 0x0101;
ptr = &prRequest;
sregs.ds = FP_SEG(ptr);
regs.x.dx= FP_OFF(ptr);
int86x(0x2f,®s,®s,&sregs);
while (search_spl_que(search_work)) /* wait till done */
{
interval_timer = 18 * 30; /* sleep for 30 seconds */
while (interval_timer)
background_limit = BACKGROUND_YIELD;
}
unlink(search_work); /* delete file */
background_limit = BACKGROUND_YIELD;
}
}
}
}
union REGS regs;
struct SREGS sregs;
void suspend_foreground()
{
/* SWAP TO BACKGROUND */
tic_count = 0;
/* save old handlers */
old_int1B= _dos_getvect(0x1B);
old_int23= _dos_getvect(0x23);
old_int24= _dos_getvect(0x24);
/* set our interrupt handlers */
_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 (interval_timer)
interval_timer--;
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 fgrnd */
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 bckgrnd*/
}
(*old_int28)(); /* call old handler */
}
main()
{
unsigned memtop;
unsigned dummy;
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 as if an 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);
#define PARAGRAPHS(x) ((FP_OFF(x) + 15) >> 4)
/* release unused heap to MS-DOS */
/* All MALLOCS for TSR section must be done in TSR_INIT() */
/* calculate top of memory, shrink block, and go TSR */
segread(&sregs);
memtop = sregs.ds + PARAGRAPHS(ptr) - _psp;
_dos_setblock(memtop, _psp, &dummy);
_dos_keep(0, memtop);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -