Exemplo n.º 1
0
/**
 * Validate timestamps of a service s
 */
static void check_timestamp(Service_T s) {
  Timestamp_T t;
  time_t      now;

  ASSERT(s && s->timestamplist);

  if ((int)time(&now) == -1) {
    Event_post(s, Event_Data, STATE_FAILED, s->action_DATA, "can't obtain actual system time");
    return;
  } else
    Event_post(s, Event_Data, STATE_SUCCEEDED, s->action_DATA, "actual system time obtained");

  for (t = s->timestamplist; t; t = t->next) {
    if (t->test_changes) {

      /* if we are testing for changes only, the value is variable */

      if (t->timestamp != s->inf->timestamp) {
        /* reset expected value for next cycle */
        t->timestamp = s->inf->timestamp;
        Event_post(s, Event_Timestamp, STATE_CHANGED, t->action, "timestamp was changed for %s", s->path);
      } else {
        DEBUG("'%s' timestamp was not changed for %s\n", s->name, s->path);
        Event_post(s, Event_Timestamp, STATE_CHANGEDNOT, t->action, "timestamp was not changed for %s", s->path);
      }
      break;
    } else {

      /* we are testing constant value for failed or succeeded state */

      if (Util_evalQExpression(t->operator, (int)(now - s->inf->timestamp), t->time))
        Event_post(s, Event_Timestamp, STATE_FAILED, t->action, "timestamp test failed for %s", s->path);
      else {
        DEBUG("'%s' timestamp test succeeded for %s\n", s->name, s->path); 
        Event_post(s, Event_Timestamp, STATE_SUCCEEDED, t->action, "timestamp succeeded");
      }
    }
  }
}
Exemplo n.º 2
0
/**
 * Check that the server returns a valid HTTP response as well as checksum
 * or content regex if required
 * @param s A socket
 * @return TRUE if the response is valid otherwise FALSE
 */
static int check_request(Socket_T socket, Port_T P) {
        int status, content_length = -1;
        char buf[LINE_SIZE];
        if (! socket_readln(socket, buf, LINE_SIZE)) {
                socket_setError(socket, "HTTP: Error receiving data -- %s", STRERROR);
                return FALSE;
        }
        Str_chomp(buf);
        if (! sscanf(buf, "%*s %d", &status)) {
                socket_setError(socket, "HTTP error: Cannot parse HTTP status in response: %s", buf);
                return FALSE;
        }
        if (! Util_evalQExpression(P->operator, status, P->status)) {
                socket_setError(socket, "HTTP error: Server returned status %d", status);
                return FALSE;
        }
        /* Get Content-Length header value */
        while (socket_readln(socket, buf, LINE_SIZE)) {
                if ((buf[0] == '\r' && buf[1] == '\n') || (buf[0] == '\n'))
                        break;
                Str_chomp(buf);
                if (Str_startsWith(buf, "Content-Length")) {
                        if (! sscanf(buf, "%*s%*[: ]%d", &content_length)) {
                                socket_setError(socket, "HTTP error: Parsing Content-Length response header '%s'", buf);
                                return FALSE;
                        }
                        if (content_length < 0) {
                                socket_setError(socket, "HTTP error: Illegal Content-Length response header '%s'", buf);
                                return FALSE;
                        }
                }
        }
        if (P->url_request && P->url_request->regex && ! do_regex(socket, content_length, P->url_request))
                return FALSE;
        if (P->request_checksum)
                return check_request_checksum(socket, content_length, P->request_checksum, P->request_hashtype);
        return TRUE;
}
Exemplo n.º 3
0
/**
 * Test size
 */
