home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c070 / 4.ddi / TOOLS.4 / TCTSRC1.EXE / IVINSTAL.C < prev    next >
Encoding:
Text File  |  1989-03-31  |  21.9 KB  |  689 lines

  1. /**
  2. *
  3. * Name        ivinstal -- Install intervention function
  4. *
  5. * Synopsis    ercode = ivinstal(pfunc,pident,pstack,stksize,
  6. *                  pkeytable,numkeys,ptimetable,numtimes,
  7. *                  option);
  8. *
  9. *        int ercode      Zero if correctly installed; other values
  10. *                  include:
  11. *                    IV_INSTALLED - Already installed.
  12. *        void cdecl (*pfunc)(IV_EVENT *)
  13. *                  Address of intervention function to be
  14. *                  installed.
  15. *        char *pident      Pointer to array of 16 bytes of
  16. *                  identifying information
  17. *        char *pstack      Address of beginning of memory block
  18. *                  (already allocated) to be used for the
  19. *                  intervention function's stack
  20. *        int stksize      Size (in bytes) of the stack
  21. *                  (must be at least 64 bytes).
  22. *        IV_KEY *pkeytable Address of array of IV_KEY structures
  23. *                  listing hot keys.
  24. *        int numkeys      Number of hot keys listed.
  25. *        IV_TIME *ptimtable
  26. *                  Address of array of IV_TIME structures
  27. *                  listing timer events.
  28. *        int numtimes      Number of timer events listed.
  29. *        int option      Requirements of the intervention
  30. *                  function.  Three bits are relevant
  31. *                  (all other bits should be zero):
  32. *
  33. *            Symbol          Meaning
  34. *            ---------------   ----------------------------
  35. *            IV_DOS_NEED       DOS functions used.
  36. *            IV_NO_DOS_NEED    No DOS functions used.
  37. *
  38. *            IV_DKEY_NEED      DOS functions 1-12 used.
  39. *            IV_NO_DKEY_NEED   DOS functions 1-12 not used.
  40. *
  41. *            IV_FLOAT_NEED     Reinstall floating point vectors
  42. *                    upon invocation.
  43. *            IV_NO_FLOAT_NEED  No need to reinstall floating
  44. *                    point vectors.
  45. *
  46. *            IV_DAILY          Repeat moment events daily.
  47. *
  48. *
  49. * Description    This function installs an intervention function (*pfunc)
  50. *        and arranges for it to be invoked when a hot key is
  51. *        pressed or when a given time of day passes.
  52. *
  53. *        The hot key(s) (if any) are specified by one or more
  54. *        IV_KEY structures which describe the character value and
  55. *        scan code of the key and the action to be taken if the
  56. *        key is pressed:
  57. *
  58. *            to invoke the intervention function;
  59. *            to put the intervention function to sleep; or
  60. *            to wake the intervention function from sleep.
  61. *
  62. *        The array of IV_KEY structures can be moved or changed
  63. *        in size by modifying the pkeytab and ktsize members in
  64. *        the intervention control block (which is defined in
  65. *        IVCTRL.ASM).  (Turn interrupts off while doing so.)
  66. *
  67. *        The timer event(s) (if any) are specified by one or more
  68. *        IV_TIME structures which describe whether each event is
  69. *        a specific time of day ("moment events") or whether it
  70. *        will recur periodically ("interval events").  Each
  71. *        IV_TIME structure specifies a number of clock ticks to
  72. *        indicate the specific time of day or the period between
  73. *        invocations.  The array of IV_TIME structures must not
  74. *        be moved as long as the intervention function is
  75. *        installed.
  76. *
  77. *        Timer events that are scheduled for a specific time of
  78. *        day are repeated daily if IV_DAILY is specified.
  79. *        Without IV_DAILY, moment events can be invoked only once
  80. *        unless their time of day is modified.
  81. *
  82. *        The IV_DAILY rescheduling takes place whenever the time
  83. *        of day gets set back (as it normally does at midnight).
  84. *        If a user sets the system time back manually, events
  85. *        scheduled for earlier in the day will recur immediately.
  86. *        To avoid an event occurring more than once in a day, you
  87. *        may wish to check the system date in your intervention
  88. *        function.
  89. *
  90. *        The calling function must allocate space for the
  91. *        intervention function's stack and pass its address as
  92. *        pstack.  This space must be static as long as the
  93. *        intervention function is installed.  2048 bytes is a
  94. *        typical stack size, but more may be needed if the
  95. *        intervention function (or any function invoked by it)
  96. *        has large local arrays.
  97. *
  98. *        Two bits of "option" must be set to indicate how the
  99. *        intervention function uses DOS functions (if at all).
  100. *        If the intervention function uses DOS and these bits are
  101. *        incorrect, serious system malfunctions will result.  If
  102. *        option indicates that DOS functions are used, then the
  103. *        intervention function will not be invoked as frequently
  104. *        as if option were zero.
  105. *
  106. *        The IV_FLOAT_NEED option causes the floating point
  107. *        interrupt vectors (if used by the floating point math
  108. *        library) to be temporarily reloaded whenever the
  109. *        intervention function is invoked.  Use the IV_FLOAT_NEED
  110. *        option if the following conditions are all met:
  111. *
  112. *            1) your intervention function (*pfunc) uses floating
  113. *               point arithmetic;
  114. *            2) your program may be linked with a math library
  115. *               that installs interrupt vectors (see the README.DOC
  116. *               file for instructions);
  117. *            3) your intervention function may be invoked while
  118. *               other programs are running.
  119. *
  120. *        If condition (1) is met, it may be safest to specify
  121. *        IV_FLOAT_NEED without regard to the other two
  122. *        conditions.
  123. *
  124. *        The sixteen bytes of identifying information are stored
  125. *        in the intervention control block to permit other
  126. *        applications to detect this program.  (See IVSENSE.C for
  127. *        an example of this.)
  128. *
  129. *        The global variable b_ivmask lists the intervention
  130. *        filters that will be installed.
  131. *
  132. * Warning    Do not specify IV_TM_NONE for any of the timer events.
  133. *
  134. * Returns    ercode          The return code is 0 if the vector is
  135. *                  is successfully set; other values
  136. *                  include:
  137. *                    IV_INSTALLED - Already installed.
  138. *
  139. * Version    6.00 (C)Copyright Blaise Computing Inc.  1987-1989
  140. *
  141. **/
  142.  
  143. #include <dos.h>              /* For use with isgetvec(),     */
  144.                       /* isputvec(), REGS, and int86()*/
  145.  
  146. #include <binterv.h>
  147. #include <bintrupt.h>
  148. #include <bkeybrd.h>
  149.  
  150. int b_ivusex = KB_USE_EXTEND;          /* Whether to use extended      */
  151.                       /*  keyboard services when      */
  152.                       /*  testing for hot keys:       */
  153.                       /*  KB_USE_EXTEND or          */
  154.                       /*  KB_USE_NORMAL.          */
  155.  
  156. extern void ivtimer(void);          /* Intervention code filters    */
  157. extern void ivkeybd(void);          /*  (in ISCTRL.ASM)          */
  158. extern void ivcom2(void);
  159. extern void ivcom1(void);
  160. extern void ivdisk(void);
  161. extern void ivdos(void);
  162. extern void ividle(void);
  163.  
  164. extern void ivbiosky(void);          /* These two filters are          */
  165. extern void ivcbreak(void);          /* installed by the scheduler   */
  166.                       /* before invoking the          */
  167.                       /* intervention function and    */
  168.                       /* removed after it exits.      */
  169.  
  170.     /* Local variables used by scheduler, initialized by installer.   */
  171.  
  172. static IV_CTRL far *pctrl = FARNIL;   /* Pointer to internal values   */
  173.                       /*  used by filters.          */
  174.                       /*                  */
  175. static IV_TIME       *ptimtab;          /* Address and size of user's   */
  176. static int        timtabsize;       /*  table of timer events.      */
  177. static int        timindex;          /* Index of found timer event.  */
  178. static int        timaction;          /* Type of timer action last    */
  179.                       /*   requested.              */
  180. static long        idleticks;          /* Clock ticks since last       */
  181.                       /*  service.              */
  182. static long        lasttime;          /* Time of last call.          */
  183.                       /*                  */
  184. static int        daily;          /* Whether to reschedule moment */
  185.                       /*  events daily.           */
  186.                       /*                  */
  187. static void                  /* Pointer to user's            */
  188.        (*ptask)(IV_EVENT *);          /*  intervention function.      */
  189.                       /*                  */
  190. static unsigned char              /* Pointer to interrupt 0x24    */
  191.         far *pint24h_flag;    /*  busy flag.              */
  192.  
  193. #if  (IS_NUM_FLOAT_VECS > 0)
  194. static char        float_need;
  195.                       /* Storage for floating point   */
  196.                       /*  vectors.              */
  197. static void    far *float_vec[IS_NUM_FLOAT_VECS];
  198. #endif
  199.  
  200.                       /* Internal functions          */
  201. static void scheduler(ALLREG *,ISRCTRL *,ISRMSG *);
  202. static void timer_req(void);
  203. static int  readytask(void);
  204. static void unschedule(void);
  205. static void reschedule(void);
  206.  
  207.  
  208. int ivinstal(pfunc,pident,pstack,stksize,
  209.          pkeytable,numkeys,ptimetable,numtimes,option)
  210. void       (*pfunc)(IV_EVENT *);
  211. const char  *pident;
  212. char        *pstack;
  213. int         stksize;
  214. IV_KEY        *pkeytable;
  215. int         numkeys;
  216. IV_TIME     *ptimetable;          /* This table must not move.    */
  217. int         numtimes;
  218. int         option;
  219. {
  220.     int        ints_were_on,i;
  221.     IV_VECTORS       vecs;
  222.     unsigned int   i24_seg,i24_offset;
  223.     static ISRCTRL schedblk = {0};    /* ISR control block for          */
  224.                       /* scheduler.              */
  225.  
  226.     pctrl    = ivctrl();          /* Find intervention control    */
  227.                       /*  structure.              */
  228.  
  229.     ints_were_on = utintflg(UT_INTOFF); /* Prevent interrupts while   */
  230.                     /* checking enabled state.    */
  231.     if (pctrl->enabled)           /*                  */
  232.     {                      /* Error:  this function must   */
  233.     utintflg(ints_were_on);       /* not be used more than once.  */
  234.     return IV_INSTALLED;          /*                  */
  235.     }                      /*                  */
  236.     pctrl->enabled = 1;           /* Prevent second use.          */
  237.     utintflg(ints_were_on);          /* Restore interrupt state.     */
  238.  
  239.     /* Initialize local variables used by scheduler.              */
  240.  
  241.     ptask    = pfunc;          /* Address of user's            */
  242.                       /*  intervention function.      */
  243.     ptimtab    = ptimetable;          /* Address and size of user's   */
  244.     timtabsize    = numtimes;          /*  table of timer events.      */
  245.     timindex    = -1;              /* Index of found timer event.  */
  246.     timaction    = IV_TM_NONE;          /* Type of timer action last    */
  247.                       /*  requested.              */
  248.     idleticks    = 0L;              /* Clock ticks since last       */
  249.                       /*  service.              */
  250.  
  251.     if (option & IV_DAILY)
  252.     {                      /* Moment events happen once    */
  253.                       /*  daily.              */
  254.     utgetclk(&lasttime);          /* Start time for reschedule(). */
  255.     unschedule();              /* Cancel today's events whose  */
  256.                       /*  time has passed.          */
  257.     daily = 1;
  258.     }
  259.     else
  260.     daily = 0;
  261.  
  262. #if  (IS_NUM_FLOAT_VECS > 0)
  263.     float_need    = (char)(0 != (option & IV_FLOAT_NEED));
  264.                       /* Save floating point vectors  */
  265.     for (i = 0; i < IS_NUM_FLOAT_VECS; i++)
  266.     float_vec[i] = isgetvec(IS_1ST_FLOAT_VEC + i);
  267. #endif
  268.  
  269.     /* Set up ISR control block through which the scheduler will be   */
  270.     /* called.                                  */
  271.  
  272.     isprep(scheduler,"TCT6.00 INTSCHED",&schedblk,pstack,stksize,1);
  273.  
  274.     /* Initialize most items in intervention control structure.       */
  275.  
  276.     pctrl->psp = utpspseg;          /* PSP of this program.          */
  277.                       /*                  */
  278.     ivvecs(IV_RETVEC,&pctrl->prev_vec); /* Save previous contents of  */
  279.                     /*  interrupt vectors.          */
  280.                       /*                  */
  281.                       /* Set the dos_need flag if     */
  282.                       /*  either the IV_DOS_NEED or   */
  283.                       /*  IV_DKEY_NEED bit is set.    */
  284.     pctrl->dos_need  = (char)
  285.                (0 != (option & (IV_DOS_NEED | IV_DKEY_NEED)));
  286.     pctrl->dkey_need = (char)(0 != (option & IV_DKEY_NEED));
  287.  
  288.     pctrl->pkeytab   = pkeytable;     /* Address and size of user's   */
  289.     pctrl->ktsize    = numkeys;       /*  table of hot keys.          */
  290.  
  291.     pctrl->key_event.ch      = 0;     /* No hot key found yet.          */
  292.     pctrl->key_event.keycode = 0;
  293.     pctrl->key_event.action  = IV_KY_NONE;
  294.  
  295.     if (   b_ivusex  == KB_USE_NORMAL
  296.     || kbequip() == KB_NOEXTENDED)
  297.     pctrl->kb_ext = 0;          /* Use normal keyboard services.*/
  298.     else
  299.     pctrl->kb_ext = 1;          /* Extended keyboard services.  */
  300.  
  301.     pctrl->wait   = 0;              /* INT 21h and INT 28h filters  */
  302.                       /*  don't need to be in wait    */
  303.                       /*  loop yet.              */
  304.     pctrl->req      = 0;              /* No service yet requested.    */
  305.     pctrl->awake  = 1;              /* Intervention code is not     */
  306.                       /*  asleep.              */
  307.     pctrl->timer_busy = 0;          /* Clear the busy flags.          */
  308.     pctrl->kb_busy    = 0;
  309.     pctrl->com2_busy  = 0;
  310.     pctrl->com1_busy  = 0;
  311.     pctrl->disk_busy  = 0;
  312.     pctrl->idle_busy  = 0;
  313.  
  314.     pctrl->idle_safe  = 0;
  315.  
  316.                       /* Entry point to scheduler.    */
  317.     pctrl->pschedblk = ((char far *)(&schedblk)) + ICB_ENTRY_OFFSET;
  318.  
  319.     utcrit();                  /* Address of DOS critical      */
  320.     pctrl->pdos_crit = b_critad;      /*  section flag (busy flag).   */
  321.  
  322.                       /* Address of interrupt 0x24    */
  323.     if (utdosmajor < 3)           /*  busy flag.              */
  324.     i24_offset = utoff(b_critad) + 1;
  325.     else if (utdosver == 0x0300)
  326.     i24_offset = 0x0167;
  327.     else
  328.     i24_offset = utoff(b_critad) - 1;
  329.     i24_seg = utseg(b_critad);
  330.     pint24h_flag = uttofaru(i24_seg,i24_offset);
  331.  
  332.     for (i = 0; i < sizeof(pctrl->_reserved); i++)
  333.     pctrl->_reserved[i] = '\0';
  334.  
  335.                       /* User's identifying string.   */
  336.     utmovmem(pident,pctrl->ident,sizeof(pctrl->ident));
  337.  
  338.                       /* Identifying signature.       */
  339.     pctrl->signature = (unsigned int)IV_SIGNATURE;
  340.     pctrl->sign2     = (unsigned int)~IV_SIGNATURE;
  341.  
  342.     /* Install the filters.  This will activate the intervention      */
  343.     /* function.                              */
  344.  
  345.     pctrl->filter_mask = b_ivmask;
  346.     vecs.ptimer = ivtimer;
  347.     vecs.pkeybd = ivkeybd;
  348.     vecs.pdisk    = ivdisk;
  349.     vecs.pdos    = ivdos;
  350.     vecs.pidle    = ividle;
  351.     vecs.pcom1    = ivcom1;
  352.     vecs.pcom2    = ivcom2;
  353.     ivvecs(IV_SETVEC,&vecs);
  354.  
  355.     return IV_NO_ERROR;
  356. }
  357.  
  358. /**
  359. *
  360. * Name        scheduler -- Invoke intervention function if appropriate
  361. *
  362. * Description    This function checks whether the intervention function
  363. *        is eligible to be invoked and invokes it if appropriate,
  364. *        based on the time of day and whether DOS services are
  365. *        necessary and available.  It also maintains certain
  366. *        fields in the intervention control block to control the
  367. *        intervention filters.
  368. *
  369. *        This function is built as an interrupt service routine
  370. *        (ISR) to be called from the intervention timer filter
  371. *        via the ISR dispatcher.
  372. *
  373. *        Interrupts are enabled.
  374. *
  375. * Returns    Members of intervention control block:
  376. *
  377. *        wait          Set to zero to release INT 21h and
  378. *                  INT 28h filters from wait loop.
  379. *        awake          Whether intervention code is asleep
  380. *                  or awake.
  381. *        key_event      The most recent detected hot key
  382. *                  is cleared.
  383. *        req          1 to indicate that the intervention
  384. *                    function needs service but must wait
  385. *                    for DOS availability;
  386. *                  0 to indicate that the intervention
  387. *                    function does not need service.
  388. *
  389. *        Member of user's table of timer events:
  390. *
  391. *        ptimetable[].ticks
  392. *                  If this event is a moment event,
  393. *                  the IV_RESCHED bit in the time of day
  394. *                  is set, effectively preventing
  395. *                  the event from occurring again.
  396. *                  At midnight, the bit is cleared.
  397. *                  (The user can reschedule the event
  398. *                  by changing the ticks member again.)
  399. *
  400. **/
  401.  
  402. static void scheduler(pregs,pisrblk,pmsg)
  403. ALLREG    *pregs;
  404. ISRCTRL *pisrblk;
  405. ISRMSG    *pmsg;
  406. {
  407.     IV_EVENT    signal;
  408.     void far *pint_1bh;
  409.     unsigned  oldproc;
  410.     int       dos_saved;
  411.     char     *p;
  412. #if  (IS_NUM_FLOAT_VECS > 0)
  413.     void far *save_float[IS_NUM_FLOAT_VECS];
  414.     int       float_switched;
  415. #endif
  416.  
  417.     p = (char *) pregs;           /* Get rid of pesky compiler    */
  418.     p = (char *) pisrblk;          /* warnings.              */
  419.     p = (char *) pmsg;
  420.     p++;
  421.  
  422.     pctrl->wait = 0;              /* Release INT 21h or INT 28h   */
  423.                       /*  filters if they are waiting.*/
  424.  
  425.     if ((!pctrl->awake) && pctrl->key_event.action != IV_KY_WAKE)
  426.     return;
  427.  
  428.     if (daily)                  /* Reschedule yesterday's       */
  429.     reschedule();              /*  moment events for today if  */
  430.                       /*  this is a new day.          */
  431.  
  432.     if (timaction == IV_TM_NONE)      /* If no timer action pending,  */
  433.     timer_req();              /* analyze time of day to see   */
  434.                       /* whether a timer action       */
  435.                       /* should be pending.          */
  436.  
  437.     if (   pctrl->key_event.action != IV_KY_NONE
  438.     || timaction           != IV_TM_NONE)
  439.     {
  440.     if (readytask())
  441.     {                  /* Now we know that we can      */
  442.                       /* execute the task.          */
  443.         pctrl->req = 0;
  444.         if (timaction == IV_TM_INTERVAL)
  445.         idleticks = 0L;
  446.         else if (timaction == IV_TM_MOMENT)
  447.                       /* Disable the event.          */
  448.         ptimtab[timindex].ticks |= IV_RESCHED;
  449.                       /* (The user can reschedule the */
  450.                       /* event by modifying the time  */
  451.                       /* table.)              */
  452.  
  453.                       /* Build signal to tell user    */
  454.                       /*  task what event(s)          */
  455.                       /*  triggered the task.          */
  456.         utmovmem((char far *) &pctrl->key_event,
  457.              (char far *) &signal.key,
  458.              sizeof(IV_KEY));
  459.         signal.time_action = timaction;
  460.         signal.time_index  = timindex;
  461.         utgetclk(&signal.time);
  462.  
  463.         pctrl->cbreak = 0;          /* No Ctrl-Break or Ctrl-C      */
  464.                       /*  encountered yet.          */
  465.  
  466.         if (pctrl->dos_need)      /* Take special precautions if  */
  467.         {                  /* DOS is used:              */
  468.  
  469.                       /* Prevent Ctrl-Break and       */
  470.                       /* Ctrl-C.              */
  471.         pctrl->prev_16h_vec = isgetvec(0x16);
  472.         pint_1bh        = isgetvec(0x1b);
  473.         isputvec(0x16,(void far *) ivbiosky);
  474.         isputvec(0x1b,(void far *) ivcbreak);
  475.                       /* Set current process to point */
  476.                       /* to us.               */
  477.         if (utdosmajor >= 3)
  478.             oldproc  = iscurprc(IS_SETPROC,utpspseg);
  479.         dos_saved    = 1;
  480.         }
  481.         else
  482.         dos_saved    = 0;
  483.  
  484. #if  (IS_NUM_FLOAT_VECS > 0)
  485.         if (float_need)
  486.         {
  487.                       /* Save current floating point  */
  488.                       /*  vectors.              */
  489.         utintflg(UT_INTOFF);
  490.         utpeekn(uttofar(0,4 * IS_1ST_FLOAT_VEC,char),
  491.             save_float,
  492.             sizeof(save_float));
  493.                       /* Reinstall our own floating   */
  494.                       /*  point vectors.          */
  495.         utpoken(float_vec,
  496.             uttofar(0,4 * IS_1ST_FLOAT_VEC,char),
  497.             sizeof(float_vec));
  498.         utintflg(UT_INTON);
  499.         float_switched = 1;
  500.         }
  501.         else
  502.         float_switched = 0;
  503. #endif
  504.  
  505.  
  506.         (*ptask)(&signal);          /* Invoke the user task.          */
  507.  
  508.  
  509. #if  (IS_NUM_FLOAT_VECS > 0)
  510.         if (float_switched)
  511.         {                  /* Restore float vectors.       */
  512.         utintflg(UT_INTOFF);
  513.         utpoken(save_float,
  514.             uttofar(0,4 * IS_1ST_FLOAT_VEC,char),
  515.             sizeof(save_float));
  516.         utintflg(UT_INTON);
  517.         }
  518. #endif
  519.  
  520.         if (dos_saved)
  521.         {
  522.                       /* Restore current process.     */
  523.         if (utdosmajor >= 3)
  524.             iscurprc(IS_SETPROC,oldproc);
  525.                       /* Restore former Ctrl-Break    */
  526.                       /* and BIOS keyboard handling.  */
  527.         isputvec(0x1b,pint_1bh);
  528.         isputvec(0x16,pctrl->prev_16h_vec);
  529.         }
  530.  
  531.         if (pctrl->key_event.action == IV_KY_SLEEP)
  532.         pctrl->awake = 0;
  533.         else if (pctrl->key_event.action == IV_KY_WAKE)
  534.         pctrl->awake = 1;
  535.  
  536.         pctrl->key_event.ch      = 0;
  537.         pctrl->key_event.keycode = 0;
  538.         pctrl->key_event.action  = IV_KY_NONE;
  539.         timaction             = IV_TM_NONE;
  540.     }
  541.     else
  542.         pctrl->req = 1;
  543.     }
  544.  
  545.     if (timaction != IV_TM_INTERVAL)
  546.     idleticks++;
  547. }
  548.  
  549. /**
  550. *
  551. * Name        timer_req -- Scan table of timer events to find one
  552. *                 that is eligible for service.
  553. *
  554. * Synopsis    timer_req();
  555. *
  556. * Returns    timaction      IV_TM_NONE if no timer event is
  557. *                    eligible;
  558. *                  IV_TM_MOMENT if a one-time event is
  559. *                    eligible;
  560. *                  IV_TM_INTERVAL if a periodic event is
  561. *                    eligible.
  562. *        timindex      Index of found event in user's table of
  563. *                    timer events.  This is meaningless
  564. *                    if IV_TM_NONE is returned.
  565. *
  566. **/
  567.  
  568. static void timer_req()
  569. {
  570.     long now;
  571.     int  i;
  572.  
  573.     utgetclk(&now);
  574.  
  575.     for (i = 0;
  576.      i < timtabsize && timaction == IV_TM_NONE;
  577.      i++)
  578.     {
  579.     if (   (   ptimtab[i].action == IV_TM_MOMENT
  580.         && ptimtab[i].ticks  <=  now)
  581.         || (   ptimtab[i].action == IV_TM_INTERVAL
  582.         && ptimtab[i].ticks  <= idleticks))
  583.     {
  584.         timaction = ptimtab[i].action;
  585.         timindex  = i;
  586.     }
  587.     }
  588. }
  589.  
  590. /**
  591. *
  592. * Name        readytask -- Return nonzero if intervention function
  593. *                 is eligible for service.
  594. *
  595. * Synopsis    ready = readytask();
  596. *
  597. *        int ready      1 if intervention function can be
  598. *                    safely executed,
  599. *                  0 if not.
  600. *
  601. **/
  602.  
  603. static int readytask()
  604. {
  605.     if (pctrl->idle_busy)          /* We're inside an INT 28h call,*/
  606.     {                      /* so DOS functions 1-12 aren't */
  607.                       /* available, but other DOS     */
  608.                       /* functions are.           */
  609.     if (pctrl->idle_safe && !pctrl->dkey_need)
  610.         return 1;
  611.     else
  612.         return 0;
  613.     }
  614.                       /* We're not in an INT 28h call.*/
  615.  
  616.     else if (pctrl->dos_need)          /* If intervention function     */
  617.     {                      /* needs any DOS or disk          */
  618.                       /* functions,              */
  619.     if (   pctrl->disk_busy
  620.         || !utdosrdy()
  621.         || *pint24h_flag)
  622.         return 0;              /* Disk or DOS is busy so fail. */
  623.     else
  624.         return 1;              /* Disk & DOS are available.    */
  625.     }
  626.     else
  627.     return 1;
  628. }
  629.  
  630. /**
  631. *
  632. * Name        unschedule -- Cancel for today all "moment" events
  633. *                  whose time has passed.
  634. *
  635. * Synopsis    unschedule();
  636. *
  637. * Description    This function sets the IV_RESCHED bit in all "moment"
  638. *        events if necessary, preventing them from executing
  639. *        today.
  640. *
  641. **/
  642.  
  643. static void unschedule()
  644. {
  645.     long now;
  646.     int  i;
  647.  
  648.     utgetclk(&now);
  649.  
  650.     for (i = 0; i < timtabsize; i++)
  651.     if (   ptimtab[i].action == IV_TM_MOMENT
  652.         && ptimtab[i].ticks  <  now)
  653.         ptimtab[i].ticks |= IV_RESCHED;
  654. }
  655.  
  656. /**
  657. *
  658. * Name        reschedule -- Reschedule all "moment" events if
  659. *                  midnight has passed.
  660. *
  661. * Synopsis    reschedule();
  662. *
  663. * Description    This function clears the IV_RESCHED bit from all
  664. *        "moment" events if necessary, allowing them to execute
  665. *        again.    It takes action only if the time of day is
  666. *        observed to go backward (as it normally does at
  667. *        midnight.)
  668. *
  669. **/
  670.  
  671. static void reschedule()
  672. {
  673.     long now;
  674.     int  i;
  675.  
  676.     utgetclk(&now);
  677.  
  678.     if (now < lasttime)
  679.     {                      /* Time went backward, so this  */
  680.                       /*  must be a new day.          */
  681.                       /* Reschedule all moment events.*/
  682.     for (i = 0; i < timtabsize; i++)
  683.         if (ptimtab[i].action == IV_TM_MOMENT)
  684.         ptimtab[i].ticks  &= ~IV_RESCHED;
  685.     }
  686.  
  687.     lasttime = now;              /* Save current time.          */
  688. }
  689.