home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 10 / 10.iso / l / l440 / 2.ddi / CHAP5 / MULTTEST.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-09-13  |  9.6 KB  |  364 lines

  1. /* MULTI.C */
  2.  
  3. #include <stddef.h>
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <dos.h>
  8. #include <io.h>
  9. #include "tsr.h"
  10.  
  11. #define SEARCH_DIR   "C:\\SPOOL\\"
  12. #define    STACK_SIZE    4096    /* must be 16 byte boundaray */
  13. #define SET_DTA        0x1a  /* SET Disk Transfer Address */
  14. #define GET_DTA        0x2f  /* GET Disk  Transfer Address */
  15.  
  16. #define STAY_RES        0x31    /* DOS Term & Stay Reg */
  17. #define ALTER_BLOCK    0x4a    /* DOS Alter Mem BLock */
  18. #define    BACKGROUND_TICS 2
  19. #define FOREGROUND_TICS 16
  20. #define BACKGROUND_YIELD 0
  21. #define FOREGROUND_YIELD 0
  22.  
  23. struct  prReq
  24. {
  25.     char level;
  26.     char far *fname;
  27. };
  28.  
  29. char    far *stack_ptr;         /* stack for our background TSR */
  30. char     far *ptr;
  31. unsigned ss_save;             /* slot for stack segment register */
  32. unsigned sp_save;             /* slot for stack pointer register */
  33. unsigned unsafe_flag = 0;     /* set true by variouse interrupts */
  34. int    first_time = 1;         /* flag for first time in running background */
  35.  
  36. int    my_psp;                 /* our TSR's psp */
  37. int    foreground_psp;         /* PSP of foreground process we've interrupted */
  38. int    foreground_dta_seg;     /* DTA of foreground process we've interrupted */
  39. int    foreground_dta_off;
  40. int    ctr=0; 
  41. int    tic_count = 0;          /* counts timer tices */
  42. int    in_progress = 0;        /* true if we're in background process */
  43. /* various work variables */
  44. int    ax,bx,cx,dx,bp,si,di,ss,sp,cs,es;
  45. int    cs_ip;
  46. union REGS regs;
  47. struct SREGS sregs;
  48. char  search_work[65];        
  49. struct   ExtErr   my_ErrInfo;
  50. struct   ExtErr   foreground_ErrInfo;
  51.  
  52. int   foreground_limit = FOREGROUND_TICS; /* limit of foreground cycle */
  53. int   background_limit = BACKGROUND_TICS; /* limit of background cycle */
  54.  
  55. char  search_dir[65] = {SEARCH_DIR}; /* directory to search for spool files */
  56. volatile int   int_28_active = 0;      /* true if activated by INT 28 */
  57.  
  58. /* old interrupt pointers are stored here */    
  59. INTVECT old_int8, old_int9, old_int10, old_int13;
  60. INTVECT old_int1B, old_int23, old_int24, old_int25;
  61. INTVECT old_int26, old_int28;
  62.  
  63. /* prototypes for this module */
  64. void main_loop();
  65. void interrupt far new_int8(INTERRUPT_REGS);
  66. void interrupt far new_int9(INTERRUPT_REGS);
  67. void interrupt far new_int10(void);
  68. void interrupt far new_int13(void);
  69. void interrupt far new_int1B(INTERRUPT_REGS);
  70. void interrupt far new_int23(INTERRUPT_REGS);
  71. void interrupt far new_int24(INTERRUPT_REGS);
  72. void interrupt far new_int25(void);
  73. void interrupt far new_int26(void);
  74. void interrupt far new_int28(INTERRUPT_REGS);
  75. int  spooler_active(void);
  76. int  search_spl_que(char * fname);
  77. void suspend_foreground(void);
  78. void suspend_background(void);
  79.  
  80. /* returns nonzero if spooler active */
  81. int   spooler_active()
  82. {
  83.     union REGS  regs;
  84.  
  85.    regs.x.ax = 0x0100;  /* spooler active request */
  86.    int86(0x2f,®s,®s);   /* call multiplex interrupt */
  87.    return(regs.h.al == 0xff); /* FF if spooler active */
  88. }
  89.  
  90. /* returns nonzero if string pointed to by fname is in the spooler queue */
  91. int   search_spl_que(char * fname)
  92. {
  93. union REGS  regs;
  94. struct SREGS   sregs;
  95. char far *  que_ptr;
  96. char que_name[65];
  97. int ii;
  98. int found;
  99.    found = 0;
  100.    if (spooler_active())
  101.    {
  102.       regs.x.ax = 0x0104;  /* get spooler status */
  103.       int86x(0x2f,®s,®s,&sregs);
  104.       /* on return from call DS:SI points to print queue */
  105.       (long) que_ptr = (sregs.ds * 0x10000L) | regs.x.si;
  106.       regs.x.ax = 0x0105;  /* release hold on spooler, side effect of status*/
  107.       int86x(0x2f,®s,®s,&sregs);
  108.       while (*que_ptr && !found)  /* while items in queue */
  109.       {
  110.          for (ii = 0; ii < 65; ii++)
  111.             que_name[ii] = *(que_ptr + ii);
  112.          found = !strcmpi(que_name,fname);
  113.          que_ptr += 65;
  114.       }
  115.    }
  116.  
  117.    return(found);
  118. }
  119.  
  120. void main_loop()
  121. {
  122. struct find_t  c_file;
  123. union REGS  regs;
  124. struct SREGS   sregs;
  125. struct prReq prRequest;
  126. struct prReq far * ptr;
  127. int   sleep_cntr;
  128.  
  129.     while (1)
  130.         {    
  131.       strcpy(search_work,search_dir);
  132.       strcat(search_work,"*.SPL");   /* create dir search string */
  133.    
  134.       sleep_cntr = 20000;
  135.       while (sleep_cntr)   /* wait a while between each dir search */
  136.          {
  137.          sleep_cntr-= 1;
  138.          }
  139.       printf("Background Active!\n");
  140.          }
  141.  
  142. }
  143.  
  144. void  suspend_foreground()
  145. {
  146.         /* SWAP TO BACKGROUND */
  147.         tic_count = 0;
  148.     /* save old interrupt-CTRL-BREAK, CTRL-C and CRIT ERROR */ 
  149.         old_int1B= _dos_getvect(0x1B); 
  150.         old_int23= _dos_getvect(0x23); 
  151.         old_int24= _dos_getvect(0x24); 
  152.  
  153.     /* set our interrupts functions */
  154.        _dos_setvect(0x1b,new_int1B);
  155.        _dos_setvect(0x23,new_int23);
  156.        _dos_setvect(0x24,new_int24);
  157.  
  158.     /* save current PSP and set to ours */
  159.     foreground_psp = GetPSP();
  160.     SetPSP(my_psp);
  161.  
  162.     /* get foreground DTA */
  163.     regs.h.ah = GET_DTA;
  164.    intdosx(®s, ®s, &sregs); 
  165.     foreground_dta_seg = sregs.es;
  166.     foreground_dta_off = regs.x.bx;
  167.  
  168.     /* set up our DTA */
  169.     regs.h.ah = SET_DTA;
  170.     regs.x.dx = 0x80;    /* use default in PSP area */
  171.     sregs.ds = my_psp;
  172.     intdosx(®s, ®s, &sregs); 
  173.  
  174.    /* save error info */
  175.    GetExtErr(&foreground_ErrInfo);
  176.  
  177.    if (! first_time)
  178.       SetExtErr(&my_ErrInfo);
  179.  
  180.    in_progress = 1;
  181.    background_limit = BACKGROUND_TICS; /* set default limit */
  182. }
  183.  
  184. void suspend_background()
  185. {
  186.         /* SWAP TO FOREGROUND */
  187.  
  188.     /* put back original DTA */
  189.     regs.h.ah = SET_DTA;
  190.     regs.x.dx = foreground_dta_off;    
  191.     sregs.ds  = foreground_dta_seg;
  192.     intdosx(®s, ®s, &sregs); 
  193.  
  194.     /* put back original PSP */
  195.     SetPSP(foreground_psp);
  196.  
  197.     /* put back original INTS */
  198.        _dos_setvect(0x1b,old_int1B);
  199.        _dos_setvect(0x23,old_int23);
  200.        _dos_setvect(0x24,old_int24);
  201.  
  202.    /* get error info */
  203.    GetExtErr(&my_ErrInfo);
  204.    SetExtErr(&foreground_ErrInfo);
  205.  
  206.     tic_count = 0;    
  207.     in_progress = 0;
  208.    int_28_active = 0;
  209.    foreground_limit = FOREGROUND_TICS; /* set default limit */
  210. }
  211.  
  212. /**********
  213. * TIMER TICK INTERRUPT HANDLER
  214. **********/
  215. void interrupt far new_int8(INTERRUPT_REGS r)
  216. {
  217.     tic_count++;
  218.  
  219.     if ((in_progress && (tic_count >= background_limit) &&  
  220.        !DosBusy() && !unsafe_flag) || 
  221.        (in_progress && int_28_active && !Int28DosBusy() && 
  222.            (tic_count >=background_limit)))
  223.     {
  224.       suspend_background();
  225.         restore_stack();
  226.     }
  227.     else if ((!in_progress && (tic_count >= foreground_limit) &&
  228.         !DosBusy() && !unsafe_flag) ||
  229.        (!in_progress && int_28_active && !Int28DosBusy() && 
  230.            (tic_count >=foreground_limit)))
  231.     {
  232.         set_stack();
  233.       suspend_foreground();
  234.       if (first_time)
  235.         {
  236.             first_time = 0;
  237.             timer_int_chain();
  238.         }
  239.     }
  240.    old_int8();    /* call old handler */
  241.  
  242. /**********
  243. * KEYBOARD INTERRUPT HANDLER
  244. **********/
  245. void interrupt far new_int9(INTERRUPT_REGS r)
  246. {
  247.    unsafe_flag++;
  248.    old_int9();     
  249.    if (in_progress)
  250.       background_limit = BACKGROUND_YIELD; /* set to swap to foreground */  
  251.    foreground_limit = 18;     /* since user hit keyboard */
  252.    unsafe_flag--;
  253.  
  254. /*********
  255. * CTRL-BREAK INTERRUPT HANDLER
  256. *********/
  257. void interrupt far new_int1B(INTERRUPT_REGS r)
  258. {
  259.     /* do nothing */
  260.                   
  261. /**********
  262. * CTRL-C INTERRUPT HANDLER
  263. **********/
  264. void interrupt far new_int23(INTERRUPT_REGS r)
  265. {
  266.     /* do nothing */
  267.  
  268. /**********
  269. * CRTITICAL ERROR INTERRUPT HANDLER
  270. **********/
  271. void interrupt far new_int24(INTERRUPT_REGS r)
  272. {
  273.     if (_osmajor >= 3)
  274.         r.ax = 3;    /* fail dos function */
  275.     else
  276.         r.ax = 0;         
  277.  
  278. /**********
  279. * DOS IDLE INTERRUPT HANDLER
  280. **********/
  281. void interrupt far new_int28(INTERRUPT_REGS r)
  282. {
  283.     if (!in_progress && !Int28DosBusy() && !unsafe_flag && 
  284.         tic_count > foreground_limit)
  285.     {
  286.       foreground_limit = FOREGROUND_YIELD;   /* stop foreground */
  287.       int_28_active = 1;      
  288.       _enable();        /* STI */
  289.       while (int_28_active);  /*spin waiting for task swap to background*/
  290.     }
  291.    old_int28();    /* call old handler */
  292.  
  293. main()
  294. {
  295.     union REGS    regs;
  296.     struct SREGS    sregs;        
  297.     unsigned    memtop;
  298.     void far* far*  tmpptr;
  299.  
  300.    puts("Multi-Tasking PRINT spooler installing");
  301.    
  302.    if (_osmajor < 3)
  303.    {
  304.       puts("Error: MS-DOS version 3.00 or greater required");
  305.       exit(1);
  306.    }
  307.    
  308.    if (! spooler_active())
  309.       puts("Warning: Print Spooler not active");
  310.  
  311.    InitInDos();
  312.    my_psp = GetPSP();
  313.  
  314.    /* MALLOC a stack for our TSR section */ 
  315.    stack_ptr = malloc(STACK_SIZE);      
  316.    stack_ptr += STACK_SIZE;
  317.  
  318.     ptr = stack_ptr;
  319.     *(--stack_ptr) = 0xF2;  /* set up stack to look like an IRET was done*/
  320.     *(--stack_ptr) = 0x02;
  321.     stack_ptr -= 4;
  322.     tmpptr = stack_ptr;
  323.     *(tmpptr) = main_loop;
  324.  
  325.     /* get interrupt vectors */
  326.    old_int8  = _dos_getvect(0x08); /* timer int */
  327.    old_int9  = _dos_getvect(0x09); /* keyboard int */
  328.    old_int10 = _dos_getvect(0x10); /* video int */
  329.    old_int13 = _dos_getvect(0x13); /* disk int */
  330.    old_int25 = _dos_getvect(0x25); /* sector read int */
  331.    old_int26 = _dos_getvect(0x26); /* sector write int */
  332.    old_int28 = _dos_getvect(0x28); /* dos idle int */
  333.  
  334.    init_intr();    /* init asm variables */ 
  335.  
  336.     _dos_setvect(0x08,new_int8); 
  337.     _dos_setvect(0x09,new_int9); 
  338.     _dos_setvect(0x10,new_int10); 
  339.     _dos_setvect(0x13,new_int13); 
  340.     _dos_setvect(0x25,new_int25); 
  341.     _dos_setvect(0x26,new_int26); 
  342.     _dos_setvect(0x28,new_int28); 
  343.     
  344.     /* release unused heap to MS-DOS */
  345.    /* All MALLOCS for TSR section must be done in TSR_INIT() */
  346.     segread(&sregs);    
  347.  
  348.    /* calculate top of memory and shrink block*/
  349.     regs.h.ah = ALTER_BLOCK;
  350.     memtop    = sregs.ds + ((FP_OFF(ptr)+15) >> 4) - _psp;
  351.     regs.x.bx = memtop;
  352.     sregs.es  = _psp;
  353.     intdosx(®s, ®s, &sregs); 
  354.  
  355.     bdos( STAY_RES, memtop, 0);  /* Make TSR */
  356. }
  357.  
  358.