/* mndrep Reporting module of reminder service 1985 Mark E. Mallett */ #include "minder.h" #include "comnd.h" #include "setjmp.h" /* Local definitions */ /* External routines */ /* External data */ extern int Curdat; /* Current date */ extern int Curtim; /* Current time */ extern EVT *Evthdr; /* Heads the event list */ extern CFB Inicfb; /* CFB for initialization */ extern int Osdate; /* Can OS give date/time ? */ extern char Tmpabf[]; /* Temp atom buffer */ extern CSB Tmpcsb; /* Temp command state block */ extern jmp_buf Tmpenv; /* setjmp environment buffer */ /* Local routines */ extern int dspack(); /* disposition: ack */ extern int dspnxt(); /* disposition: next */ /* Local data */ static char *Mntbl[] = { /* Names of months */ "Foo", /* (month 0) */ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; /* dispositions command keyword and dispatch tables */ BYTE *Dspktb[] = { /* Command keywords.. */ "ACKNOWLEDGE", /* Ack the event, as required */ "NEXT", /* Move along to next event */ NULL /* Ends with a null pointer */ }; int (*Dspdsp[])() = { dspack, /* ACKNOWLEDGE */ dspnxt, /* NEXT */ 0 /* Ends with a zero for convenience */ }; /* COMND blocks */ CFB Dskcfb = {_CMKEY, _CFHPP|_CFDPP, 0, &Dspktb, "Command, ", "NEXT"}; /* *//* report() The reporting function of the minder program This routine is responsible for showing events which have become active. Accepts : Returns : */ report () { IND EVT *EVTptr; /* Pointer to event.. */ IND EVT *EVTptr1; /* another pointer */ IND EVT *EVTlst; /* Points to action list */ IND int intcnt; /* Counts interactive events */ IND int okflg; /* OK to proceed flag */ if (Osdate) /* If OS gives it */ curdtm (&Curdat, &Curtim); /* Get current date/time */ /* Go through and report events with automatic dispositions; also make note of events which need interaction */ EVTptr = Evthdr; /* Point to header */ intcnt = 0; /* Count of events rq action */ while (EVTptr) { EVTptr -> EVT_FLG &= ~(_EFACT|_EFRDA); /* Mark not active, no action */ okflg = chkfor (EVTptr); /* Init ok-to-look flag */ if (okflg) /* If ok.. */ { if (chkact ((EVTptr->EVT_DTD - EVTptr->EVT_ADV), EVTptr -> EVT_DTM)) { EVTptr -> EVT_FLG |= _EFACT; /* Set active */ if (EVTptr -> EVT_FLG & _EFACK) /* If ack rqd... */ intcnt++; /* Count interactive.. */ else /* Not auto mode */ { if (chkact (EVTptr -> EVT_DTD, EVTptr -> EVT_DTM)) EVTptr -> EVT_FLG |= _EFRDA; /* If action should be taken */ prtrep (EVTptr); /* Print report for this alarm */ } } } EVTptr = EVTptr -> EVT_FLK; /* Link to next */ } /* Now process active events, if any, requiring interaction */ if (intcnt) { printf ("\n***Event(s) requiring interaction follow***\n\n"); EVTptr = Evthdr; /* Start at beginning again */ while (EVTptr) { if ((EVTptr -> EVT_FLG & _EFACT) /* Marked active ? */ && (EVTptr -> EVT_FLG & _EFACK)) { prtrep (EVTptr); /* Print report */ repdsp (EVTptr); /* Do disposition */ } EVTptr = EVTptr -> EVT_FLK; } } /* Now attend to events marked as needing attention. */ EVTlst = NULL; /* No disposed-of list, yet */ EVTptr = Evthdr; /* Start at beginning of list */ while (EVTptr) /* Go through it */ { EVTptr1 = EVTptr; /* Get working copy */ EVTptr = EVTptr -> EVT_FLK; /* Get addr of next one, now */ if (EVTptr1 -> EVT_FLG & _EFRDA) /* Take action ? */ { remev (EVTptr1); /* Remove this from the list */ switch (EVTptr1 -> EVT_DIS) /* Process by disposition */ { case _EDDEL: /* delete? */ break; /* just lose it! */ case _EDSCH: /* Reschedule ... */ resched (EVTptr1); /* Process rescheduling */ /* Drop through to keep case */ case _EDKEEP: /* Keep event */ EVTptr1 -> EVT_FLK = EVTlst; EVTlst = EVTptr1; break; default: printf ("Bad value in disposition\n"); } } } while (EVTlst) /* Add processed EVTs back in */ { EVTptr = EVTlst; EVTlst = EVTlst -> EVT_FLK; addev (EVTptr); } } /* *//* repdsp (EVTptr) Handles interactive disposition of an event Accepts : EVTptr Address of the event block Returns : */ repdsp (EVTptr) EVT *EVTptr; /* Address of event block */ { IND int i; /* Scratch */ IND BYTE **kptr; /* Points to kwd table entry */ printf ("\nPlease enter disposition for this event\n"); Tmpcsb.CSB_PMT = "MIND-DISP> "; /* Set prompt */ /* Enter command loop */ while (TRUE) /* Forever */ { if (COMND (&Tmpcsb, &Inicfb) != _CROK) /* eh? */ { printf ("Fatal error initializing COMND\n"); exit(); } setjmp (Tmpenv); /* Mark here for reparse */ if (COMNDi (&Tmpcsb, &Dskcfb) != _CROK) /* Collect keyword */ continue; kptr = (char **) (Tmpcsb.CSB_RVL._ADR); i = kptr - (&Dspktb[0]); /* Get keyword index */ if ((*Dspdsp[i])(EVTptr)) /* Process command */ break; /* Exit command loop on done */ } } /* *//* dspack (EVTptr) Processes the ACKNOWLEDGE disposition-command. Accepts : EVTptr Address of event block Returns : */ dspack (EVTptr) EVT *EVTptr; /* Addr of EVT block */ { if (!noise (&Tmpcsb, "event")) /* Give guide words */ return; if (!confrm (&Tmpcsb)) /* Confirm the command */ return; EVTptr -> EVT_FLG |= _EFRDA; /* Do the action. */ return (TRUE); } /* *//* dspnxt (EVTptr) Processes the NEXT disposition-command. Accepts : EVTptr Address of event block Returns : */ dspnxt (EVTptr) EVT *EVTptr; /* Addr of EVT block */ { if (!noise (&Tmpcsb, "event")) /* Give guide words */ return; if (!confrm (&Tmpcsb)) /* Confirm the command */ return; return (TRUE); } /* *//* prtrep (EVTptr) Print report for an event Accepts : EVTptr Address of event block Returns : */ prtrep (EVTptr) EVT *EVTptr; /* Addr of event block */ { IND int i; /* Scratch */ IND int m,d,y,hh,mm; /* Date/time components */ IND int nl; /* Newline flag */ cvided (EVTptr -> EVT_DTD, EVTptr -> EVT_DTM, &m, &d, &y, &hh, &mm); nl = FALSE; if (EVTptr -> EVT_FRM) /* If any from */ { printf ("From: %-10s ", EVTptr -> EVT_FRM); nl = TRUE; } if (!chkact (EVTptr -> EVT_DTD, EVTptr -> EVT_DTM)) if (chkact (EVTptr->EVT_DTD - EVTptr->EVT_ADV, EVTptr->EVT_DTM)) { printf (" *** Advance Notice ***"); nl = TRUE; } if (nl) printf ("\n"); printf (" *** \"%s\"", EVTptr -> EVT_NAM); i = 20 - strlen(EVTptr -> EVT_NAM); while (i-- > 0) putchar (' '); printf ("%s %2d, %04d %02d:%02d", Mntbl[m], d, y, hh, mm); if (strlen (EVTptr -> EVT_MSG) >= 23) printf ("\n"); printf (" >>%s<<\n\n", EVTptr -> EVT_MSG); } /* *//* chkact (chkdat, chktim) Check a date and time for activation Accepts : chkdat Date to check for active chktim Time to check for active Returns : TRUE if chkdat/chktim is le Curdat/Curtim FALSE if not */ chkact (chkdat, chktim) int chkdat; /* date to check */ int chktim; /* time to check */ { if (chkdat < Curdat) /* If lt. */ return (TRUE); /* then definitely active */ if (chkdat == Curdat) /* If same */ if (chktim <= Curtim) /* If times lt */ return (TRUE); /* then true */ return (FALSE); /* Not true */ } /* *//* resched (EVTptr) Reschedule an event based on its information Accepts : EVTptr Address of EVT Returns : Event data modified for rescheduling. */ resched (EVTptr) EVT *EVTptr; /* Addr of EVT */ { IND int id, it, m, d, y, hh, mm; /* Date/time values */ id = EVTptr -> EVT_DTD; /* Pickup date/time */ it = EVTptr -> EVT_DTM; cvided (id, it, &m, &d, &y, &hh, &mm); /* Get components */ switch (EVTptr -> EVT_RSU) { /* Reschedule by units */ case 0: /* Days */ id += EVTptr -> EVT_RSV; /* Just add in the days */ break; /* Done. */ case 1: /* Weeks */ id += EVTptr -> EVT_RSV*7; break; case 2: /* Months */ m += EVTptr -> EVT_RSV; while (m > 12) { y++; m -= 12; } cvedid (&id, &it, m, d, y, mm, hh); break; case 3: /* Years */ y += EVTptr -> EVT_RSV; cvedid (&id, &it, m, d, y, mm, hh); break; } EVTptr -> EVT_DTD = id; /* Store date */ EVTptr -> EVT_DTM = it; /* And time. */ }