/*
* $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);
}
}
syntax highlighted by Code2HTML, v. 0.9.1