static void check_size(Service_T s) {
  Size_T sl;

  ASSERT(s && s->sizelist);

  for (sl = s->sizelist; sl; sl = sl->next) {

    /* if we are testing for changes only, the value is variable */
    if (sl->test_changes) {
      if (!sl->test_changes_ok) {
        /* the size was not initialized during monit start, so set the size now
         * and allow further size change testing */
        sl->test_changes_ok = TRUE;
        sl->size = s->inf->priv.file.st_size;
      } else {
        if (sl->size != s->inf->priv.file.st_size) {
          Event_post(s, Event_Size, STATE_CHANGED, sl->action, "size was changed for %s", s->path);
          /* reset expected value for next cycle */
          sl->size = s->inf->priv.file.st_size;
        } else {
          DEBUG("'%s' size has not changed [current size=%llu B]\n", s->name, s->inf->priv.file.st_size);
          Event_post(s, Event_Size, STATE_CHANGEDNOT, sl->action, "size was not changed", s->path);
        }
      }
      break;
    }

    /* we are testing constant value for failed or succeeded state */
    if (Util_evalQExpression(sl->operator, s->inf->priv.file.st_size, sl->size))
      Event_post(s, Event_Size, STATE_FAILED, sl->action, "size test failed for %s -- current size is %llu B", s->path, s->inf->priv.file.st_size);
    else {
      DEBUG("'%s' file size check succeeded [current size=%llu B]\n", s->name, s->inf->priv.file.st_size);
      Event_post(s, Event_Size, STATE_SUCCEEDED, sl->action, "size succeeded");
    }
  }
}
Exemplo n.º 4
0
/**
 * Extract the Scoreboard line from the mod_status response.
 * Count the active apache child processes, and those which are
 * in other states. If each percentage exceeds the corresponding
 * limit, then return FALSE.
 * @param s A socket
 * @param limit The maximum percentage of logging processes
 * @return TRUE if logging is OK otherwise FALSE
 */
