Logo Search packages:      
Sourcecode: hobbit version File versions  Download package

hobbitd_capture.c

/*----------------------------------------------------------------------------*/
/* Hobbit message daemon.                                                     */
/*                                                                            */
/* Hobbitd worker module, to capture status messages for a particulr host     */
/* or test, or data type. This is fed from the status- or data-channel, and   */
/* simply logs the data received to a file.                                   */
/*                                                                            */
/* Copyright (C) 2004-2006 Henrik Storner <henrik@hswn.dk>                    */
/*                                                                            */
/* This program is released under the GNU General Public License (GPL),       */
/* version 2. See the file "COPYING" for details.                             */
/*                                                                            */
/*----------------------------------------------------------------------------*/

static char rcsid[] = "$Id: hobbitd_capture.c,v 1.3 2006/07/20 16:06:41 henrik Rel $";

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>

#include "libbbgen.h"
#include "hobbitd_worker.h"

#define MAX_META 20     /* The maximum number of meta-data items in a message */


int main(int argc, char *argv[])
{
      char *msg;
      int running;
      int argi, seq;
      struct timeval *timeout = NULL;
      pcre *hostexp = NULL;
      pcre *exhostexp = NULL;
      pcre *testexp = NULL;
      pcre *extestexp = NULL;
      pcre *colorexp = NULL;
        const char *errmsg = NULL;
      int errofs = 0;
      FILE *logfd = stdout;

      /* Handle program options. */
      for (argi = 1; (argi < argc); argi++) {
            if (strcmp(argv[argi], "--debug") == 0) {
                  /*
                   * A global "debug" variable is available. If
                   * it is set, then "dbgprintf()" outputs debug messages.
                   */
                  debug = 1;
            }
            else if (strncmp(argv[argi], "--timeout=", 10) == 0) {
                  /*
                   * You can have a timeout when waiting for new
                   * messages. If it happens, you will get a "@@idle\n"
                   * message with sequence number 0.
                   * If you dont want a timeout, just pass a NULL for the timeout parameter.
                   */
                  timeout = (struct timeval *)(malloc(sizeof(struct timeval)));
                  timeout->tv_sec = (atoi(argv[argi]+10));
                  timeout->tv_usec = 0;
            }
            else if (argnmatch(argv[argi], "--hosts=")) {
                  char *exp = strchr(argv[argi], '=') + 1;
                  hostexp = pcre_compile(exp, PCRE_CASELESS, &errmsg, &errofs, NULL);
                  if (hostexp == NULL) printf("Invalid expression '%s'\n", exp);
            }
            else if (argnmatch(argv[argi], "--exhosts=")) {
                  char *exp = strchr(argv[argi], '=') + 1;
                  exhostexp = pcre_compile(exp, PCRE_CASELESS, &errmsg, &errofs, NULL);
                  if (exhostexp == NULL) printf("Invalid expression '%s'\n", exp);
            }
            else if (argnmatch(argv[argi], "--tests=")) {
                  char *exp = strchr(argv[argi], '=') + 1;
                  testexp = pcre_compile(exp, PCRE_CASELESS, &errmsg, &errofs, NULL);
                  if (testexp == NULL) printf("Invalid expression '%s'\n", exp);
            }
            else if (argnmatch(argv[argi], "--extests=")) {
                  char *exp = strchr(argv[argi], '=') + 1;
                  extestexp = pcre_compile(exp, PCRE_CASELESS, &errmsg, &errofs, NULL);
                  if (extestexp == NULL) printf("Invalid expression '%s'\n", exp);
            }
            else if (argnmatch(argv[argi], "--colors=")) {
                  char *exp = strchr(argv[argi], '=') + 1;
                  colorexp = pcre_compile(exp, PCRE_CASELESS, &errmsg, &errofs, NULL);
                  if (colorexp == NULL) printf("Invalid expression '%s'\n", exp);
            }
            else if (argnmatch(argv[argi], "--outfile=")) {
                  char *fn = strchr(argv[argi], '=') + 1;
                  logfd = fopen(fn, "a");
                  if (logfd == NULL) {
                        printf("Cannot open logfile %s: %s\n", fn, strerror(errno));
                        logfd = stdout;
                  }
            }
            else {
                  printf("Unknown option %s\n", argv[argi]);
                  printf("Usage: %s [--hosts=EXP] [--tests=EXP] [--exhosts=EXP] [--extests=EXP] [--color=EXP] [--outfile=FILENAME]\n", argv[0]);
                  return 0;
            }
      }

      running = 1;
      while (running) {
            char *eoln, *restofmsg, *p;
            char *metadata[MAX_META+1];
            int metacount;

            msg = get_hobbitd_message(C_LAST, argv[0], &seq, timeout);
            if (msg == NULL) {
                  /*
                   * get_hobbitd_message will return NULL if hobbitd_channel closes
                   * the input pipe. We should shutdown when that happens.
                   */
                  running = 0;
                  continue;
            }

            /*
             * Now we have a message. So do something with it.
             *
             * The first line of the message is always a '|' separated
             * list of meta-data about the message. After the first
             * line, the content varies by channel.
             */

            /* Split the message in the first line (with meta-data), and the rest */
            eoln = strchr(msg, '\n');
            if (eoln) {
                  *eoln = '\0';
                  restofmsg = eoln+1;
            }
            else {
                  restofmsg = "";
            }

            /* 
             * Now parse the meta-data into elements.
             * We use our own "gettok()" routine which works
             * like strtok(), but can handle empty elements.
             */
            metacount = 0; 
            p = gettok(msg, "|");
            while (p && (metacount < MAX_META)) {
                  metadata[metacount++] = p;
                  p = gettok(NULL, "|");
            }
            metadata[metacount] = NULL;

            /*
             * A "shutdown" message is sent when the master daemon
             * terminates. The child workers should shutdown also.
             */
            if (strncmp(metadata[0], "@@shutdown", 10) == 0) {
                  printf("Shutting down\n");
                  running = 0;
                  continue;
            }

            /*
             * A "logrotate" message is sent when the Hobbit logs are
             * rotated. The child workers must re-open their logfiles,
             * typically stdin and stderr - the filename is always
             * provided in the HOBBITCHANNEL_LOGFILENAME environment.
             */
            else if (strncmp(metadata[0], "@@logrotate", 11) == 0) {
                  char *fn = xgetenv("HOBBITCHANNEL_LOGFILENAME");
                  if (fn && strlen(fn)) {
                        freopen(fn, "a", stdout);
                        freopen(fn, "a", stderr);
                  }
                  continue;
            }

            /*
             * An "idle" message appears when get_hobbitd_message() 
             * exceeds the timeout setting (ie. you passed a timeout
             * value). This allows your worker module to perform
             * some internal processing even though no messages arrive.
             */
            else if (strncmp(metadata[0], "@@idle", 6) == 0) {
                  printf("Got an 'idle' message\n");
            }

            /*
             * The "drophost", "droptest", "renamehost" and "renametst"
             * indicates that a host/test was deleted or renamed. If the
             * worker module maintains some internal storage (in memory
             * or persistent file-storage), it should act on these
             * messages to maintain data consistency.
             */
            else if ((metacount > 3) && (strncmp(metadata[0], "@@drophost", 10) == 0)) {
                  printf("Got a 'drophost' message for host '%s'\n", metadata[3]);
            }
            else if ((metacount > 4) && (strncmp(metadata[0], "@@droptest", 10) == 0)) {
                  printf("Got a 'droptest' message for host '%s' test '%s'\n", metadata[3], metadata[4]);
            }
            else if ((metacount > 4) && (strncmp(metadata[0], "@@renamehost", 12) == 0)) {
                  printf("Got a 'renamehost' message for host '%s' -> '%s'\n", metadata[3], metadata[4]);
            }
            else if ((metacount > 5) && (strncmp(metadata[0], "@@renametest", 12) == 0)) {
                  printf("Got a 'renametest' message for host '%s' test '%s' -> '%s'\n", 
                        metadata[3], metadata[4], metadata[5]);
            }

            /*
             * What happens next is up to the worker module.
             *
             * For this sample module, we'll just print out the data we got.
             */
            else {
                  int ovector[30];
                  int match, i;
                  char *hostname = metadata[4];
                  char *testname = metadata[5];
                  char *color = metadata[7];

                  if (hostexp) {
                        match = (pcre_exec(hostexp, NULL, hostname, strlen(hostname), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0);
                        if (!match) continue;
                  }
                  if (exhostexp) {
                        match = (pcre_exec(exhostexp, NULL, hostname, strlen(hostname), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0);
                        if (match) continue;
                  }
                  if (testexp) {
                        match = (pcre_exec(testexp, NULL, testname, strlen(testname), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0);
                        if (!match) continue;
                  }
                  if (exhostexp) {
                        match = (pcre_exec(extestexp, NULL, testname, strlen(testname), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0);
                        if (match) continue;
                  }
                  if (colorexp) {
                        match = (pcre_exec(colorexp, NULL, color, strlen(color), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0);
                        if (!match) continue;
                  }

                  printf("## ");
                  for (i=0; (i < metacount); i++) printf("%s ", metadata[i]);
                  printf("\n");
                  printf("%s\n", restofmsg);
            }
      }

      return 0;
}


Generated by  Doxygen 1.6.0   Back to index