/* * $Id: event.c,v 2.0.1.5 1996/06/26 18:39:38 alexis Exp alexis $ * * UPS Daemon * The Wild Wind Communications, 1995, 1996 * * See file LICENSE for the distribution terms of this software. */ #include "upsd.h" #include "apc.h" /* * Acts. Intended to be called with traverse(). * * This function returns no value. */ void act(action) struct action *action; { switch(action->type) { case A_NONE: break; case A_EVENT: process((struct event *)action->action); break; case A_EXEC: execute(expand((char *)action->action)); break; case A_RAISE: traverse2((struct chain *)upsp->eventv, (void *)trig, action->action); break; case A_DROP: traverse2((struct chain *)upsp->eventv, (void *)drop, action->action); break; case A_POLL: upsp->model->poll((struct ups_val *)action->action); break; case A_TUNE: upsp->model->tune((struct ups_val *)action->action); break; case A_LOG: syslog(((struct message *)action->action)->priority, expand(((struct message *)action->action)->message)); break; case A_SLEEP: (void) select(0, NULL, NULL, NULL, (struct timeval *)action->action); break; default: syslog(LOG_ERR, "act: incorrect action type"); } } /* * Processes the event. */ void process(event) struct event *event; { if(checkcondition(event)) { if(event->first == 0) { event->nextrun = 0; event->first = event->last = current_time; } else { event->last = current_time; } } /* The event is inactive || expires. */ if((event->first == 0) || (event->when->act_for != 0 && (current_time - event->last > event->when->act_for))) { event->first = event->last = event->nextrun = 0; return; } if(event->nextrun == 0) { event->nextrun = event->first + event->when->act_after; } /* Act if the time has come. */ if(event->nextrun <= current_time) { /* XXX: we may want to move the next line into act() */ traverse2((struct chain *)event->acts, (void *)atrig, (void *)zero_trig); traverse((struct chain *)event->acts, (void *)act); event->nextrun += event->when->act_every; /* The event already acted once. */ if(event->when->act_every == 0) { event->first = event->last = event->nextrun = 0; return; } } if(((next_time == 0) || ((event->nextrun < next_time) && ((event->first + event->when->act_for > event->nextrun) || (event->when->act_for == 0))))) { next_time = event->nextrun; } } /* * Trig an event. */ void trig(event, trigger) struct event *event; struct ups_trig *trigger; { if((event->condition == 0) && (event->v == NULL)) { if(event->trigger == trigger->id) { if(event->first == 0) { event->nextrun = 0; event->first = event->last = current_time; } else { event->last = current_time; } } else if(event->trigger == trigger->drop) { event->nextrun = event->first = event->last = 0; } } } /* * Drops an event. */ void drop(event, trigger) struct event *event; struct ups_trig *trigger; { if((event->condition == 0) && (event->v == NULL) && (event->trigger == trigger->id)) { event->nextrun = event->first = event->last = 0; } } /* * Returns the trigger id if any or zero if none. */ struct ups_trig * checktrigger(buffer, size) char *buffer; size_t size; { register struct ups_trig *tp; for(;size > 0; buffer++, size--) { for(tp = upsp->model->triggers; tp->id != 0; tp++) { if(size < tp->size) { continue; } if(!bcmp(tp->trigger, buffer, tp->size)) { return tp; } } } return NULL; } /* * Checks if condition occured. */ int checkcondition(event) struct event *event; { register struct ups_val *v; register struct ups_reg *r; if((event->trigger == 0) && (event->condition != 0) && (event->v != NULL)) { if((r = REGISTERID(event->v->id)) == NULL) { syslog(LOG_ERR, "check: incorrect register id"); return 0; } if((v = VALUEID(event->v->id)) == NULL) { syslog(LOG_ERR, "check: value is not in the state"); return 0; } if((event->condition & C_STRING) == 0) { switch(event->condition & C_COND) { case C_LESS: return (v->val.number < event->v->val.number); case C_MORE: return (v->val.number > event->v->val.number); case C_EQUAL: return (v->val.number == event->v->val.number); case C_NEQUAL: return (v->val.number != event->v->val.number); default: return 0; } } else { /* XXX: strcmp() is not applicable. Should be bcmp(). */ switch(event->condition & C_COND) { case C_LESS: return (strcmp(v->val.binary, event->v->val.binary) < 0); case C_MORE: return (strcmp(v->val.binary, event->v->val.binary) > 0); case C_EQUAL: return (strcmp(v->val.binary, event->v->val.binary) == 0); case C_NEQUAL: return (strcmp(v->val.binary, event->v->val.binary) != 0); default: return 0; } /* NOTREACHED */ } /* NOTREACHED */ } return 0; } /* * Trigs an event given an action pointer if the action is the evenet. */ void atrig(action, trigger) struct action *action; struct ups_trig *trigger; { if(action->type == A_EVENT) { trig((struct event *)action->action, trigger); } }