static int check_apache_stat(Socket_T socket) {

  int scored = 0;
  int errors = 0;
  char line[READ_SIZE];
  char search_string[READ_SIZE + 1];

  int loglimit= 0;
  int closelimit= 0;
  int dnslimit= 0;
  int keepalivelimit= 0;
  int replylimit= 0;
  int requestlimit= 0;
  int startlimit= 0;
  int waitlimit= 0;
  int gracefullimit= 0;
  int cleanuplimit= 0;

  int no_logging = 0;
  int no_close = 0;
  int no_dns = 0;
  int no_keepalive = 0;
  int no_reply = 0;
  int no_request = 0;
  int no_start = 0;
  int no_wait = 0;
  int no_graceful = 0;
  int no_cleanup = 0;
  int active_servers = 0;
  char *p;
  Port_T myPort= (Port_T)socket_get_Port(socket);

  ASSERT(myPort);

  loglimit= myPort->ApacheStatus.loglimit;
  closelimit= myPort->ApacheStatus.closelimit;
  dnslimit= myPort->ApacheStatus.dnslimit;
  keepalivelimit= myPort->ApacheStatus.keepalivelimit;
  replylimit= myPort->ApacheStatus.replylimit;
  requestlimit= myPort->ApacheStatus.requestlimit;
  startlimit= myPort->ApacheStatus.startlimit;
  waitlimit= myPort->ApacheStatus.waitlimit;
  gracefullimit= myPort->ApacheStatus.gracefullimit;
  cleanuplimit= myPort->ApacheStatus.cleanuplimit;


  while(NULL != socket_readln(socket, line, READ_SIZE)) {
    if(Str_startsWith(line, "Scoreboard")) {
      if(1 != sscanf(line, "%*s%*[: ]%1024s", search_string)) {
       Str_chomp(line);
       socket_setError(socket, "APACHE-STATUS error: parsing Apache status response '%s'\n",
         line);
       return FALSE;
      } else {
        scored = 1;
      }
    }
  }

  DEBUG("Scoreboard: %s\n", search_string);

  /* Check that some scoreboard line was found, if not return an error */
  if(!scored){
    socket_setError(socket, "APACHE-STATUS error: no scoreboard line returned by Apache\n");
    return FALSE;
  }

  /* Total each of the status messages in the scoreboard */
  for(p = search_string ; *p ; p++){
    active_servers++;
    switch(*p){
    case 'S':
      no_start++;
      break;
    case 'R':
      no_request++;
      break;
    case 'W':
      no_reply++;
      break;
    case 'K':
      no_keepalive++;
      break;
    case 'D':
      no_dns++;
      break;
    case 'C':
      no_close++;
      break;
    case 'L':
      no_logging++;
      break;
    case 'G':
      no_graceful++;
      break;
    case 'I':
      no_cleanup++;
      break;
    case '_':
      no_wait++;
      break;
    case '.':
      active_servers--;
      break;
    }
  }

  if(active_servers <= 0){
    socket_setError(socket, "APACHE-STATUS warning: No idle server or threads found\n");
    /* This is not really an error, only a very bussy server */
    return TRUE;
  }

  /*
   * Conditions are only tested if the limit parameter is greater than zero.
   */

  if(loglimit > 0){
    if(Util_evalQExpression(myPort->ApacheStatus.loglimitOP,
                            (100 * no_logging / active_servers), loglimit)) {
      socket_setError(socket, "APACHE-STATUS error:"
          " %i percent of Apache processes are logging\n", loglimit);
      errors++;
    }
  }

  if(startlimit > 0){
    if(Util_evalQExpression(myPort->ApacheStatus.startlimitOP,
                            (100 * no_start / active_servers), startlimit)) {
      socket_setError(socket, "APACHE-STATUS error:"
          " %i percent of Apache processes are starting\n", startlimit);
      errors++;
    }
  }

  if(requestlimit > 0){
    if(Util_evalQExpression(myPort->ApacheStatus.requestlimitOP,
                    (100 * no_request / active_servers), requestlimit)) {
      socket_setError(socket, "APACHE-STATUS error:"
          " %i percent of Apache processes are reading requests\n",
          requestlimit);
      errors++;
    }
  }

  if(replylimit > 0 ){
    if(Util_evalQExpression(myPort->ApacheStatus.replylimitOP,
                            (100 * no_reply / active_servers), replylimit)) {
      socket_setError(socket, "APACHE-STATUS error:"
          " %i percent of Apache processes are sending a reply\n", replylimit);
      errors++;
    }
  }

  if(keepalivelimit > 0){
    if(Util_evalQExpression(myPort->ApacheStatus.keepalivelimitOP,
                    (100 * no_keepalive / active_servers), keepalivelimit)) {
      socket_setError(socket, "APACHE-STATUS error:"
          " %i percent of Apache processes are in keepalive\n", keepalivelimit);
      errors++;
    }
  }

  if(dnslimit > 0){
    if(Util_evalQExpression(myPort->ApacheStatus.dnslimitOP,
                            (100 * no_dns / active_servers), dnslimit)) {
      socket_setError(socket, "APACHE-STATUS error:"
          " %i percent of Apache processes are waiting for DNS\n", dnslimit);
      errors++;
    }
  }

  if(closelimit > 0){
    if(Util_evalQExpression(myPort->ApacheStatus.closelimitOP,
                            (100 * no_close / active_servers), closelimit)){
      socket_setError(socket, "APACHE-STATUS error:"
          " %i percent of Apache processes are closing connections\n",
          closelimit);
      errors++;
    }
  }

  if(gracefullimit > 0){
    if(Util_evalQExpression(myPort->ApacheStatus.gracefullimitOP,
                     (100 * no_graceful / active_servers), gracefullimit)) {
      socket_setError(socket, "APACHE-STATUS error:"
          " %i percent of Apache processes are finishing gracefully\n",
          gracefullimit);
      errors++;
    }
  }

  if(cleanuplimit > 0){
    if(Util_evalQExpression(myPort->ApacheStatus.cleanuplimitOP,
                    (100 * no_cleanup / active_servers), cleanuplimit)) {
      socket_setError(socket, "APACHE-STATUS error:"
          " %i percent of Apache processes are in idle cleanup\n",
          cleanuplimit);
      errors++;
    }
  }

  if(waitlimit > 0){
    if(Util_evalQExpression(myPort->ApacheStatus.waitlimitOP,
                            (100 * no_wait / active_servers), waitlimit)) {
      socket_setError(socket, "APACHE-STATUS error:"
          " %i percent of Apache processes are waiting for a connection\n",
          waitlimit);
      errors++;
    }
  }

  return (errors==0);

}
Exemplo n.º 5
0
static int parse_scoreboard(Socket_T socket, char *scoreboard) {
        int logging = 0, close = 0, dns = 0, keepalive = 0, reply = 0, request = 0, start = 0, wait = 0, graceful = 0, cleanup = 0, open = 0;
        for (char *state = scoreboard; *state; state++) {
                switch (*state) {
                        case 'S':
                                start++;
                                break;
                        case 'R':
                                request++;
                                break;
                        case 'W':
                                reply++;
                                break;
                        case 'K':
                                keepalive++;
                                break;
                        case 'D':
                                dns++;
                                break;
                        case 'C':
                                close++;
                                break;
                        case 'L':
                                logging++;
                                break;
                        case 'G':
                                graceful++;
                                break;
                        case 'I':
                                cleanup++;
                                break;
                        case '_':
                                wait++;
                                break;
                        case '.':
                                open++;
                                break;
                }
        }

        int total = logging + close + dns + keepalive + reply + request + start + wait + graceful + cleanup + open;
        if (! total)
                return TRUE; // Idle server

        int errors = 0;
        Port_T p = socket_get_Port(socket);
        ASSERT(p);

        //FIXME: socket_setError overrides previous => either stop on first error, or append errors and set error at the end (convert error buffer to stringbuffer?)
        if (p->ApacheStatus.loglimit > 0 && Util_evalQExpression(p->ApacheStatus.loglimitOP, (100 * logging / total), p->ApacheStatus.loglimit)) {
                socket_setError(socket, "APACHE-STATUS: error -- %d percent of processes are logging", 100 * logging / total);
                errors++;
        }
        if (p->ApacheStatus.startlimit > 0 && Util_evalQExpression(p->ApacheStatus.startlimitOP, (100 * start / total), p->ApacheStatus.startlimit)) {
                socket_setError(socket, "APACHE-STATUS: error -- %d percent of processes are starting", 100 * start / total);
                errors++;
        }
        if (p->ApacheStatus.requestlimit > 0 && Util_evalQExpression(p->ApacheStatus.requestlimitOP, (100 * request / total), p->ApacheStatus.requestlimit)) {
                socket_setError(socket, "APACHE-STATUS: error -- %d percent of processes are reading requests", 100 * request / total);
                errors++;
        }
        if (p->ApacheStatus.replylimit > 0 && Util_evalQExpression(p->ApacheStatus.replylimitOP, (100 * reply / total), p->ApacheStatus.replylimit)) {
                socket_setError(socket, "APACHE-STATUS: error -- %d percent of processes are sending a reply", 100 * reply / total);
                errors++;
        }
        if (p->ApacheStatus.keepalivelimit > 0 && Util_evalQExpression(p->ApacheStatus.keepalivelimitOP, (100 * keepalive / total), p->ApacheStatus.keepalivelimit)) {
                socket_setError(socket, "APACHE-STATUS: error -- %d percent of processes are in keepalive", 100 * keepalive / total);
                errors++;
        }
        if (p->ApacheStatus.dnslimit > 0 && Util_evalQExpression(p->ApacheStatus.dnslimitOP, (100 * dns / total), p->ApacheStatus.dnslimit)) {
                socket_setError(socket, "APACHE-STATUS: error -- %d percent of processes are waiting for DNS", 100 * dns / total);
                errors++;
        }
        if (p->ApacheStatus.closelimit > 0 && Util_evalQExpression(p->ApacheStatus.closelimitOP, (100 * close / total), p->ApacheStatus.closelimit)) {
                socket_setError(socket, "APACHE-STATUS: error -- %d percent of processes are closing connections", 100 * close / total);
                errors++;
        }
        if (p->ApacheStatus.gracefullimit > 0 && Util_evalQExpression(p->ApacheStatus.gracefullimitOP, (100 * graceful / total), p->ApacheStatus.gracefullimit)) {
                socket_setError(socket, "APACHE-STATUS: error -- %d percent of processes are finishing gracefully", 100 * graceful / total);
                errors++;
        }
        if (p->ApacheStatus.cleanuplimit > 0 && Util_evalQExpression(p->ApacheStatus.cleanuplimitOP, (100 * cleanup / total), p->ApacheStatus.cleanuplimit)) {
                socket_setError(socket, "APACHE-STATUS: error -- %d percent of processes are in idle cleanup", 100 * cleanup / total);
                errors++;
        }
        if (p->ApacheStatus.waitlimit > 0 && Util_evalQExpression(p->ApacheStatus.waitlimitOP, (100 * wait / total), p->ApacheStatus.waitlimit)) {
                socket_setError(socket, "APACHE-STATUS: error -- %d percent of processes are waiting for a connection", 100 * wait / total);
                errors++;
        }

        return (errors == 0);
}
Exemplo n.º 6
0
/**
 * Check process resources
 */
static void check_process_resources(Service_T s, Resource_T r) {

  int okay = TRUE;
  char report[STRLEN]={0};

  ASSERT(s && r);

  switch(r->resource_id) {

  case RESOURCE_ID_CPU_PERCENT:
    if (s->monitor == MONITOR_INIT || s->inf->priv.process.cpu_percent < 0) {
      DEBUG("'%s' cpu usage check skipped (initializing)\n", s->name);
    } else if (Util_evalQExpression(r->operator, s->inf->priv.process.cpu_percent, r->limit)) {
      snprintf(report, STRLEN, "cpu usage of %.1f%% matches resource limit [cpu usage%s%.1f%%]", s->inf->priv.process.cpu_percent/10.0, operatorshortnames[r->operator], r->limit/10.0);
      okay = FALSE;
    } else
      snprintf(report, STRLEN, "'%s' cpu usage check succeeded [current cpu usage=%.1f%%]", s->name, s->inf->priv.process.cpu_percent/10.0);
    break;

  case RESOURCE_ID_TOTAL_CPU_PERCENT:
    if (s->monitor == MONITOR_INIT || s->inf->priv.process.total_cpu_percent < 0) {
      DEBUG("'%s' total cpu usage check skipped (initializing)\n", s->name);
    } else if (Util_evalQExpression(r->operator, s->inf->priv.process.total_cpu_percent, r->limit)) {
      snprintf(report, STRLEN, "total cpu usage of %.1f%% matches resource limit [cpu usage%s%.1f%%]", s->inf->priv.process.total_cpu_percent/10.0, operatorshortnames[r->operator], r->limit/10.0);
      okay = FALSE;
    } else
      snprintf(report, STRLEN, "'%s' total cpu usage check succeeded [current cpu usage=%.1f%%]", s->name, s->inf->priv.process.total_cpu_percent/10.0);
    break;

  case RESOURCE_ID_CPUUSER:
    if (s->monitor == MONITOR_INIT || systeminfo.total_cpu_user_percent < 0) {
      DEBUG("'%s' cpu user usage check skipped (initializing)\n", s->name);
    } else if (Util_evalQExpression(r->operator, systeminfo.total_cpu_user_percent, r->limit)) {
      snprintf(report, STRLEN, "cpu user usage of %.1f%% matches resource limit [cpu user usage%s%.1f%%]", systeminfo.total_cpu_user_percent/10.0, operatorshortnames[r->operator], r->limit/10.0);
      okay = FALSE;
    } else
      snprintf(report, STRLEN, "'%s' cpu user usage check succeeded [current cpu user usage=%.1f%%]", s->name, systeminfo.total_cpu_user_percent/10.0);
    break;

  case RESOURCE_ID_CPUSYSTEM:
    if (s->monitor == MONITOR_INIT || systeminfo.total_cpu_syst_percent < 0) {
      DEBUG("'%s' cpu system usage check skipped (initializing)\n", s->name);
    } else if (Util_evalQExpression(r->operator, systeminfo.total_cpu_syst_percent, r->limit)) {
      snprintf(report, STRLEN, "cpu system usage of %.1f%% matches resource limit [cpu system usage%s%.1f%%]", systeminfo.total_cpu_syst_percent/10.0, operatorshortnames[r->operator], r->limit/10.0);
      okay = FALSE;
    } else
      snprintf(report, STRLEN, "'%s' cpu system usage check succeeded [current cpu system usage=%.1f%%]", s->name, systeminfo.total_cpu_syst_percent/10.0);
    break;

  case RESOURCE_ID_CPUWAIT:
    if (s->monitor == MONITOR_INIT || systeminfo.total_cpu_wait_percent < 0) {
      DEBUG("'%s' cpu wait usage check skipped (initializing)\n", s->name);
    } else if (Util_evalQExpression(r->operator, systeminfo.total_cpu_wait_percent, r->limit)) {
      snprintf(report, STRLEN, "cpu wait usage of %.1f%% matches resource limit [cpu wait usage%s%.1f%%]", systeminfo.total_cpu_wait_percent/10.0, operatorshortnames[r->operator], r->limit/10.0);
      okay = FALSE;
    } else
      snprintf(report, STRLEN, "'%s' cpu wait usage check succeeded [current cpu wait usage=%.1f%%]", s->name, systeminfo.total_cpu_wait_percent/10.0);
    break;

  case RESOURCE_ID_MEM_PERCENT:
    if (s->type == TYPE_SYSTEM) {
      if (Util_evalQExpression(r->operator, systeminfo.total_mem_percent, r->limit)) {
        snprintf(report, STRLEN, "mem usage of %.1f%% matches resource limit [mem usage%s%.1f%%]", systeminfo.total_mem_percent/10.0, operatorshortnames[r->operator], r->limit/10.0);
        okay = FALSE;
      } else
        snprintf(report, STRLEN, "'%s' mem usage check succeeded [current mem usage=%.1f%%]", s->name, systeminfo.total_mem_percent/10.0);
    } else {
      if (Util_evalQExpression(r->operator, s->inf->priv.process.mem_percent, r->limit)) {
        snprintf(report, STRLEN, "mem usage of %.1f%% matches resource limit [mem usage%s%.1f%%]", s->inf->priv.process.mem_percent/10.0, operatorshortnames[r->operator], r->limit/10.0);
        okay = FALSE;
      } else
        snprintf(report, STRLEN, "'%s' mem usage check succeeded [current mem usage=%.1f%%]", s->name, s->inf->priv.process.mem_percent/10.0);
    }
    break;

  case RESOURCE_ID_MEM_KBYTE:
    if (s->type == TYPE_SYSTEM) {
      if (Util_evalQExpression(r->operator, systeminfo.total_mem_kbyte, r->limit)) {
        snprintf(report, STRLEN, "mem amount of %ldkB matches resource limit [mem amount%s%ldkB]", systeminfo.total_mem_kbyte, operatorshortnames[r->operator], r->limit);
        okay = FALSE;
      } else
        snprintf(report, STRLEN, "'%s' mem amount check succeeded [current mem amount=%ldkB]", s->name, systeminfo.total_mem_kbyte);
    } else {
      if (Util_evalQExpression(r->operator, s->inf->priv.process.mem_kbyte, r->limit)) {
        snprintf(report, STRLEN, "mem amount of %ldkB matches resource limit [mem amount%s%ldkB]", s->inf->priv.process.mem_kbyte, operatorshortnames[r->operator], r->limit);
        okay = FALSE;
      } else
        snprintf(report, STRLEN, "'%s' mem amount check succeeded [current mem amount=%ldkB]", s->name, s->inf->priv.process.mem_kbyte);
    }
    break;

  case RESOURCE_ID_SWAP_PERCENT:
    if (s->type == TYPE_SYSTEM) {
      if (Util_evalQExpression(r->operator, systeminfo.total_swap_percent, r->limit)) {
        snprintf(report, STRLEN, "swap usage of %.1f%% matches resource limit [swap usage%s%.1f%%]", systeminfo.total_swap_percent/10.0, operatorshortnames[r->operator], r->limit/10.0);
        okay = FALSE;
      } else
        snprintf(report, STRLEN, "'%s' swap usage check succeeded [current swap usage=%.1f%%]", s->name, systeminfo.total_swap_percent/10.0);
    }
    break;

  case RESOURCE_ID_SWAP_KBYTE:
    if (s->type == TYPE_SYSTEM) {
      if (Util_evalQExpression(r->operator, systeminfo.total_swap_kbyte, r->limit)) {
        snprintf(report, STRLEN, "swap amount of %ldkB matches resource limit [swap amount%s%ldkB]", systeminfo.total_swap_kbyte, operatorshortnames[r->operator], r->limit);
        okay = FALSE;
      } else
        snprintf(report, STRLEN, "'%s' swap amount check succeeded [current swap amount=%ldkB]", s->name, systeminfo.total_swap_kbyte);
    }
    break;

  case RESOURCE_ID_LOAD1:
    if (Util_evalQExpression(r->operator, (int)(systeminfo.loadavg[0]*10.0), r->limit)) {
      snprintf(report, STRLEN, "loadavg(1min) of %.1f matches resource limit [loadavg(1min)%s%.1f]", systeminfo.loadavg[0], operatorshortnames[r->operator], r->limit/10.0);
      okay = FALSE;
    } else
      snprintf(report, STRLEN, "'%s' loadavg(1min) check succeeded [current loadavg(1min)=%.1f]", s->name, systeminfo.loadavg[0]);
    break;

  case RESOURCE_ID_LOAD5:
    if (Util_evalQExpression(r->operator, (int)(systeminfo.loadavg[1]*10.0), r->limit)) {
      snprintf(report, STRLEN, "loadavg(5min) of %.1f matches resource limit [loadavg(5min)%s%.1f]", systeminfo.loadavg[1], operatorshortnames[r->operator], r->limit/10.0);
      okay = FALSE;
    } else
      snprintf(report, STRLEN, "'%s' loadavg(5min) check succeeded [current loadavg(5min)=%.1f]", s->name, systeminfo.loadavg[1]);
    break;

  case RESOURCE_ID_LOAD15:
    if (Util_evalQExpression(r->operator, (int)(systeminfo.loadavg[2]*10.0), r->limit)) {
      snprintf(report, STRLEN, "loadavg(15min) of %.1f matches resource limit [loadavg(15min)%s%.1f]", systeminfo.loadavg[2], operatorshortnames[r->operator], r->limit/10.0);
      okay = FALSE;
    } else
      snprintf(report, STRLEN, "'%s' loadavg(15min) check succeeded [current loadavg(15min)=%.1f]", s->name, systeminfo.loadavg[2]);
    break;

  case RESOURCE_ID_CHILDREN:
    if (Util_evalQExpression(r->operator, s->inf->priv.process.children, r->limit)) {
      snprintf(report, STRLEN, "children of %i matches resource limit [children%s%ld]", s->inf->priv.process.children, operatorshortnames[r->operator], r->limit);
      okay = FALSE;
    } else
      snprintf(report, STRLEN, "'%s' children check succeeded [current children=%i]", s->name, s->inf->priv.process.children);
    break;

  case RESOURCE_ID_TOTAL_MEM_KBYTE:
    if (Util_evalQExpression(r->operator, s->inf->priv.process.total_mem_kbyte, r->limit)) {
      snprintf(report, STRLEN, "total mem amount of %ldkB matches resource limit [total mem amount%s%ldkB]", s->inf->priv.process.total_mem_kbyte, operatorshortnames[r->operator], r->limit);
      okay = FALSE;
    } else
      snprintf(report, STRLEN, "'%s' total mem amount check succeeded [current total mem amount=%ldkB]", s->name, s->inf->priv.process.total_mem_kbyte);
    break;

  case RESOURCE_ID_TOTAL_MEM_PERCENT:
    if (Util_evalQExpression(r->operator, s->inf->priv.process.total_mem_percent, r->limit)) {
      snprintf(report, STRLEN, "total mem amount of %.1f%% matches resource limit [total mem amount%s%.1f%%]", (float)s->inf->priv.process.total_mem_percent/10.0, operatorshortnames[r->operator], (float)r->limit/10.0);
      okay = FALSE;
    } else
      snprintf(report, STRLEN, "'%s' total mem amount check succeeded [current total mem amount=%.1f%%]", s->name, s->inf->priv.process.total_mem_percent/10.0);
    break;

  default:
    LogError("'%s' error -- unknown resource ID: [%d]\n", s->name, r->resource_id);
    return;
  }

  if (! okay)
    Event_post(s, Event_Resource, STATE_FAILED, r->action, "%s", report);
  else {
    Event_post(s, Event_Resource, STATE_SUCCEEDED, r->action, "%s", report);
    if (*report)
        DEBUG("%s\n", report);
  }
}